]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/binfmt/binfmt.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / binfmt / binfmt.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
151b190e
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2010 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
151b190e
LP
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 15 Lesser General Public License for more details.
151b190e 16
5430f7f2 17 You should have received a copy of the GNU Lesser General Public License
151b190e
LP
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
151b190e 21#include <errno.h>
fabe5c0e 22#include <getopt.h>
3f6fd1ba
LP
23#include <limits.h>
24#include <stdbool.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
151b190e 28
b5efdb8a 29#include "alloc-util.h"
3f6fd1ba 30#include "conf-files.h"
a0f29c76 31#include "def.h"
3ffd4af2 32#include "fd-util.h"
3f6fd1ba 33#include "fileio.h"
151b190e 34#include "log.h"
07630cea 35#include "string-util.h"
db1413d7 36#include "strv.h"
151b190e
LP
37#include "util.h"
38
75eb6154 39static const char conf_file_dirs[] = CONF_PATHS_NULSTR("binfmt.d");
fabe5c0e 40
151b190e 41static int delete_rule(const char *rule) {
fabe5c0e
LP
42 _cleanup_free_ char *x = NULL, *fn = NULL;
43 char *e;
151b190e
LP
44
45 assert(rule[0]);
46
fabe5c0e
LP
47 x = strdup(rule);
48 if (!x)
14212119 49 return log_oom();
151b190e
LP
50
51 e = strchrnul(x+1, x[0]);
52 *e = 0;
53
fabe5c0e 54 fn = strappend("/proc/sys/fs/binfmt_misc/", x+1);
151b190e 55 if (!fn)
14212119 56 return log_oom();
151b190e 57
4c1fc3e4 58 return write_string_file(fn, "-1", 0);
151b190e
LP
59}
60
61static int apply_rule(const char *rule) {
62 int r;
63
64 delete_rule(rule);
65
4c1fc3e4 66 r = write_string_file("/proc/sys/fs/binfmt_misc/register", rule, 0);
23bbb0de
MS
67 if (r < 0)
68 return log_error_errno(r, "Failed to add binary format: %m");
151b190e
LP
69
70 return 0;
71}
72
73static int apply_file(const char *path, bool ignore_enoent) {
fabe5c0e
LP
74 _cleanup_fclose_ FILE *f = NULL;
75 int r;
151b190e
LP
76
77 assert(path);
78
4cf7ea55 79 r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f);
fabe5c0e
LP
80 if (r < 0) {
81 if (ignore_enoent && r == -ENOENT)
151b190e
LP
82 return 0;
83
23bbb0de 84 return log_error_errno(r, "Failed to open file '%s', ignoring: %m", path);
151b190e
LP
85 }
86
9f6445e3 87 log_debug("apply: %s", path);
fabe5c0e 88 for (;;) {
151b190e
LP
89 char l[LINE_MAX], *p;
90 int k;
91
92 if (!fgets(l, sizeof(l), f)) {
93 if (feof(f))
94 break;
95
e1427b13 96 return log_error_errno(errno, "Failed to read file '%s', ignoring: %m", path);
151b190e
LP
97 }
98
99 p = strstrip(l);
151b190e
LP
100 if (!*p)
101 continue;
d3b6d0c2 102 if (strchr(COMMENTS "\n", *p))
151b190e
LP
103 continue;
104
fabe5c0e
LP
105 k = apply_rule(p);
106 if (k < 0 && r == 0)
151b190e
LP
107 r = k;
108 }
109
151b190e
LP
110 return r;
111}
112
601185b4 113static void help(void) {
fabe5c0e
LP
114 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
115 "Registers binary formats.\n\n"
eb9da376 116 " -h --help Show this help\n"
601185b4
ZJS
117 " --version Show package version\n"
118 , program_invocation_short_name);
fabe5c0e
LP
119}
120
121static int parse_argv(int argc, char *argv[]) {
122
eb9da376
LP
123 enum {
124 ARG_VERSION = 0x100,
125 };
126
fabe5c0e
LP
127 static const struct option options[] = {
128 { "help", no_argument, NULL, 'h' },
eb9da376
LP
129 { "version", no_argument, NULL, ARG_VERSION },
130 {}
fabe5c0e
LP
131 };
132
133 int c;
134
135 assert(argc >= 0);
136 assert(argv);
137
601185b4 138 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
fabe5c0e
LP
139
140 switch (c) {
141
142 case 'h':
601185b4
ZJS
143 help();
144 return 0;
eb9da376
LP
145
146 case ARG_VERSION:
3f6fd1ba 147 return version();
fabe5c0e
LP
148
149 case '?':
150 return -EINVAL;
151
152 default:
eb9da376 153 assert_not_reached("Unhandled option");
fabe5c0e 154 }
fabe5c0e
LP
155
156 return 1;
157}
158
151b190e 159int main(int argc, char *argv[]) {
fabe5c0e
LP
160 int r, k;
161
162 r = parse_argv(argc, argv);
163 if (r <= 0)
164 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
151b190e 165
151b190e
LP
166 log_set_target(LOG_TARGET_AUTO);
167 log_parse_environment();
168 log_open();
169
4c12626c
LP
170 umask(0022);
171
fabe5c0e 172 r = 0;
13317670 173
fabe5c0e
LP
174 if (argc > optind) {
175 int i;
13317670 176
fabe5c0e 177 for (i = optind; i < argc; i++) {
170dcb7b 178 k = apply_file(argv[i], false);
13317670
LP
179 if (k < 0 && r == 0)
180 r = k;
181 }
db1413d7 182 } else {
fabe5c0e
LP
183 _cleanup_strv_free_ char **files = NULL;
184 char **f;
db1413d7 185
b5084605 186 r = conf_files_list_nulstr(&files, ".conf", NULL, 0, conf_file_dirs);
44143309 187 if (r < 0) {
da927ba9 188 log_error_errno(r, "Failed to enumerate binfmt.d files: %m");
44143309
KS
189 goto finish;
190 }
151b190e 191
13317670 192 /* Flush out all rules */
ad118bda 193 write_string_file("/proc/sys/fs/binfmt_misc/status", "-1", 0);
13317670 194
db1413d7 195 STRV_FOREACH(f, files) {
db1413d7
KS
196 k = apply_file(*f, true);
197 if (k < 0 && r == 0)
198 r = k;
199 }
db1413d7 200 }
fabe5c0e 201
44143309 202finish:
151b190e
LP
203 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
204}