]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/binfmt/binfmt.c
util-lib: move character class definitions to string-util.h
[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
151b190e 22#include <errno.h>
fabe5c0e 23#include <getopt.h>
3f6fd1ba
LP
24#include <limits.h>
25#include <stdbool.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
151b190e 29
b5efdb8a 30#include "alloc-util.h"
3f6fd1ba 31#include "conf-files.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
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
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
56f64d95 96 log_error_errno(errno, "Failed to read file '%s', ignoring: %m", path);
fabe5c0e 97 return -errno;
151b190e
LP
98 }
99
100 p = strstrip(l);
151b190e
LP
101 if (!*p)
102 continue;
d3b6d0c2 103 if (strchr(COMMENTS "\n", *p))
151b190e
LP
104 continue;
105
fabe5c0e
LP
106 k = apply_rule(p);
107 if (k < 0 && r == 0)
151b190e
LP
108 r = k;
109 }
110
151b190e
LP
111 return r;
112}
113
601185b4 114static void help(void) {
fabe5c0e
LP
115 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
116 "Registers binary formats.\n\n"
eb9da376 117 " -h --help Show this help\n"
601185b4
ZJS
118 " --version Show package version\n"
119 , program_invocation_short_name);
fabe5c0e
LP
120}
121
122static int parse_argv(int argc, char *argv[]) {
123
eb9da376
LP
124 enum {
125 ARG_VERSION = 0x100,
126 };
127
fabe5c0e
LP
128 static const struct option options[] = {
129 { "help", no_argument, NULL, 'h' },
eb9da376
LP
130 { "version", no_argument, NULL, ARG_VERSION },
131 {}
fabe5c0e
LP
132 };
133
134 int c;
135
136 assert(argc >= 0);
137 assert(argv);
138
601185b4 139 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
fabe5c0e
LP
140
141 switch (c) {
142
143 case 'h':
601185b4
ZJS
144 help();
145 return 0;
eb9da376
LP
146
147 case ARG_VERSION:
3f6fd1ba 148 return version();
fabe5c0e
LP
149
150 case '?':
151 return -EINVAL;
152
153 default:
eb9da376 154 assert_not_reached("Unhandled option");
fabe5c0e 155 }
fabe5c0e
LP
156
157 return 1;
158}
159
151b190e 160int main(int argc, char *argv[]) {
fabe5c0e
LP
161 int r, k;
162
163 r = parse_argv(argc, argv);
164 if (r <= 0)
165 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
151b190e 166
151b190e
LP
167 log_set_target(LOG_TARGET_AUTO);
168 log_parse_environment();
169 log_open();
170
4c12626c
LP
171 umask(0022);
172
fabe5c0e 173 r = 0;
13317670 174
fabe5c0e
LP
175 if (argc > optind) {
176 int i;
13317670 177
fabe5c0e 178 for (i = optind; i < argc; i++) {
170dcb7b 179 k = apply_file(argv[i], false);
13317670
LP
180 if (k < 0 && r == 0)
181 r = k;
182 }
db1413d7 183 } else {
fabe5c0e
LP
184 _cleanup_strv_free_ char **files = NULL;
185 char **f;
db1413d7 186
fabe5c0e 187 r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
44143309 188 if (r < 0) {
da927ba9 189 log_error_errno(r, "Failed to enumerate binfmt.d files: %m");
44143309
KS
190 goto finish;
191 }
151b190e 192
13317670 193 /* Flush out all rules */
ad118bda 194 write_string_file("/proc/sys/fs/binfmt_misc/status", "-1", 0);
13317670 195
db1413d7 196 STRV_FOREACH(f, files) {
db1413d7
KS
197 k = apply_file(*f, true);
198 if (k < 0 && r == 0)
199 r = k;
200 }
db1413d7 201 }
fabe5c0e 202
44143309 203finish:
151b190e
LP
204 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
205}