From: Antonio Ospite <ospite@studenti.unina.it>
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=inline

Initial import

Signed-off-by: Antonio Ospite <ospite@studenti.unina.it>
---

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 <ospite@studenti.unina.it>
+
+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 <ospite@studenti.unina.it>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/* 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libgen.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ctype.h>
+
+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;
+}