aboutsummaryrefslogtreecommitdiff
path: root/archival/cpio.c
diff options
context:
space:
mode:
Diffstat (limited to 'archival/cpio.c')
-rw-r--r--archival/cpio.c81
1 files changed, 65 insertions, 16 deletions
diff --git a/archival/cpio.c b/archival/cpio.c
index 1c30d89a8..929d544ff 100644
--- a/archival/cpio.c
+++ b/archival/cpio.c
@@ -259,8 +259,9 @@ int cpio_main(int argc UNUSED_PARAM, char **argv)
259 CPIO_OPT_FILE = (1 << 4), 259 CPIO_OPT_FILE = (1 << 4),
260 CPIO_OPT_CREATE_LEADING_DIR = (1 << 5), 260 CPIO_OPT_CREATE_LEADING_DIR = (1 << 5),
261 CPIO_OPT_PRESERVE_MTIME = (1 << 6), 261 CPIO_OPT_PRESERVE_MTIME = (1 << 6),
262 CPIO_OPT_CREATE = (1 << 7), 262 CPIO_OPT_CREATE = (1 << 7) * ENABLE_FEATURE_CPIO_O,
263 CPIO_OPT_FORMAT = (1 << 8), 263 CPIO_OPT_FORMAT = (1 << 8) * ENABLE_FEATURE_CPIO_O,
264 CPIO_OPT_PASSTHROUGH = (1 << 9) * ENABLE_FEATURE_CPIO_P,
264 }; 265 };
265 266
266#if ENABLE_GETOPT_LONG 267#if ENABLE_GETOPT_LONG
@@ -270,21 +271,66 @@ int cpio_main(int argc UNUSED_PARAM, char **argv)
270#if ENABLE_FEATURE_CPIO_O 271#if ENABLE_FEATURE_CPIO_O
271 "create\0" No_argument "o" 272 "create\0" No_argument "o"
272 "format\0" Required_argument "H" 273 "format\0" Required_argument "H"
274#if ENABLE_FEATURE_CPIO_P
275 "pass-through\0" No_argument "p"
276#endif
273#endif 277#endif
274 ; 278 ;
275#endif 279#endif
276 280
277 /* Initialize */ 281 /* As of now we do not enforce this: */
278 archive_handle = init_handle(); 282 /* -i,-t,-o,-p are mutually exclusive */
279 archive_handle->src_fd = STDIN_FILENO; 283 /* -u,-d,-m make sense only with -i or -p */
280 archive_handle->seek = seek_by_read; 284 /* -F makes sense only with -o */
281 archive_handle->ah_flags = ARCHIVE_EXTRACT_NEWER; 285#if !ENABLE_FEATURE_CPIO_O
282 286 opt = getopt32(argv, "ituvF:dm", &cpio_filename);
283#if ENABLE_FEATURE_CPIO_O 287#else
284 opt = getopt32(argv, "ituvF:dmoH:", &cpio_filename, &cpio_fmt); 288 opt = getopt32(argv, "ituvF:dmoH:" USE_FEATURE_CPIO_P("p"), &cpio_filename, &cpio_fmt);
289 if (opt & CPIO_OPT_PASSTHROUGH) {
290 pid_t pid;
291 struct fd_pair pp;
285 292
293 if (argv[optind] == NULL)
294 bb_show_usage();
295 if (opt & CPIO_OPT_CREATE_LEADING_DIR)
296 mkdir(argv[optind], 0777);
297 /* Crude existence check:
298 * close(xopen(argv[optind], O_RDONLY | O_DIRECTORY));
299 * We can also xopen, fstat, IS_DIR, later fchdir.
300 * This would check for existence earlier and cleaner.
301 * As it stands now, if we fail xchdir later,
302 * child dies on EPIPE, unless it caught
303 * a diffrerent problem earlier.
304 * This is good enough for now.
305 */
306#if !BB_MMU
307 pp.rd = 3;
308 pp.wr = 4;
309 if (!re_execed) {
310 close(3);
311 close(4);
312 xpiped_pair(pp);
313 }
314#else
315 xpiped_pair(pp);
316#endif
317 pid = fork_or_rexec(argv);
318 if (pid == 0) { /* child */
319 close(pp.rd);
320 xmove_fd(pp.wr, STDOUT_FILENO);
321 goto dump;
322 }
323 /* parent */
324 xchdir(argv[optind++]);
325 close(pp.wr);
326 xmove_fd(pp.rd, STDIN_FILENO);
327 opt &= ~CPIO_OPT_PASSTHROUGH;
328 opt |= CPIO_OPT_EXTRACT;
329 goto skip;
330 }
331 /* -o */
286 if (opt & CPIO_OPT_CREATE) { 332 if (opt & CPIO_OPT_CREATE) {
287 if (*cpio_fmt != 'n') 333 if (*cpio_fmt != 'n') /* we _require_ "-H newc" */
288 bb_show_usage(); 334 bb_show_usage();
289 if (opt & CPIO_OPT_FILE) { 335 if (opt & CPIO_OPT_FILE) {
290 fclose(stdout); 336 fclose(stdout);
@@ -292,13 +338,18 @@ int cpio_main(int argc UNUSED_PARAM, char **argv)
292 /* Paranoia: I don't trust libc that much */ 338 /* Paranoia: I don't trust libc that much */
293 xdup2(fileno(stdout), STDOUT_FILENO); 339 xdup2(fileno(stdout), STDOUT_FILENO);
294 } 340 }
341 dump:
295 return cpio_o(); 342 return cpio_o();
296 } 343 }
297#else 344 skip:
298 opt = getopt32(argv, "ituvF:dm", &cpio_filename);
299#endif 345#endif
300 argv += optind; 346 argv += optind;
301 347
348 archive_handle = init_handle();
349 archive_handle->src_fd = STDIN_FILENO;
350 archive_handle->seek = seek_by_read;
351 archive_handle->ah_flags = ARCHIVE_EXTRACT_NEWER;
352
302 /* One of either extract or test options must be given */ 353 /* One of either extract or test options must be given */
303 if ((opt & (CPIO_OPT_TEST | CPIO_OPT_EXTRACT)) == 0) { 354 if ((opt & (CPIO_OPT_TEST | CPIO_OPT_EXTRACT)) == 0) {
304 bb_show_usage(); 355 bb_show_usage();
@@ -306,9 +357,7 @@ int cpio_main(int argc UNUSED_PARAM, char **argv)
306 357
307 if (opt & CPIO_OPT_TEST) { 358 if (opt & CPIO_OPT_TEST) {
308 /* if both extract and test options are given, ignore extract option */ 359 /* if both extract and test options are given, ignore extract option */
309 if (opt & CPIO_OPT_EXTRACT) { 360 opt &= ~CPIO_OPT_EXTRACT;
310 opt &= ~CPIO_OPT_EXTRACT;
311 }
312 archive_handle->action_header = header_list; 361 archive_handle->action_header = header_list;
313 } 362 }
314 if (opt & CPIO_OPT_EXTRACT) { 363 if (opt & CPIO_OPT_EXTRACT) {