]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/binfmt/binfmt.c
util-lib: split our string related calls from util.[ch] into its own file string...
[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
3f6fd1ba
LP
30#include "conf-files.h"
31#include "fileio.h"
151b190e 32#include "log.h"
07630cea 33#include "string-util.h"
db1413d7 34#include "strv.h"
151b190e
LP
35#include "util.h"
36
7f0a55d4 37static const char conf_file_dirs[] = CONF_DIRS_NULSTR("binfmt");
fabe5c0e 38
151b190e 39static int delete_rule(const char *rule) {
fabe5c0e
LP
40 _cleanup_free_ char *x = NULL, *fn = NULL;
41 char *e;
151b190e
LP
42
43 assert(rule[0]);
44
fabe5c0e
LP
45 x = strdup(rule);
46 if (!x)
14212119 47 return log_oom();
151b190e
LP
48
49 e = strchrnul(x+1, x[0]);
50 *e = 0;
51
fabe5c0e 52 fn = strappend("/proc/sys/fs/binfmt_misc/", x+1);
151b190e 53 if (!fn)
14212119 54 return log_oom();
151b190e 55
4c1fc3e4 56 return write_string_file(fn, "-1", 0);
151b190e
LP
57}
58
59static int apply_rule(const char *rule) {
60 int r;
61
62 delete_rule(rule);
63
4c1fc3e4 64 r = write_string_file("/proc/sys/fs/binfmt_misc/register", rule, 0);
23bbb0de
MS
65 if (r < 0)
66 return log_error_errno(r, "Failed to add binary format: %m");
151b190e
LP
67
68 return 0;
69}
70
71static int apply_file(const char *path, bool ignore_enoent) {
fabe5c0e
LP
72 _cleanup_fclose_ FILE *f = NULL;
73 int r;
151b190e
LP
74
75 assert(path);
76
4cf7ea55 77 r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f);
fabe5c0e
LP
78 if (r < 0) {
79 if (ignore_enoent && r == -ENOENT)
151b190e
LP
80 return 0;
81
23bbb0de 82 return log_error_errno(r, "Failed to open file '%s', ignoring: %m", path);
151b190e
LP
83 }
84
9f6445e3 85 log_debug("apply: %s", path);
fabe5c0e 86 for (;;) {
151b190e
LP
87 char l[LINE_MAX], *p;
88 int k;
89
90 if (!fgets(l, sizeof(l), f)) {
91 if (feof(f))
92 break;
93
56f64d95 94 log_error_errno(errno, "Failed to read file '%s', ignoring: %m", path);
fabe5c0e 95 return -errno;
151b190e
LP
96 }
97
98 p = strstrip(l);
151b190e
LP
99 if (!*p)
100 continue;
d3b6d0c2 101 if (strchr(COMMENTS "\n", *p))
151b190e
LP
102 continue;
103
fabe5c0e
LP
104 k = apply_rule(p);
105 if (k < 0 && r == 0)
151b190e
LP
106 r = k;
107 }
108
151b190e
LP
109 return r;
110}
111
601185b4 112static void help(void) {
fabe5c0e
LP
113 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
114 "Registers binary formats.\n\n"
eb9da376 115 " -h --help Show this help\n"
601185b4
ZJS
116 " --version Show package version\n"
117 , program_invocation_short_name);
fabe5c0e
LP
118}
119
120static int parse_argv(int argc, char *argv[]) {
121
eb9da376
LP
122 enum {
123 ARG_VERSION = 0x100,
124 };
125
fabe5c0e
LP
126 static const struct option options[] = {
127 { "help", no_argument, NULL, 'h' },
eb9da376
LP
128 { "version", no_argument, NULL, ARG_VERSION },
129 {}
fabe5c0e
LP
130 };
131
132 int c;
133
134 assert(argc >= 0);
135 assert(argv);
136
601185b4 137 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
fabe5c0e
LP
138
139 switch (c) {
140
141 case 'h':
601185b4
ZJS
142 help();
143 return 0;
eb9da376
LP
144
145 case ARG_VERSION:
3f6fd1ba 146 return version();
fabe5c0e
LP
147
148 case '?':
149 return -EINVAL;
150
151 default:
eb9da376 152 assert_not_reached("Unhandled option");
fabe5c0e 153 }
fabe5c0e
LP
154
155 return 1;
156}
157
151b190e 158int main(int argc, char *argv[]) {
fabe5c0e
LP
159 int r, k;
160
161 r = parse_argv(argc, argv);
162 if (r <= 0)
163 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
151b190e 164
151b190e
LP
165 log_set_target(LOG_TARGET_AUTO);
166 log_parse_environment();
167 log_open();
168
4c12626c
LP
169 umask(0022);
170
fabe5c0e 171 r = 0;
13317670 172
fabe5c0e
LP
173 if (argc > optind) {
174 int i;
13317670 175
fabe5c0e 176 for (i = optind; i < argc; i++) {
170dcb7b 177 k = apply_file(argv[i], false);
13317670
LP
178 if (k < 0 && r == 0)
179 r = k;
180 }
db1413d7 181 } else {
fabe5c0e
LP
182 _cleanup_strv_free_ char **files = NULL;
183 char **f;
db1413d7 184
fabe5c0e 185 r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
44143309 186 if (r < 0) {
da927ba9 187 log_error_errno(r, "Failed to enumerate binfmt.d files: %m");
44143309
KS
188 goto finish;
189 }
151b190e 190
13317670 191 /* Flush out all rules */
ad118bda 192 write_string_file("/proc/sys/fs/binfmt_misc/status", "-1", 0);
13317670 193
db1413d7 194 STRV_FOREACH(f, files) {
db1413d7
KS
195 k = apply_file(*f, true);
196 if (k < 0 && r == 0)
197 r = k;
198 }
db1413d7 199 }
fabe5c0e 200
44143309 201finish:
151b190e
LP
202 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
203}