1 /* main.c - main program and argument processing for cpio.
2 Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
18 /* Written by Phil Nelson <phil@cs.wwu.edu>,
19 David MacKenzie <djm@gnu.ai.mit.edu>,
20 and John Oleynick <juo@klinzhai.rutgers.edu>. */
22 /* $FreeBSD: src/contrib/cpio/main.c,v 1.3 1999/09/15 01:47:13 peter Exp $ */
26 #include <sys/types.h>
28 #ifdef HAVE_SYS_PARAM_H
29 #include <sys/param.h>
31 #if (defined(BSD) && (BSD >= 199306))
34 #include "filetypes.h"
41 struct option long_opts[] =
44 {"append", 0, 0, 'A'},
45 {"block-size", 1, 0, 130},
46 {"create", 0, 0, 'o'},
47 {"dereference", 0, 0, 'L'},
49 {"extract", 0, 0, 'i'},
51 {"force-local", 0, &f_force_local, 1},
52 {"format", 1, 0, 'H'},
54 {"io-size", 1, 0, 'C'},
55 {"link", 0, &link_flag, TRUE},
56 {"list", 0, &table_flag, TRUE},
57 {"make-directories", 0, &create_dir_flag, TRUE},
58 {"message", 1, 0, 'M'},
59 {"no-absolute-filenames", 0, 0, 136},
60 {"no-preserve-owner", 0, 0, 134},
61 {"nonmatching", 0, ©_matching_files, FALSE},
62 {"numeric-uid-gid", 0, &numeric_uid, TRUE},
63 {"only-verify-crc", 0, 0, 139},
65 {"pass-through", 0, 0, 'p'},
66 {"pattern-file", 1, 0, 'E'},
67 {"preserve-modification-time", 0, &retain_time_flag, TRUE},
68 {"rename", 0, &rename_flag, TRUE},
69 {"rename-batch-file", 1, 0, 137},
71 {"sparse", 0, 0, 135},
73 {"swap-bytes", 0, 0, 's'},
74 {"swap-halfwords", 0, 0, 'S'},
75 {"reset-access-time", 0, &reset_time_flag, TRUE},
76 {"unconditional", 0, &unconditional_flag, TRUE},
77 {"verbose", 0, &verbose_flag, TRUE},
78 {"version", 0, 0, 131},
80 {"debug", 0, &debug_flag, TRUE},
85 /* Print usage message and exit with error. */
93 Usage: %s {-o|--create} [-0acvABLV] [-C bytes] [-H format] [-M message]\n\
94 [-O [[user@]host:]archive] [-F [[user@]host:]archive]\n\
95 [--file=[[user@]host:]archive] [--format=format] [--message=message]\n\
96 [--null] [--reset-access-time] [--verbose] [--dot] [--append]\n\
97 [--block-size=blocks] [--dereference] [--io-size=bytes] [--quiet]\n\
98 [--force-local] [--help] [--version] < name-list [> archive]\n", program_name);
100 %s {-i|--extract} [-bcdfmnrtsuvBSV] [-C bytes] [-E file] [-H format]\n\
101 [-M message] [-R [user][:.][group]] [-I [[user@]host:]archive]\n\
102 [-F [[user@]host:]archive] [--file=[[user@]host:]archive]\n\
103 [--make-directories] [--nonmatching] [--preserve-modification-time]\n\
104 [--numeric-uid-gid] [--rename] [--list] [--swap-bytes] [--swap] [--dot]\n\
105 [--unconditional] [--verbose] [--block-size=blocks] [--swap-halfwords]\n\
106 [--io-size=bytes] [--pattern-file=file] [--format=format]\n\
107 [--owner=[user][:.][group]] [--no-preserve-owner] [--message=message]\n\
108 [--force-local] [--no-absolute-filenames] [--sparse] [--only-verify-crc]\n\
109 [--quiet] [--help] [--version] [pattern...] [< archive]\n",
112 %s {-p|--pass-through} [-0adlmuvLV] [-R [user][:.][group]]\n\
113 [--null] [--reset-access-time] [--make-directories] [--link] [--quiet]\n\
114 [--preserve-modification-time] [--unconditional] [--verbose] [--dot]\n\
115 [--dereference] [--owner=[user][:.][group]] [--no-preserve-owner]\n\
116 [--sparse] [--help] [--version] destination-directory < name-list\n", program_name);
120 /* Process the arguments. Set all options and set up the copy pass
121 directory or the copy in patterns. */
124 process_args (argc, argv)
128 extern char *version_string;
129 void (*copy_in) (); /* Work around for pcc bug. */
132 char *input_archive_name = 0;
133 char *output_archive_name = 0;
140 while ((c = getopt_long (argc, argv,
141 "0aAbBcC:dfE:F:H:iI:lLmM:noO:prR:sStuvVz",
142 long_opts, (int *) 0)) != -1)
146 case 0: /* A long option that just sets a flag. */
149 case '0': /* Read null-terminated filenames. */
153 case 'a': /* Reset access times. */
154 reset_time_flag = TRUE;
157 case 'A': /* Append to the archive. */
161 case 'b': /* Swap bytes and halfwords. */
162 swap_bytes_flag = TRUE;
163 swap_halfwords_flag = TRUE;
166 case 'B': /* Set block size to 5120. */
167 io_block_size = 5120;
170 case 130: /* --block-size */
171 io_block_size = atoi (optarg);
172 if (io_block_size < 1)
173 error (2, 0, "invalid block size");
174 io_block_size *= 512;
177 case 'c': /* Use the old portable ASCII format. */
178 if (archive_format != arf_unknown)
181 archive_format = arf_newascii; /* -H newc. */
183 archive_format = arf_oldascii; /* -H odc. */
187 case 'C': /* Block size. */
188 io_block_size = atoi (optarg);
189 if (io_block_size < 1)
190 error (2, 0, "invalid block size");
193 case 'd': /* Create directories where needed. */
194 create_dir_flag = TRUE;
197 case 'f': /* Only copy files not matching patterns. */
198 copy_matching_files = FALSE;
201 case 'E': /* Pattern file name. */
202 pattern_file_name = optarg;
205 case 'F': /* Archive file name. */
206 archive_name = optarg;
209 case 'H': /* Header format name. */
210 if (archive_format != arf_unknown)
212 if (!strcmp (optarg, "crc") || !strcmp (optarg, "CRC"))
213 archive_format = arf_crcascii;
214 else if (!strcmp (optarg, "newc") || !strcmp (optarg, "NEWC"))
215 archive_format = arf_newascii;
216 else if (!strcmp (optarg, "odc") || !strcmp (optarg, "ODC"))
217 archive_format = arf_oldascii;
218 else if (!strcmp (optarg, "bin") || !strcmp (optarg, "BIN"))
219 archive_format = arf_binary;
220 else if (!strcmp (optarg, "ustar") || !strcmp (optarg, "USTAR"))
221 archive_format = arf_ustar;
222 else if (!strcmp (optarg, "tar") || !strcmp (optarg, "TAR"))
223 archive_format = arf_tar;
224 else if (!strcmp (optarg, "hpodc") || !strcmp (optarg, "HPODC"))
225 archive_format = arf_hpoldascii;
226 else if (!strcmp (optarg, "hpbin") || !strcmp (optarg, "HPBIN"))
227 archive_format = arf_hpbinary;
230 invalid archive format `%s'; valid formats are:\n\
231 crc newc odc bin ustar tar (all-caps also recognized)", optarg);
234 case 'i': /* Copy-in mode. */
235 if (copy_function != 0)
237 copy_function = process_copy_in;
240 case 'I': /* Input archive file name. */
241 input_archive_name = optarg;
244 case 'k': /* Handle corrupted archives. We always handle
245 corrupted archives, but recognize this
246 option for compatability. */
249 case 'l': /* Link files when possible. */
253 case 'L': /* Dereference symbolic links. */
257 case 'm': /* Retain previous file modify times. */
258 retain_time_flag = TRUE;
261 case 'M': /* New media message. */
262 set_new_media_message (optarg);
265 case 'n': /* Long list owner and group as numbers. */
269 case 136: /* --no-absolute-filenames */
270 no_abs_paths_flag = TRUE;
273 case 134: /* --no-preserve-owner */
274 if (set_owner_flag || set_group_flag)
276 no_chown_flag = TRUE;
279 case 'o': /* Copy-out mode. */
280 if (copy_function != 0)
282 copy_function = process_copy_out;
285 case 'O': /* Output archive file name. */
286 output_archive_name = optarg;
290 only_verify_crc_flag = TRUE;
293 case 'p': /* Copy-pass mode. */
294 if (copy_function != 0)
296 copy_function = process_copy_pass;
299 case 'r': /* Interactively rename. */
304 rename_batch_file = optarg;
311 case 'R': /* Set the owner. */
318 e = parse_user_spec (optarg, &set_owner, &set_group, &u, &g);
320 error (2, 0, "%s: %s", optarg, e);
324 set_owner_flag = TRUE;
329 set_group_flag = TRUE;
335 case 's': /* Swap bytes. */
336 swap_bytes_flag = TRUE;
339 case 'S': /* Swap halfwords. */
340 swap_halfwords_flag = TRUE;
343 case 't': /* Only print a list. */
347 case 'u': /* Replace all! Unconditionally! */
348 unconditional_flag = TRUE;
351 case 'v': /* Verbose! */
355 case 'V': /* Print `.' for each file. */
360 printf ("GNU cpio %s", version_string);
368 case 132: /* --help */
377 /* Do error checking and look at other args. */
379 if (copy_function == 0)
382 copy_function = process_copy_in;
387 if ((!table_flag || !verbose_flag) && numeric_uid)
390 /* Work around for pcc bug. */
391 copy_in = process_copy_in;
392 copy_out = process_copy_out;
394 if (copy_function == copy_in)
397 if (link_flag || reset_time_flag || xstat != lstat || append_flag
399 || output_archive_name
400 || (archive_name && input_archive_name))
402 if (archive_format == arf_crcascii)
404 num_patterns = argc - optind;
405 save_patterns = &argv[optind];
406 if (input_archive_name)
407 archive_name = input_archive_name;
409 else if (copy_function == copy_out)
412 if (argc != optind || create_dir_flag || rename_flag
413 || table_flag || unconditional_flag || link_flag
414 || retain_time_flag || no_chown_flag || set_owner_flag
415 || set_group_flag || swap_bytes_flag || swap_halfwords_flag
416 || (append_flag && !(archive_name || output_archive_name))
417 || rename_batch_file || no_abs_paths_flag
418 || input_archive_name || (archive_name && output_archive_name))
420 if (archive_format == arf_unknown)
421 archive_format = arf_binary;
422 if (output_archive_name)
423 archive_name = output_archive_name;
429 if (argc - 1 != optind || archive_format != arf_unknown
430 || swap_bytes_flag || swap_halfwords_flag
431 || table_flag || rename_flag || append_flag
432 || rename_batch_file || no_abs_paths_flag)
434 directory_name = argv[optind];
439 if (copy_function != copy_in && copy_function != copy_out)
441 archive_des = open_archive (archive_name);
443 error (1, errno, "%s", archive_name);
447 /* Prevent SysV non-root users from giving away files inadvertantly.
448 This happens automatically on BSD, where only root can give
450 if (set_owner_flag == FALSE && set_group_flag == FALSE && geteuid ())
451 no_chown_flag = TRUE;
455 /* Initialize the input and output buffers to their proper size and
456 initialize all variables associated with the input and output
460 initialize_buffers ()
462 int in_buf_size, out_buf_size;
464 if (copy_function == process_copy_in)
466 /* Make sure the input buffer can always hold 2 blocks and that it
467 is big enough to hold 1 tar record (512 bytes) even if it
468 is not aligned on a block boundary. The extra buffer space
469 is needed by process_copyin and peek_in_buf to automatically
470 figure out what kind of archive it is reading. */
471 if (io_block_size >= 512)
472 in_buf_size = 2 * io_block_size;
475 out_buf_size = DISK_IO_BLOCK_SIZE;
477 else if (copy_function == process_copy_out)
479 in_buf_size = DISK_IO_BLOCK_SIZE;
480 out_buf_size = io_block_size;
484 in_buf_size = DISK_IO_BLOCK_SIZE;
485 out_buf_size = DISK_IO_BLOCK_SIZE;
488 input_buffer = (char *) xmalloc (in_buf_size);
489 in_buff = input_buffer;
490 input_buffer_size = in_buf_size;
494 output_buffer = (char *) xmalloc (out_buf_size);
495 out_buff = output_buffer;
499 /* Clear the block of zeros. */
500 bzero (zeros_512, 512);
508 program_name = argv[0];
510 #if (defined(BSD) && (BSD >= 199306))
511 (void) setlocale (LC_ALL, "");
515 _fmode = O_BINARY; /* Put stdin and stdout in binary mode. */
517 #ifdef __EMX__ /* gcc on OS/2. */
518 _response (&argc, &argv);
519 _wildcard (&argc, &argv);
522 process_args (argc, argv);
525 initialize_buffers ();
529 if (archive_des >= 0 && rmtclose (archive_des) == -1)
530 error (1, errno, "error closing archive");