]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/binfmt/binfmt.c
binfmt: move sources to subdirectory
[thirdparty/systemd.git] / src / binfmt / binfmt.c
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
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
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
16 General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
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>
28 #include <stdarg.h>
29
30 #include "log.h"
31 #include "hashmap.h"
32 #include "strv.h"
33 #include "util.h"
34
35 static int delete_rule(const char *rule) {
36 char *x, *fn = NULL, *e;
37 int r;
38
39 assert(rule[0]);
40
41 if (!(x = strdup(rule)))
42 return -ENOMEM;
43
44 e = strchrnul(x+1, x[0]);
45 *e = 0;
46
47 asprintf(&fn, "/proc/sys/fs/binfmt_misc/%s", x+1);
48 free(x);
49
50 if (!fn)
51 return -ENOMEM;
52
53 r = write_one_line_file(fn, "-1");
54 free(fn);
55
56 return r;
57 }
58
59 static int apply_rule(const char *rule) {
60 int r;
61
62 delete_rule(rule);
63
64 if ((r = write_one_line_file("/proc/sys/fs/binfmt_misc/register", rule)) < 0) {
65 log_error("Failed to add binary format: %s", strerror(-r));
66 return r;
67 }
68
69 return 0;
70 }
71
72 static int apply_file(const char *path, bool ignore_enoent) {
73 FILE *f;
74 int r = 0;
75
76 assert(path);
77
78 if (!(f = fopen(path, "re"))) {
79 if (ignore_enoent && errno == ENOENT)
80 return 0;
81
82 log_error("Failed to open file '%s', ignoring: %m", path);
83 return -errno;
84 }
85
86 log_debug("apply: %s\n", path);
87 while (!feof(f)) {
88 char l[LINE_MAX], *p;
89 int k;
90
91 if (!fgets(l, sizeof(l), f)) {
92 if (feof(f))
93 break;
94
95 log_error("Failed to read file '%s', ignoring: %m", path);
96 r = -errno;
97 goto finish;
98 }
99
100 p = strstrip(l);
101
102 if (!*p)
103 continue;
104
105 if (strchr(COMMENTS, *p))
106 continue;
107
108 if ((k = apply_rule(p)) < 0 && r == 0)
109 r = k;
110 }
111
112 finish:
113 fclose(f);
114
115 return r;
116 }
117
118 int main(int argc, char *argv[]) {
119 int r = 0;
120
121 if (argc > 2) {
122 log_error("This program expects one or no arguments.");
123 return EXIT_FAILURE;
124 }
125
126 log_set_target(LOG_TARGET_AUTO);
127 log_parse_environment();
128 log_open();
129
130 umask(0022);
131
132 if (argc > 1) {
133 r = apply_file(argv[1], false);
134 } else {
135 char **files, **f;
136
137 /* Flush out all rules */
138 write_one_line_file("/proc/sys/fs/binfmt_misc/status", "-1");
139
140 r = conf_files_list(&files, ".conf",
141 "/run/binfmt.d",
142 "/etc/binfmt.d",
143 "/usr/local/lib/binfmt.d",
144 "/usr/lib/binfmt.d",
145 NULL);
146
147 if (r < 0) {
148 log_error("Failed to enumerate binfmt.d files: %s", strerror(-r));
149 goto finish;
150 }
151
152 STRV_FOREACH(f, files) {
153 int k;
154
155 k = apply_file(*f, true);
156 if (k < 0 && r == 0)
157 r = k;
158 }
159
160 strv_free(files);
161 }
162 finish:
163 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
164 }