//usage: "If /dev/mdev.log file exists, debug log will be appended to it."
#include "libbb.h"
+#include "common_bufsiz.h"
#include "xregex.h"
/* "mdev -s" scans /sys/class/xxx, looking for directories which have dev
struct rule cur_rule;
char timestr[sizeof("HH:MM:SS.123456")];
} FIX_ALIASING;
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define INIT_G() do { \
+ setup_common_bufsiz(); \
IF_NOT_FEATURE_MDEV_CONF(G.cur_rule.maj = -1;) \
IF_NOT_FEATURE_MDEV_CONF(G.cur_rule.mode = 0660;) \
} while (0)
}
/* 2nd field: uid:gid - device ownership */
- if (get_uidgid(&G.cur_rule.ugid, tokens[1], /*allow_numeric:*/ 1) == 0) {
+ if (get_uidgid(&G.cur_rule.ugid, tokens[1]) == 0) {
bb_error_msg("unknown user/group '%s' on line %d", tokens[1], G.parser->lineno);
goto next_rule;
}
/* 3rd field: mode - device permissions */
- bb_parse_mode(tokens[2], &G.cur_rule.mode);
+ G.cur_rule.mode = bb_parse_mode(tokens[2], G.cur_rule.mode);
/* 4th field (opt): ">|=alias" or "!" to not create the node */
val = tokens[3];
/* mknod in /dev based on a path like "/sys/block/hda/hda1"
* NB1: path parameter needs to have SCRATCH_SIZE scratch bytes
- * after NUL, but we promise to not mangle (IOW: to restore NUL if needed)
- * path string.
+ * after NUL, but we promise to not mangle it (IOW: to restore NUL if needed).
* NB2: "mdev -s" may call us many times, do not leak memory/fds!
*
* device_name = $DEVNAME (may be NULL)
} /* for (;;) */
}
-/* File callback for /sys/ traversal */
+/* File callback for /sys/ traversal.
+ * We act only on "/sys/.../dev" (pseudo)file
+ */
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;
-
- /* len check is for paranoid reasons */
- if (strcmp(fileName + len, "/dev") != 0 || len >= PATH_MAX)
- return FALSE;
-
- strcpy(scratch, fileName);
- scratch[len] = '\0';
- make_device(/*DEVNAME:*/ NULL, scratch, OP_add);
-
- return TRUE;
-}
-
-/* Directory callback for /sys/ traversal */
-static int FAST_FUNC dirAction(const char *fileName UNUSED_PARAM,
- struct stat *statbuf UNUSED_PARAM,
- void *userData UNUSED_PARAM,
- int depth)
-{
- /* Extract device subsystem -- the name of the directory
- * under /sys/class/ */
- if (1 == depth) {
+ char *path = userData; /* char array[PATH_MAX + SCRATCH_SIZE] */
+ char subsys[PATH_MAX];
+ int res;
+
+ /* Is it a ".../dev" file? (len check is for paranoid reasons) */
+ if (strcmp(fileName + len, "/dev") != 0 || len >= PATH_MAX - 32)
+ return FALSE; /* not .../dev */
+
+ strcpy(path, fileName);
+ path[len] = '\0';
+
+ /* Read ".../subsystem" symlink in the same directory where ".../dev" is */
+ strcpy(subsys, path);
+ strcpy(subsys + len, "/subsystem");
+ res = readlink(subsys, subsys, sizeof(subsys)-1);
+ if (res > 0) {
+ subsys[res] = '\0';
free(G.subsystem);
if (G.subsys_env) {
bb_unsetenv_and_free(G.subsys_env);
G.subsys_env = NULL;
}
- G.subsystem = strrchr(fileName, '/');
+ /* Set G.subsystem and $SUBSYSTEM from symlink's last component */
+ G.subsystem = strrchr(subsys, '/');
if (G.subsystem) {
G.subsystem = xstrdup(G.subsystem + 1);
G.subsys_env = xasprintf("%s=%s", "SUBSYSTEM", G.subsystem);
}
}
+ make_device(/*DEVNAME:*/ NULL, path, OP_add);
+
+ return TRUE;
+}
+
+/* Directory callback for /sys/ traversal */
+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);
}
int firmware_fd, loading_fd;
/* check for /lib/firmware/$FIRMWARE */
- xchdir("/lib/firmware");
- firmware_fd = open(firmware, O_RDONLY); /* can fail */
+ firmware_fd = -1;
+ if (chdir("/lib/firmware") == 0)
+ firmware_fd = open(firmware, O_RDONLY); /* can fail */
/* check for /sys/$DEVPATH/loading ... give 30 seconds to appear */
xchdir(sysfs_path);
putenv((char*)"ACTION=add");
- /* 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)
- */
- if (access("/sys/class/block", F_OK) != 0) {
- /* Scan obsolete /sys/block only if /sys/class/block
- * doesn't exist. Otherwise we'll have dupes.
- * Also, do not complain if it doesn't exist.
- * Some people configure kernel to have no blockdevs.
- */
- recursive_action("/sys/block",
- ACTION_RECURSE | ACTION_FOLLOWLINKS | ACTION_QUIET,
- fileAction, dirAction, temp, 0);
- }
- recursive_action("/sys/class",
- ACTION_RECURSE | ACTION_FOLLOWLINKS,
- fileAction, dirAction, temp, 0);
+ /* Create all devices from /sys/dev hierarchy */
+ recursive_action("/sys/dev",
+ ACTION_RECURSE | ACTION_FOLLOWLINKS,
+ fileAction, dirAction, temp, 0);
} else {
char *fw;
char *seq;