diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | archival/libunarchive/get_header_tar.c | 4 | ||||
-rw-r--r-- | archival/tar.c | 6 | ||||
-rw-r--r-- | coreutils/tail.c | 2 | ||||
-rw-r--r-- | shell/ash.c | 189 | ||||
-rw-r--r-- | shell/ash_test/ash-read/read_ifs.right | 7 | ||||
-rwxr-xr-x | shell/ash_test/ash-read/read_ifs.tests | 7 | ||||
-rw-r--r-- | shell/hush.c | 95 | ||||
-rw-r--r-- | shell/hush_test/hush-parsing/starquoted2.right | 1 | ||||
-rwxr-xr-x | shell/hush_test/hush-parsing/starquoted2.tests | 3 | ||||
-rw-r--r-- | util-linux/volume_id/get_devname.c | 4 |
11 files changed, 239 insertions, 81 deletions
@@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 13 -SUBLEVEL = 3 +SUBLEVEL = 4 EXTRAVERSION = NAME = Unnamed diff --git a/archival/libunarchive/get_header_tar.c b/archival/libunarchive/get_header_tar.c index bf0f92b..4c063b3 100644 --- a/archival/libunarchive/get_header_tar.c +++ b/archival/libunarchive/get_header_tar.c @@ -91,7 +91,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) again_after_align: -#if ENABLE_DESKTOP +#if ENABLE_DESKTOP || ENABLE_FEATURE_TAR_AUTODETECT /* to prevent misdetection of bz2 sig */ *(uint32_t*)(&tar) = 0; i = full_read(archive_handle->src_fd, &tar, 512); @@ -142,7 +142,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) #if ENABLE_FEATURE_TAR_AUTODETECT char FAST_FUNC (*get_header_ptr)(archive_handle_t *); - USE_DESKTOP(autodetect:) + autodetect: /* tar gz/bz autodetect: check for gz/bz2 magic. * If we see the magic, and it is the very first block, * we can switch to get_header_tar_gz/bz2/lzma(). diff --git a/archival/tar.c b/archival/tar.c index 47cc39c..b6beede 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -934,8 +934,10 @@ int tar_main(int argc UNUSED_PARAM, char **argv) tar_handle->src_fd = fileno(tar_stream); tar_handle->seek = seek_by_read; } else { - if (ENABLE_FEATURE_TAR_AUTODETECT && flags == O_RDONLY) { - get_header_ptr = get_header_tar; + if (ENABLE_FEATURE_TAR_AUTODETECT + && get_header_ptr == get_header_tar + && flags == O_RDONLY + ) { tar_handle->src_fd = open_zipped(tar_filename); if (tar_handle->src_fd < 0) bb_perror_msg_and_die("can't open '%s'", tar_filename); diff --git a/coreutils/tail.c b/coreutils/tail.c index 2505fc3..5dae2d3 100644 --- a/coreutils/tail.c +++ b/coreutils/tail.c @@ -104,7 +104,7 @@ int tail_main(int argc, char **argv) if (argv[1] && (argv[1][0] == '+' || argv[1][0] == '-') && isdigit(argv[1][1]) ) { - count = eat_num(&argv[1][1]); + count = eat_num(argv[1]); argv++; argc--; } diff --git a/shell/ash.c b/shell/ash.c index d6fd388..e3f79fc 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -30,7 +30,7 @@ */ /* - * The follow should be set to reflect the type of system you have: + * The following should be set to reflect the type of system you have: * JOBS -> 1 if you have Berkeley job control, 0 otherwise. * define SYSV if you are running under System V. * define DEBUG=1 to compile in debugging ('set -o debug' to turn on) @@ -40,6 +40,11 @@ * a quit signal will generate a core dump. */ #define DEBUG 0 +/* Tweak debug output verbosity here */ +#define DEBUG_TIME 0 +#define DEBUG_PID 1 +#define DEBUG_SIG 1 + #define PROFILE 0 #define IFS_BROKEN @@ -47,9 +52,9 @@ #define JOBS ENABLE_ASH_JOB_CONTROL #if DEBUG -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif +# ifndef _GNU_SOURCE +# define _GNU_SOURCE +# endif #endif #include "busybox.h" /* for applet_names */ @@ -57,15 +62,15 @@ #include <setjmp.h> #include <fnmatch.h> #if JOBS || ENABLE_ASH_READ_NCHARS -#include <termios.h> +# include <termios.h> #endif #ifndef PIPE_BUF -#define PIPE_BUF 4096 /* amount of buffering in a pipe */ +# define PIPE_BUF 4096 /* amount of buffering in a pipe */ #endif #if defined(__uClinux__) -#error "Do not even bother, ash will not run on uClinux" +# error "Do not even bother, ash will not run on uClinux" #endif @@ -76,14 +81,6 @@ #define CMDTABLESIZE 31 /* should be prime */ -/* ============ Misc helpers */ - -#define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0) - -/* C99 say: "char" declaration may be signed or unsigned default */ -#define signed_char2int(sc) ((int)((signed char)sc)) - - /* ============ Shell options */ static const char *const optletters_optnames[] = { @@ -245,7 +242,30 @@ extern struct globals_misc *const ash_ptr_to_globals_misc; } while (0) +/* ============ DEBUG */ +#if DEBUG +static void trace_printf(const char *fmt, ...); +static void trace_vprintf(const char *fmt, va_list va); +# define TRACE(param) trace_printf param +# define TRACEV(param) trace_vprintf param +# define close(f) do { \ + int dfd = (f); \ + if (close(dfd) < 0) \ + bb_error_msg("bug on %d: closing %d(%x)", \ + __LINE__, dfd, dfd); \ +} while (0) +#else +# define TRACE(param) +# define TRACEV(param) +#endif + + /* ============ Utility functions */ +#define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0) + +/* C99 say: "char" declaration may be signed or unsigned by default */ +#define signed_char2int(sc) ((int)(signed char)(sc)) + static int isdigit_str9(const char *str) { int maxlen = 9 + 1; /* max 9 digits: 999999999 */ @@ -284,6 +304,12 @@ raise_exception(int e) exception = e; longjmp(exception_handler->loc, 1); } +#if DEBUG +#define raise_exception(e) do { \ + TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \ + raise_exception(e); \ +} while (0) +#endif /* * Called from trap.c when a SIGINT is received. (If the user specifies @@ -316,6 +342,12 @@ raise_interrupt(void) raise_exception(i); /* NOTREACHED */ } +#if DEBUG +#define raise_interrupt() do { \ + TRACE(("raising interrupt on line %d\n", __LINE__)); \ + raise_interrupt(); \ +} while (0) +#endif #if ENABLE_ASH_OPTIMIZE_FOR_SIZE static void @@ -334,7 +366,9 @@ force_int_on(void) raise_interrupt(); } #define FORCE_INT_ON force_int_on() -#else + +#else /* !ASH_OPTIMIZE_FOR_SIZE */ + #define INT_ON do { \ xbarrier(); \ if (--suppressint == 0 && intpending) \ @@ -346,7 +380,7 @@ force_int_on(void) if (intpending) \ raise_interrupt(); \ } while (0) -#endif /* ASH_OPTIMIZE_FOR_SIZE */ +#endif /* !ASH_OPTIMIZE_FOR_SIZE */ #define SAVE_INT(v) ((v) = suppressint) @@ -376,7 +410,6 @@ static void onsig(int signo) { gotsig[signo - 1] = 1; - pendingsig = signo; if (/* exsig || */ (signo == SIGINT && !trap[SIGINT])) { if (!suppressint) { @@ -384,6 +417,8 @@ onsig(int signo) raise_interrupt(); /* does not return */ } intpending = 1; + } else { + pendingsig = signo; } } @@ -684,6 +719,12 @@ trace_printf(const char *fmt, ...) if (debug != 1) return; + if (DEBUG_TIME) + fprintf(tracefile, "%u ", (int) time(NULL)); + if (DEBUG_PID) + fprintf(tracefile, "[%u] ", (int) getpid()); + if (DEBUG_SIG) + fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pendingsig, intpending, suppressint); va_start(va, fmt); vfprintf(tracefile, fmt, va); va_end(va); @@ -694,6 +735,12 @@ trace_vprintf(const char *fmt, va_list va) { if (debug != 1) return; + if (DEBUG_TIME) + fprintf(tracefile, "%u ", (int) time(NULL)); + if (DEBUG_PID) + fprintf(tracefile, "[%u] ", (int) getpid()); + if (DEBUG_SIG) + fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pendingsig, intpending, suppressint); vfprintf(tracefile, fmt, va); } @@ -998,14 +1045,6 @@ showtree(union node *n) shtree(n, 1, NULL, stdout); } -#define TRACE(param) trace_printf param -#define TRACEV(param) trace_vprintf param - -#else - -#define TRACE(param) -#define TRACEV(param) - #endif /* DEBUG */ @@ -3779,7 +3818,7 @@ dowait(int wait_flags, struct job *job) * NB: _not_ safe_waitpid, we need to detect EINTR */ pid = waitpid(-1, &status, (doing_jobctl ? (wait_flags | WUNTRACED) : wait_flags)); - TRACE(("wait returns pid=%d, status=0x%x\n", pid, status)); + TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n", pid, status, errno, strerror(errno))); if (pid <= 0) { /* If we were doing blocking wait and (probably) got EINTR, @@ -5031,7 +5070,9 @@ redirect(union node *redir, int flags) if (newfd < 0) { /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */ if (redir->ndup.dupfd < 0) { /* "fd>&-" */ - close(fd); + /* Don't want to trigger debugging */ + if (fd != -1) + close(fd); } else { copyfd(redir->ndup.dupfd, fd | COPYFD_EXACT); } @@ -5084,7 +5125,7 @@ popredir(int drop, int restore) /*close(fd);*/ copyfd(copy, fd | COPYFD_EXACT); } - close(copy); + close(copy & ~COPYFD_RESTORE); } } redirlist = rp->next; @@ -7871,20 +7912,30 @@ dotrap(void) pendingsig = 0; xbarrier(); + TRACE(("dotrap entered\n")); for (i = 1, q = gotsig; i < NSIG; i++, q++) { if (!*q) continue; - *q = '\0'; p = trap[i]; + /* non-trapped SIGINT is handled separately by raise_interrupt, + * don't upset it by resetting gotsig[SIGINT-1] */ + if (i == SIGINT && !p) + continue; + + TRACE(("sig %d is active, will run handler '%s'\n", i, p)); + *q = '\0'; if (!p) continue; skip = evalstring(p, SKIPEVAL); exitstatus = savestatus; - if (skip) + if (skip) { + TRACE(("dotrap returns %d\n", skip)); return skip; + } } + TRACE(("dotrap returns 0\n")); return 0; } @@ -7906,28 +7957,32 @@ static void prehash(union node *); static void evaltree(union node *n, int flags) { - struct jmploc *volatile savehandler = exception_handler; struct jmploc jmploc; int checkexit = 0; void (*evalfn)(union node *, int); int status; + int int_level; + + SAVE_INT(int_level); if (n == NULL) { TRACE(("evaltree(NULL) called\n")); goto out1; } - TRACE(("pid %d, evaltree(%p: %d, %d) called\n", - getpid(), n, n->type, flags)); + TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags)); exception_handler = &jmploc; { int err = setjmp(jmploc.loc); if (err) { /* if it was a signal, check for trap handlers */ - if (exception == EXSIG) + if (exception == EXSIG) { + TRACE(("exception %d (EXSIG) in evaltree, err=%d\n", exception, err)); goto out; + } /* continue on the way out */ + TRACE(("exception %d in evaltree, propagating err=%d\n", exception, err)); exception_handler = savehandler; longjmp(exception_handler->loc, err); } @@ -8010,7 +8065,8 @@ evaltree(union node *n, int flags) if (exitstatus == 0) { n = n->nif.ifpart; goto evaln; - } else if (n->nif.elsepart) { + } + if (n->nif.elsepart) { n = n->nif.elsepart; goto evaln; } @@ -8036,6 +8092,9 @@ evaltree(union node *n, int flags) exexit: raise_exception(EXEXIT); } + + RESTORE_INT(int_level); + TRACE(("leaving evaltree (no interrupts)\n")); } #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3) @@ -8281,7 +8340,9 @@ evalpipe(union node *n, int flags) if (prevfd >= 0) close(prevfd); prevfd = pip[0]; - close(pip[1]); + /* Don't want to trigger debugging */ + if (pip[1] != -1) + close(pip[1]); } if (n->npipe.pipe_backgnd == 0) { exitstatus = waitforjob(jp); @@ -8913,6 +8974,7 @@ evalcommand(union node *cmd, int flags) if (forkshell(jp, cmd, FORK_FG) != 0) { exitstatus = waitforjob(jp); INT_ON; + TRACE(("forked child exited with %d\n", exitstatus)); break; } FORCE_INT_ON; @@ -12391,7 +12453,7 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) #endif status = 0; - startword = 1; + startword = 2; backslash = 0; #if ENABLE_ASH_READ_TIMEOUT if (timeout) /* NB: ensuring end_ms is nonzero */ @@ -12399,6 +12461,8 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) #endif STARTSTACKSTR(p); do { + const char *is_ifs; + #if ENABLE_ASH_READ_TIMEOUT if (end_ms) { struct pollfd pfd[1]; @@ -12428,25 +12492,34 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) continue; } if (!rflag && c == '\\') { - backslash++; + backslash = 1; continue; } if (c == '\n') break; - if (startword && *ifs == ' ' && strchr(ifs, c)) { - continue; + is_ifs = strchr(ifs, c); + if (startword && is_ifs) { + if (isspace(c)) + continue; + /* non-space ifs char */ + startword--; + if (startword == 1) /* first one? */ + continue; } startword = 0; - if (ap[1] != NULL && strchr(ifs, c) != NULL) { + if (ap[1] != NULL && is_ifs) { + const char *beg; STACKSTRNUL(p); - setvar(*ap, stackblock(), 0); + beg = stackblock(); + setvar(*ap, beg, 0); ap++; - startword = 1; + /* can we skip one non-space ifs? (2: yes) */ + startword = isspace(c) ? 2 : 1; STARTSTACKSTR(p); - } else { - put: - STPUTC(c, p); + continue; } + put: + STPUTC(c, p); } /* end of do {} while: */ #if ENABLE_ASH_READ_NCHARS @@ -12460,8 +12533,8 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) #endif STACKSTRNUL(p); - /* Remove trailing blanks */ - while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL) + /* Remove trailing space ifs chars */ + while ((char *)stackblock() <= --p && isspace(*p) && strchr(ifs, *p) != NULL) *p = '\0'; setvar(*ap, stackblock(), 0); while (*++ap != NULL) @@ -13640,7 +13713,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv) exception_handler = &jmploc; #if DEBUG opentrace(); - trace_puts("Shell args: "); + TRACE(("Shell args: ")); trace_puts_args(argv); #endif rootpid = getpid(); @@ -13692,8 +13765,14 @@ int ash_main(int argc UNUSED_PARAM, char **argv) } state3: state = 4; - if (minusc) + if (minusc) { + /* evalstring pushes parsefile stack. + * Ensure we don't falsely claim that 0 (stdin) + * is one of stacked source fds */ + if (!sflag) + g_parsefile->fd = -1; evalstring(minusc, 0); + } if (sflag || minusc == NULL) { #if ENABLE_FEATURE_EDITING_SAVEHISTORY @@ -13720,14 +13799,6 @@ int ash_main(int argc UNUSED_PARAM, char **argv) /* NOTREACHED */ } -#if DEBUG -const char *applet_name = "debug stuff usage"; -int main(int argc, char **argv) -{ - return ash_main(argc, argv); -} -#endif - /*- * Copyright (c) 1989, 1991, 1993, 1994 diff --git a/shell/ash_test/ash-read/read_ifs.right b/shell/ash_test/ash-read/read_ifs.right new file mode 100644 index 0000000..027ecd1 --- /dev/null +++ b/shell/ash_test/ash-read/read_ifs.right @@ -0,0 +1,7 @@ +.a. .b. .c. +.a. .b. .c. +.a. .. .b,c. +.a. .. .b,c. +.a. .. .c. +.a. .. .c. .d. +.a. .. .b,c,d , ,. diff --git a/shell/ash_test/ash-read/read_ifs.tests b/shell/ash_test/ash-read/read_ifs.tests new file mode 100755 index 0000000..cf7cd93 --- /dev/null +++ b/shell/ash_test/ash-read/read_ifs.tests @@ -0,0 +1,7 @@ +printf 'a\t\tb\tc\n' | ( IFS=$(printf "\t") read a b c; echo ".$a. .$b. .$c." ) +printf 'a\t\tb\tc\n' | ( IFS=$(printf " \t") read a b c; echo ".$a. .$b. .$c." ) +printf 'a,,b,c\n' | ( IFS="," read a b c; echo ".$a. .$b. .$c." ) +printf 'a,,b,c\n' | ( IFS=" ," read a b c; echo ".$a. .$b. .$c." ) +printf 'a ,, c\n' | ( IFS=" ," read a b c; echo ".$a. .$b. .$c." ) +printf 'a ,, c d\n' | ( IFS=" ," read a b c d; echo ".$a. .$b. .$c. .$d." ) +printf ' a,,b,c,d , ,\n' | ( IFS=" ," read a b c; echo ".$a. .$b. .$c." ) diff --git a/shell/hush.c b/shell/hush.c index 4212729..9e7b105 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -458,8 +458,11 @@ struct globals { smallint fake_mode; /* these three support $?, $#, and $1 */ smalluint last_return_code; - char **global_argv; + /* is global_argv and global_argv[1..n] malloced? (note: not [0]) */ + smalluint global_args_malloced; + /* how many non-NULL argv's we have. NB: $# + 1 */ int global_argc; + char **global_argv; #if ENABLE_HUSH_LOOPS unsigned depth_break_continue; unsigned depth_of_loop; @@ -633,7 +636,7 @@ static char *unbackslash(char *src) return dst; } -static char **add_strings_to_strings(char **strings, char **add) +static char **add_strings_to_strings(char **strings, char **add, int need_to_dup) { int i; unsigned count1; @@ -658,7 +661,7 @@ static char **add_strings_to_strings(char **strings, char **add) v[count1 + count2] = NULL; i = count2; while (--i >= 0) - v[count1 + i] = add[i]; + v[count1 + i] = (need_to_dup ? xstrdup(add[i]) : add[i]); return v; } @@ -667,7 +670,7 @@ static char **add_string_to_strings(char **strings, char *add) char *v[2]; v[0] = add; v[1] = NULL; - return add_strings_to_strings(strings, v); + return add_strings_to_strings(strings, v, /*dup:*/ 0); } static void putenv_all(char **strings) @@ -1213,8 +1216,13 @@ static int o_glob(o_string *o, int n) * Otherwise, just finish current list[] and start new */ static int o_save_ptr(o_string *o, int n) { - if (o->o_glob) - return o_glob(o, n); /* o_save_ptr_helper is inside */ + if (o->o_glob) { /* if globbing is requested */ + /* If o->has_empty_slot, list[n] was already globbed + * (if it was requested back then when it was filled) + * so don't do that again! */ + if (!o->has_empty_slot) + return o_glob(o, n); /* o_save_ptr_helper is inside */ + } return o_save_ptr_helper(o, n); } @@ -4279,6 +4287,11 @@ int hush_main(int argc, char **argv) switch (opt) { case 'c': G.global_argv = argv + optind; + if (!argv[optind]) { + /* -c 'script' (no params): prevent empty $0 */ + *--G.global_argv = argv[0]; + optind--; + } /* else -c 'script' PAR0 PAR1: $0 is PAR0 */ G.global_argc = argc - optind; opt = parse_and_run_string(optarg, 0 /* parse_flag */); goto final_return; @@ -4639,17 +4652,68 @@ static int builtin_read(char **argv) return set_local_var(string, 0); } -/* built-in 'set [VAR=value]' handler */ +/* built-in 'set' handler + * SUSv3 says: + * set [-abCefmnuvx] [-h] [-o option] [argument...] + * set [+abCefmnuvx] [+h] [+o option] [argument...] + * set -- [argument...] + * set -o + * set +o + * Implementations shall support the options in both their hyphen and + * plus-sign forms. These options can also be specified as options to sh. + * Examples: + * Write out all variables and their values: set + * Set $1, $2, and $3 and set "$#" to 3: set c a b + * Turn on the -x and -v options: set -xv + * Unset all positional parameters: set -- + * Set $1 to the value of x, even if it begins with '-' or '+': set -- "$x" + * Set the positional parameters to the expansion of x, even if x expands + * with a leading '-' or '+': set -- $x + * + * So far, we only support "set -- [argument...]" by ignoring all options + * (also, "-o option" will be mishandled by taking "option" as parameter #1). + */ static int builtin_set(char **argv) { - char *temp = argv[1]; struct variable *e; + char **pp; + char *arg = *++argv; - if (temp == NULL) + if (arg == NULL) { for (e = G.top_var; e; e = e->next) puts(e->varstr); - else - set_local_var(xstrdup(temp), 0); + } else { + /* NB: G.global_argv[0] ($0) is never freed/changed */ + + if (G.global_args_malloced) { + pp = G.global_argv; + while (*++pp) + free(*pp); + G.global_argv[1] = NULL; + } else { + G.global_args_malloced = 1; + pp = xzalloc(sizeof(pp[0]) * 2); + pp[0] = G.global_argv[0]; /* retain $0 */ + G.global_argv = pp; + } + do { + if (arg[0] == '+') + continue; + if (arg[0] != '-') + break; + if (arg[1] == '-' && arg[2] == '\0') { + argv++; + break; + } + } while ((arg = *++argv) != NULL); + /* Now argv[0] is 1st argument */ + + /* This realloc's G.global_argv */ + G.global_argv = pp = add_strings_to_strings(G.global_argv, argv, /*dup:*/ 1); + G.global_argc = 1; + while (*++pp) + G.global_argc++; + } return EXIT_SUCCESS; } @@ -4661,9 +4725,14 @@ static int builtin_shift(char **argv) n = atoi(argv[1]); } if (n >= 0 && n < G.global_argc) { - G.global_argv[n] = G.global_argv[0]; + if (G.global_args_malloced) { + int m = 1; + while (m <= n) + free(G.global_argv[m++]); + } G.global_argc -= n; - G.global_argv += n; + memmove(&G.global_argv[1], &G.global_argv[n+1], + G.global_argc * sizeof(G.global_argv[0])); return EXIT_SUCCESS; } return EXIT_FAILURE; diff --git a/shell/hush_test/hush-parsing/starquoted2.right b/shell/hush_test/hush-parsing/starquoted2.right index 46f2436..f4624da 100644 --- a/shell/hush_test/hush-parsing/starquoted2.right +++ b/shell/hush_test/hush-parsing/starquoted2.right @@ -1,2 +1,3 @@ Should be printed Should be printed +Empty: diff --git a/shell/hush_test/hush-parsing/starquoted2.tests b/shell/hush_test/hush-parsing/starquoted2.tests index 782d71b..3475ede 100755 --- a/shell/hush_test/hush-parsing/starquoted2.tests +++ b/shell/hush_test/hush-parsing/starquoted2.tests @@ -12,3 +12,6 @@ for a in "$@"""; do echo Should not be printed; done for a in """$@"; do echo Should not be printed; done for a in """$@"''"$@"''; do echo Should not be printed; done for a in ""; do echo Should be printed; done + +# Bug 207: "$@" expands to nothing, and we erroneously glob "%s\\n" twice: +printf "Empty:%s\\n" "$@" diff --git a/util-linux/volume_id/get_devname.c b/util-linux/volume_id/get_devname.c index d82808f..4408c24 100644 --- a/util-linux/volume_id/get_devname.c +++ b/util-linux/volume_id/get_devname.c @@ -223,13 +223,11 @@ void display_uuid_cache(void) char *get_devname_from_label(const char *spec) { struct uuidCache_s *uc; - int spec_len = strlen(spec); uuidcache_init(); uc = uuidCache; while (uc) { -// FIXME: empty label ("LABEL=") matches anything??! - if (uc->label[0] && strncmp(spec, uc->label, spec_len) == 0) { + if (uc->label[0] && strcmp(spec, uc->label) == 0) { return xstrdup(uc->device); } uc = uc->next; |