aboutsummaryrefslogtreecommitdiff
path: root/util-linux/mdev.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-04-13 23:18:52 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-04-13 23:18:52 +0000
commitf2b39e088d6ccbf4a540c741059c2f661eebc9ac (patch)
treeb375683a37729c04af06f71047cba19e162ac27e /util-linux/mdev.c
parent065c7147914bf545ede2dbdbc07c48386d750c77 (diff)
downloadbusybox-w32-f2b39e088d6ccbf4a540c741059c2f661eebc9ac.tar.gz
busybox-w32-f2b39e088d6ccbf4a540c741059c2f661eebc9ac.tar.bz2
busybox-w32-f2b39e088d6ccbf4a540c741059c2f661eebc9ac.zip
mdev: add support for - "dont stop here" char
function old new delta make_device 1340 1362 +22 packed_usage 26291 26299 +8 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 30/0) Total: 30 bytes
Diffstat (limited to 'util-linux/mdev.c')
-rw-r--r--util-linux/mdev.c179
1 files changed, 97 insertions, 82 deletions
diff --git a/util-linux/mdev.c b/util-linux/mdev.c
index 3b0ef351e..b1f3d051c 100644
--- a/util-linux/mdev.c
+++ b/util-linux/mdev.c
@@ -57,21 +57,12 @@ static char *build_alias(char *alias, const char *device_name)
57/* NB: "mdev -s" may call us many times, do not leak memory/fds! */ 57/* NB: "mdev -s" may call us many times, do not leak memory/fds! */
58static void make_device(char *path, int delete) 58static void make_device(char *path, int delete)
59{ 59{
60 const char *device_name;
61 int major, minor, type, len;
62 int mode = 0660;
63#if ENABLE_FEATURE_MDEV_CONF 60#if ENABLE_FEATURE_MDEV_CONF
64 struct bb_uidgid_t ugid = { 0, 0 };
65 parser_t *parser; 61 parser_t *parser;
66 char *tokens[5];
67# if ENABLE_FEATURE_MDEV_EXEC
68 char *command = NULL;
69# endif
70# if ENABLE_FEATURE_MDEV_RENAME
71 char *alias = NULL;
72 char aliaslink = aliaslink; /* for compiler */
73# endif
74#endif 62#endif
63 const char *device_name;
64 int major, minor, type, len;
65 int mode;
75 char *dev_maj_min = path + strlen(path); 66 char *dev_maj_min = path + strlen(path);
76 67
77 /* Force the configuration file settings exactly. */ 68 /* Force the configuration file settings exactly. */
@@ -111,14 +102,37 @@ static void make_device(char *path, int delete)
111 parser = config_open2("/etc/mdev.conf", fopen_for_read); 102 parser = config_open2("/etc/mdev.conf", fopen_for_read);
112 103
113 /* If we have config file, look up user settings */ 104 /* If we have config file, look up user settings */
114 while (config_read(parser, tokens, 4, 3, "# \t", PARSE_NORMAL)) { 105 while (1) {
115 regmatch_t off[1 + 9*ENABLE_FEATURE_MDEV_RENAME_REGEXP]; 106 regmatch_t off[1 + 9*ENABLE_FEATURE_MDEV_RENAME_REGEXP];
116 char *val = tokens[0]; 107 int keep_matching;
108 char *val;
109 struct bb_uidgid_t ugid;
110 char *tokens[4];
111# if ENABLE_FEATURE_MDEV_EXEC
112 char *command = NULL;
113# endif
114# if ENABLE_FEATURE_MDEV_RENAME
115 char *alias = NULL;
116 char aliaslink = aliaslink; /* for compiler */
117# endif
118 /* Defaults in case we won't match any line */
119 ugid.uid = ugid.gid = 0;
120 keep_matching = 0;
121 mode = 0660;
122
123 if (!config_read(parser, tokens, 4, 3, "# \t", PARSE_NORMAL)) {
124 /* End of file, create dev node with default params */
125 goto line_matches;
126 }
127
128 val = tokens[0];
129 keep_matching = ('-' == val[0]);
130 val += keep_matching; /* swallow leading dash */
117 131
118 /* Fields: regex uid:gid mode [alias] [cmd] */ 132 /* Fields: regex uid:gid mode [alias] [cmd] */
119 133
120 /* 1st field: @<numeric maj,min>... */ 134 /* 1st field: @<numeric maj,min>... */
121 if (tokens[0][0] == '@') { 135 if (val[0] == '@') {
122 /* @major,minor[-last] */ 136 /* @major,minor[-last] */
123 /* (useful when name is ambiguous: 137 /* (useful when name is ambiguous:
124 * "/sys/class/usb/lp0" and 138 * "/sys/class/usb/lp0" and
@@ -126,12 +140,12 @@ static void make_device(char *path, int delete)
126 int cmaj, cmin0, cmin1, sc; 140 int cmaj, cmin0, cmin1, sc;
127 if (major < 0) 141 if (major < 0)
128 continue; /* no dev, no match */ 142 continue; /* no dev, no match */
129 sc = sscanf(tokens[0], "@%u,%u-%u", &cmaj, &cmin0, &cmin1); 143 sc = sscanf(val, "@%u,%u-%u", &cmaj, &cmin0, &cmin1);
130 if (sc < 1 || major != cmaj 144 if (sc < 1 || major != cmaj
131 || (sc == 2 && minor != cmin0) 145 || (sc == 2 && minor != cmin0)
132 || (sc == 3 && (minor < cmin0 || minor > cmin1)) 146 || (sc == 3 && (minor < cmin0 || minor > cmin1))
133 ) { 147 ) {
134 continue; /* no match */ 148 continue; /* this line doesn't match */
135 } 149 }
136 } else { /* ... or regex to match device name */ 150 } else { /* ... or regex to match device name */
137 regex_t match; 151 regex_t match;
@@ -160,12 +174,12 @@ static void make_device(char *path, int delete)
160 if (result || off[0].rm_so 174 if (result || off[0].rm_so
161 || ((int)off[0].rm_eo != (int)strlen(dev_name_or_subsystem)) 175 || ((int)off[0].rm_eo != (int)strlen(dev_name_or_subsystem))
162 ) { 176 ) {
163 continue; 177 continue; /* this line doesn't match */
164 } 178 }
165 } 179 }
166 180
167 /* This line matches: stop parsing the file 181 /* This line matches: stop parsing the file after parsing
168 * after parsing the rest of fields */ 182 * the rest of fields unless keep_matching == 1 */
169 183
170 /* 2nd field: uid:gid - device ownership */ 184 /* 2nd field: uid:gid - device ownership */
171 parse_chown_usergroup_or_die(&ugid, tokens[1]); 185 parse_chown_usergroup_or_die(&ugid, tokens[1]);
@@ -174,24 +188,25 @@ static void make_device(char *path, int delete)
174 mode = strtoul(tokens[2], NULL, 8); 188 mode = strtoul(tokens[2], NULL, 8);
175 189
176 val = tokens[3]; 190 val = tokens[3];
177 /* 4th field (opt): >alias */ 191 /* 4th field (opt): >|=alias */
178# if ENABLE_FEATURE_MDEV_RENAME 192# if ENABLE_FEATURE_MDEV_RENAME
179 if (!val) 193 if (!val)
180 break; 194 goto line_matches;
181 aliaslink = *val; 195 aliaslink = val[0];
182 if (aliaslink == '>' || aliaslink == '=') { 196 if (aliaslink == '>' || aliaslink == '=') {
183 char *s, *st; 197 char *a, *s, *st;
184# if ENABLE_FEATURE_MDEV_RENAME_REGEXP 198# if ENABLE_FEATURE_MDEV_RENAME_REGEXP
185 char *p; 199 char *p;
186 unsigned i, n; 200 unsigned i, n;
187# endif 201# endif
188 char *a = val; 202 a = val;
189 s = strchrnul(val, ' '); 203 s = strchrnul(val, ' ');
190 st = strchrnul(val, '\t'); 204 st = strchrnul(val, '\t');
191 if (st < s) 205 if (st < s)
192 s = st; 206 s = st;
193 val = (s[0] && s[1]) ? s+1 : NULL; 207 val = (s[0] && s[1]) ? s+1 : NULL;
194 s[0] = '\0'; 208 s[0] = '\0';
209
195# if ENABLE_FEATURE_MDEV_RENAME_REGEXP 210# if ENABLE_FEATURE_MDEV_RENAME_REGEXP
196 /* substitute %1..9 with off[1..9], if any */ 211 /* substitute %1..9 with off[1..9], if any */
197 n = 0; 212 n = 0;
@@ -223,12 +238,12 @@ static void make_device(char *path, int delete)
223# endif /* ENABLE_FEATURE_MDEV_RENAME */ 238# endif /* ENABLE_FEATURE_MDEV_RENAME */
224 239
225# if ENABLE_FEATURE_MDEV_EXEC 240# if ENABLE_FEATURE_MDEV_EXEC
226 /* The rest (opt): command to run */ 241 /* The rest (opt): @|$|*command */
227 if (!val) 242 if (!val)
228 break; 243 goto line_matches;
229 { 244 {
230 const char *s = "@$*"; 245 const char *s = "@$*";
231 const char *s2 = strchr(s, *val); 246 const char *s2 = strchr(s, val[0]);
232 247
233 if (!s2) 248 if (!s2)
234 bb_error_msg_and_die("bad line %u", parser->lineno); 249 bb_error_msg_and_die("bad line %u", parser->lineno);
@@ -244,71 +259,71 @@ static void make_device(char *path, int delete)
244 } 259 }
245 } 260 }
246# endif 261# endif
247 /* end of field parsing */ 262 /* End of field parsing */
248 break; /* we found matching line, stop */ 263 line_matches:
249 } /* end of "while line is read from /etc/mdev.conf" */
250
251 config_close(parser);
252#endif /* ENABLE_FEATURE_MDEV_CONF */ 264#endif /* ENABLE_FEATURE_MDEV_CONF */
253 265
254 if (!delete && major >= 0) { 266 /* "Execute" the line we found */
255
256 if (ENABLE_FEATURE_MDEV_RENAME)
257 unlink(device_name);
258
259 if (mknod(device_name, mode | type, makedev(major, minor)) && errno != EEXIST)
260 bb_perror_msg_and_die("mknod %s", device_name);
261
262 if (major == root_major && minor == root_minor)
263 symlink(device_name, "root");
264 267
268 if (!delete && major >= 0) {
269 if (ENABLE_FEATURE_MDEV_RENAME)
270 unlink(device_name);
271 if (mknod(device_name, mode | type, makedev(major, minor)) && errno != EEXIST)
272 bb_perror_msg_and_die("mknod %s", device_name);
273 if (major == root_major && minor == root_minor)
274 symlink(device_name, "root");
265#if ENABLE_FEATURE_MDEV_CONF 275#if ENABLE_FEATURE_MDEV_CONF
266 chown(device_name, ugid.uid, ugid.gid); 276 chown(device_name, ugid.uid, ugid.gid);
267
268# if ENABLE_FEATURE_MDEV_RENAME 277# if ENABLE_FEATURE_MDEV_RENAME
269 if (alias) { 278 if (alias) {
270 alias = build_alias(alias, device_name); 279 alias = build_alias(alias, device_name);
271 280 /* move the device, and optionally
272 /* move the device, and optionally 281 * make a symlink to moved device node */
273 * make a symlink to moved device node */ 282 if (rename(device_name, alias) == 0 && aliaslink == '>')
274 if (rename(device_name, alias) == 0 && aliaslink == '>') 283 symlink(alias, device_name);
275 symlink(alias, device_name); 284 free(alias);
276 285 }
277 free(alias);
278 }
279# endif 286# endif
280#endif 287#endif
281 } 288 }
282
283#if ENABLE_FEATURE_MDEV_EXEC 289#if ENABLE_FEATURE_MDEV_EXEC
284 if (command) { 290 if (command) {
285 /* setenv will leak memory, use putenv/unsetenv/free */ 291 /* setenv will leak memory, use putenv/unsetenv/free */
286 char *s = xasprintf("%s=%s", "MDEV", device_name); 292 char *s = xasprintf("%s=%s", "MDEV", device_name);
287 char *s1 = xasprintf("%s=%s", "SUBSYSTEM", subsystem); 293 char *s1 = xasprintf("%s=%s", "SUBSYSTEM", subsystem);
288 putenv(s); 294 putenv(s);
289 putenv(s1); 295 putenv(s1);
290 if (system(command) == -1) 296 if (system(command) == -1)
291 bb_perror_msg_and_die("can't run '%s'", command); 297 bb_perror_msg_and_die("can't run '%s'", command);
292 unsetenv("SUBSYSTEM"); 298 unsetenv("SUBSYSTEM");
293 free(s1); 299 free(s1);
294 unsetenv("MDEV"); 300 unsetenv("MDEV");
295 free(s); 301 free(s);
296 free(command); 302 free(command);
297 } 303 }
298#endif 304#endif
299 305 if (delete) {
300 if (delete) { 306 unlink(device_name);
301 unlink(device_name); 307 /* At creation time, device might have been moved
302 /* At creation time, device might have been moved 308 * and a symlink might have been created. Undo that. */
303 * and a symlink might have been created. Undo that. */
304#if ENABLE_FEATURE_MDEV_RENAME 309#if ENABLE_FEATURE_MDEV_RENAME
305 if (alias) { 310 if (alias) {
306 alias = build_alias(alias, device_name); 311 alias = build_alias(alias, device_name);
307 unlink(alias); 312 unlink(alias);
308 free(alias); 313 free(alias);
309 } 314 }
310#endif 315#endif
311 } 316 }
317
318#if ENABLE_FEATURE_MDEV_CONF
319 /* We found matching line.
320 * Stop unless it was prefixed with '-' */
321 if (!keep_matching)
322 break;
323 } /* end of "while line is read from /etc/mdev.conf" */
324
325 config_close(parser);
326#endif /* ENABLE_FEATURE_MDEV_CONF */
312} 327}
313 328
314/* File callback for /sys/ traversal */ 329/* File callback for /sys/ traversal */