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