From: Prajwal Mohan Date: Fri, 27 Apr 2012 23:02:23 +0000 (-0700) Subject: Initial Import X-Git-Tag: 20120504.0~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3ee9d3bdb92b367c82d159128698a55e5025e107;p=profile%2Fivi%2Fmkdevnodes.git Initial Import --- 3ee9d3bdb92b367c82d159128698a55e5025e107 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d6bfbbf --- /dev/null +++ b/Makefile @@ -0,0 +1,36 @@ + +VERSION = 0.2 + +CC := gcc + +CFLAGS += -W -Wall -g -Os \ + `pkg-config --cflags glib-2.0` `pkg-config --cflags libpng` \ + -D VERSION=\"$(VERSION)\" -fstack-protector -D_FORTIFY_SOURCE=2 \ + -Wformat -fno-common -Wimplicit-function-declaration -Wimplicit-int + +PROG = mkdevnodes + +OBJS := $(PROG).o + +all: $(PROG) + + +%.o: %.c Makefile + @echo " CC $<" + @$(CC) $(CFLAGS) -c -o $@ $< + +$(PROG): $(PROG).o + @echo " LD $@" + @$(CC) $^ -o $@ + +clean: + rm -f *~ *.o $(PROG) + +install: + mkdir -p $(DESTDIR)/sbin + install -D -m0755 $(PROG) $(DESTDIR)/sbin/$(PROG) + +dist: clean + git tag v$(VERSION) + git archive --format=tar -v --prefix="$(PROG)-$(VERSION)/" \ + v$(VERSION) | gzip > $(PROG)-$(VERSION).tar.gz diff --git a/mkdevnodes.c b/mkdevnodes.c new file mode 100644 index 0000000..ccf2d5f --- /dev/null +++ b/mkdevnodes.c @@ -0,0 +1,260 @@ + +/* + * (C) Copyright 2010 Intel Corporation + * + * Author: Auke Kok + * + * 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; version 2 + * of the License. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * dev_info - filter table + * + * devices found in sysfs often require different base permissions or + * group/owner ids. To set things up as correctly as possible, we + * traverse a table with overrides. The table is parsed in order and + * multiple fields can hit (e.g. one with the ALL wildcard, and one + * specific for the minor node number). The last field to hit will + * effectively be used. + * + * ALL in the minor node field marks all minor nodes to use that field. + * ALL in the major node field marks the end of the table. + * + * a non-NULL string in the 'dir' field allows you to prepend a + * path between the device node and the /dev/ folder name. This is + * mostly used for alsa and v4l device nodes. + */ + +#define DEV "/dev" + +#define ALL 256 + + +struct dev_info { + unsigned int major; + unsigned int minor; /* 256 = all */ + const char *dir; + const char *owner; + const char *group; + unsigned int perms; + int uid; /* -1 in these fields cause owner/group to be */ + int gid; /* looked up in /etc/group and /etc/passwd */ +}; + +static struct dev_info di_chr[] = { + { 1, 1, NULL, "root", "kmem", 0640, 0, -1 }, /* mem */ + { 1, 2, NULL, "root", "kmem", 0640, 0, -1 }, /* kmem */ + { 1, 3, NULL, "root", "root", 0666, 0, 0 }, /* null */ + { 1, 4, NULL, "root", "kmem", 0640, 0, -1 }, /* port */ + { 1, 5, NULL, "root", "root", 0666, 0, 0 }, /* zero */ + { 1, 7, NULL, "root", "root", 0666, 0, 0 }, /* full */ + { 1, 8, NULL, "root", "root", 0666, 0, 0 }, /* random */ + { 1, 9, NULL, "root", "root", 0666, 0, 0 }, /* urandom */ + { 2, ALL, NULL, "root", "tty", 0660, 0, -1 }, /* pty */ + { 3, ALL, NULL, "root", "tty", 0660, 0, -1 }, /* tty* */ + { 4, ALL, NULL, "root", "tty", 0660, 0, -1 }, /* ttyS* */ + { 5, 0, NULL, "root", "tty", 0666, 0, -1 }, /* tty */ + { 5, 1, NULL, "root", "tty", 0600, 0, -1 }, /* console */ + { 5, 2, NULL, "root", "tty", 0666, 0, -1 }, /* ptmx */ + { 7, ALL, NULL, "root", "tty", 0660, 0, -1 }, /* vcs* */ + { 13, ALL, "input", "root", "video", 0660, 0, -1 }, /* input */ + { 10, 232, NULL, "root", "kvm", 0660, 0, -1 }, /* kvm */ + { 14, ALL, NULL, "root", "audio", 0660, 0, -1 }, /* oss */ + { 21, ALL, NULL, "root", "disk", 0640, 0, -1 }, /* sg* */ + { 29, ALL, NULL, "root", "video", 0600, 0, -1 }, /* fb* */ + { 81, ALL, "v4l", "root", "video", 0660, 0, -1 }, /* v4l */ + { 116, ALL, "snd", "root", "audio", 0660, 0, -1 }, /* alsa */ + { 189, ALL, "usb", "root", "root", 0600, 0, 0 }, /* usb */ + { 226, ALL, "dri", "root", "video", 0660, 0, 0 }, /* dri */ + + /* terminate */ + { ALL, 0, NULL, NULL, NULL, 0, 0, 0 }, +}; + +static struct dev_info di_blk[] = { + { 1, ALL, NULL, "root", "disk", 0640, 0, -1 }, /* ram* */ + { 8, ALL, NULL, "root", "disk", 0640, 0, -1 }, /* sd* */ + { 11, ALL, NULL, "root", "cdrom", 0640, 0, -1 }, /* sr* */ + /* terminate */ + { ALL, 0, NULL, NULL, NULL, 0, 0, 0 }, +}; + +static void node_add(int type, unsigned int maj, unsigned int min, + char* name, struct dev_info *di) +{ + struct passwd *p; + struct group *g; + unsigned int perms = 0660; + int owner = 0; + int group = 0; + char path[PATH_MAX]; + int n = 0; + + /* defaults */ + snprintf(path, PATH_MAX, "%s/%s", DEV, name); + + while (di[n].major != ALL) { + if (maj != di[n].major) + goto out; + if ((min != di[n].minor) && (di[n].minor != ALL)) + goto out; + + if (di[n].dir != NULL) { + snprintf(path, PATH_MAX, "%s/%s", DEV, di[n].dir); + mkdir(path, 0755); + snprintf(path, PATH_MAX, "%s/%s/%s", DEV, di[n].dir, name); + } + + perms = di[n].perms; + + if (di[n].uid == -1) { + p = getpwnam(di[n].owner); + if (p) { + owner = p->pw_uid; + di[n].uid = owner; + } + } else { + owner = di[n].uid; + } + + if (di[n].gid == -1) { + g = getgrnam(di[n].group); + if (g) { + group = g->gr_gid; + di[n].gid = group; + } + } else { + group = di[n].gid; + } + /* don't break, allow more filters to hit */ +out: + n++; + } + + if ((owner == 0) && (group == 0)) { + mknod(path, type | perms, makedev(maj, min)); + } else { + if (mknod(path, type, makedev(maj, min))) + return; + if (chown(path, owner, group)) + return; + chmod(path, perms); + } +} + +static void walk(const char *dir, int type, struct dev_info *di) +{ + DIR *d; + struct dirent *entry; + char path[PATH_MAX]; + ssize_t len; + unsigned int maj; + unsigned int min; + + d = opendir(dir); + if (!d) + return; + + while ((entry = readdir(d))) { + char p[PATH_MAX]; + + if ((strcmp(".", entry->d_name) == 0) || + (strcmp("..", entry->d_name) == 0)) + continue; + + sscanf(entry->d_name, "%d:%d", &maj, &min); + + snprintf(p, PATH_MAX, "%s/%s", dir, entry->d_name); + len = readlink(p, path, PATH_MAX - 1); + if (len != -1) + path[len] = '\0'; + + node_add(type, maj, min, basename(path), di); + + } + + closedir(d); +} + +void populate_dev_blk(void) +{ + int u = umask(0000); + walk("/sys/dev/block", S_IFBLK, di_blk); + umask(u); +} + +void populate_dev_chr(void) +{ + int u = umask(0000); + walk("/sys/dev/char", S_IFCHR, di_chr); + umask(u); +} + +static struct option opts[] = { + { "block", 0, NULL, 'b' }, + { "char", 0, NULL, 'c' }, + { "help", 0, NULL, 'h' }, + { 0, 0, NULL, 0 } +}; + +void usage(const char *name) +{ + printf("Usage: %s [OPTION...]\n", name); + printf(" -b, --block Only create block device nodes\n"); + printf(" -c, --char Only create char device nodes \n"); + printf(" -h, --help Show this help message\n"); +} + +int main(int argc, char **argv) +{ + int c; + int i; + int blk = 1; + int chr = 1; + + while (1) { + c = getopt_long(argc, argv, "bch", opts, &i); + if (c == -1) + break; + + switch (c) { + case 'b': + chr = 0; + break; + case 'c': + blk = 0; + break; + case 'h': + usage(argv[0]); + exit (EXIT_SUCCESS); + break; + default: + break; + } + } + + if (blk) + populate_dev_blk(); + if (chr) + populate_dev_chr(); + exit (EXIT_SUCCESS); +} diff --git a/packaging/mkdevnodes.changes b/packaging/mkdevnodes.changes new file mode 100644 index 0000000..cd7353d --- /dev/null +++ b/packaging/mkdevnodes.changes @@ -0,0 +1,6 @@ +* Thu Oct 21 2010 Auke Kok - 0.2 +- Fix compile issue on ARM (don't force arch). + +* Thu Oct 21 2010 Auke Kok - 0.1 +- Splitting this out of the udev package, posted upstream repo. +- Initial automated packaging diff --git a/packaging/mkdevnodes.spec b/packaging/mkdevnodes.spec new file mode 100644 index 0000000..3dd1dac --- /dev/null +++ b/packaging/mkdevnodes.spec @@ -0,0 +1,42 @@ +# +# + +Name: mkdevnodes +Summary: Fast MAKEDEV replacement +Version: 0.2 +Release: 1 +Group: Applications/System +License: GPLv2 +Source0: mkdevnodes-%{version}.tar.gz + + +%description +A replacement for MAKEDEV. Instead of parsing hard-coded text files, mkdevnodes uses the information provided in sysfs to generate device nodes with mknod() as needed, as well as a few base device nodes that always need to be present. Mkdevnodes is thus extremely fast, as it doesn not need to read and/or parse text files from the root filesystem. + + + + +%prep +%setup -q -n %{name}-%{version} + + +%build + + +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +%make_install + + + + + + + +%files +%defattr(-,root,root,-) +/sbin/mkdevnodes + +