aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2007-11-19 09:04:22 +0000
committerMike Frysinger <vapier@gentoo.org>2007-11-19 09:04:22 +0000
commitc881c733bb05286f7147d0ca49ad238b86f6d848 (patch)
tree0987e9d7ec77dabfb312e23116f0f941f108cf76
parented6a49c657ae204f6ba8ad84315fa04c09297a7c (diff)
downloadbusybox-w32-c881c733bb05286f7147d0ca49ad238b86f6d848.tar.gz
busybox-w32-c881c733bb05286f7147d0ca49ad238b86f6d848.tar.bz2
busybox-w32-c881c733bb05286f7147d0ca49ad238b86f6d848.zip
cleanup comments and coding style and rewrite the mdev.conf parser to use common busybox functions and call strdup() less often ... saves a ~few hundred bytes
-rw-r--r--util-linux/mdev.c193
1 files changed, 98 insertions, 95 deletions
diff --git a/util-linux/mdev.c b/util-linux/mdev.c
index a9c146942..927adf66f 100644
--- a/util-linux/mdev.c
+++ b/util-linux/mdev.c
@@ -35,154 +35,146 @@ static void make_device(char *path, int delete)
35 /* Try to read major/minor string. Note that the kernel puts \n after 35 /* Try to read major/minor string. Note that the kernel puts \n after
36 * the data, so we don't need to worry about null terminating the string 36 * the data, so we don't need to worry about null terminating the string
37 * because sscanf() will stop at the first nondigit, which \n is. We 37 * because sscanf() will stop at the first nondigit, which \n is. We
38 * also depend on path having writeable space after it. */ 38 * also depend on path having writeable space after it.
39 39 */
40 if (!delete) { 40 if (!delete) {
41 strcat(path, "/dev"); 41 strcat(path, "/dev");
42 len = open_read_close(path, temp + 1, 64); 42 len = open_read_close(path, temp + 1, 64);
43 *temp++ = 0; 43 *temp++ = 0;
44 if (len < 1) return; 44 if (len < 1)
45 return;
45 } 46 }
46 47
47 /* Determine device name, type, major and minor */ 48 /* Determine device name, type, major and minor */
48
49 device_name = bb_basename(path); 49 device_name = bb_basename(path);
50 type = path[5]=='c' ? S_IFCHR : S_IFBLK; 50 type = (path[5] == 'c' ? S_IFCHR : S_IFBLK);
51
52 /* If we have a config file, look up permissions for this device */
53 51
54 if (ENABLE_FEATURE_MDEV_CONF) { 52 if (ENABLE_FEATURE_MDEV_CONF) {
55 char *conf, *pos, *end; 53 FILE *fp;
56 int line, fd; 54 char *line, *vline;
55 size_t lineno = 0;
57 56
58 /* mmap the config file */ 57 /* If we have a config file, look up the user settings */
59 fd = open("/etc/mdev.conf", O_RDONLY); 58 fp = fopen_or_warn("/etc/mdev.conf", "r");
60 if (fd < 0) 59 if (!fp)
61 goto end_parse;
62 len = xlseek(fd, 0, SEEK_END);
63 conf = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
64 close(fd);
65 if (!conf)
66 goto end_parse; 60 goto end_parse;
67 61
68 line = 0; 62 while ((vline = line = xmalloc_getline(fp)) != NULL) {
69 /* Loop through lines in mmaped file*/
70 for (pos=conf; pos-conf<len;) {
71 int field; 63 int field;
72 char *end2;
73 64
74 line++; 65 /* A pristine copy for command execution. */
75 /* find end of this line */ 66 char *orig_line;
76 for (end=pos; end-conf<len && *end!='\n'; end++) 67 if (ENABLE_FEATURE_MDEV_EXEC)
77 ; 68 orig_line = xstrdup(line);
69
70 ++lineno;
78 71
79 /* Three fields: regex, uid:gid, mode */ 72 /* Three fields: regex, uid:gid, mode */
80 for (field=0; field < (3 + ENABLE_FEATURE_MDEV_EXEC); 73 for (field = 0; field < (3 + ENABLE_FEATURE_MDEV_EXEC); ++field) {
81 field++) 74
82 { 75 /* Find a non-empty field */
83 /* Skip whitespace */ 76 char *val;
84 while (pos<end && isspace(*pos)) pos++; 77 do {
85 if (pos==end || *pos=='#') break; 78 val = strtok(vline, " \t");
86 for (end2=pos; 79 vline = NULL;
87 end2<end && !isspace(*end2) && *end2!='#'; end2++) 80 } while (val && !*val);
88 ; 81 if (!val)
82 break;
89 83
90 if (field == 0) { 84 if (field == 0) {
91 /* Regex to match this device */
92 85
93 char *regex = xstrndup(pos, end2-pos); 86 /* Regex to match this device */
94 regex_t match; 87 regex_t match;
95 regmatch_t off; 88 regmatch_t off;
96 int result; 89 int result;
97 90
98 /* Is this it? */ 91 /* Is this it? */
99 xregcomp(&match,regex, REG_EXTENDED); 92 xregcomp(&match, val, REG_EXTENDED);
100 result = regexec(&match, device_name, 1, &off, 0); 93 result = regexec(&match, device_name, 1, &off, 0);
101 regfree(&match); 94 regfree(&match);
102 free(regex);
103 95
104 /* If not this device, skip rest of line */ 96 /* If not this device, skip rest of line */
105 if (result || off.rm_so 97 if (result || off.rm_so || off.rm_eo != strlen(device_name))
106 || off.rm_eo != strlen(device_name)) 98 goto next_line;
107 break;
108 }
109 if (field == 1) {
110 /* uid:gid */
111 99
112 char *s, *s2; 100 } else if (field == 1) {
113 101
114 /* Find : */ 102 /* uid:gid device ownership */
115 for (s=pos; s<end2 && *s!=':'; s++) 103 struct passwd *pass;
116 ; 104 struct group *grp;
117 if (s == end2) break; 105
106 char *str_uid = val;
107 char *str_gid = strchr(val, ':');
108 if (str_gid)
109 *str_gid = '\0', ++str_gid;
118 110
119 /* Parse UID */ 111 /* Parse UID */
120 uid = strtoul(pos, &s2, 10); 112 pass = getpwnam(str_uid);
121 if (s != s2) { 113 if (pass)
122 struct passwd *pass;
123 char *_unam = xstrndup(pos, s-pos);
124 pass = getpwnam(_unam);
125 free(_unam);
126 if (!pass) break;
127 uid = pass->pw_uid; 114 uid = pass->pw_uid;
128 } 115 else
129 s++; 116 uid = strtoul(str_uid, NULL, 10);
117
130 /* parse GID */ 118 /* parse GID */
131 gid = strtoul(s, &s2, 10); 119 grp = getgrnam(str_gid);
132 if (end2 != s2) { 120 if (grp)
133 struct group *grp;
134 char *_grnam = xstrndup(s, end2-s);
135 grp = getgrnam(_grnam);
136 free(_grnam);
137 if (!grp) break;
138 gid = grp->gr_gid; 121 gid = grp->gr_gid;
139 } 122 else
140 } 123 gid = strtoul(str_gid, NULL, 10);
141 if (field == 2) {
142 /* mode */
143 124
144 mode = strtoul(pos, &pos, 8); 125 } else if (field == 2) {
145 if (pos != end2) break; 126
146 } 127 /* Mode device permissions */
147 if (ENABLE_FEATURE_MDEV_EXEC && field == 3) { 128 mode = strtoul(val, NULL, 8);
148 // Command to run 129
130 } else if (ENABLE_FEATURE_MDEV_EXEC && field == 3) {
131
132 /* Optional command to run */
149 const char *s = "@$*"; 133 const char *s = "@$*";
150 const char *s2; 134 const char *s2 = strchr(s, *val);
151 s2 = strchr(s, *pos++); 135
152 if (!s2) { 136 if (!s2) {
153 // Force error 137 /* Force error */
154 field = 1; 138 field = 1;
155 break; 139 break;
156 } 140 }
157 if ((s2-s+1) & (1<<delete))
158 command = xstrndup(pos, end-pos);
159 }
160 141
161 pos = end2; 142 /* Correlate the position in the "@$*" with the delete
143 * step so that we get the proper behavior.
144 */
145 if ((s2 - s + 1) & (1 << delete))
146 command = xstrdup(orig_line + (val + 1 - line));
147 }
162 } 148 }
163 149
164 /* Did everything parse happily? */ 150 /* Did everything parse happily? */
151 if (field <= 2)
152 bb_error_msg_and_die("bad line %i", lineno);
165 153
166 if (field > 2) break; 154 next_line:
167 if (field) bb_error_msg_and_die("bad line %d",line); 155 free(line);
168 156 if (ENABLE_FEATURE_MDEV_EXEC)
169 /* Next line */ 157 free(orig_line);
170 pos = ++end;
171 } 158 }
172 munmap(conf, len); 159
160 if (ENABLE_FEATURE_CLEAN_UP)
161 fclose(fp);
162
173 end_parse: /* nothing */ ; 163 end_parse: /* nothing */ ;
174 } 164 }
175 165
176 umask(0); 166 umask(0);
177 if (!delete) { 167 if (!delete) {
178 if (sscanf(temp, "%d:%d", &major, &minor) != 2) return; 168 if (sscanf(temp, "%d:%d", &major, &minor) != 2)
169 return;
179 if (mknod(device_name, mode | type, makedev(major, minor)) && errno != EEXIST) 170 if (mknod(device_name, mode | type, makedev(major, minor)) && errno != EEXIST)
180 bb_perror_msg_and_die("mknod %s", device_name); 171 bb_perror_msg_and_die("mknod %s", device_name);
181 172
182 if (major == root_major && minor == root_minor) 173 if (major == root_major && minor == root_minor)
183 symlink(device_name, "root"); 174 symlink(device_name, "root");
184 175
185 if (ENABLE_FEATURE_MDEV_CONF) chown(device_name, uid, gid); 176 if (ENABLE_FEATURE_MDEV_CONF)
177 chown(device_name, uid, gid);
186 } 178 }
187 if (command) { 179 if (command) {
188 /* setenv will leak memory, so use putenv */ 180 /* setenv will leak memory, so use putenv */
@@ -195,7 +187,8 @@ static void make_device(char *path, int delete)
195 free(s); 187 free(s);
196 free(command); 188 free(command);
197 } 189 }
198 if (delete) unlink(device_name); 190 if (delete)
191 remove_file(device_name, FILEUTILS_FORCE);
199} 192}
200 193
201/* File callback for /sys/ traversal */ 194/* File callback for /sys/ traversal */
@@ -296,9 +289,12 @@ int mdev_main(int argc, char **argv)
296 289
297 xchdir("/dev"); 290 xchdir("/dev");
298 291
299 /* Scan */
300
301 if (argc == 2 && !strcmp(argv[1],"-s")) { 292 if (argc == 2 && !strcmp(argv[1],"-s")) {
293
294 /* Scan:
295 * mdev -s
296 */
297
302 struct stat st; 298 struct stat st;
303 299
304 xstat("/", &st); 300 xstat("/", &st);
@@ -313,9 +309,14 @@ int mdev_main(int argc, char **argv)
313 ACTION_RECURSE | ACTION_FOLLOWLINKS, 309 ACTION_RECURSE | ACTION_FOLLOWLINKS,
314 fileAction, dirAction, temp, 0); 310 fileAction, dirAction, temp, 0);
315 311
316 /* Hotplug */
317
318 } else { 312 } else {
313
314 /* Hotplug:
315 * env ACTION=... DEVPATH=... mdev
316 * ACTION can be "add" or "remove"
317 * DEVPATH is like "/block/sda" or "/class/input/mice"
318 */
319
319 action = getenv("ACTION"); 320 action = getenv("ACTION");
320 env_path = getenv("DEVPATH"); 321 env_path = getenv("DEVPATH");
321 if (!action || !env_path) 322 if (!action || !env_path)
@@ -332,6 +333,8 @@ int mdev_main(int argc, char **argv)
332 } 333 }
333 } 334 }
334 335
335 if (ENABLE_FEATURE_CLEAN_UP) RELEASE_CONFIG_BUFFER(temp); 336 if (ENABLE_FEATURE_CLEAN_UP)
337 RELEASE_CONFIG_BUFFER(temp);
338
336 return 0; 339 return 0;
337} 340}