diff options
author | Mike Frysinger <vapier@gentoo.org> | 2007-11-19 09:04:22 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2007-11-19 09:04:22 +0000 |
commit | c881c733bb05286f7147d0ca49ad238b86f6d848 (patch) | |
tree | 0987e9d7ec77dabfb312e23116f0f941f108cf76 | |
parent | ed6a49c657ae204f6ba8ad84315fa04c09297a7c (diff) | |
download | busybox-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.c | 193 |
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 | } |