From a89b1a3883b2ee3552334b70e4465ff9426bab2e Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 8 Mar 2013 23:48:20 +0100 Subject: [PATCH] add mknod wrapper --- mkdev.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 mkdev.c diff --git a/mkdev.c b/mkdev.c new file mode 100644 index 0000000..c502f70 --- /dev/null +++ b/mkdev.c @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2013 Felix Fietkau + * Copyright (C) 2013 John Crispin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define _BSD_SOURCE + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "procd.h" + +static char **patterns; +static int n_patterns; +static char buf[PATH_MAX]; +static char buf2[PATH_MAX]; +static unsigned int mode = 0600; + +static bool find_pattern(const char *name) +{ + int i; + + for (i = 0; i < n_patterns; i++) + if (!fnmatch(patterns[i], name, 0)) + return true; + + return false; +} + +static void make_dev(const char *path, bool block, int major, int minor) +{ + unsigned int _mode = mode | (block ? S_IFBLK : S_IFCHR); + DEBUG(2, "Creating %s device %s(%d,%d)\n", + block ? "block" : "character", + path, major, minor); + + mknod(path, _mode, makedev(major, minor)); +} + +static void find_devs(bool block) +{ + char *path = block ? "/sys/dev/block" : "/sys/dev/char"; + struct dirent *dp; + DIR *dir; + + dir = opendir(path); + if (!dir) + return; + + path = buf2 + sprintf(buf2, "%s/", path); + while ((dp = readdir(dir)) != NULL) { + char *c; + int major = 0, minor = 0; + int len; + + if (dp->d_type != DT_LNK) + continue; + + if (sscanf(dp->d_name, "%d:%d", &major, &minor) != 2) + continue; + + strcpy(path, dp->d_name); + len = readlink(buf2, buf, sizeof(buf)); + if (len <= 0) + continue; + + buf[len] = 0; + if (!find_pattern(buf)) + continue; + + c = strrchr(buf, '/'); + if (!c) + continue; + + c++; + make_dev(c, block, major, minor); + } + closedir(dir); +} + +static char *add_pattern(const char *name) +{ + char *str = malloc(strlen(name) + 2); + + str[0] = '*'; + strcpy(str + 1, name); + return str; +} + +int mkdev(const char *name, int _mode) +{ + char *pattern; + + if (chdir("/dev")) { + perror("chdir"); + return 1; + } + + pattern = add_pattern(name); + patterns = &pattern; + mode = _mode; + n_patterns = 1; + find_devs(true); + find_devs(false); + chdir("/"); + + return 0; +} -- 2.25.1