aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--util-linux/Config.in2
-rw-r--r--util-linux/mdev.c137
2 files changed, 123 insertions, 16 deletions
diff --git a/util-linux/Config.in b/util-linux/Config.in
index 5ab54e038..bf3e13b2a 100644
--- a/util-linux/Config.in
+++ b/util-linux/Config.in
@@ -254,7 +254,7 @@ config CONFIG_MDEV
254 have it handle hotplug events afterwards. Device names are taken 254 have it handle hotplug events afterwards. Device names are taken
255 from sysfs. 255 from sysfs.
256 256
257config CONFIG_FEATURE_MDEV_CONFIG 257config CONFIG_FEATURE_MDEV_CONF
258 bool " Support /etc/mdev.conf" 258 bool " Support /etc/mdev.conf"
259 default n 259 default n
260 depends on CONFIG_MDEV 260 depends on CONFIG_MDEV
diff --git a/util-linux/mdev.c b/util-linux/mdev.c
index 49904d17a..688100c3a 100644
--- a/util-linux/mdev.c
+++ b/util-linux/mdev.c
@@ -8,25 +8,31 @@
8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
9 */ 9 */
10 10
11#include <ctype.h>
11#include <dirent.h> 12#include <dirent.h>
12#include <errno.h> 13#include <errno.h>
13#include <fcntl.h> 14#include <fcntl.h>
14#include <stdio.h> 15#include <stdio.h>
15#include <string.h> 16#include <string.h>
17#include <sys/mman.h>
16#include <sys/stat.h> 18#include <sys/stat.h>
17#include <sys/types.h> 19#include <sys/types.h>
18#include <unistd.h> 20#include <unistd.h>
21#include "busybox.h"
22#include "xregex.h"
19 23
20#define DEV_PATH "/dev" 24#define DEV_PATH "/tmp/dev"
21#define DEV_MODE 0660
22 25
23#include <busybox.h> 26#include <busybox.h>
24 27
25/* mknod in /dev based on a path like "/sys/block/hda/hda1" */ 28/* mknod in /dev based on a path like "/sys/block/hda/hda1" */
26void make_device(char *path) 29static void make_device(char *path)
27{ 30{
28 char *device_name, *s; 31 char *device_name,*s;
29 int major,minor,type,len,fd; 32 int major,minor,type,len,fd;
33 int mode=0660;
34 uid_t uid=0;
35 gid_t gid=0;
30 36
31 RESERVE_CONFIG_BUFFER(temp,PATH_MAX); 37 RESERVE_CONFIG_BUFFER(temp,PATH_MAX);
32 38
@@ -44,8 +50,8 @@ void make_device(char *path)
44 device_name = strrchr(path, '/') + 1; 50 device_name = strrchr(path, '/') + 1;
45 type = strncmp(path+5, "block/" ,6) ? S_IFCHR : S_IFBLK; 51 type = strncmp(path+5, "block/" ,6) ? S_IFCHR : S_IFBLK;
46 major = minor = 0; 52 major = minor = 0;
47 for(s = temp; *s; s++) { 53 for (s = temp; *s; s++) {
48 if(*s == ':') { 54 if (*s == ':') {
49 major = minor; 55 major = minor;
50 minor = 0; 56 minor = 0;
51 } else { 57 } else {
@@ -54,14 +60,115 @@ void make_device(char *path)
54 } 60 }
55 } 61 }
56 62
57/* Open config file here, look up permissions */ 63 /* If we have a config file, look up permissions for this device */
64
65 if (ENABLE_FEATURE_MDEV_CONF) {
66 char *conf,*pos,*end;
67
68 /* mmap the config file */
69 if (-1!=(fd=open("/etc/mdev.conf",O_RDONLY))) {
70 len=lseek(fd,0,SEEK_END);
71 conf=mmap(NULL,len,PROT_READ,MAP_SHARED,fd,0);
72 if (conf) {
73 int line=0;
74
75 /* Loop through lines in mmaped file*/
76 for (pos=conf;pos-conf<len;) {
77 int field;
78 char *end2;
79
80 line++;
81 /* find end of this line */
82 for(end=pos;end-conf<len && *end!='\n';end++);
83
84 /* Three fields: regex, uid:gid, mode */
85 for (field=3;field;field--) {
86 /* Skip whitespace */
87 while (pos<end && isspace(*pos)) pos++;
88 if (pos==end || *pos=='#') break;
89 for (end2=pos;
90 end2<end && !isspace(*end2) && *end2!='#'; end2++);
91 switch(field) {
92 /* Regex to match this device */
93 case 3:
94 {
95 char *regex=strndupa(pos,end2-pos);
96 regex_t match;
97 regmatch_t off;
98 int result;
99
100 /* Is this it? */
101 xregcomp(&match,regex,REG_EXTENDED);
102 result=regexec(&match,device_name,1,&off,0);
103 regfree(&match);
104
105 /* If not this device, skip rest of line */
106 if(result || off.rm_so
107 || off.rm_eo!=strlen(device_name))
108 goto end_line;
109
110 break;
111 }
112 /* uid:gid */
113 case 2:
114 {
115 char *s2;
116
117 /* Find : */
118 for(s=pos;s<end2 && *s!=':';s++);
119 if(s==end2) goto end_line;
120
121 /* Parse UID */
122 uid=strtoul(pos,&s2,10);
123 if(s!=s2) {
124 struct passwd *pass;
125 pass=getpwnam(strndupa(pos,s-pos));
126 if(!pass) goto end_line;
127 uid=pass->pw_uid;
128 }
129 s++;
130 /* parse GID */
131 gid=strtoul(s,&s2,10);
132 if(end2!=s2) {
133 struct group *grp;
134 grp=getgrnam(strndupa(s,end2-s));
135 if(!grp) goto end_line;
136 gid=grp->gr_gid;
137 }
138 break;
139 }
140 /* mode */
141 case 1:
142 {
143 mode=strtoul(pos,&pos,8);
144 if(pos!=end2) goto end_line;
145 goto found_device;
146 }
147 }
148 pos=end2;
149 }
150end_line:
151 /* Did everything parse happily? */
152 if (field && field!=3)
153 bb_error_msg_and_die("Bad line %d",line);
154
155 /* Next line */
156 pos=++end;
157 }
158found_device:
159 munmap(conf,len);
160 }
161 close(fd);
162 }
163 }
58 164
59 sprintf(temp, "%s/%s", DEV_PATH, device_name); 165 sprintf(temp, "%s/%s", DEV_PATH, device_name);
60 if(mknod(temp, DEV_MODE | type, makedev(major, minor)) && errno != EEXIST) 166 umask(0);
167 if (mknod(temp, mode | type, makedev(major, minor)) && errno != EEXIST)
61 bb_perror_msg_and_die("mknod %s failed", temp); 168 bb_perror_msg_and_die("mknod %s failed", temp);
62
63/* Perform shellout here */
64 169
170 if (ENABLE_FEATURE_MDEV_CONF) chown(temp,uid,gid);
171
65end: 172end:
66 RELEASE_CONFIG_BUFFER(temp); 173 RELEASE_CONFIG_BUFFER(temp);
67} 174}
@@ -69,18 +176,18 @@ end:
69/* Recursive search of /sys/block or /sys/class. path must be a writeable 176/* Recursive search of /sys/block or /sys/class. path must be a writeable
70 * buffer of size PATH_MAX containing the directory string to start at. */ 177 * buffer of size PATH_MAX containing the directory string to start at. */
71 178
72void find_dev(char *path) 179static void find_dev(char *path)
73{ 180{
74 DIR *dir; 181 DIR *dir;
75 int len=strlen(path); 182 int len=strlen(path);
76 183
77 if(!(dir = opendir(path))) 184 if (!(dir = opendir(path)))
78 bb_perror_msg_and_die("No %s",path); 185 bb_perror_msg_and_die("No %s",path);
79 186
80 for(;;) { 187 for (;;) {
81 struct dirent *entry = readdir(dir); 188 struct dirent *entry = readdir(dir);
82 189
83 if(!entry) break; 190 if (!entry) break;
84 191
85 /* Skip "." and ".." (also skips hidden files, which is ok) */ 192 /* Skip "." and ".." (also skips hidden files, which is ok) */
86 193
@@ -103,7 +210,7 @@ void find_dev(char *path)
103int mdev_main(int argc, char *argv[]) 210int mdev_main(int argc, char *argv[])
104{ 211{
105 if (argc > 1) { 212 if (argc > 1) {
106 if(argc == 2 && !strcmp(argv[1],"-s")) { 213 if (argc == 2 && !strcmp(argv[1],"-s")) {
107 RESERVE_CONFIG_BUFFER(temp,PATH_MAX); 214 RESERVE_CONFIG_BUFFER(temp,PATH_MAX);
108 strcpy(temp,"/sys/block"); 215 strcpy(temp,"/sys/block");
109 find_dev(temp); 216 find_dev(temp);