binfmt.c revision 151b190e79e64824552e01849352ca8f6ac7dedb
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering/***
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering This file is part of systemd.
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering Copyright 2010 Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering systemd is free software; you can redistribute it and/or modify it
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering under the terms of the GNU General Public License as published by
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering the Free Software Foundation; either version 2 of the License, or
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering (at your option) any later version.
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering systemd is distributed in the hope that it will be useful, but
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering General Public License for more details.
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering You should have received a copy of the GNU General Public License
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering***/
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering#include <stdlib.h>
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering#include <stdbool.h>
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering#include <errno.h>
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering#include <string.h>
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering#include <stdio.h>
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering#include <limits.h>
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering#include "log.h"
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering#include "util.h"
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poetteringstatic int delete_rule(const char *rule) {
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering char *x, *fn, *e;
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering int r;
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering assert(rule[0]);
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering if (!(x = strdup(rule)))
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering return -ENOMEM;
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering e = strchrnul(x+1, x[0]);
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering *e = 0;
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering asprintf(&fn, "/proc/sys/fs/binfmt_misc/%s", x+1);
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering free(x);
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering if (!fn)
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering return -ENOMEM;
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering r = write_one_line_file(fn, "-1");
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering free(fn);
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering return r;
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering}
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poetteringstatic int apply_rule(const char *rule) {
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering int r;
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering delete_rule(rule);
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering if ((r = write_one_line_file("/proc/sys/fs/binfmt_misc/register", rule)) < 0) {
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering log_error("Failed to add binary format: %s", strerror(-r));
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering return r;
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering }
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering return 0;
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering}
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poetteringstatic int apply_file(const char *path, bool ignore_enoent) {
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering FILE *f;
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering int r = 0;
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering assert(path);
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering if (!(f = fopen(path, "re"))) {
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering if (ignore_enoent && errno == ENOENT)
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering return 0;
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering log_error("Failed to open file '%s', ignoring: %m", path);
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering return -errno;
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering }
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering while (!feof(f)) {
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering char l[LINE_MAX], *p;
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering int k;
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering if (!fgets(l, sizeof(l), f)) {
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering if (feof(f))
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering break;
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering log_error("Failed to read file '%s', ignoring: %m", path);
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering r = -errno;
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering goto finish;
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering }
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering p = strstrip(l);
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering if (!*p)
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering continue;
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering if (strchr(COMMENTS, *p))
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering continue;
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering if ((k = apply_rule(p)) < 0 && r == 0)
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering r = k;
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering }
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poetteringfinish:
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering fclose(f);
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering return r;
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering}
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poetteringstatic int scandir_filter(const struct dirent *d) {
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering assert(d);
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering if (ignore_file(d->d_name))
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering return 0;
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering if (d->d_type != DT_REG &&
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering d->d_type != DT_LNK &&
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering d->d_type != DT_UNKNOWN)
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering return 0;
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering
a8eedf4953d379dc09ee2b04e69a0a54ba247a02Lennart Poettering return endswith(d->d_name, ".conf");
}
static int apply_tree(const char *path) {
struct dirent **de = NULL;
int n, i, r = 0;
if ((n = scandir(path, &de, scandir_filter, alphasort)) < 0) {
if (errno == ENOENT)
return 0;
log_error("Failed to enumerate %s files: %m", path);
return -errno;
}
for (i = 0; i < n; i++) {
char *fn;
int k;
k = asprintf(&fn, "%s/%s", path, de[i]->d_name);
free(de[i]);
if (k < 0) {
log_error("Failed to allocate file name.");
if (r == 0)
r = -ENOMEM;
continue;
}
if ((k = apply_file(fn, true)) < 0 && r == 0)
r = k;
}
free(de);
return r;
}
int main(int argc, char *argv[]) {
int r = 0;
if (argc > 2) {
log_error("This program expects one or no arguments.");
return EXIT_FAILURE;
}
log_set_target(LOG_TARGET_AUTO);
log_parse_environment();
log_open();
if (argc > 1)
r = apply_file(argv[1], false);
else {
/* Flush out all rules */
write_one_line_file("/proc/sys/fs/binfmt_misc/status", "-1");
r = apply_tree("/etc/binfmt.d");
}
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}