aboutsummaryrefslogtreecommitdiff
path: root/util-linux/mdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'util-linux/mdev.c')
-rw-r--r--util-linux/mdev.c137
1 files changed, 122 insertions, 15 deletions
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);