]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/binfmt/binfmt.c
analyze: add --root option for cat-config
[thirdparty/systemd.git] / src / binfmt / binfmt.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2010 Lennart Poettering
6 ***/
7
8 #include <errno.h>
9 #include <getopt.h>
10 #include <limits.h>
11 #include <stdbool.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15
16 #include "alloc-util.h"
17 #include "conf-files.h"
18 #include "def.h"
19 #include "fd-util.h"
20 #include "fileio.h"
21 #include "log.h"
22 #include "string-util.h"
23 #include "strv.h"
24 #include "util.h"
25
26 static const char conf_file_dirs[] = CONF_PATHS_NULSTR("binfmt.d");
27
28 static int delete_rule(const char *rule) {
29 _cleanup_free_ char *x = NULL, *fn = NULL;
30 char *e;
31
32 assert(rule[0]);
33
34 x = strdup(rule);
35 if (!x)
36 return log_oom();
37
38 e = strchrnul(x+1, x[0]);
39 *e = 0;
40
41 fn = strappend("/proc/sys/fs/binfmt_misc/", x+1);
42 if (!fn)
43 return log_oom();
44
45 return write_string_file(fn, "-1", 0);
46 }
47
48 static int apply_rule(const char *rule) {
49 int r;
50
51 delete_rule(rule);
52
53 r = write_string_file("/proc/sys/fs/binfmt_misc/register", rule, 0);
54 if (r < 0)
55 return log_error_errno(r, "Failed to add binary format: %m");
56
57 return 0;
58 }
59
60 static int apply_file(const char *path, bool ignore_enoent) {
61 _cleanup_fclose_ FILE *f = NULL;
62 int r;
63
64 assert(path);
65
66 r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f);
67 if (r < 0) {
68 if (ignore_enoent && r == -ENOENT)
69 return 0;
70
71 return log_error_errno(r, "Failed to open file '%s', ignoring: %m", path);
72 }
73
74 log_debug("apply: %s", path);
75 for (;;) {
76 char l[LINE_MAX], *p;
77 int k;
78
79 if (!fgets(l, sizeof(l), f)) {
80 if (feof(f))
81 break;
82
83 return log_error_errno(errno, "Failed to read file '%s', ignoring: %m", path);
84 }
85
86 p = strstrip(l);
87 if (!*p)
88 continue;
89 if (strchr(COMMENTS "\n", *p))
90 continue;
91
92 k = apply_rule(p);
93 if (k < 0 && r == 0)
94 r = k;
95 }
96
97 return r;
98 }
99
100 static void help(void) {
101 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
102 "Registers binary formats.\n\n"
103 " -h --help Show this help\n"
104 " --version Show package version\n"
105 , program_invocation_short_name);
106 }
107
108 static int parse_argv(int argc, char *argv[]) {
109
110 enum {
111 ARG_VERSION = 0x100,
112 };
113
114 static const struct option options[] = {
115 { "help", no_argument, NULL, 'h' },
116 { "version", no_argument, NULL, ARG_VERSION },
117 {}
118 };
119
120 int c;
121
122 assert(argc >= 0);
123 assert(argv);
124
125 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
126
127 switch (c) {
128
129 case 'h':
130 help();
131 return 0;
132
133 case ARG_VERSION:
134 return version();
135
136 case '?':
137 return -EINVAL;
138
139 default:
140 assert_not_reached("Unhandled option");
141 }
142
143 return 1;
144 }
145
146 int main(int argc, char *argv[]) {
147 int r, k;
148
149 r = parse_argv(argc, argv);
150 if (r <= 0)
151 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
152
153 log_set_target(LOG_TARGET_AUTO);
154 log_parse_environment();
155 log_open();
156
157 umask(0022);
158
159 r = 0;
160
161 if (argc > optind) {
162 int i;
163
164 for (i = optind; i < argc; i++) {
165 k = apply_file(argv[i], false);
166 if (k < 0 && r == 0)
167 r = k;
168 }
169 } else {
170 _cleanup_strv_free_ char **files = NULL;
171 char **f;
172
173 r = conf_files_list_nulstr(&files, ".conf", NULL, 0, conf_file_dirs);
174 if (r < 0) {
175 log_error_errno(r, "Failed to enumerate binfmt.d files: %m");
176 goto finish;
177 }
178
179 /* Flush out all rules */
180 write_string_file("/proc/sys/fs/binfmt_misc/status", "-1", 0);
181
182 STRV_FOREACH(f, files) {
183 k = apply_file(*f, true);
184 if (k < 0 && r == 0)
185 r = k;
186 }
187 }
188
189 finish:
190 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
191 }