Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include <errno.h>
4 : : #include <getopt.h>
5 : : #include <limits.h>
6 : : #include <stdbool.h>
7 : : #include <stdio.h>
8 : : #include <stdlib.h>
9 : : #include <string.h>
10 : : #include <sys/stat.h>
11 : : #include <sys/types.h>
12 : :
13 : : #include "alloc-util.h"
14 : : #include "conf-files.h"
15 : : #include "def.h"
16 : : #include "fd-util.h"
17 : : #include "fileio.h"
18 : : #include "log.h"
19 : : #include "main-func.h"
20 : : #include "pager.h"
21 : : #include "path-util.h"
22 : : #include "pretty-print.h"
23 : : #include "string-util.h"
24 : : #include "strv.h"
25 : :
26 : : static bool arg_cat_config = false;
27 : : static PagerFlags arg_pager_flags = 0;
28 : :
29 : 0 : static int delete_rule(const char *rule) {
30 : 0 : _cleanup_free_ char *x = NULL, *fn = NULL;
31 : : char *e;
32 : :
33 [ # # ]: 0 : assert(rule);
34 [ # # ]: 0 : assert(rule[0]);
35 : :
36 : 0 : x = strdup(rule);
37 [ # # ]: 0 : if (!x)
38 : 0 : return log_oom();
39 : :
40 : 0 : e = strchrnul(x+1, x[0]);
41 : 0 : *e = 0;
42 : :
43 [ # # ]: 0 : if (!filename_is_valid(x + 1))
44 [ # # ]: 0 : return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
45 : : "Rule file name '%s' is not valid, refusing.", x + 1);
46 : :
47 : 0 : fn = path_join("/proc/sys/fs/binfmt_misc", x+1);
48 [ # # ]: 0 : if (!fn)
49 : 0 : return log_oom();
50 : :
51 : 0 : return write_string_file(fn, "-1", WRITE_STRING_FILE_DISABLE_BUFFER);
52 : : }
53 : :
54 : 0 : static int apply_rule(const char *rule) {
55 : : int r;
56 : :
57 : 0 : (void) delete_rule(rule);
58 : :
59 : 0 : r = write_string_file("/proc/sys/fs/binfmt_misc/register", rule, WRITE_STRING_FILE_DISABLE_BUFFER);
60 [ # # ]: 0 : if (r < 0)
61 [ # # ]: 0 : return log_error_errno(r, "Failed to add binary format: %m");
62 : :
63 : 0 : return 0;
64 : : }
65 : :
66 : 0 : static int apply_file(const char *path, bool ignore_enoent) {
67 : 0 : _cleanup_fclose_ FILE *f = NULL;
68 : : int r;
69 : :
70 [ # # ]: 0 : assert(path);
71 : :
72 : 0 : r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("binfmt.d"), &f);
73 [ # # ]: 0 : if (r < 0) {
74 [ # # # # ]: 0 : if (ignore_enoent && r == -ENOENT)
75 : 0 : return 0;
76 : :
77 [ # # ]: 0 : return log_error_errno(r, "Failed to open file '%s': %m", path);
78 : : }
79 : :
80 [ # # ]: 0 : log_debug("apply: %s", path);
81 : 0 : for (;;) {
82 [ # # # # ]: 0 : _cleanup_free_ char *line = NULL;
83 : : char *p;
84 : : int k;
85 : :
86 : 0 : k = read_line(f, LONG_LINE_MAX, &line);
87 [ # # ]: 0 : if (k < 0)
88 [ # # ]: 0 : return log_error_errno(k, "Failed to read file '%s': %m", path);
89 [ # # ]: 0 : if (k == 0)
90 : 0 : break;
91 : :
92 : 0 : p = strstrip(line);
93 [ # # ]: 0 : if (isempty(p))
94 : 0 : continue;
95 [ # # ]: 0 : if (strchr(COMMENTS, p[0]))
96 : 0 : continue;
97 : :
98 : 0 : k = apply_rule(p);
99 [ # # # # ]: 0 : if (k < 0 && r == 0)
100 : 0 : r = k;
101 : : }
102 : :
103 : 0 : return r;
104 : : }
105 : :
106 : 12 : static int help(void) {
107 : 12 : _cleanup_free_ char *link = NULL;
108 : : int r;
109 : :
110 : 12 : r = terminal_urlify_man("systemd-binfmt.service", "8", &link);
111 [ - + ]: 12 : if (r < 0)
112 : 0 : return log_oom();
113 : :
114 : 12 : printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
115 : : "Registers binary formats with the kernel.\n\n"
116 : : " -h --help Show this help\n"
117 : : " --version Show package version\n"
118 : : " --cat-config Show configuration files\n"
119 : : " --no-pager Do not pipe output into a pager\n"
120 : : "\nSee the %s for details.\n"
121 : : , program_invocation_short_name
122 : : , link
123 : : );
124 : :
125 : 12 : return 0;
126 : : }
127 : :
128 : 16 : static int parse_argv(int argc, char *argv[]) {
129 : : enum {
130 : : ARG_VERSION = 0x100,
131 : : ARG_CAT_CONFIG,
132 : : ARG_NO_PAGER,
133 : : };
134 : :
135 : : static const struct option options[] = {
136 : : { "help", no_argument, NULL, 'h' },
137 : : { "version", no_argument, NULL, ARG_VERSION },
138 : : { "cat-config", no_argument, NULL, ARG_CAT_CONFIG },
139 : : { "no-pager", no_argument, NULL, ARG_NO_PAGER },
140 : : {}
141 : : };
142 : :
143 : : int c;
144 : :
145 [ - + ]: 16 : assert(argc >= 0);
146 [ - + ]: 16 : assert(argv);
147 : :
148 [ + - ]: 16 : while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
149 : :
150 [ + - - - : 16 : switch (c) {
+ - ]
151 : :
152 : 12 : case 'h':
153 : 12 : return help();
154 : :
155 : 0 : case ARG_VERSION:
156 : 0 : return version();
157 : :
158 : 0 : case ARG_CAT_CONFIG:
159 : 0 : arg_cat_config = true;
160 : 0 : break;
161 : :
162 : 0 : case ARG_NO_PAGER:
163 : 0 : arg_pager_flags |= PAGER_DISABLE;
164 : 0 : break;
165 : :
166 : 4 : case '?':
167 : 4 : return -EINVAL;
168 : :
169 : 0 : default:
170 : 0 : assert_not_reached("Unhandled option");
171 : : }
172 : :
173 [ # # # # ]: 0 : if (arg_cat_config && argc > optind)
174 [ # # ]: 0 : return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
175 : : "Positional arguments are not allowed with --cat-config");
176 : :
177 : 0 : return 1;
178 : : }
179 : :
180 : 16 : static int run(int argc, char *argv[]) {
181 : : int r, k;
182 : :
183 : 16 : r = parse_argv(argc, argv);
184 [ + - ]: 16 : if (r <= 0)
185 : 16 : return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
186 : :
187 : 0 : log_setup_service();
188 : :
189 : 0 : umask(0022);
190 : :
191 : 0 : r = 0;
192 : :
193 [ # # ]: 0 : if (argc > optind) {
194 : : int i;
195 : :
196 [ # # ]: 0 : for (i = optind; i < argc; i++) {
197 : 0 : k = apply_file(argv[i], false);
198 [ # # # # ]: 0 : if (k < 0 && r == 0)
199 : 0 : r = k;
200 : : }
201 : : } else {
202 [ # # ]: 0 : _cleanup_strv_free_ char **files = NULL;
203 : : char **f;
204 : :
205 : 0 : r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char**) CONF_PATHS_STRV("binfmt.d"));
206 [ # # ]: 0 : if (r < 0)
207 [ # # ]: 0 : return log_error_errno(r, "Failed to enumerate binfmt.d files: %m");
208 : :
209 [ # # ]: 0 : if (arg_cat_config) {
210 : 0 : (void) pager_open(arg_pager_flags);
211 : :
212 : 0 : return cat_files(NULL, files, 0);
213 : : }
214 : :
215 : : /* Flush out all rules */
216 : 0 : (void) write_string_file("/proc/sys/fs/binfmt_misc/status", "-1", WRITE_STRING_FILE_DISABLE_BUFFER);
217 : :
218 [ # # # # ]: 0 : STRV_FOREACH(f, files) {
219 : 0 : k = apply_file(*f, true);
220 [ # # # # ]: 0 : if (k < 0 && r == 0)
221 : 0 : r = k;
222 : : }
223 : : }
224 : :
225 : 0 : return r;
226 : : }
227 : :
228 : 16 : DEFINE_MAIN_FUNCTION(run);
|