Compatibility fixes:
No binary (build failed)
—
(log yok)
| @@ -110,6 +110,7 @@ CONFIG_BUNZIP2=y | |
| CONFIG_BZIP2=y | |
| CONFIG_CPIO=y | |
| CONFIG_FEATURE_CPIO_O=y | |
| + | CONFIG_FEATURE_CPIO_P=y |
| CONFIG_DPKG=y | |
| CONFIG_DPKG_DEB=y | |
| CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY=y | |
| @@ -110,6 +110,13 @@ config FEATURE_CPIO_O | |
| This implementation of cpio can create cpio archives in the "newc" | |
| format only. | |
| + | config FEATURE_CPIO_P |
| + | bool "Support for passthrough mode" |
| + | default n |
| + | depends on FEATURE_CPIO_O |
| + | help |
| + | Passthrough mode. Rarely used. |
| + | |
| config DPKG | |
| bool "dpkg" | |
| default n | |
| @@ -259,8 +259,9 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) | |
| CPIO_OPT_FILE = (1 << 4), | |
| CPIO_OPT_CREATE_LEADING_DIR = (1 << 5), | |
| CPIO_OPT_PRESERVE_MTIME = (1 << 6), | |
| - | CPIO_OPT_CREATE = (1 << 7), |
| - | CPIO_OPT_FORMAT = (1 << 8), |
| + | CPIO_OPT_CREATE = (1 << 7) * ENABLE_FEATURE_CPIO_O, |
| + | CPIO_OPT_FORMAT = (1 << 8) * ENABLE_FEATURE_CPIO_O, |
| + | CPIO_OPT_PASSTHROUGH = (1 << 9) * ENABLE_FEATURE_CPIO_P, |
| }; | |
| #if ENABLE_GETOPT_LONG | |
| @@ -270,21 +271,66 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) | |
| #if ENABLE_FEATURE_CPIO_O | |
| "create\0" No_argument "o" | |
| "format\0" Required_argument "H" | |
| + | #if ENABLE_FEATURE_CPIO_P |
| + | "pass-through\0" No_argument "p" |
| + | #endif |
| #endif | |
| ; | |
| #endif | |
| - | /* Initialize */ |
| - | archive_handle = init_handle(); |
| - | archive_handle->src_fd = STDIN_FILENO; |
| - | archive_handle->seek = seek_by_read; |
| - | archive_handle->ah_flags = ARCHIVE_EXTRACT_NEWER; |
| - | |
| - | #if ENABLE_FEATURE_CPIO_O |
| - | opt = getopt32(argv, "ituvF:dmoH:", &cpio_filename, &cpio_fmt); |
| + | /* As of now we do not enforce this: */ |
| + | /* -i,-t,-o,-p are mutually exclusive */ |
| + | /* -u,-d,-m make sense only with -i or -p */ |
| + | /* -F makes sense only with -o */ |
| + | #if !ENABLE_FEATURE_CPIO_O |
| + | opt = getopt32(argv, "ituvF:dm", &cpio_filename); |
| + | #else |
| + | opt = getopt32(argv, "ituvF:dmoH:" USE_FEATURE_CPIO_P("p"), &cpio_filename, &cpio_fmt); |
| + | if (opt & CPIO_OPT_PASSTHROUGH) { |
| + | pid_t pid; |
| + | struct fd_pair pp; |
| + | if (argv[optind] == NULL) |
| + | bb_show_usage(); |
| + | if (opt & CPIO_OPT_CREATE_LEADING_DIR) |
| + | mkdir(argv[optind], 0777); |
| + | /* Crude existence check: |
| + | * close(xopen(argv[optind], O_RDONLY | O_DIRECTORY)); |
| + | * We can also xopen, fstat, IS_DIR, later fchdir. |
| + | * This would check for existence earlier and cleaner. |
| + | * As it stands now, if we fail xchdir later, |
| + | * child dies on EPIPE, unless it caught |
| + | * a diffrerent problem earlier. |
| + | * This is good enough for now. |
| + | */ |
| + | #if !BB_MMU |
| + | pp.rd = 3; |
| + | pp.wr = 4; |
| + | if (!re_execed) { |
| + | close(3); |
| + | close(4); |
| + | xpiped_pair(pp); |
| + | } |
| + | #else |
| + | xpiped_pair(pp); |
| + | #endif |
| + | pid = fork_or_rexec(argv); |
| + | if (pid == 0) { /* child */ |
| + | close(pp.rd); |
| + | xmove_fd(pp.wr, STDOUT_FILENO); |
| + | goto dump; |
| + | } |
| + | /* parent */ |
| + | xchdir(argv[optind++]); |
| + | close(pp.wr); |
| + | xmove_fd(pp.rd, STDIN_FILENO); |
| + | opt &= ~CPIO_OPT_PASSTHROUGH; |
| + | opt |= CPIO_OPT_EXTRACT; |
| + | goto skip; |
| + | } |
| + | /* -o */ |
| if (opt & CPIO_OPT_CREATE) { | |
| - | if (*cpio_fmt != 'n') |
| + | if (*cpio_fmt != 'n') /* we _require_ "-H newc" */ |
| bb_show_usage(); | |
| if (opt & CPIO_OPT_FILE) { | |
| fclose(stdout); | |
| @@ -292,13 +338,18 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) | |
| /* Paranoia: I don't trust libc that much */ | |
| xdup2(fileno(stdout), STDOUT_FILENO); | |
| } | |
| + | dump: |
| return cpio_o(); | |
| } | |
| - | #else |
| - | opt = getopt32(argv, "ituvF:dm", &cpio_filename); |
| + | skip: |
| #endif | |
| argv += optind; | |
| + | archive_handle = init_handle(); |
| + | archive_handle->src_fd = STDIN_FILENO; |
| + | archive_handle->seek = seek_by_read; |
| + | archive_handle->ah_flags = ARCHIVE_EXTRACT_NEWER; |
| + | |
| /* One of either extract or test options must be given */ | |
| if ((opt & (CPIO_OPT_TEST | CPIO_OPT_EXTRACT)) == 0) { | |
| bb_show_usage(); | |
| @@ -306,9 +357,7 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) | |
| if (opt & CPIO_OPT_TEST) { | |
| /* if both extract and test options are given, ignore extract option */ | |
| - | if (opt & CPIO_OPT_EXTRACT) { |
| - | opt &= ~CPIO_OPT_EXTRACT; |
| - | } |
| + | opt &= ~CPIO_OPT_EXTRACT; |
| archive_handle->action_header = header_list; | |
| } | |
| if (opt & CPIO_OPT_EXTRACT) { | |
| @@ -381,9 +381,11 @@ static int FAST_FUNC fileAction(const char *fileName, | |
| { | |
| int i; | |
| #if ENABLE_FEATURE_FIND_MAXDEPTH | |
| - | int maxdepth = (int)(ptrdiff_t)userData; |
| + | #define minmaxdepth ((int*)userData) |
| - | if (depth > maxdepth) return SKIP; |
| + | if (depth < minmaxdepth[0]) return TRUE; |
| + | if (depth > minmaxdepth[1]) return SKIP; |
| + | #undef minmaxdepth |
| #endif | |
| #if ENABLE_FEATURE_FIND_XDEV | |
| @@ -812,19 +814,21 @@ int find_main(int argc, char **argv) | |
| static const char options[] ALIGN1 = | |
| "-follow\0" | |
| USE_FEATURE_FIND_XDEV( "-xdev\0" ) | |
| - | USE_FEATURE_FIND_MAXDEPTH("-maxdepth\0") |
| + | USE_FEATURE_FIND_MAXDEPTH("-mindepth\0""-maxdepth\0") |
| ; | |
| enum { | |
| OPT_FOLLOW, | |
| USE_FEATURE_FIND_XDEV( OPT_XDEV ,) | |
| - | USE_FEATURE_FIND_MAXDEPTH(OPT_MAXDEPTH,) |
| + | USE_FEATURE_FIND_MAXDEPTH(OPT_MINDEPTH,) |
| }; | |
| char *arg; | |
| char **argp; | |
| int i, firstopt, status = EXIT_SUCCESS; | |
| #if ENABLE_FEATURE_FIND_MAXDEPTH | |
| - | int maxdepth = INT_MAX; |
| + | int minmaxdepth[2] = { 0, INT_MAX }; |
| + | #else |
| + | #define minmaxdepth NULL |
| #endif | |
| for (firstopt = 1; firstopt < argc; firstopt++) { | |
| @@ -875,10 +879,10 @@ USE_FEATURE_FIND_MAXDEPTH(OPT_MAXDEPTH,) | |
| } | |
| #endif | |
| #if ENABLE_FEATURE_FIND_MAXDEPTH | |
| - | if (opt == OPT_MAXDEPTH) { |
| + | if (opt == OPT_MINDEPTH || opt == OPT_MINDEPTH + 1) { |
| if (!argp[1]) | |
| bb_show_usage(); | |
| - | maxdepth = xatoi_u(argp[1]); |
| + | minmaxdepth[opt - OPT_MINDEPTH] = xatoi_u(argp[1]); |
| argp[0] = (char*)"-a"; | |
| argp[1] = (char*)"-a"; | |
| argp++; | |
| @@ -895,9 +899,7 @@ USE_FEATURE_FIND_MAXDEPTH(OPT_MAXDEPTH,) | |
| fileAction, /* file action */ | |
| fileAction, /* dir action */ | |
| #if ENABLE_FEATURE_FIND_MAXDEPTH | |
| - | /* double cast suppresses |
| - | * "cast to ptr from int of different size" */ |
| - | (void*)(ptrdiff_t)maxdepth,/* user data */ |
| + | minmaxdepth, /* user data */ |
| #else | |
| NULL, /* user data */ | |
| #endif | |
| @@ -28,7 +28,9 @@ | |
| USE_FEATURE_GREP_CONTEXT("A:B:C:") \ | |
| USE_FEATURE_GREP_EGREP_ALIAS("E") \ | |
| USE_DESKTOP("w") \ | |
| + | USE_EXTRA_COMPAT("z") \ |
| "aI" | |
| + | |
| /* ignored: -a "assume all files to be text" */ | |
| /* ignored: -I "assume binary files have no matches" */ | |
| @@ -54,6 +56,7 @@ enum { | |
| USE_FEATURE_GREP_CONTEXT( OPTBIT_C ,) /* -C NUM: -A and -B combined */ | |
| USE_FEATURE_GREP_EGREP_ALIAS(OPTBIT_E ,) /* extended regexp */ | |
| USE_DESKTOP( OPTBIT_w ,) /* whole word match */ | |
| + | USE_EXTRA_COMPAT( OPTBIT_z ,) /* input is NUL terminated */ |
| OPT_l = 1 << OPTBIT_l, | |
| OPT_n = 1 << OPTBIT_n, | |
| OPT_q = 1 << OPTBIT_q, | |
| @@ -75,6 +78,7 @@ enum { | |
| OPT_C = USE_FEATURE_GREP_CONTEXT( (1 << OPTBIT_C)) + 0, | |
| OPT_E = USE_FEATURE_GREP_EGREP_ALIAS((1 << OPTBIT_E)) + 0, | |
| OPT_w = USE_DESKTOP( (1 << OPTBIT_w)) + 0, | |
| + | OPT_z = USE_EXTRA_COMPAT( (1 << OPTBIT_z)) + 0, |
| }; | |
| #define PRINT_FILES_WITH_MATCHES (option_mask32 & OPT_l) | |
| @@ -84,6 +88,7 @@ enum { | |
| #define PRINT_MATCH_COUNTS (option_mask32 & OPT_c) | |
| #define FGREP_FLAG (option_mask32 & OPT_F) | |
| #define PRINT_FILES_WITHOUT_MATCHES (option_mask32 & OPT_L) | |
| + | #define NUL_DELIMITED (option_mask32 & OPT_z) |
| struct globals { | |
| int max_matches; | |
| @@ -186,7 +191,7 @@ static void print_line(const char *line, size_t line_len, int linenum, char deco | |
| puts(line); | |
| #else | |
| fwrite(line, 1, line_len, stdout); | |
| - | putchar('\n'); |
| + | putchar(NUL_DELIMITED ? '\0' : '\n'); |
| #endif | |
| } | |
| } | |
| @@ -197,12 +202,13 @@ static ssize_t FAST_FUNC bb_getline(char **line_ptr, size_t *line_alloc_len, FIL | |
| { | |
| ssize_t res_sz; | |
| char *line; | |
| + | int delim = (NUL_DELIMITED ? '\0' : '\n'); |
| - | res_sz = getline(line_ptr, line_alloc_len, file); |
| + | res_sz = getdelim(line_ptr, line_alloc_len, delim, file); |
| line = *line_ptr; | |
| if (res_sz > 0) { | |
| - | if (line[res_sz - 1] == '\n') |
| + | if (line[res_sz - 1] == delim) |
| line[--res_sz] = '\0'; | |
| } else { | |
| free(line); /* uclibc allocates a buffer even on EOF. WTF? */ | |
| @@ -407,8 +413,11 @@ static int grep_file(FILE *file) | |
| #endif | |
| /* Did we print all context after last requested match? */ | |
| if ((option_mask32 & OPT_m) | |
| - | && !print_n_lines_after && nmatches == max_matches) |
| + | && !print_n_lines_after |
| + | && nmatches == max_matches |
| + | ) { |
| break; | |
| + | } |
| } /* while (read line) */ | |
| /* special-case file post-processing for options where we don't print line | |
| @@ -797,9 +797,9 @@ int run_nofork_applet_prime(struct nofork_save_area *old, int applet_no, char ** | |
| * Both of the above will redirect fd 0,1,2 to /dev/null and drop ctty | |
| * (will do setsid()). | |
| * | |
| - | * forkexit_or_rexec(argv) = bare-bones "fork + parent exits" on MMU, |
| + | * fork_or_rexec(argv) = bare-bones "fork" on MMU, |
| * "vfork + re-exec ourself" on NOMMU. No fd redirection, no setsid(). | |
| - | * Currently used for setsid only. On MMU ignores argv. |
| + | * On MMU ignores argv. |
| * | |
| * Helper for network daemons in foreground mode: | |
| * | |
| @@ -813,14 +813,14 @@ enum { | |
| DAEMON_ONLY_SANITIZE = 8, /* internal use */ | |
| }; | |
| #if BB_MMU | |
| - | void forkexit_or_rexec(void) FAST_FUNC; |
| + | pid_t fork_or_rexec(void) FAST_FUNC; |
| enum { re_execed = 0 }; | |
| - | # define forkexit_or_rexec(argv) forkexit_or_rexec() |
| + | # define fork_or_rexec(argv) fork_or_rexec() |
| # define bb_daemonize_or_rexec(flags, argv) bb_daemonize_or_rexec(flags) | |
| # define bb_daemonize(flags) bb_daemonize_or_rexec(flags, bogus) | |
| #else | |
| void re_exec(char **argv) NORETURN FAST_FUNC; | |
| - | void forkexit_or_rexec(char **argv) FAST_FUNC; |
| + | pid_t fork_or_rexec(char **argv) FAST_FUNC; |
| extern bool re_execed; | |
| int BUG_fork_is_unavailable_on_nommu(void) FAST_FUNC; | |
| int BUG_daemon_is_unavailable_on_nommu(void) FAST_FUNC; | |
| @@ -531,24 +531,29 @@ | |
| "\n -l,-s Create (sym)links" \ | |
| #define cpio_trivial_usage \ | |
| - | "-[dim" USE_FEATURE_CPIO_O("o") "tuv][F cpiofile]" \ |
| - | USE_FEATURE_CPIO_O( "[H newc]" ) |
| + | "-[ti" USE_FEATURE_CPIO_O("o") USE_FEATURE_CPIO_P("p") "dmvu] [-F FILE]" \ |
| + | USE_FEATURE_CPIO_O( " [-H newc]" ) |
| #define cpio_full_usage "\n\n" \ | |
| "Extract or list files from a cpio archive" \ | |
| USE_FEATURE_CPIO_O( ", or create a cpio archive" ) \ | |
| - | "\n" \ |
| - | "Main operation mode:" \ |
| - | "\n d Make leading directories" \ |
| - | "\n i Extract" \ |
| - | "\n m Preserve mtime" \ |
| + | "\nMain operation mode:" \ |
| + | "\n -t List" \ |
| + | "\n -i Extract" \ |
| USE_FEATURE_CPIO_O( \ | |
| - | "\n o Create" \ |
| - | "\n H newc Define format" \ |
| + | "\n -o Create" \ |
| + | ) \ |
| + | USE_FEATURE_CPIO_P( \ |
| + | "\n -p Passthrough" \ |
| + | ) \ |
| + | "\nOptions:" \ |
| + | "\n -d Make leading directories" \ |
| + | "\n -m Preserve mtime" \ |
| + | "\n -v Verbose" \ |
| + | "\n -u Overwrite" \ |
| + | "\n -F Input file" \ |
| + | USE_FEATURE_CPIO_O( \ |
| + | "\n -H Define format" \ |
| ) \ | |
| - | "\n t List" \ |
| - | "\n v Verbose" \ |
| - | "\n u Unconditional overwrite" \ |
| - | "\n F Input from file" \ |
| #define crond_trivial_usage \ | |
| "-fbS -l N " USE_FEATURE_CROND_D("-d N ") "-L LOGFILE -c DIR" | |
| @@ -1167,6 +1172,7 @@ | |
| USE_FEATURE_FIND_MAXDEPTH( \ | |
| "\n -maxdepth N Descend at most N levels. -maxdepth 0 applies" \ | |
| "\n tests/actions to command line arguments only") \ | |
| + | "\n -mindepth N Do not act on first N levels" \ |
| "\n -name PATTERN File name (w/o directory name) matches PATTERN" \ | |
| "\n -iname PATTERN Case insensitive -name" \ | |
| USE_FEATURE_FIND_PATH( \ | |
| @@ -1425,6 +1431,7 @@ | |
| "eF" \ | |
| USE_FEATURE_GREP_EGREP_ALIAS("E") \ | |
| USE_FEATURE_GREP_CONTEXT("ABC") \ | |
| + | USE_EXTRA_COMPAT("z") \ |
| "] PATTERN [FILEs...]" | |
| #define grep_full_usage "\n\n" \ | |
| "Search for PATTERN in each FILE or standard input\n" \ | |
| @@ -1453,6 +1460,8 @@ | |
| "\n -A Print NUM lines of trailing context" \ | |
| "\n -B Print NUM lines of leading context" \ | |
| "\n -C Print NUM lines of output context") \ | |
| + | USE_EXTRA_COMPAT( \ |
| + | "\n -z Input is NUL terminated") \ |
| #define grep_example_usage \ | |
| "$ grep root /etc/passwd\n" \ | |
| @@ -251,35 +251,33 @@ void FAST_FUNC re_exec(char **argv) | |
| bb_perror_msg_and_die("exec %s", bb_busybox_exec_path); | |
| } | |
| - | void FAST_FUNC forkexit_or_rexec(char **argv) |
| + | pid_t FAST_FUNC fork_or_rexec(char **argv) |
| { | |
| pid_t pid; | |
| /* Maybe we are already re-execed and come here again? */ | |
| if (re_execed) | |
| - | return; |
| + | return 0; /* child */ |
| pid = vfork(); | |
| if (pid < 0) /* wtf? */ | |
| bb_perror_msg_and_die("vfork"); | |
| if (pid) /* parent */ | |
| - | exit(EXIT_SUCCESS); |
| + | return pid; |
| /* child - re-exec ourself */ | |
| re_exec(argv); | |
| } | |
| #else | |
| /* Dance around (void)...*/ | |
| - | #undef forkexit_or_rexec |
| - | void FAST_FUNC forkexit_or_rexec(void) |
| + | #undef fork_or_rexec |
| + | pid_t FAST_FUNC fork_or_rexec(void) |
| { | |
| pid_t pid; | |
| pid = fork(); | |
| if (pid < 0) /* wtf? */ | |
| bb_perror_msg_and_die("fork"); | |
| - | if (pid) /* parent */ |
| - | exit(EXIT_SUCCESS); |
| - | /* child */ |
| + | return pid; |
| } | |
| - | #define forkexit_or_rexec(argv) forkexit_or_rexec() |
| + | #define fork_or_rexec(argv) fork_or_rexec() |
| #endif | |
| /* Due to a #define in libbb.h on MMU systems we actually have 1 argument - | |
| @@ -310,7 +308,8 @@ void FAST_FUNC bb_daemonize_or_rexec(int flags, char **argv) | |
| fd = dup(fd); /* have 0,1,2 open at least to /dev/null */ | |
| if (!(flags & DAEMON_ONLY_SANITIZE)) { | |
| - | forkexit_or_rexec(argv); |
| + | if (fork_or_rexec(argv)) |
| + | exit(EXIT_SUCCESS); /* parent */ |
| /* if daemonizing, make sure we detach from stdio & ctty */ | |
| setsid(); | |
| dup2(fd, 0); | |
| @@ -26,7 +26,8 @@ int setsid_main(int argc UNUSED_PARAM, char **argv) | |
| * Otherwise our PID serves as PGID of some existing process group | |
| * and cannot be used as PGID of a new process group. */ | |
| if (getpgrp() == getpid()) | |
| - | forkexit_or_rexec(argv); |
| + | if (fork_or_rexec(argv)) |
| + | exit(EXIT_SUCCESS); /* parent */ |
| setsid(); /* no error possible */ | |
| @@ -112,6 +112,7 @@ CONFIG_BUNZIP2=y | |
| CONFIG_BZIP2=y | |
| CONFIG_CPIO=y | |
| CONFIG_FEATURE_CPIO_O=y | |
| + | CONFIG_FEATURE_CPIO_P=y |
| # CONFIG_DPKG is not set | |
| # CONFIG_DPKG_DEB is not set | |
| # CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY is not set | |