From: Antonio Ospite Date: Sat, 26 Mar 2011 10:16:23 +0000 (+0100) Subject: Initial import X-Git-Url: https://git.ao2.it/mkmisc.git/commitdiff_plain/3292bd2e5b3000d9b0ab19639f6f2cd939ddaa02?ds=sidebyside Initial import Signed-off-by: Antonio Ospite --- 3292bd2e5b3000d9b0ab19639f6f2cd939ddaa02 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..209314d --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*~ +*.o +mkmisc diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3e893d3 --- /dev/null +++ b/Makefile @@ -0,0 +1,34 @@ +CFLAGS=-ansi -pedantic -pedantic-errors -Wall -g3 -O2 -D_ANSI_SOURCE_ +CFLAGS+=-fno-common \ +-Wall \ +-Wdeclaration-after-statement \ +-Wextra \ +-Wformat=2 \ +-Winit-self \ +-Winline \ +-Wpacked \ +-Wp,-D_FORTIFY_SOURCE=2 \ +-Wpointer-arith \ +-Wlarger-than-65500 \ +-Wmissing-declarations \ +-Wmissing-format-attribute \ +-Wmissing-noreturn \ +-Wmissing-prototypes \ +-Wnested-externs \ +-Wold-style-definition \ +-Wredundant-decls \ +-Wsign-compare \ +-Wstrict-aliasing=2 \ +-Wstrict-prototypes \ +-Wswitch-enum \ +-Wundef \ +-Wunreachable-code \ +-Wunsafe-loop-optimizations \ +-Wwrite-strings + +CFLAGS += -D_BSD_SOURCE -D_XOPEN_SOURCE + +mkmisc: mkmisc.o + +clean: + -rm -f *~ *.o mkmisc diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..2c90e7b --- /dev/null +++ b/README.txt @@ -0,0 +1,7 @@ +mkmisc - make misc device nodes with dynamic minor number + +Copyright (C) 2011 Antonio Ospite + +A misc device is a character device node which can have a dynamic minor +number, see: +http://www.linux.it/~rubini/docs/misc/misc.html diff --git a/mkmisc.c b/mkmisc.c new file mode 100644 index 0000000..4e6b0bc --- /dev/null +++ b/mkmisc.c @@ -0,0 +1,216 @@ +/* mkmisc - make misc device nodes with dynamic minor number + * + * Copyright (C) 2011 Antonio Ospite + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* A misc device is a character device node which can have a dynamic minor + * number, see: + * http://www.linux.it/~rubini/docs/misc/misc.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int verbose = 0; +static int force = 0; +static unsigned int mode = 0664; + +static int misc_get_major(void) +{ + FILE *fp; + char line[256]; + int major; + char name[64]; + + fp = fopen("/proc/devices", "r"); + if (fp == NULL) { + perror("/proc/devices"); + return -1; + } + + while (fgets(line, sizeof(line) - 1, fp)) { + if(sscanf(line, "%d %64s", &major, name) == 2) + if (strcmp(name, "misc") == 0) { + fclose(fp); + return major; + } + } + fclose(fp); + + return -1; +} + +static int misc_get_minor(char *node) +{ + FILE *fp; + int minor; + char name[64]; + + fp = fopen("/proc/misc", "r"); + if (fp == NULL) { + perror("/proc/misc"); + return -1; + } + + while (fscanf(fp, "%d %64s", &minor, name) == 2) { + if (strcmp(name, node) == 0) { + fclose(fp); + return minor; + } + } + fclose(fp); + + return -1; +} + +static int mkmisc(char *device) +{ + char *path; + char *node; + int major; + int minor; + dev_t dev; + int ret; + + major = misc_get_major(); + if (major < 0) { + fprintf(stderr, "Cannot get misc major number\n"); + return major; + } + + path = strdup(device); + node = basename(path); + + minor = misc_get_minor(node); + if (minor < 0) { + fprintf(stderr, "Cannot get misc minor for %s\n", device); + free(path); + return minor; + } + free(path); + + if (verbose) + printf("Creating device: %s, major: %d, minor: %d\n", + device, major, minor); + + if (force) { + ret = unlink(device); + if (ret < 0) { + perror("unlink"); + /* + return ret; + */ + } + } + + dev = makedev(major, minor); + mode |= S_IFCHR; + ret = mknod(device, mode, dev); + if (ret < 0) { + perror("mknod"); + return ret; + } + + return 0; +} + +static void usage(void) +{ + printf("Usage: mkmisc [OPTION]... NAME\n"); + printf("Create the special file NAME as a misc device with a dynamic minor number.\n"); + printf("\n"); + printf("OPTION can be any of:\n"); + printf(" -f force creation even if the file already exists\n"); + printf(" -m MODE set file permission bits to MODE, not a=rw - umask\n"); + printf(" -v verbose output\n"); + printf(" -h display this help and exit\n"); +} + +static void parse_options(int argc, char *argv[]) +{ + int c; + int ret; + + while ((c = getopt (argc, argv, "fm:vh")) != -1) + switch (c) { + case 'f': + force = 1; + break; + case 'm': + ret = sscanf(optarg, "0%o", &mode); + if (ret != 1) { + fprintf(stderr, "mode must be octal (e.g 0664)\n"); + exit(EXIT_FAILURE); + } + break; + case 'v': + verbose = 1; + break; + case 'h': + usage(); + exit(0); + case '?': + /* skip known options with missing arguments */ + if (optopt != 'm') { + if(isprint(optopt)) + fprintf (stderr, + "Unknown option `-%c'.\n", + optopt); + else + fprintf (stderr, + "Unknown option character `\\x%x'.\n", + optopt); + } + default: + usage(); + exit(EXIT_FAILURE); + } +} + +int main(int argc, char *argv[]) +{ + int ret; + char *device = NULL; + + parse_options(argc, argv); + + if (optind >= argc) { + fprintf(stderr, "Missing argument NAME\n\n"); + usage(); + exit(EXIT_FAILURE); + } else if ((argc - optind) > 1) { + fprintf(stderr, "Too many arguments\n\n"); + usage(); + exit(EXIT_FAILURE); + } + + device = strdup(argv[optind]); + + ret = mkmisc(device); + if (ret < 0) + fprintf(stderr, "Cannot create %s\n", device); + + free(device); + + return ret; +}