Compatibility fixes:
grep: support -z find: support --mindepth together +45 bytes cpio: support -p (configurable, +230 bytes) libbb: tweaks for cpio
This commit is contained in:
parent
0b28103cc7
commit
83518d18a3
@ -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;
|
||||
}
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user