mdev: do not complain if mdev.conf does not exist;

use #if to prevent gcc from generating dead code
 (sadly, it's more ugly this way)
This commit is contained in:
Denis Vlasenko 2008-07-26 18:35:10 +00:00
parent 48a9971bd4
commit df96df9c7c
3 changed files with 155 additions and 134 deletions

View File

@ -60,18 +60,23 @@ matched, then the default of 0:0 660 is used. To set your own default, simply
create your own total match like so: create your own total match like so:
.* 1:1 777 .* 1:1 777
You can rename/relocate device nodes by using the next optional field. You can rename/move device nodes by using the next optional field.
<device regex> <uid>:<gid> <octal permissions> [>path] <device regex> <uid>:<gid> <octal permissions> [=path]
So if you want to place the device node into a subdirectory, make sure the path So if you want to place the device node into a subdirectory, make sure the path
has a trailing /. If you want to rename the device node, just place the name. has a trailing /. If you want to rename the device node, just place the name.
hda 0:3 660 >drives/ hda 0:3 660 =drives/
This will relocate "hda" into the drives/ subdirectory. This will move "hda" into the drives/ subdirectory.
hdb 0:3 660 >cdrom hdb 0:3 660 =cdrom
This will rename "hdb" to "cdrom". This will rename "hdb" to "cdrom".
Similarly, ">path" renames/moves the device but it also creates
a direct symlink /dev/DEVNAME to the renamed/moved device.
If you also enable support for executing your own commands, then the file has If you also enable support for executing your own commands, then the file has
the format: the format:
<device regex> <uid>:<gid> <octal permissions> [<@|$|*> <command>] <device regex> <uid>:<gid> <octal permissions> [=path] [@|$|*<command>]
or
<device regex> <uid>:<gid> <octal permissions> [>path] [@|$|*<command>]
The special characters have the meaning: The special characters have the meaning:
@ Run after creating the device. @ Run after creating the device.
$ Run before removing the device. $ Run before removing the device.

View File

@ -29,7 +29,6 @@ testing "mdev add /block/sda" \
"env - ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; "env - ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1;
ls -ln mdev.testdir/dev | $FILTER_LS" \ ls -ln mdev.testdir/dev | $FILTER_LS" \
"\ "\
mdev: /etc/mdev.conf: No such file or directory
brw-rw---- 1 0 0 8,0 sda brw-rw---- 1 0 0 8,0 sda
" \ " \
"" "" "" ""

View File

@ -25,6 +25,7 @@ struct globals {
/* We use additional 64+ bytes in make_device() */ /* We use additional 64+ bytes in make_device() */
#define SCRATCH_SIZE 80 #define SCRATCH_SIZE 80
#if ENABLE_FEATURE_MDEV_RENAME
/* Builds an alias path. /* Builds an alias path.
* This function potentionally reallocates the alias parameter. * This function potentionally reallocates the alias parameter.
*/ */
@ -48,6 +49,7 @@ static char *build_alias(char *alias, const char *device_name)
return alias; return alias;
} }
#endif
/* mknod in /dev based on a path like "/sys/block/hda/hda1" */ /* mknod in /dev based on a path like "/sys/block/hda/hda1" */
/* NB: "mdev -s" may call us many times, do not leak memory/fds! */ /* NB: "mdev -s" may call us many times, do not leak memory/fds! */
@ -56,12 +58,20 @@ static void make_device(char *path, int delete)
const char *device_name; const char *device_name;
int major, minor, type, len; int major, minor, type, len;
int mode = 0660; int mode = 0660;
#if ENABLE_FEATURE_MDEV_CONF
uid_t uid = 0; uid_t uid = 0;
gid_t gid = 0; gid_t gid = 0;
char *dev_maj_min = path + strlen(path); parser_t *parser;
char *tokens[5];
#endif
#if ENABLE_FEATURE_MDEV_EXEC
char *command = NULL; char *command = NULL;
#endif
#if ENABLE_FEATURE_MDEV_RENAME
char *alias = NULL; char *alias = NULL;
char aliaslink = aliaslink; /* for compiler */ char aliaslink = aliaslink; /* for compiler */
#endif
char *dev_maj_min = path + strlen(path);
/* Force the configuration file settings exactly. */ /* Force the configuration file settings exactly. */
umask(0); umask(0);
@ -93,148 +103,149 @@ static void make_device(char *path, int delete)
if (strstr(path, "/block/")) if (strstr(path, "/block/"))
type = S_IFBLK; type = S_IFBLK;
if (ENABLE_FEATURE_MDEV_CONF) { #if ENABLE_FEATURE_MDEV_CONF
parser_t *parser = config_open("/etc/mdev.conf"); parser = config_open2("/etc/mdev.conf", fopen_for_read);
char *tokens[5];
/* If we have config file, look up user settings */ /* If we have config file, look up user settings */
if (!parser) if (!parser)
goto end_parse; goto end_parse;
while (config_read(parser, tokens, 4, 3, "# \t", PARSE_LAST_IS_GREEDY)) { while (config_read(parser, tokens, 4, 3, "# \t", PARSE_LAST_IS_GREEDY)) {
regmatch_t off[1+9*ENABLE_FEATURE_MDEV_RENAME_REGEXP]; regmatch_t off[1 + 9*ENABLE_FEATURE_MDEV_RENAME_REGEXP];
char *val; char *val;
/* Fields: regex uid:gid mode [alias] [cmd] */ /* Fields: regex uid:gid mode [alias] [cmd] */
/* 1st field: regex to match this device */ /* 1st field: regex to match this device */
{ {
regex_t match; regex_t match;
int result; int result;
/* Is this it? */ /* Is this it? */
xregcomp(&match, tokens[0], REG_EXTENDED); xregcomp(&match, tokens[0], REG_EXTENDED);
result = regexec(&match, device_name, ARRAY_SIZE(off), off, 0); result = regexec(&match, device_name, ARRAY_SIZE(off), off, 0);
regfree(&match); regfree(&match);
//bb_error_msg("matches:"); //bb_error_msg("matches:");
//for (int i = 0; i < ARRAY_SIZE(off); i++) { //for (int i = 0; i < ARRAY_SIZE(off); i++) {
// if (off[i].rm_so < 0) continue; // if (off[i].rm_so < 0) continue;
// bb_error_msg("match %d: '%.*s'\n", i, // bb_error_msg("match %d: '%.*s'\n", i,
// (int)(off[i].rm_eo - off[i].rm_so), // (int)(off[i].rm_eo - off[i].rm_so),
// device_name + off[i].rm_so); // device_name + off[i].rm_so);
//} //}
/* If not this device, skip rest of line */ /* If not this device, skip rest of line */
/* (regexec returns whole pattern as "range" 0) */ /* (regexec returns whole pattern as "range" 0) */
if (result || off[0].rm_so if (result || off[0].rm_so
|| ((int)off[0].rm_eo != (int)strlen(device_name)) || ((int)off[0].rm_eo != (int)strlen(device_name))
) { ) {
continue; continue;
}
} }
}
/* This line matches: stop parsing the file /* This line matches: stop parsing the file
* after parsing the rest of fields */ * after parsing the rest of fields */
/* 2nd field: uid:gid - device ownership */ /* 2nd field: uid:gid - device ownership */
{ {
struct passwd *pass; struct passwd *pass;
struct group *grp; struct group *grp;
char *str_uid = tokens[1]; char *str_uid = tokens[1];
char *str_gid = strchrnul(str_uid, ':'); char *str_gid = strchrnul(str_uid, ':');
if (*str_gid) if (*str_gid)
*str_gid++ = '\0'; *str_gid++ = '\0';
/* Parse UID */ /* Parse UID */
pass = getpwnam(str_uid); pass = getpwnam(str_uid);
if (pass) if (pass)
uid = pass->pw_uid; uid = pass->pw_uid;
else else
uid = strtoul(str_uid, NULL, 10); uid = strtoul(str_uid, NULL, 10);
/* Parse GID */ /* Parse GID */
grp = getgrnam(str_gid); grp = getgrnam(str_gid);
if (grp) if (grp)
gid = grp->gr_gid; gid = grp->gr_gid;
else else
gid = strtoul(str_gid, NULL, 10); gid = strtoul(str_gid, NULL, 10);
} }
/* 3rd field: mode - device permissions */ /* 3rd field: mode - device permissions */
mode = strtoul(tokens[2], NULL, 8); mode = strtoul(tokens[2], NULL, 8);
val = tokens[3]; val = tokens[3];
/* 4th field (opt): >alias */ /* 4th field (opt): >alias */
#if ENABLE_FEATURE_MDEV_RENAME #if ENABLE_FEATURE_MDEV_RENAME
if (!val) if (!val)
break; break;
aliaslink = *val; aliaslink = *val;
if (aliaslink == '>' || aliaslink == '=') { if (aliaslink == '>' || aliaslink == '=') {
char *s; char *s;
#if ENABLE_FEATURE_MDEV_RENAME_REGEXP #if ENABLE_FEATURE_MDEV_RENAME_REGEXP
char *p; char *p;
unsigned i, n; unsigned i, n;
#endif #endif
char *a = val; char *a = val;
s = strchr(val, ' '); s = strchr(val, ' ');
val = (s && s[1]) ? s+1 : NULL; val = (s && s[1]) ? s+1 : NULL;
#if ENABLE_FEATURE_MDEV_RENAME_REGEXP #if ENABLE_FEATURE_MDEV_RENAME_REGEXP
/* substitute %1..9 with off[1..9], if any */ /* substitute %1..9 with off[1..9], if any */
n = 0; n = 0;
s = a; s = a;
while (*s) while (*s)
if (*s++ == '%') if (*s++ == '%')
n++; n++;
p = alias = xzalloc(strlen(a) + n * strlen(device_name)); p = alias = xzalloc(strlen(a) + n * strlen(device_name));
s = a + 1; s = a + 1;
while (*s) { while (*s) {
*p = *s; *p = *s;
if ('%' == *s) { if ('%' == *s) {
i = (s[1] - '0'); i = (s[1] - '0');
if (i <= 9 && off[i].rm_so >= 0) { if (i <= 9 && off[i].rm_so >= 0) {
n = off[i].rm_eo - off[i].rm_so; n = off[i].rm_eo - off[i].rm_so;
strncpy(p, device_name + off[i].rm_so, n); strncpy(p, device_name + off[i].rm_so, n);
p += n - 1; p += n - 1;
s++; s++;
}
} }
p++;
s++;
} }
#else p++;
alias = xstrdup(a + 1); s++;
#endif
} }
#else
alias = xstrdup(a + 1);
#endif
}
#endif /* ENABLE_FEATURE_MDEV_RENAME */ #endif /* ENABLE_FEATURE_MDEV_RENAME */
/* The rest (opt): command to run */ #if ENABLE_FEATURE_MDEV_EXEC
if (!val) /* The rest (opt): command to run */
break; if (!val)
if (ENABLE_FEATURE_MDEV_EXEC) { break;
const char *s = "@$*"; {
const char *s2 = strchr(s, *val); const char *s = "@$*";
const char *s2 = strchr(s, *val);
if (!s2) if (!s2)
bb_error_msg_and_die("bad line %u", parser->lineno); bb_error_msg_and_die("bad line %u", parser->lineno);
/* Correlate the position in the "@$*" with the delete /* Correlate the position in the "@$*" with the delete
* step so that we get the proper behavior: * step so that we get the proper behavior:
* @cmd: run on create * @cmd: run on create
* $cmd: run on delete * $cmd: run on delete
* *cmd: run on both * *cmd: run on both
*/ */
if ((s2 - s + 1) /*1/2/3*/ & /*1/2*/ (1 + delete)) { if ((s2 - s + 1) /*1/2/3*/ & /*1/2*/ (1 + delete)) {
command = xstrdup(val + 1); command = xstrdup(val + 1);
}
} }
/* end of field parsing */ }
break; /* we found matching line, stop */ #endif
} /* end of "while line is read from /etc/mdev.conf" */ /* end of field parsing */
break; /* we found matching line, stop */
} /* end of "while line is read from /etc/mdev.conf" */
config_close(parser); config_close(parser);
}
end_parse: end_parse:
#endif /* ENABLE_FEATURE_MDEV_CONF */
if (!delete && sscanf(dev_maj_min, "%u:%u", &major, &minor) == 2) { if (!delete && sscanf(dev_maj_min, "%u:%u", &major, &minor) == 2) {
@ -247,23 +258,26 @@ static void make_device(char *path, int delete)
if (major == root_major && minor == root_minor) if (major == root_major && minor == root_minor)
symlink(device_name, "root"); symlink(device_name, "root");
if (ENABLE_FEATURE_MDEV_CONF) { #if ENABLE_FEATURE_MDEV_CONF
chown(device_name, uid, gid); chown(device_name, uid, gid);
if (ENABLE_FEATURE_MDEV_RENAME && alias) { #if ENABLE_FEATURE_MDEV_RENAME
alias = build_alias(alias, device_name); if (alias) {
alias = build_alias(alias, device_name);
/* move the device, and optionally /* move the device, and optionally
* make a symlink to moved device node */ * make a symlink to moved device node */
if (rename(device_name, alias) == 0 && aliaslink == '>') if (rename(device_name, alias) == 0 && aliaslink == '>')
symlink(alias, device_name); symlink(alias, device_name);
free(alias); free(alias);
}
} }
#endif
#endif
} }
if (ENABLE_FEATURE_MDEV_EXEC && command) { #if ENABLE_FEATURE_MDEV_EXEC
if (command) {
/* setenv will leak memory, use putenv/unsetenv/free */ /* setenv will leak memory, use putenv/unsetenv/free */
char *s = xasprintf("MDEV=%s", device_name); char *s = xasprintf("MDEV=%s", device_name);
putenv(s); putenv(s);
@ -274,16 +288,19 @@ static void make_device(char *path, int delete)
free(s); free(s);
free(command); free(command);
} }
#endif
if (delete) { if (delete) {
unlink(device_name); unlink(device_name);
/* At creation time, device might have been moved /* At creation time, device might have been moved
* and a symlink might have been created. Undo that. */ * and a symlink might have been created. Undo that. */
if (ENABLE_FEATURE_MDEV_RENAME && alias) { #if ENABLE_FEATURE_MDEV_RENAME
if (alias) {
alias = build_alias(alias, device_name); alias = build_alias(alias, device_name);
unlink(alias); unlink(alias);
free(alias); free(alias);
} }
#endif
} }
} }