]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/binfmt/binfmt.c
Introduce CONF_DIRS_NULSTR helper to define standard conf dirs
[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
7f0a55d4 39static const char conf_file_dirs[] = CONF_DIRS_NULSTR("binfmt");
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
574d5f2d 58 return write_string_file(fn, "-1");
151b190e
LP
59}
60
61static int apply_rule(const char *rule) {
62 int r;
63
64 delete_rule(rule);
65
574d5f2d 66 r = write_string_file("/proc/sys/fs/binfmt_misc/register", rule);
fabe5c0e 67 if (r < 0) {
151b190e
LP
68 log_error("Failed to add binary format: %s", strerror(-r));
69 return r;
70 }
71
72 return 0;
73}
74
75static int apply_file(const char *path, bool ignore_enoent) {
fabe5c0e
LP
76 _cleanup_fclose_ FILE *f = NULL;
77 int r;
151b190e
LP
78
79 assert(path);
80
4cf7ea55 81 r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f);
fabe5c0e
LP
82 if (r < 0) {
83 if (ignore_enoent && r == -ENOENT)
151b190e
LP
84 return 0;
85
fabe5c0e
LP
86 log_error("Failed to open file '%s', ignoring: %s", path, strerror(-r));
87 return r;
151b190e
LP
88 }
89
9f6445e3 90 log_debug("apply: %s", path);
fabe5c0e 91 for (;;) {
151b190e
LP
92 char l[LINE_MAX], *p;
93 int k;
94
95 if (!fgets(l, sizeof(l), f)) {
96 if (feof(f))
97 break;
98
99 log_error("Failed to read file '%s', ignoring: %m", path);
fabe5c0e 100 return -errno;
151b190e
LP
101 }
102
103 p = strstrip(l);
151b190e
LP
104 if (!*p)
105 continue;
d3b6d0c2 106 if (strchr(COMMENTS "\n", *p))
151b190e
LP
107 continue;
108
fabe5c0e
LP
109 k = apply_rule(p);
110 if (k < 0 && r == 0)
151b190e
LP
111 r = k;
112 }
113
151b190e
LP
114 return r;
115}
116
601185b4 117static void help(void) {
fabe5c0e
LP
118 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
119 "Registers binary formats.\n\n"
eb9da376 120 " -h --help Show this help\n"
601185b4
ZJS
121 " --version Show package version\n"
122 , program_invocation_short_name);
fabe5c0e
LP
123}
124
125static int parse_argv(int argc, char *argv[]) {
126
eb9da376
LP
127 enum {
128 ARG_VERSION = 0x100,
129 };
130
fabe5c0e
LP
131 static const struct option options[] = {
132 { "help", no_argument, NULL, 'h' },
eb9da376
LP
133 { "version", no_argument, NULL, ARG_VERSION },
134 {}
fabe5c0e
LP
135 };
136
137 int c;
138
139 assert(argc >= 0);
140 assert(argv);
141
601185b4 142 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
fabe5c0e
LP
143
144 switch (c) {
145
146 case 'h':
601185b4
ZJS
147 help();
148 return 0;
eb9da376
LP
149
150 case ARG_VERSION:
151 puts(PACKAGE_STRING);
152 puts(SYSTEMD_FEATURES);
fabe5c0e
LP
153 return 0;
154
155 case '?':
156 return -EINVAL;
157
158 default:
eb9da376 159 assert_not_reached("Unhandled option");
fabe5c0e 160 }
fabe5c0e
LP
161
162 return 1;
163}
164
151b190e 165int main(int argc, char *argv[]) {
fabe5c0e
LP
166 int r, k;
167
168 r = parse_argv(argc, argv);
169 if (r <= 0)
170 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
151b190e 171
151b190e
LP
172 log_set_target(LOG_TARGET_AUTO);
173 log_parse_environment();
174 log_open();
175
4c12626c
LP
176 umask(0022);
177
fabe5c0e 178 r = 0;
13317670 179
fabe5c0e
LP
180 if (argc > optind) {
181 int i;
13317670 182
fabe5c0e 183 for (i = optind; i < argc; i++) {
170dcb7b 184 k = apply_file(argv[i], false);
13317670
LP
185 if (k < 0 && r == 0)
186 r = k;
187 }
db1413d7 188 } else {
fabe5c0e
LP
189 _cleanup_strv_free_ char **files = NULL;
190 char **f;
db1413d7 191
fabe5c0e 192 r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
44143309
KS
193 if (r < 0) {
194 log_error("Failed to enumerate binfmt.d files: %s", strerror(-r));
195 goto finish;
196 }
151b190e 197
13317670 198 /* Flush out all rules */
574d5f2d 199 write_string_file("/proc/sys/fs/binfmt_misc/status", "-1");
13317670 200
db1413d7 201 STRV_FOREACH(f, files) {
db1413d7
KS
202 k = apply_file(*f, true);
203 if (k < 0 && r == 0)
204 r = k;
205 }
db1413d7 206 }
fabe5c0e 207
44143309 208finish:
151b190e
LP
209 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
210}