#define root_major (G.root_major)
#define root_minor (G.root_minor)
-#define MAX_SYSFS_DEPTH 3 /* prevent infinite loops in /sys symlinks */
+/* Prevent infinite loops in /sys symlinks */
+#define MAX_SYSFS_DEPTH 3
/* We use additional 64+ bytes in make_device() */
#define SCRATCH_SIZE 80
char *dev_maj_min = path + strlen(path);
char *command = NULL;
char *alias = NULL;
+ char aliaslink = aliaslink; /* for compiler */
/* Force the configuration file settings exactly. */
umask(0);
/* Determine device name, type, major and minor */
device_name = bb_basename(path);
/* http://kernel.org/doc/pending/hotplug.txt says that only
- * "/sys/block/..." is for block devices. "sys/bus" etc is not! */
- type = (strncmp(&path[5], "block/", 6) == 0 ? S_IFBLK : S_IFCHR);
+ * "/sys/block/..." is for block devices. "/sys/bus" etc is not!
+ * Since kernel 2.6.25 block devices are also in /sys/class/block. */
+ /* TODO: would it be acceptable to just use strstr(path, "/block/")? */
+ if (strncmp(&path[5], "class/block/"+6, 6) != 0
+ && strncmp(&path[5], "class/block/", 12) != 0)
+ type = S_IFCHR;
+ else
+ type = S_IFBLK;
if (ENABLE_FEATURE_MDEV_CONF) {
FILE *fp;
/* If not this device, skip rest of line */
/* (regexec returns whole pattern as "range" 0) */
- if (result || off[0].rm_so || off[0].rm_eo != strlen(device_name))
+ if (result || off[0].rm_so
+ || ((int)off[0].rm_eo != (int)strlen(device_name))
+ ) {
goto next_line;
+ }
}
/* This line matches: stop parsing the file
#if ENABLE_FEATURE_MDEV_RENAME
if (!next)
break;
- if (*next == '>') {
+ if (*next == '>' || *next == '=') {
#if ENABLE_FEATURE_MDEV_RENAME_REGEXP
char *s, *p;
unsigned i, n;
+ aliaslink = *next;
val = next;
next = next_field(val);
/* substitute %1..9 with off[1..9], if any */
n = 0;
s = val;
- while (*s && *s++ == '%')
- n++;
+ while (*s)
+ if (*s++ == '%')
+ n++;
p = alias = xzalloc(strlen(val) + n * strlen(device_name));
s = val + 1;
s++;
}
#else
+ aliaslink = *next;
val = next;
next = next_field(val);
alias = xstrdup(val + 1);
}
}
- /* recreate device_name as a symlink to moved device node */
- if (rename(device_name, alias) == 0) {
+ /* move the device, and optionally
+ * make a symlink to moved device node */
+ if (rename(device_name, alias) == 0 && aliaslink == '>')
symlink(alias, device_name);
- }
free(alias);
}
}
/* File callback for /sys/ traversal */
-static int fileAction(const char *fileName,
- struct stat *statbuf ATTRIBUTE_UNUSED,
- void *userData,
- int depth ATTRIBUTE_UNUSED)
+static int FAST_FUNC fileAction(const char *fileName,
+ struct stat *statbuf UNUSED_PARAM,
+ void *userData,
+ int depth UNUSED_PARAM)
{
size_t len = strlen(fileName) - 4; /* can't underflow */
char *scratch = userData;
}
/* Directory callback for /sys/ traversal */
-static int dirAction(const char *fileName ATTRIBUTE_UNUSED,
- struct stat *statbuf ATTRIBUTE_UNUSED,
- void *userData ATTRIBUTE_UNUSED,
- int depth)
+static int FAST_FUNC dirAction(const char *fileName UNUSED_PARAM,
+ struct stat *statbuf UNUSED_PARAM,
+ void *userData UNUSED_PARAM,
+ int depth)
{
return (depth >= MAX_SYSFS_DEPTH ? SKIP : TRUE);
}
char *env_path;
RESERVE_CONFIG_BUFFER(temp, PATH_MAX + SCRATCH_SIZE);
+ /* We can be called as hotplug helper */
+ /* Kernel cannot provide suitable stdio fds for us, do it ourself */
+#if 1
+ bb_sanitize_stdio();
+#else
+ /* Debug code */
+ /* Replace LOGFILE by other file or device name if you need */
+#define LOGFILE "/dev/console"
+ /* Just making sure fd 0 is not closed,
+ * we don't really intend to read from it */
+ xmove_fd(xopen("/", O_RDONLY), STDIN_FILENO);
+ xmove_fd(xopen(LOGFILE, O_WRONLY|O_APPEND), STDOUT_FILENO);
+ xmove_fd(xopen(LOGFILE, O_WRONLY|O_APPEND), STDERR_FILENO);
+#endif
+
xchdir("/dev");
if (argc == 2 && !strcmp(argv[1], "-s")) {
root_major = major(st.st_dev);
root_minor = minor(st.st_dev);
+ /* ACTION_FOLLOWLINKS is needed since in newer kernels
+ * /sys/block/loop* (for example) are symlinks to dirs,
+ * not real directories.
+ * (kernel's CONFIG_SYSFS_DEPRECATED makes them real dirs,
+ * but we can't enforce that on users) */
recursive_action("/sys/block",
ACTION_RECURSE | ACTION_FOLLOWLINKS,
fileAction, dirAction, temp, 0);
-
recursive_action("/sys/class",
ACTION_RECURSE | ACTION_FOLLOWLINKS,
fileAction, dirAction, temp, 0);
-
} else {
/* Hotplug:
* env ACTION=... DEVPATH=... mdev