From e73f3c1d3d83699b723251f7e6a981021ce75475 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 29 Jun 2013 17:00:22 +0200 Subject: [PATCH] Apply post-1.21.0 patches, bump version to 1.21.1 Signed-off-by: Denys Vlasenko --- Makefile | 2 +- archival/libarchive/decompress_unxz.c | 47 ++- include/platform.h | 2 +- util-linux/mdev.c | 402 +++++++++++++++++++------- util-linux/volume_id/ntfs.c | 2 +- 5 files changed, 341 insertions(+), 114 deletions(-) diff --git a/Makefile b/Makefile index c31ca899b..ca0644230 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 21 -SUBLEVEL = 0 +SUBLEVEL = 1 EXTRAVERSION = NAME = Unnamed diff --git a/archival/libarchive/decompress_unxz.c b/archival/libarchive/decompress_unxz.c index 79b48a152..986b7b191 100644 --- a/archival/libarchive/decompress_unxz.c +++ b/archival/libarchive/decompress_unxz.c @@ -30,8 +30,8 @@ static uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc) /* We use arch-optimized unaligned accessors */ #define get_unaligned_le32(buf) ({ uint32_t v; move_from_unaligned32(v, buf); SWAP_LE32(v); }) #define get_unaligned_be32(buf) ({ uint32_t v; move_from_unaligned32(v, buf); SWAP_BE32(v); }) -#define put_unaligned_le32(val, buf) move_to_unaligned16(buf, SWAP_LE32(val)) -#define put_unaligned_be32(val, buf) move_to_unaligned16(buf, SWAP_BE32(val)) +#define put_unaligned_le32(val, buf) move_to_unaligned32(buf, SWAP_LE32(val)) +#define put_unaligned_be32(val, buf) move_to_unaligned32(buf, SWAP_BE32(val)) #include "unxz/xz_dec_bcj.c" #include "unxz/xz_dec_lzma2.c" @@ -40,6 +40,7 @@ static uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc) IF_DESKTOP(long long) int FAST_FUNC unpack_xz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) { + enum xz_ret xz_result; struct xz_buf iobuf; struct xz_dec *state; unsigned char *membuf; @@ -63,9 +64,8 @@ unpack_xz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) /* Limit memory usage to about 64 MiB. */ state = xz_dec_init(XZ_DYNALLOC, 64*1024*1024); + xz_result = X_OK; while (1) { - enum xz_ret r; - if (iobuf.in_pos == iobuf.in_size) { int rd = safe_read(src_fd, membuf, BUFSIZ); if (rd < 0) { @@ -73,28 +73,57 @@ unpack_xz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) total = -1; break; } + if (rd == 0 && xz_result == XZ_STREAM_END) + break; iobuf.in_size = rd; iobuf.in_pos = 0; } + if (xz_result == XZ_STREAM_END) { + /* + * Try to start decoding next concatenated stream. + * Stream padding must always be a multiple of four + * bytes to preserve four-byte alignment. To keep the + * code slightly smaller, we aren't as strict here as + * the .xz spec requires. We just skip all zero-bytes + * without checking the alignment and thus can accept + * files that aren't valid, e.g. the XZ utils test + * files bad-0pad-empty.xz and bad-0catpad-empty.xz. + */ + do { + if (membuf[iobuf.in_pos] != 0) { + xz_dec_reset(state); + goto do_run; + } + iobuf.in_pos++; + } while (iobuf.in_pos < iobuf.in_size); + } + do_run: // bb_error_msg(">in pos:%d size:%d out pos:%d size:%d", // iobuf.in_pos, iobuf.in_size, iobuf.out_pos, iobuf.out_size); - r = xz_dec_run(state, &iobuf); + xz_result = xz_dec_run(state, &iobuf); // bb_error_msg("|=PATH]|[!]") //usage: IF_FEATURE_MDEV_EXEC(" [@|$|*PROG]") //usage: "\n" @@ -230,9 +230,34 @@ * SUBSYSTEM=block */ -static const char keywords[] ALIGN1 = "add\0remove\0change\0"; +#define DEBUG_LVL 2 + +#if DEBUG_LVL >= 1 +# define dbg1(...) do { if (G.verbose) bb_error_msg(__VA_ARGS__); } while(0) +#else +# define dbg1(...) ((void)0) +#endif +#if DEBUG_LVL >= 2 +# define dbg2(...) do { if (G.verbose >= 2) bb_error_msg(__VA_ARGS__); } while(0) +#else +# define dbg2(...) ((void)0) +#endif +#if DEBUG_LVL >= 3 +# define dbg3(...) do { if (G.verbose >= 3) bb_error_msg(__VA_ARGS__); } while(0) +#else +# define dbg3(...) ((void)0) +#endif + + +static const char keywords[] ALIGN1 = "add\0remove\0"; // "change\0" enum { OP_add, OP_remove }; +struct envmatch { + struct envmatch *next; + char *envname; + regex_t match; +}; + struct rule { bool keep_matching; bool regex_compiled; @@ -243,12 +268,14 @@ struct rule { char *ren_mov; IF_FEATURE_MDEV_EXEC(char *r_cmd;) regex_t match; + struct envmatch *envmatch; }; struct globals { int root_major, root_minor; smallint verbose; char *subsystem; + char *subsys_env; /* for putenv("SUBSYSTEM=subsystem") */ #if ENABLE_FEATURE_MDEV_CONF const char *filename; parser_t *parser; @@ -256,6 +283,7 @@ struct globals { unsigned rule_idx; #endif struct rule cur_rule; + char timestr[sizeof("60.123456")]; } FIX_ALIASING; #define G (*(struct globals*)&bb_common_bufsiz1) #define INIT_G() do { \ @@ -267,15 +295,8 @@ struct globals { /* Prevent infinite loops in /sys symlinks */ #define MAX_SYSFS_DEPTH 3 -/* We use additional 64+ bytes in make_device() */ -#define SCRATCH_SIZE 80 - -#if 0 -# define dbg(...) bb_error_msg(__VA_ARGS__) -#else -# define dbg(...) ((void)0) -#endif - +/* We use additional bytes in make_device() */ +#define SCRATCH_SIZE 128 #if ENABLE_FEATURE_MDEV_CONF @@ -288,14 +309,65 @@ static void make_default_cur_rule(void) static void clean_up_cur_rule(void) { + struct envmatch *e; + free(G.cur_rule.envvar); + free(G.cur_rule.ren_mov); if (G.cur_rule.regex_compiled) regfree(&G.cur_rule.match); - free(G.cur_rule.ren_mov); IF_FEATURE_MDEV_EXEC(free(G.cur_rule.r_cmd);) + e = G.cur_rule.envmatch; + while (e) { + free(e->envname); + regfree(&e->match); + e = e->next; + } make_default_cur_rule(); } +/* In later versions, endofname is in libbb */ +#define endofname mdev_endofname +static +const char* FAST_FUNC +endofname(const char *name) +{ +#define is_name(c) ((c) == '_' || isalpha((unsigned char)(c))) +#define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c))) + if (!is_name(*name)) + return name; + while (*++name) { + if (!is_in_name(*name)) + break; + } + return name; +} + +static char *parse_envmatch_pfx(char *val) +{ + struct envmatch **nextp = &G.cur_rule.envmatch; + + for (;;) { + struct envmatch *e; + char *semicolon; + char *eq = strchr(val, '='); + if (!eq /* || eq == val? */) + return val; + if (endofname(val) != eq) + return val; + semicolon = strchr(eq, ';'); + if (!semicolon) + return val; + /* ENVVAR=regex;... */ + *nextp = e = xzalloc(sizeof(*e)); + nextp = &e->next; + e->envname = xstrndup(val, eq - val); + *semicolon = '\0'; + xregcomp(&e->match, eq + 1, REG_EXTENDED); + *semicolon = ';'; + val = semicolon + 1; + } +} + static void parse_next_rule(void) { /* Note: on entry, G.cur_rule is set to default */ @@ -308,12 +380,13 @@ static void parse_next_rule(void) break; /* Fields: [-]regex uid:gid mode [alias] [cmd] */ - dbg("token1:'%s'", tokens[1]); + dbg3("token1:'%s'", tokens[1]); /* 1st field */ val = tokens[0]; G.cur_rule.keep_matching = ('-' == val[0]); val += G.cur_rule.keep_matching; /* swallow leading dash */ + val = parse_envmatch_pfx(val); if (val[0] == '@') { /* @major,minor[-minor2] */ /* (useful when name is ambiguous: @@ -328,8 +401,10 @@ static void parse_next_rule(void) if (sc == 2) G.cur_rule.min1 = G.cur_rule.min0; } else { + char *eq = strchr(val, '='); if (val[0] == '$') { - char *eq = strchr(++val, '='); + /* $ENVVAR=regex ... */ + val++; if (!eq) { bb_error_msg("bad $envvar=regex on line %d", G.parser->lineno); goto next_rule; @@ -373,7 +448,7 @@ static void parse_next_rule(void) clean_up_cur_rule(); } /* while (config_read) */ - dbg("config_close(G.parser)"); + dbg3("config_close(G.parser)"); config_close(G.parser); G.parser = NULL; @@ -390,7 +465,7 @@ static const struct rule *next_rule(void) /* Open conf file if we didn't do it yet */ if (!G.parser && G.filename) { - dbg("config_open('%s')", G.filename); + dbg3("config_open('%s')", G.filename); G.parser = config_open2(G.filename, fopen_for_read); G.filename = NULL; } @@ -399,7 +474,7 @@ static const struct rule *next_rule(void) /* mdev -s */ /* Do we have rule parsed already? */ if (G.rule_vec[G.rule_idx]) { - dbg("< G.rule_vec[G.rule_idx:%d]=%p", G.rule_idx, G.rule_vec[G.rule_idx]); + dbg3("< G.rule_vec[G.rule_idx:%d]=%p", G.rule_idx, G.rule_vec[G.rule_idx]); return G.rule_vec[G.rule_idx++]; } make_default_cur_rule(); @@ -416,13 +491,28 @@ static const struct rule *next_rule(void) rule = memcpy(xmalloc(sizeof(G.cur_rule)), &G.cur_rule, sizeof(G.cur_rule)); G.rule_vec = xrealloc_vector(G.rule_vec, 4, G.rule_idx); G.rule_vec[G.rule_idx++] = rule; - dbg("> G.rule_vec[G.rule_idx:%d]=%p", G.rule_idx, G.rule_vec[G.rule_idx]); + dbg3("> G.rule_vec[G.rule_idx:%d]=%p", G.rule_idx, G.rule_vec[G.rule_idx]); } } return rule; } +static int env_matches(struct envmatch *e) +{ + while (e) { + int r; + char *val = getenv(e->envname); + if (!val) + return 0; + r = regexec(&e->match, val, /*size*/ 0, /*range[]*/ NULL, /*eflags*/ 0); + if (r != 0) /* no match */ + return 0; + e = e->next; + } + return 1; +} + #else # define next_rule() (&G.cur_rule) @@ -468,7 +558,7 @@ static char *build_alias(char *alias, const char *device_name) /* 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 if needed) + * after NUL, but we promise to not mangle (IOW: to restore NUL if needed) * path string. * NB2: "mdev -s" may call us many times, do not leak memory/fds! * @@ -478,9 +568,7 @@ static char *build_alias(char *alias, const char *device_name) static void make_device(char *device_name, char *path, int operation) { int major, minor, type, len; - - if (G.verbose) - bb_error_msg("device: %s, %s", device_name, path); + char *path_end = path + strlen(path); /* Try to read major/minor string. Note that the kernel puts \n after * the data, so we don't need to worry about null terminating the string @@ -489,29 +577,51 @@ static void make_device(char *device_name, char *path, int operation) */ major = -1; if (operation == OP_add) { - char *dev_maj_min = path + strlen(path); - - strcpy(dev_maj_min, "/dev"); - len = open_read_close(path, dev_maj_min + 1, 64); - *dev_maj_min = '\0'; + strcpy(path_end, "/dev"); + len = open_read_close(path, path_end + 1, SCRATCH_SIZE - 1); + *path_end = '\0'; if (len < 1) { if (!ENABLE_FEATURE_MDEV_EXEC) return; /* no "dev" file, but we can still run scripts * based on device name */ - } else if (sscanf(++dev_maj_min, "%u:%u", &major, &minor) == 2) { - if (G.verbose) - bb_error_msg("maj,min: %u,%u", major, minor); + } else if (sscanf(path_end + 1, "%u:%u", &major, &minor) == 2) { + dbg1("dev %u,%u", major, minor); } else { major = -1; } } /* else: for delete, -1 still deletes the node, but < -1 suppresses that */ - /* Determine device name, type, major and minor */ - if (!device_name) - device_name = (char*) bb_basename(path); - /* http://kernel.org/doc/pending/hotplug.txt says that only + /* Determine device name */ + if (!device_name) { + /* + * There was no $DEVNAME envvar (for example, mdev -s never has). + * But it is very useful: it contains the *path*, not only basename, + * Thankfully, uevent file has it. + * Example of .../sound/card0/controlC0/uevent file on Linux-3.7.7: + * MAJOR=116 + * MINOR=7 + * DEVNAME=snd/controlC0 + */ + strcpy(path_end, "/uevent"); + len = open_read_close(path, path_end + 1, SCRATCH_SIZE - 1); + if (len < 0) + len = 0; + *path_end = '\0'; + path_end[1 + len] = '\0'; + device_name = strstr(path_end + 1, "\nDEVNAME="); + if (device_name) { + device_name += sizeof("\nDEVNAME=")-1; + strchrnul(device_name, '\n')[0] = '\0'; + } else { + /* Fall back to just basename */ + device_name = (char*) bb_basename(path); + } + } + /* Determine device type */ + /* + * http://kernel.org/doc/pending/hotplug.txt says that only * "/sys/block/..." is for block devices. "/sys/bus" etc is not. * But since 2.6.25 block devices are also in /sys/class/block. * We use strstr("/block/") to forestall future surprises. @@ -537,6 +647,8 @@ static void make_device(char *device_name, char *path, int operation) rule = next_rule(); #if ENABLE_FEATURE_MDEV_CONF + if (!env_matches(rule->envmatch)) + continue; if (rule->maj >= 0) { /* @maj,min rule */ if (major != rule->maj) continue; @@ -547,7 +659,7 @@ static void make_device(char *device_name, char *path, int operation) } if (rule->envvar) { /* $envvar=regex rule */ str_to_match = getenv(rule->envvar); - dbg("getenv('%s'):'%s'", rule->envvar, str_to_match); + dbg3("getenv('%s'):'%s'", rule->envvar, str_to_match); if (!str_to_match) continue; } @@ -555,7 +667,7 @@ static void make_device(char *device_name, char *path, int operation) if (rule->regex_compiled) { int regex_match = regexec(&rule->match, str_to_match, ARRAY_SIZE(off), off, 0); - dbg("regex_match for '%s':%d", str_to_match, regex_match); + dbg3("regex_match for '%s':%d", str_to_match, regex_match); //bb_error_msg("matches:"); //for (int i = 0; i < ARRAY_SIZE(off); i++) { // if (off[i].rm_so < 0) continue; @@ -574,9 +686,8 @@ static void make_device(char *device_name, char *path, int operation) } /* else: it's final implicit "match-all" rule */ rule_matches: + dbg2("rule matched, line %d", G.parser ? G.parser->lineno : -1); #endif - dbg("rule matched"); - /* Build alias name */ alias = NULL; if (ENABLE_FEATURE_MDEV_RENAME && rule->ren_mov) { @@ -619,34 +730,30 @@ static void make_device(char *device_name, char *path, int operation) } } } - dbg("alias:'%s'", alias); + dbg3("alias:'%s'", alias); command = NULL; IF_FEATURE_MDEV_EXEC(command = rule->r_cmd;) if (command) { - const char *s = "$@*"; - const char *s2 = strchr(s, command[0]); - /* Are we running this command now? - * Run $cmd on delete, @cmd on create, *cmd on both + * Run @cmd on create, $cmd on delete, *cmd on any */ - if (s2 - s != (operation == OP_remove) || *s2 == '*') { - /* We are here if: '*', - * or: '@' and delete = 0, - * or: '$' and delete = 1 - */ + if ((command[0] == '@' && operation == OP_add) + || (command[0] == '$' && operation == OP_remove) + || (command[0] == '*') + ) { command++; } else { command = NULL; } } - dbg("command:'%s'", command); + dbg3("command:'%s'", command); /* "Execute" the line we found */ node_name = device_name; if (ENABLE_FEATURE_MDEV_RENAME && alias) { node_name = alias = build_alias(alias, device_name); - dbg("alias2:'%s'", alias); + dbg3("alias2:'%s'", alias); } if (operation == OP_add && major >= 0) { @@ -656,8 +763,17 @@ static void make_device(char *device_name, char *path, int operation) mkdir_recursive(node_name); *slash = '/'; } - if (G.verbose) - bb_error_msg("mknod: %s (%d,%d) %o", node_name, major, minor, rule->mode | type); + if (ENABLE_FEATURE_MDEV_CONF) { + dbg1("mknod %s (%d,%d) %o" + " %u:%u", + node_name, major, minor, rule->mode | type, + rule->ugid.uid, rule->ugid.gid + ); + } else { + dbg1("mknod %s (%d,%d) %o", + node_name, major, minor, rule->mode | type + ); + } if (mknod(node_name, rule->mode | type, makedev(major, minor)) && errno != EEXIST) bb_perror_msg("can't create '%s'", node_name); if (ENABLE_FEATURE_MDEV_CONF) { @@ -671,8 +787,7 @@ static void make_device(char *device_name, char *path, int operation) //TODO: on devtmpfs, device_name already exists and symlink() fails. //End result is that instead of symlink, we have two nodes. //What should be done? - if (G.verbose) - bb_error_msg("symlink: %s", device_name); + dbg1("symlink: %s", device_name); symlink(node_name, device_name); } } @@ -681,27 +796,21 @@ static void make_device(char *device_name, char *path, int operation) if (ENABLE_FEATURE_MDEV_EXEC && command) { /* setenv will leak memory, use putenv/unsetenv/free */ char *s = xasprintf("%s=%s", "MDEV", node_name); - char *s1 = xasprintf("%s=%s", "SUBSYSTEM", G.subsystem); putenv(s); - putenv(s1); - if (G.verbose) - bb_error_msg("running: %s", command); + dbg1("running: %s", command); if (system(command) == -1) bb_perror_msg("can't run '%s'", command); - bb_unsetenv_and_free(s1); bb_unsetenv_and_free(s); } if (operation == OP_remove && major >= -1) { if (ENABLE_FEATURE_MDEV_RENAME && alias) { if (aliaslink == '>') { - if (G.verbose) - bb_error_msg("unlink: %s", device_name); + dbg1("unlink: %s", device_name); unlink(device_name); } } - if (G.verbose) - bb_error_msg("unlink: %s", node_name); + dbg1("unlink: %s", node_name); unlink(node_name); } @@ -746,9 +855,16 @@ static int FAST_FUNC dirAction(const char *fileName UNUSED_PARAM, * under /sys/class/ */ if (1 == depth) { free(G.subsystem); + if (G.subsys_env) { + bb_unsetenv_and_free(G.subsys_env); + G.subsys_env = NULL; + } G.subsystem = strrchr(fileName, '/'); - if (G.subsystem) + if (G.subsystem) { G.subsystem = xstrdup(G.subsystem + 1); + G.subsys_env = xasprintf("%s=%s", "SUBSYSTEM", G.subsystem); + putenv(G.subsys_env); + } } return (depth >= MAX_SYSFS_DEPTH ? SKIP : TRUE); @@ -813,12 +929,107 @@ static void load_firmware(const char *firmware, const char *sysfs_path) full_write(loading_fd, "-1", 2); out: + xchdir("/dev"); if (ENABLE_FEATURE_CLEAN_UP) { close(firmware_fd); close(loading_fd); } } +static char *curtime(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + sprintf(G.timestr, "%u.%06u", (unsigned)tv.tv_sec % 60, (unsigned)tv.tv_usec); + return G.timestr; +} + +static void open_mdev_log(const char *seq, unsigned my_pid) +{ + int logfd = open("mdev.log", O_WRONLY | O_APPEND); + if (logfd >= 0) { + xmove_fd(logfd, STDERR_FILENO); + G.verbose = 2; + applet_name = xasprintf("%s[%s]", applet_name, seq ? seq : utoa(my_pid)); + } +} + +/* If it exists, does /dev/mdev.seq match $SEQNUM? + * If it does not match, earlier mdev is running + * in parallel, and we need to wait. + * Active mdev pokes us with SIGCHLD to check the new file. + */ +static int +wait_for_seqfile(const char *seq) +{ + /* We time out after 2 sec */ + static const struct timespec ts = { 0, 32*1000*1000 }; + int timeout = 2000 / 32; + int seq_fd = -1; + int do_once = 1; + sigset_t set_CHLD; + + sigemptyset(&set_CHLD); + sigaddset(&set_CHLD, SIGCHLD); + sigprocmask(SIG_BLOCK, &set_CHLD, NULL); + + for (;;) { + int seqlen; + char seqbuf[sizeof(int)*3 + 2]; + + if (seq_fd < 0) { + seq_fd = open("mdev.seq", O_RDWR); + if (seq_fd < 0) + break; + } + seqlen = pread(seq_fd, seqbuf, sizeof(seqbuf) - 1, 0); + if (seqlen < 0) { + close(seq_fd); + seq_fd = -1; + break; + } + seqbuf[seqlen] = '\0'; + if (seqbuf[0] == '\n') { + /* seed file: write out seq ASAP */ + xwrite_str(seq_fd, seq); + xlseek(seq_fd, 0, SEEK_SET); + dbg2("first seq written"); + break; + } + if (strcmp(seq, seqbuf) == 0) { + /* correct idx */ + break; + } + if (do_once) { + dbg2("%s waiting for '%s'", curtime(), seqbuf); + do_once = 0; + } + if (sigtimedwait(&set_CHLD, NULL, &ts) >= 0) { + dbg3("woken up"); + continue; /* don't decrement timeout! */ + } + if (--timeout == 0) { + dbg1("%s waiting for '%s'", "timed out", seqbuf); + break; + } + } + sigprocmask(SIG_UNBLOCK, &set_CHLD, NULL); + return seq_fd; +} + +static void signal_mdevs(unsigned my_pid) +{ + procps_status_t* p = NULL; + while ((p = procps_scan(p, PSSCAN_ARGV0)) != NULL) { + if (p->pid != my_pid + && p->argv0 + && strcmp(bb_basename(p->argv0), "mdev") == 0 + ) { + kill(p->pid, SIGCHLD); + } + } +} + int mdev_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int mdev_main(int argc UNUSED_PARAM, char **argv) { @@ -840,8 +1051,8 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) xchdir("/dev"); if (argv[1] && strcmp(argv[1], "-s") == 0) { - /* Scan: - * mdev -s + /* + * Scan: mdev -s */ struct stat st; @@ -853,6 +1064,8 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) G.root_major = major(st.st_dev); G.root_minor = minor(st.st_dev); + putenv((char*)"ACTION=add"); + /* ACTION_FOLLOWLINKS is needed since in newer kernels * /sys/block/loop* (for example) are symlinks to dirs, * not real directories. @@ -878,11 +1091,13 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) char *action; char *env_devname; char *env_devpath; + unsigned my_pid; + int seq_fd; smalluint op; /* Hotplug: * env ACTION=... DEVPATH=... SUBSYSTEM=... [SEQNUM=...] mdev - * ACTION can be "add" or "remove" + * ACTION can be "add", "remove", "change" * DEVPATH is like "/block/sda" or "/class/input/mice" */ action = getenv("ACTION"); @@ -893,39 +1108,20 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) if (!action || !env_devpath /*|| !G.subsystem*/) bb_show_usage(); fw = getenv("FIRMWARE"); - /* If it exists, does /dev/mdev.seq match $SEQNUM? - * If it does not match, earlier mdev is running - * in parallel, and we need to wait */ seq = getenv("SEQNUM"); - if (seq) { - int timeout = 2000 / 32; /* 2000 msec */ - do { - int seqlen; - char seqbuf[sizeof(int)*3 + 2]; - - seqlen = open_read_close("mdev.seq", seqbuf, sizeof(seqbuf) - 1); - if (seqlen < 0) { - seq = NULL; - break; - } - seqbuf[seqlen] = '\0'; - if (seqbuf[0] == '\n' /* seed file? */ - || strcmp(seq, seqbuf) == 0 /* correct idx? */ - ) { - break; - } - usleep(32*1000); - } while (--timeout); - } - { - int logfd = open("/dev/mdev.log", O_WRONLY | O_APPEND); - if (logfd >= 0) { - xmove_fd(logfd, STDERR_FILENO); - G.verbose = 1; - bb_error_msg("seq: %s action: %s", seq, action); - } - } + my_pid = getpid(); + open_mdev_log(seq, my_pid); + + seq_fd = seq ? wait_for_seqfile(seq) : -1; + + dbg1("%s " + "ACTION:%s SUBSYSTEM:%s DEVNAME:%s DEVPATH:%s" + "%s%s", + curtime(), + action, G.subsystem, env_devname, env_devpath, + fw ? " FW:" : "", fw ? fw : "" + ); snprintf(temp, PATH_MAX, "/sys%s", env_devpath); if (op == OP_remove) { @@ -935,16 +1131,18 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) if (!fw) make_device(env_devname, temp, op); } - else if (op == OP_add) { + else { make_device(env_devname, temp, op); if (ENABLE_FEATURE_MDEV_LOAD_FIRMWARE) { - if (fw) + if (op == OP_add && fw) load_firmware(fw, temp); } } - if (seq) { - xopen_xwrite_close("mdev.seq", utoa(xatou(seq) + 1)); + dbg1("%s exiting", curtime()); + if (seq_fd >= 0) { + xwrite_str(seq_fd, utoa(xatou(seq) + 1)); + signal_mdevs(my_pid); } } diff --git a/util-linux/volume_id/ntfs.c b/util-linux/volume_id/ntfs.c index 7b2612f01..0444e546b 100644 --- a/util-linux/volume_id/ntfs.c +++ b/util-linux/volume_id/ntfs.c @@ -150,7 +150,7 @@ int FAST_FUNC volume_id_probe_ntfs(struct volume_id *id /*,uint64_t off*/) attr = (struct file_attribute*) &buf[attr_off]; attr_type = le32_to_cpu(attr->type); - attr_len = le16_to_cpu(attr->len); + attr_len = le32_to_cpu(attr->len); val_off = le16_to_cpu(attr->value_offset); val_len = le32_to_cpu(attr->value_len); attr_off += attr_len; -- 2.25.1