3 /* main.c - main program and argument processing for cpio.
4 Copyright (C) 1990, 1991, 1992, 2001, 2003, 2004, 2005, 2006
5 Free Software Foundation, Inc.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public
18 License along with this program; if not, write to the Free
19 Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301 USA. */
22 /* Written by Phil Nelson <phil@cs.wwu.edu>,
23 David MacKenzie <djm@gnu.ai.mit.edu>,
24 John Oleynick <juo@klinzhai.rutgers.edu>,
25 and Sergey Poznyakoff <gray@mirddin.farlep.net> */
33 #include <sys/types.h>
40 #include "filetypes.h"
45 #include <rmt-command.h>
48 NO_ABSOLUTE_FILENAMES_OPTION=256,
49 ABSOLUTE_FILENAMES_OPTION,
50 NO_PRESERVE_OWNER_OPTION,
51 ONLY_VERIFY_CRC_OPTION,
52 RENAME_BATCH_FILE_OPTION,
67 const char *argp_program_version = "cpio (" PACKAGE_NAME ") " VERSION;
68 const char *argp_program_bug_address = "<" PACKAGE_BUGREPORT ">";
69 static char doc[] = N_("GNU `cpio' copies files to and from archives\n\
72 # Copy files named in name-list to the archive\n\
73 cpio -o < name-list [> archive]\n\
74 # Extract files from the archive\n\
75 cpio -i [< archive]\n\
76 # Copy files named in name-list to destination-directory\n\
77 cpio -p destination-directory < name-list\n");
79 /* Print usage error message and exit with error. */
81 #define CHECK_USAGE(cond, opt, mode_opt) \
83 ERROR((PAXEXIT_FAILURE, 0, _("%s is meaningless with %s"), opt, mode_opt));
85 static struct argp_option options[] = {
89 N_("Main operation mode:"), GRID },
91 N_("Create the archive (run in copy-out mode)"), GRID },
92 {"extract", 'i', 0, 0,
93 N_("Extract files from an archive (run in copy-in mode)"), GRID },
94 {"pass-through", 'p', 0, 0,
95 N_("Run in copy-pass mode"), GRID },
97 N_("Print a table of contents of the input"), GRID },
103 N_("Operation modifiers valid in any mode:"), GRID },
105 {"file", 'F', N_("[[USER@]HOST:]FILE-NAME"), 0,
106 N_("Use this FILE-NAME instead of standard input or output. Optional USER and HOST specify the user and host names in case of a remote archive"), GRID+1 },
107 {"force-local", FORCE_LOCAL_OPTION, 0, 0,
108 N_("Archive file is local, even if its name contains colons"), GRID+1 },
109 {"format", 'H', N_("FORMAT"), 0,
110 N_("Use given archive FORMAT"), GRID+1 },
112 N_("Set the I/O block size to 5120 bytes"), GRID+1 },
113 {"block-size", BLOCK_SIZE_OPTION, N_("BLOCK-SIZE"), 0,
114 N_("Set the I/O block size to BLOCK-SIZE * 512 bytes"), GRID+1 },
116 N_("Use the old portable (ASCII) archive format"), GRID+1 },
117 {"dot", 'V', NULL, 0,
118 N_("Print a \".\" for each file processed"), GRID+1 },
119 {"io-size", 'C', N_("NUMBER"), 0,
120 N_("Set the I/O block size to the given NUMBER of bytes"), GRID+1 },
121 {"message", 'M', N_("STRING"), 0,
122 N_("Print STRING when the end of a volume of the backup media is reached"),
124 {"nonmatching", 'f', 0, 0,
125 N_("Only copy files that do not match any of the given patterns"), GRID+1 },
126 {"numeric-uid-gid", 'n', 0, 0,
127 N_("In the verbose table of contents listing, show numeric UID and GID"),
129 {"rsh-command", RSH_COMMAND_OPTION, N_("COMMAND"), 0,
130 N_("Use remote COMMAND instead of rsh"), GRID+1 },
131 {"quiet", QUIET_OPTION, NULL, 0,
132 N_("Do not print the number of blocks copied"), GRID+1 },
133 {"verbose", 'v', NULL, 0,
134 N_("Verbosely list the files processed"), GRID+1 },
136 {"debug", DEBUG_OPTION, NULL, 0,
137 N_("Enable debugging info"), GRID+1 },
139 {"warning", 'W', N_("FLAG"), 0,
140 N_("Control warning display. Currently FLAG is one of 'none', 'truncate', 'all'. Multiple options accumulate."), GRID+1 },
146 N_("Operation modifiers valid only in copy-in mode:"), GRID },
147 {"pattern-file", 'E', N_("FILE"), 0,
148 N_("Read additional patterns specifying filenames to extract or list from FILE"), 210},
149 {"absolute-filenames", ABSOLUTE_FILENAMES_OPTION, 0, 0,
150 N_("do not strip leading file name components that contain \"..\" and leading slashes from file names"), 210},
151 {"only-verify-crc", ONLY_VERIFY_CRC_OPTION, 0, 0,
152 N_("When reading a CRC format archive, only verify the CRC's of each file in the archive, don't actually extract the files"), 210},
153 {"rename", 'r', 0, 0,
154 N_("Interactively rename files"), GRID+1 },
155 {"rename-batch-file", RENAME_BATCH_FILE_OPTION, N_("FILE"), OPTION_HIDDEN,
157 {"swap", 'b', NULL, 0,
158 N_("Swap both halfwords of words and bytes of halfwords in the data. Equivalent to -sS"), GRID+1 },
159 {"swap-bytes", 's', NULL, 0,
160 N_("Swap the bytes of each halfword in the files"), GRID+1 },
161 {"swap-halfwords", 'S', NULL, 0,
162 N_("Swap the halfwords of each word (4 bytes) in the files"),
164 {"to-stdout", TO_STDOUT_OPTION, NULL, 0,
165 N_("Extract files to standard output"), GRID+1 },
171 N_("Operation modifiers valid only in copy-out mode:"), GRID },
172 {"append", 'A', 0, 0,
173 N_("Append to an existing archive."), GRID+1 },
174 {NULL, 'O', N_("[[USER@]HOST:]FILE-NAME"), 0,
175 N_("Archive filename to use instead of standard output. Optional USER and HOST specify the user and host names in case of a remote archive"), GRID+1 },
181 N_("Operation modifiers valid only in copy-pass mode:"), GRID},
183 N_("Link files instead of copying them, when possible"), GRID+1 },
190 N_("Operation modifiers valid in copy-in and copy-out modes:"), GRID },
191 {"absolute-filenames", ABSOLUTE_FILENAMES_OPTION, 0, 0,
192 N_("Do not strip file system prefix components from the file names"),
194 {"no-absolute-filenames", NO_ABSOLUTE_FILENAMES_OPTION, 0, 0,
195 N_("Create all files relative to the current directory"), GRID+1 },
200 N_("Operation modifiers valid in copy-out and copy-pass modes:"), GRID },
202 N_("A list of filenames is terminated by a null character instead of a newline"), GRID+1 },
203 {NULL, 'I', N_("[[USER@]HOST:]FILE-NAME"), 0,
204 N_("Archive filename to use instead of standard input. Optional USER and HOST specify the user and host names in case of a remote archive"), GRID+1 },
205 {"dereference", 'L', 0, 0,
206 N_("Dereference symbolic links (copy the files that they point to instead of copying the links)."), GRID+1 },
207 {"owner", 'R', N_("[USER][:.][GROUP]"), 0,
208 N_("Set the ownership of all files created to the specified USER and/or GROUP"), GRID+1 },
209 {"reset-access-time", 'a', NULL, 0,
210 N_("Reset the access times of files after reading them"), GRID+1 },
216 N_("Operation modifiers valid in copy-in and copy-pass modes:"), GRID },
217 {"preserve-modification-time", 'm', 0, 0,
218 N_("Retain previous file modification times when creating files"), GRID+1 },
219 {"make-directories", 'd', 0, 0,
220 N_("Create leading directories where needed"), GRID+1 },
221 {"no-preserve-owner", NO_PRESERVE_OWNER_OPTION, 0, 0,
222 N_("Do not change the ownership of the files"), GRID+1 },
223 {"unconditional", 'u', NULL, 0,
224 N_("Replace all files unconditionally"), GRID+1 },
225 {"sparse", SPARSE_OPTION, NULL, 0,
226 N_("Write files with large blocks of zeros as sparse files"), GRID+1 },
232 N_("Informative options:"), GRID },
234 {"help", '?', 0, 0, N_("Give this help list"), -1},
235 {"usage", USAGE_OPTION, 0, 0, N_("Give a short usage message"), -1},
236 {"license", LICENSE_OPTION, 0, 0, N_("Print license and exit"), -1},
237 {"version", VERSION_OPTION, 0, 0, N_("Print program version"), -1},
238 /* FIXME -V (--dot) conflicts with the default short option for
240 {"HANG", HANG_OPTION, "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
241 N_("hang for SECS seconds (default 3600)"), 0},
246 static char *input_archive_name = 0;
247 static char *output_archive_name = 0;
252 printf ("%s (%s) %s\n%s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION,
253 "Copyright (C) 2004 Free Software Foundation, Inc.\n");
254 printf (_(" GNU cpio is free software; you can redistribute it and/or modify\n"
255 " it under the terms of the GNU General Public License as published by\n"
256 " the Free Software Foundation; either version 2 of the License, or\n"
257 " (at your option) any later version.\n"
259 " GNU cpio is distributed in the hope that it will be useful,\n"
260 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
261 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
262 " GNU General Public License for more details.\n"
264 " You should have received a copy of the GNU General Public License\n"
265 " along with GNU cpio; if not, write to the Free Software Foundation,\n"
266 " Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n\n"));
271 warn_control (char *arg)
273 static struct warn_tab {
277 { "none", CPIO_WARN_ALL },
278 { "truncate", CPIO_WARN_TRUNCATE },
279 { "all", CPIO_WARN_ALL },
285 if (strcmp (arg, "none") == 0)
291 if (strlen (arg) > 2 && memcmp (arg, "no-", 3) == 0)
294 for (wt = warn_tab; wt->name; wt++)
295 if (strcmp (arg + offset, wt->name) == 0)
298 warn_option &= ~wt->flag;
300 warn_option |= wt->flag;
308 parse_opt (int key, char *arg, struct argp_state *state)
310 static volatile int _argp_hang;
313 case '0': /* Read null-terminated filenames. */
317 case 'a': /* Reset access times. */
318 reset_time_flag = true;
321 case 'A': /* Append to the archive. */
325 case 'b': /* Swap bytes and halfwords. */
326 swap_bytes_flag = true;
327 swap_halfwords_flag = true;
330 case 'B': /* Set block size to 5120. */
331 io_block_size = 5120;
334 case BLOCK_SIZE_OPTION: /* --block-size */
335 io_block_size = atoi (arg);
336 if (io_block_size < 1)
337 error (2, 0, _("invalid block size"));
338 io_block_size *= 512;
341 case 'c': /* Use the old portable ASCII format. */
342 if (archive_format != arf_unknown)
343 error (0, EXIT_FAILURE, _("Archive format multiply defined"));
345 archive_format = arf_newascii; /* -H newc. */
347 archive_format = arf_oldascii; /* -H odc. */
351 case 'C': /* Block size. */
352 io_block_size = atoi (arg);
353 if (io_block_size < 1)
354 error (2, 0, _("invalid block size"));
357 case 'd': /* Create directories where needed. */
358 create_dir_flag = true;
361 case 'f': /* Only copy files not matching patterns. */
362 copy_matching_files = false;
365 case 'E': /* Pattern file name. */
366 pattern_file_name = arg;
369 case 'F': /* Archive file name. */
373 case 'H': /* Header format name. */
374 if (archive_format != arf_unknown)
375 error (PAXEXIT_FAILURE, 0, _("Archive format multiply defined"));
376 if (!strcasecmp (arg, "crc"))
377 archive_format = arf_crcascii;
378 else if (!strcasecmp (arg, "newc"))
379 archive_format = arf_newascii;
380 else if (!strcasecmp (arg, "odc"))
381 archive_format = arf_oldascii;
382 else if (!strcasecmp (arg, "bin"))
383 archive_format = arf_binary;
384 else if (!strcasecmp (arg, "ustar"))
385 archive_format = arf_ustar;
386 else if (!strcasecmp (arg, "tar"))
387 archive_format = arf_tar;
388 else if (!strcasecmp (arg, "hpodc"))
389 archive_format = arf_hpoldascii;
390 else if (!strcasecmp (arg, "hpbin"))
391 archive_format = arf_hpbinary;
394 invalid archive format `%s'; valid formats are:\n\
395 crc newc odc bin ustar tar (all-caps also recognized)"), arg);
398 case 'i': /* Copy-in mode. */
399 if (copy_function != 0)
400 error (PAXEXIT_FAILURE, 0, _("Mode already defined"));
401 copy_function = process_copy_in;
404 case 'I': /* Input archive file name. */
405 input_archive_name = arg;
408 case 'k': /* Handle corrupted archives. We always handle
409 corrupted archives, but recognize this
410 option for compatability. */
413 case 'l': /* Link files when possible. */
417 case 'L': /* Dereference symbolic links. */
421 case 'm': /* Retain previous file modify times. */
422 retain_time_flag = true;
425 case 'M': /* New media message. */
426 set_new_media_message (arg);
429 case 'n': /* Long list owner and group as numbers. */
433 case NO_ABSOLUTE_FILENAMES_OPTION: /* --no-absolute-filenames */
434 abs_paths_flag = false;
437 case ABSOLUTE_FILENAMES_OPTION: /* --absolute-filenames */
438 abs_paths_flag = true;
441 case NO_PRESERVE_OWNER_OPTION: /* --no-preserve-owner */
442 if (set_owner_flag || set_group_flag)
443 error (PAXEXIT_FAILURE, 0,
444 _("--no-preserve-owner cannot be used with --owner"));
445 no_chown_flag = true;
448 case 'o': /* Copy-out mode. */
449 if (copy_function != 0)
450 error (PAXEXIT_FAILURE, 0, _("Mode already defined"));
451 copy_function = process_copy_out;
454 case 'O': /* Output archive file name. */
455 output_archive_name = arg;
458 case ONLY_VERIFY_CRC_OPTION:
459 only_verify_crc_flag = true;
462 case 'p': /* Copy-pass mode. */
463 if (copy_function != 0)
464 error (PAXEXIT_FAILURE, 0, _("Mode already defined"));
465 copy_function = process_copy_pass;
468 case RSH_COMMAND_OPTION:
469 rsh_command_option = arg;
472 case 'r': /* Interactively rename. */
476 case RENAME_BATCH_FILE_OPTION:
477 rename_batch_file = arg;
484 case 'R': /* Set the owner. */
486 error (PAXEXIT_FAILURE, 0,
487 _("--owner cannot be used with --no-preserve-owner"));
492 e = parse_user_spec (arg, &set_owner, &set_group, &u, &g);
494 error (PAXEXIT_FAILURE, 0, "%s: %s", arg, e);
498 set_owner_flag = true;
503 set_group_flag = true;
508 case 's': /* Swap bytes. */
509 swap_bytes_flag = true;
512 case 'S': /* Swap halfwords. */
513 swap_halfwords_flag = true;
516 case 't': /* Only print a list. */
520 case 'u': /* Replace all! Unconditionally! */
521 unconditional_flag = true;
524 case 'v': /* Verbose! */
528 case 'V': /* Print `.' for each file. */
533 if (warn_control (arg))
534 argp_error (state, _("Invalid value for --warning option: %s"), arg);
541 case FORCE_LOCAL_OPTION:
542 force_local_option = 1;
551 case TO_STDOUT_OPTION:
552 to_stdout_option = true;
556 _argp_hang = atoi (arg ? arg : "3600");
557 while (_argp_hang-- > 0)
562 argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP);
566 argp_state_help (state, state->out_stream,
567 ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
571 fprintf (state->out_stream, "%s\n", argp_program_version);
579 return ARGP_ERR_UNKNOWN;
584 static struct argp argp = {
587 N_("[destination-directory]"),
594 /* Process the arguments. Set all options and set up the copy pass
595 directory or the copy in patterns. */
598 process_args (int argc, char *argv[])
600 void (*copy_in) (); /* Work around for pcc bug. */
605 error (PAXEXIT_FAILURE, 0,
606 _("You must specify one of -oipt options.\nTry `%s --help' or `%s --usage' for more information.\n"),
607 program_name, program_name);
611 if (argp_parse (&argp, argc, argv, ARGP_IN_ORDER|ARGP_NO_HELP, &index, NULL))
614 /* Do error checking and look at other args. */
616 if (copy_function == 0)
619 copy_function = process_copy_in;
621 error (PAXEXIT_FAILURE, 0,
622 _("You must specify one of -oipt options.\nTry `%s --help' or `%s --usage' for more information.\n"),
623 program_name, program_name);
626 /* Work around for pcc bug. */
627 copy_in = process_copy_in;
628 copy_out = process_copy_out;
630 if (copy_function == copy_in)
633 CHECK_USAGE(link_flag, "--link", "--extract");
634 CHECK_USAGE(reset_time_flag, "--reset", "--extract");
635 CHECK_USAGE(xstat != lstat, "--dereference", "--extract");
636 CHECK_USAGE(append_flag, "--append", "--extract");
637 CHECK_USAGE(output_archive_name, "-O", "--extract");
638 if (to_stdout_option)
640 CHECK_USAGE(create_dir_flag, "--make-directories", "--to-stdout");
641 CHECK_USAGE(rename_flag, "--rename", "--to-stdout");
642 CHECK_USAGE(no_chown_flag, "--no-preserve-owner", "--to-stdout");
643 CHECK_USAGE(set_owner_flag||set_group_flag, "--owner", "--to-stdout");
644 CHECK_USAGE(retain_time_flag, "--preserve-modification-time",
648 if (archive_name && input_archive_name)
649 error (PAXEXIT_FAILURE, 0,
650 _("Both -I and -F are used in copy-in mode"));
652 if (archive_format == arf_crcascii)
654 num_patterns = argc - index;
655 save_patterns = &argv[index];
656 if (input_archive_name)
657 archive_name = input_archive_name;
659 else if (copy_function == copy_out)
662 error (PAXEXIT_FAILURE, 0, _("Too many arguments"));
665 CHECK_USAGE(create_dir_flag, "--make-directories", "--create");
666 CHECK_USAGE(rename_flag, "--rename", "--create");
667 CHECK_USAGE(table_flag, "--list", "--create");
668 CHECK_USAGE(unconditional_flag, "--unconditional", "--create");
669 CHECK_USAGE(link_flag, "--link", "--create");
670 CHECK_USAGE(sparse_flag, "--sparse", "--create");
671 CHECK_USAGE(retain_time_flag, "--preserve-modification-time",
673 CHECK_USAGE(no_chown_flag, "--no-preserve-owner", "--create");
674 CHECK_USAGE(swap_bytes_flag, "--swap-bytes (--swap)", "--create");
675 CHECK_USAGE(swap_halfwords_flag, "--swap-halfwords (--swap)",
677 CHECK_USAGE(to_stdout_option, "--to-stdout", "--create");
679 if (append_flag && !(archive_name || output_archive_name))
680 error (PAXEXIT_FAILURE, 0,
681 _("--append is used but no archive file name is given (use -F or -O options)"));
683 CHECK_USAGE(rename_batch_file, "--rename-batch-file", "--create");
684 CHECK_USAGE(abs_paths_flag, "--absolute-pathnames", "--create");
685 CHECK_USAGE(input_archive_name, "-I", "--create");
686 if (archive_name && output_archive_name)
687 error (PAXEXIT_FAILURE, 0,
688 _("Both -O and -F are used in copy-out mode"));
690 if (archive_format == arf_unknown)
691 archive_format = arf_binary;
692 if (output_archive_name)
693 archive_name = output_archive_name;
698 if (index < argc - 1)
699 error (PAXEXIT_FAILURE, 0, _("Too many arguments"));
700 else if (index > argc - 1)
701 error (PAXEXIT_FAILURE, 0, _("Not enough arguments"));
703 if (archive_format != arf_unknown)
704 error (PAXEXIT_FAILURE, 0,
705 _("Archive format is not specified in copy-pass mode (use --format option)"));
707 CHECK_USAGE(swap_bytes_flag, "--swap-bytes (--swap)", "--pass-through");
708 CHECK_USAGE(swap_halfwords_flag, "--swap-halfwords (--swap)",
710 CHECK_USAGE(table_flag, "--list", "--pass-through");
711 CHECK_USAGE(rename_flag, "--rename", "--pass-through");
712 CHECK_USAGE(append_flag, "--append", "--pass-through");
713 CHECK_USAGE(rename_batch_file, "--rename-batch-file", "--pass-through");
714 CHECK_USAGE(abs_paths_flag, "--absolute-pathnames",
716 CHECK_USAGE(to_stdout_option, "--to-stdout", "--pass-through");
718 directory_name = argv[index];
723 if (copy_function != copy_in && copy_function != copy_out)
724 error (PAXEXIT_FAILURE, 0,
725 _("-F can be used only with --create or --extract"));
726 archive_des = open_archive (archive_name);
728 error (PAXEXIT_FAILURE, errno, _("Cannot open %s"),
729 quotearg_colon (archive_name));
732 /* Prevent SysV non-root users from giving away files inadvertantly.
733 This happens automatically on BSD, where only root can give
735 if (set_owner_flag == false && set_group_flag == false && geteuid ())
736 no_chown_flag = true;
739 /* Initialize the input and output buffers to their proper size and
740 initialize all variables associated with the input and output
744 initialize_buffers ()
746 int in_buf_size, out_buf_size;
748 if (copy_function == process_copy_in)
750 /* Make sure the input buffer can always hold 2 blocks and that it
751 is big enough to hold 1 tar record (512 bytes) even if it
752 is not aligned on a block boundary. The extra buffer space
753 is needed by process_copyin and peek_in_buf to automatically
754 figure out what kind of archive it is reading. */
755 if (io_block_size >= 512)
756 in_buf_size = 2 * io_block_size;
759 out_buf_size = DISK_IO_BLOCK_SIZE;
761 else if (copy_function == process_copy_out)
763 in_buf_size = DISK_IO_BLOCK_SIZE;
764 out_buf_size = io_block_size;
768 in_buf_size = DISK_IO_BLOCK_SIZE;
769 out_buf_size = DISK_IO_BLOCK_SIZE;
772 input_buffer = (char *) xmalloc (in_buf_size);
773 in_buff = input_buffer;
774 input_buffer_size = in_buf_size;
778 output_buffer = (char *) xmalloc (out_buf_size);
779 out_buff = output_buffer;
785 main (int argc, char *argv[])
787 setlocale (LC_ALL, "");
788 bindtextdomain (PACKAGE, LOCALEDIR);
789 textdomain (PACKAGE);
791 program_name = argv[0];
793 process_args (argc, argv);
796 initialize_buffers ();
800 if (archive_des >= 0 && rmtclose (archive_des) == -1)
801 error (1, errno, _("error closing archive"));