]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - contrib/cpio/src/main.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / contrib / cpio / src / main.c
1 /* $FreeBSD$ */
2
3 /* main.c - main program and argument processing for cpio.
4    Copyright (C) 1990, 1991, 1992, 2001, 2003, 2004 Free Software Foundation, Inc.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License along
17    with this program; if not, write to the Free Software Foundation, Inc.,
18    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20 /* Written by Phil Nelson <phil@cs.wwu.edu>,
21    David MacKenzie <djm@gnu.ai.mit.edu>,
22    John Oleynick <juo@klinzhai.rutgers.edu>,
23    and Sergey Poznyakoff <gray@mirddin.farlep.net> */
24
25 #include <system.h>
26
27 #include <stdio.h>
28 #include <getopt.h>
29 #include <argp.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32
33 #ifdef HAVE_LOCALE_H
34 #  include <locale.h>
35 #endif
36
37 #include "filetypes.h"
38 #include "cpiohdr.h"
39 #include "dstring.h"
40 #include "extern.h"
41 #include <rmt.h>
42 #include <localedir.h>
43
44 enum cpio_options {
45   NO_ABSOLUTE_FILENAMES_OPTION=256,  
46   ABSOLUTE_FILENAMES_OPTION,  
47   NO_PRESERVE_OWNER_OPTION,      
48   ONLY_VERIFY_CRC_OPTION,        
49   RENAME_BATCH_FILE_OPTION,      
50   RSH_COMMAND_OPTION,            
51   QUIET_OPTION,                  
52   SPARSE_OPTION,                 
53   FORCE_LOCAL_OPTION,            
54   DEBUG_OPTION,                  
55   BLOCK_SIZE_OPTION,             
56   TO_STDOUT_OPTION,              
57
58   USAGE_OPTION,               
59   LICENSE_OPTION,             
60   VERSION_OPTION
61 };
62
63 const char *argp_program_version = "cpio (" PACKAGE_NAME ") " VERSION;
64 const char *argp_program_bug_address = "<" PACKAGE_BUGREPORT ">";
65 static char doc[] = N_("GNU `cpio' copies files to and from archives\n\
66 \n\
67 Examples:\n\
68   # Copy files named in name-list to the archive\n\
69   cpio -o < name-list [> archive]\n\
70   # Extract files from the archive\n\
71   cpio -i [< archive]\n\
72   # Copy files named in name-list to destination-directory\n\
73   cpio -p destination-directory < name-list\n");
74
75 /*  Print usage error message and exit with error.  */
76
77 #define USAGE_ERROR(args) do { error args; exit(2); } while (0)
78 #define CHECK_USAGE(cond, opt, mode_opt) \
79  if (cond) USAGE_ERROR((0, 0, _("%s is meaningless with %s"), opt, mode_opt));
80
81 static struct argp_option options[] = {
82   {NULL, 0, NULL, 0,
83    N_("Main operation mode:"), 10},
84   {"create", 'o', 0, 0,
85    N_("Create the archive (run in copy-out mode)"), 10},
86   {"extract", 'i', 0, 0,
87    N_("Extract files from an archive (run in copy-in mode)")},
88   {"pass-through", 'p', 0, 0,
89    N_("Run in copy-pass mode"), 10},
90   {"list", 't', 0, 0,
91    N_("Print a table of contents of the input"), 10},
92
93   {NULL, 0, NULL, 0,
94    N_("Operation modifiers valid in any mode:"), 100},
95
96   {"file", 'F', N_("[[USER@]HOST:]FILE-NAME"), 0,
97    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"), 110},
98   {"force-local", FORCE_LOCAL_OPTION, 0, 0,
99    N_("Archive file is local, even if its name contains colons"), 110},
100   {"format", 'H', N_("FORMAT"), 0,
101    N_("Use given archive FORMAT"), 110},
102   {NULL, 'B', NULL, 0,
103    N_("Set the I/O block size to 5120 bytes"), 110},
104   {"block-size", BLOCK_SIZE_OPTION, N_("BLOCK-SIZE"), 0,
105    N_("Set the I/O block size to BLOCK-SIZE * 512 bytes"), 110},
106   {NULL, 'c', NULL, 0,
107    N_("Use the old portable (ASCII) archive format"), 0},
108   {"dot", 'V', NULL, 0, 
109    N_("Print a \".\" for each file processed"), 110},
110   {"io-size", 'C', N_("NUMBER"), 0,
111    N_("Set the I/O block size to the given NUMBER of bytes"), 110},
112   {"message", 'M', N_("STRING"), 0,
113    N_("Print STRING when the end of a volume of the backup media is reached"),
114    110},
115   {"nonmatching", 'f', 0, 0,
116    N_("Only copy files that do not match any of the given patterns"), 110},
117   {"numeric-uid-gid", 'n', 0, 0,
118    N_("In the verbose table of contents listing, show numeric UID and GID"),
119    110},
120   {"rsh-command", RSH_COMMAND_OPTION, N_("COMMAND"), 0,
121    N_("Use remote COMMAND instead of rsh"), 110},
122   {"quiet", QUIET_OPTION, NULL, 0,
123    N_("Do not print the number of blocks copied"), 110},
124   {"verbose", 'v', NULL, 0,
125    N_("Verbosely list the files processed"), 110},
126 #ifdef DEBUG_CPIO
127   {"debug", DEBUG_OPTION, NULL, 0,
128    N_("Enable debugging info"), 110},
129 #endif
130   {"warning", 'W', N_("FLAG"), 0,
131    N_("Control warning display. Currently FLAG is one of 'none', 'truncate', 'all'. Multiple options accumulate."), 110 },
132
133   /* ********** */
134   {NULL, 0, NULL, 0,
135    N_("Operation modifiers valid only in copy-in mode:"), 200},
136   {"pattern-file", 'E', N_("FILE"), 0,
137    N_("In copy-in mode, read additional patterns specifying filenames to extract or list from FILE"), 210},
138   {"no-absolute-filenames", NO_ABSOLUTE_FILENAMES_OPTION, 0, 0,
139    N_("Create all files relative to the current directory"), 210},
140   {"absolute-filenames", ABSOLUTE_FILENAMES_OPTION, 0, 0,
141    N_("do not strip leading file name components that contain \"..\" and leading slashes from file names"), 210},
142   {"only-verify-crc", ONLY_VERIFY_CRC_OPTION, 0, 0,
143    N_("When reading a CRC format archive in copy-in mode, only verify the CRC's of each file in the archive, don't actually extract the files"), 210},
144   {"rename", 'r', 0, 0,
145    N_("Interactively rename files"), 210},
146   {"rename-batch-file", RENAME_BATCH_FILE_OPTION, N_("FILE"), OPTION_HIDDEN,
147    "", 210},
148   {"swap", 'b', NULL, 0,
149    N_("Swap both halfwords of words and bytes of halfwords in the data. Equivalent to -sS"), 210},
150   {"swap-bytes", 's', NULL, 0,
151    N_("Swap the bytes of each halfword in the files"), 210},
152   {"swap-halfwords", 'S', NULL, 0,
153    N_("Swap the halfwords of each word (4 bytes) in the files"),
154    210},
155   {"to-stdout", TO_STDOUT_OPTION, NULL, 0,
156    N_("Extract files to standard output"), 210},
157
158   /* ********** */
159   {NULL, 0, NULL, 0,
160    N_("Operation modifiers valid only in copy-out mode:"), 300},
161   {"append", 'A', 0, 0,
162    N_("Append to an existing archive."), 310 },
163   {NULL, 'O', N_("[[USER@]HOST:]FILE-NAME"), 0,
164    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"), 310},
165   
166   /* ********** */
167   {NULL, 0, NULL, 0,
168    N_("Operation modifiers valid only in copy-pass mode:"), 400},
169   {"link", 'l', 0, 0,
170    N_("Link files instead of copying them, when  possible"), 410},
171
172   /* ********** */
173   {NULL, 0, NULL, 0,
174    N_("Operation modifiers valid for copy-out and copy-pass modes:"), 500},
175   {"null", '0', 0, 0,
176    N_("A list of filenames is terminated by a null character instead of a newline"), 510 },
177   {NULL, 'I', N_("[[USER@]HOST:]FILE-NAME"), 0,
178    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"), 510},
179   {"dereference", 'L', 0, 0,
180    N_("Dereference  symbolic  links  (copy  the files that they point to instead of copying the links)."), 510},
181   {"owner", 'R', N_("[USER][:.][GROUP]"), 0,
182    N_("Set the ownership of all files created to the specified USER and/or GROUP"), 510},
183   {"sparse", SPARSE_OPTION, NULL, 0,
184    N_("Write files with large blocks of zeros as sparse files"), 510},
185   {"reset-access-time", 'a', NULL, 0,
186    N_("Reset the access times of files after reading them"), 510},
187
188   /* ********** */
189   {NULL, 0, NULL, 0,
190    N_("Operation modifiers valid for copy-in and copy-pass modes:"), 600},
191   {"preserve-modification-time", 'm', 0, 0,
192    N_("Retain previous file modification times when creating files"), 610},
193   {"make-directories", 'd', 0, 0,
194    N_("Create leading directories where needed"), 610},
195   {"no-preserve-owner", NO_PRESERVE_OWNER_OPTION, 0, 0,
196    N_("Do not change the ownership of the files"), 610},
197   {"unconditional", 'u', NULL, 0,
198    N_("Replace all files unconditionally"), 610},
199
200   {NULL, 0, NULL, 0,
201    N_("Informative options:"), 700 },
202
203   {"help",  '?', 0, 0,  N_("Give this help list"), -1},
204   {"usage", USAGE_OPTION, 0, 0,  N_("Give a short usage message"), -1},
205   {"license", LICENSE_OPTION, 0, 0, N_("Print license and exit"), -1},
206   {"version", VERSION_OPTION, 0, 0,  N_("Print program version"), -1},
207   /* FIXME -V (--dot) conflicts with the default short option for
208      --version */
209   
210   {0, 0, 0, 0}
211 };
212
213 static char *input_archive_name = 0;
214 static char *output_archive_name = 0;
215
216 static void
217 license ()
218 {
219   printf ("%s (%s) %s\n%s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION,
220           "Copyright (C) 2004 Free Software Foundation, Inc.\n");
221   printf (_("   GNU cpio is free software; you can redistribute it and/or modify\n"
222     "   it under the terms of the GNU General Public License as published by\n"
223     "   the Free Software Foundation; either version 2 of the License, or\n"
224     "   (at your option) any later version.\n"
225     "\n"
226     "   GNU cpio is distributed in the hope that it will be useful,\n"
227     "   but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
228     "   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
229     "   GNU General Public License for more details.\n"
230     "\n"
231     "   You should have received a copy of the GNU General Public License\n"
232     "   along with GNU cpio; if not, write to the Free Software\n"
233     "   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA\n\n"));
234   exit (0);
235 }
236
237 static int
238 warn_control (char *arg)
239 {
240   static struct warn_tab {
241     char *name;
242     int flag;
243   } warn_tab[] = {
244     { "none",       CPIO_WARN_ALL       },
245     { "truncate",   CPIO_WARN_TRUNCATE  },
246     { "all",        CPIO_WARN_ALL       },
247     { NULL }
248   };
249   struct warn_tab *wt;
250   int offset = 0;
251
252   if (strcmp (arg, "none") == 0)
253     {
254       warn_option = 0;
255       return 0;
256     }
257   
258   if (strlen (arg) > 2 && memcmp (arg, "no-", 3) == 0)
259     offset = 3;
260       
261   for (wt = warn_tab; wt->name; wt++)
262     if (strcmp (arg + offset, wt->name) == 0)
263       {
264         if (offset)
265           warn_option &= ~wt->flag;
266         else
267           warn_option |= wt->flag;
268         return 0;
269       }
270
271   return 1;
272 }
273
274 static error_t
275 parse_opt (int key, char *arg, struct argp_state *state)
276 {
277   switch (key)
278     {
279     case '0':           /* Read null-terminated filenames.  */
280       name_end = '\0';
281       break;
282
283     case 'a':           /* Reset access times.  */
284       reset_time_flag = true;
285       break;
286
287     case 'A':           /* Append to the archive.  */
288       append_flag = true;
289       break;
290
291     case 'b':           /* Swap bytes and halfwords.  */
292       swap_bytes_flag = true;
293       swap_halfwords_flag = true;
294       break;
295
296     case 'B':           /* Set block size to 5120.  */
297       io_block_size = 5120;
298       break;
299
300     case BLOCK_SIZE_OPTION:             /* --block-size */
301       io_block_size = atoi (arg);
302       if (io_block_size < 1)
303         error (2, 0, _("invalid block size"));
304       io_block_size *= 512;
305       break;
306
307     case 'c':           /* Use the old portable ASCII format.  */
308       if (archive_format != arf_unknown)
309         USAGE_ERROR ((0, 0, _("Archive format multiply defined")));
310 #ifdef SVR4_COMPAT
311       archive_format = arf_newascii; /* -H newc.  */
312 #else
313       archive_format = arf_oldascii; /* -H odc.  */
314 #endif
315       break;
316
317     case 'C':           /* Block size.  */
318       io_block_size = atoi (arg);
319       if (io_block_size < 1)
320         error (2, 0, _("invalid block size"));
321       break;
322
323     case 'd':           /* Create directories where needed.  */
324       create_dir_flag = true;
325       break;
326
327     case 'f':           /* Only copy files not matching patterns.  */
328       copy_matching_files = false;
329       break;
330
331     case 'E':           /* Pattern file name.  */
332       pattern_file_name = arg;
333       break;
334
335     case 'F':           /* Archive file name.  */
336       archive_name = arg;
337       break;
338
339     case 'H':           /* Header format name.  */
340       if (archive_format != arf_unknown)
341         USAGE_ERROR ((0, 0, _("Archive format multiply defined")));
342       if (!strcasecmp (arg, "crc"))
343         archive_format = arf_crcascii;
344       else if (!strcasecmp (arg, "newc"))
345         archive_format = arf_newascii;
346       else if (!strcasecmp (arg, "odc"))
347         archive_format = arf_oldascii;
348       else if (!strcasecmp (arg, "bin"))
349         archive_format = arf_binary;
350       else if (!strcasecmp (arg, "ustar"))
351         archive_format = arf_ustar;
352       else if (!strcasecmp (arg, "tar"))
353         archive_format = arf_tar;
354       else if (!strcasecmp (arg, "hpodc"))
355         archive_format = arf_hpoldascii;
356       else if (!strcasecmp (arg, "hpbin"))
357         archive_format = arf_hpbinary;
358       else
359         error (2, 0, _("\
360 invalid archive format `%s'; valid formats are:\n\
361 crc newc odc bin ustar tar (all-caps also recognized)"), arg);
362       break;
363           
364     case 'i':           /* Copy-in mode.  */
365       if (copy_function != 0)
366         USAGE_ERROR ((0, 0, _("Mode already defined")));
367       copy_function = process_copy_in;
368       break;
369
370     case 'I':           /* Input archive file name.  */
371       input_archive_name = arg;
372       break;
373
374     case 'k':           /* Handle corrupted archives.  We always handle
375                            corrupted archives, but recognize this
376                            option for compatability.  */
377       break;
378
379     case 'l':           /* Link files when possible.  */
380       link_flag = true;
381       break;
382
383     case 'L':           /* Dereference symbolic links.  */
384       xstat = stat;
385       break;
386
387     case 'm':           /* Retain previous file modify times.  */
388       retain_time_flag = true;
389       break;
390
391     case 'M':           /* New media message.  */
392       set_new_media_message (arg);
393       break;
394
395     case 'n':           /* Long list owner and group as numbers.  */
396       numeric_uid = true;
397       break;
398
399     case NO_ABSOLUTE_FILENAMES_OPTION:          /* --no-absolute-filenames */
400       abs_paths_flag = false;
401       break;
402         
403     case ABSOLUTE_FILENAMES_OPTION:             /* --absolute-filenames */
404       abs_paths_flag = true;
405       break;
406         
407     case NO_PRESERVE_OWNER_OPTION:              /* --no-preserve-owner */
408       if (set_owner_flag || set_group_flag)
409         USAGE_ERROR ((0, 0,
410                      _("--no-preserve-owner cannot be used with --owner")));
411       no_chown_flag = true;
412       break;
413
414     case 'o':           /* Copy-out mode.  */
415       if (copy_function != 0)
416         USAGE_ERROR ((0, 0, _("Mode already defined")));
417       copy_function = process_copy_out;
418       break;
419
420     case 'O':           /* Output archive file name.  */
421       output_archive_name = arg;
422       break;
423
424     case ONLY_VERIFY_CRC_OPTION:
425       only_verify_crc_flag = true;
426       break;
427
428     case 'p':           /* Copy-pass mode.  */
429       if (copy_function != 0)
430         USAGE_ERROR ((0, 0, _("Mode already defined")));
431       copy_function = process_copy_pass;
432       break;
433           
434     case RSH_COMMAND_OPTION:
435       rsh_command_option = arg;
436       break;
437
438     case 'r':           /* Interactively rename.  */
439       rename_flag = true;
440       break;
441
442     case RENAME_BATCH_FILE_OPTION:
443       rename_batch_file = arg;
444       break;
445
446     case QUIET_OPTION:
447       quiet_flag = true;
448       break;
449
450     case 'R':           /* Set the owner.  */
451       if (no_chown_flag)
452         USAGE_ERROR ((0, 0,
453                       _("--owner cannot be used with --no-preserve-owner")));
454       {
455         char *e, *u, *g;
456
457         e = parse_user_spec (arg, &set_owner, &set_group, &u, &g);
458         if (e)
459           error (2, 0, "%s: %s", arg, e);
460         if (u)
461           {
462             free (u);
463             set_owner_flag = true;
464           }
465         if (g)
466           {
467             free (g);
468             set_group_flag = true;
469           }
470       }
471       break;
472
473     case 's':           /* Swap bytes.  */
474       swap_bytes_flag = true;
475       break;
476
477     case 'S':           /* Swap halfwords.  */
478       swap_halfwords_flag = true;
479       break;
480
481     case 't':           /* Only print a list.  */
482       table_flag = true;
483       break;
484
485     case 'u':           /* Replace all!  Unconditionally!  */
486       unconditional_flag = true;
487       break;
488
489     case 'v':           /* Verbose!  */
490       verbose_flag = true;
491       break;
492
493     case 'V':           /* Print `.' for each file.  */
494       dot_flag = true;
495       break;
496
497     case 'W':
498       if (warn_control (arg))
499         argp_error (state, _("Invalid value for --warning option: %s"), arg);
500       break;
501       
502     case SPARSE_OPTION:
503       sparse_flag = true;
504       break;
505
506     case FORCE_LOCAL_OPTION:
507       force_local_option = 1;
508       break;
509
510 #ifdef DEBUG_CPIO
511     case DEBUG_OPTION:
512       debug_flag = true;
513       break;
514 #endif
515
516     case TO_STDOUT_OPTION:
517       to_stdout_option = true;
518       break;
519       
520     case '?':
521       argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP);
522       break;
523
524     case USAGE_OPTION:
525       argp_state_help (state, state->out_stream,
526                        ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
527       break;
528
529     case VERSION_OPTION:
530       fprintf (state->out_stream, "%s\n", argp_program_version);
531       exit (0);
532
533     case LICENSE_OPTION:
534       license ();
535       break;
536
537     default:
538       return ARGP_ERR_UNKNOWN;
539     }
540   return 0;
541 }
542
543 static struct argp argp = {
544   options,
545   parse_opt,
546   N_("[destination-directory]"),
547   doc,
548   NULL,
549   NULL,
550   NULL
551 };
552
553 /* Process the arguments.  Set all options and set up the copy pass
554    directory or the copy in patterns.  */
555
556 void
557 process_args (int argc, char *argv[])
558 {
559   void (*copy_in) ();           /* Work around for pcc bug.  */
560   void (*copy_out) ();
561   int index;
562
563   if (argc < 2)
564     USAGE_ERROR ((0, 0,
565                   _("You must specify one of -oipt options.\nTry `%s --help' or `%s --usage' for more information.\n"),
566                   program_name, program_name));
567
568   xstat = lstat;
569
570   if (argp_parse (&argp, argc, argv, ARGP_IN_ORDER|ARGP_NO_HELP, &index, NULL))
571     exit (1); 
572
573   /* Do error checking and look at other args.  */
574
575   if (copy_function == 0)
576     {
577       if (table_flag)
578         copy_function = process_copy_in;
579       else
580         USAGE_ERROR ((0, 0,
581                       _("You must specify one of -oipt options.\nTry `%s --help' or `%s --usage' for more information.\n"),
582                       program_name, program_name));
583     }
584
585   /* Work around for pcc bug.  */
586   copy_in = process_copy_in;
587   copy_out = process_copy_out;
588
589   if (copy_function == copy_in)
590     {
591       archive_des = 0;
592       CHECK_USAGE(link_flag, "--link", "--extract");
593       CHECK_USAGE(reset_time_flag, "--reset", "--extract");
594       CHECK_USAGE(xstat != lstat, "--dereference", "--extract");
595       CHECK_USAGE(append_flag, "--append", "--extract");
596       CHECK_USAGE(sparse_flag, "--sparse", "--extract");
597       CHECK_USAGE(output_archive_name, "-O", "--extract");
598       if (to_stdout_option)
599         {
600           CHECK_USAGE(create_dir_flag, "--make-directories", "--to-stdout");
601           CHECK_USAGE(rename_flag, "--rename", "--to-stdout");
602           CHECK_USAGE(no_chown_flag, "--no-preserve-owner", "--to-stdout");
603           CHECK_USAGE(set_owner_flag||set_group_flag, "--owner", "--to-stdout");
604           CHECK_USAGE(retain_time_flag, "--preserve-modification-time",
605                       "--to-stdout");
606         }
607       
608       if (archive_name && input_archive_name)
609         USAGE_ERROR((0, 0, _("Both -I and -F are used in copy-in mode")));
610
611       if (archive_format == arf_crcascii)
612         crc_i_flag = true;
613       num_patterns = argc - index;
614       save_patterns = &argv[index];
615       if (input_archive_name)
616         archive_name = input_archive_name;
617     }
618   else if (copy_function == copy_out)
619     {
620       if (index != argc)
621         USAGE_ERROR ((0, 0, _("Too many arguments")));
622
623       archive_des = 1;
624       CHECK_USAGE(create_dir_flag, "--make-directories", "--create");
625       CHECK_USAGE(rename_flag, "--rename", "--create");
626       CHECK_USAGE(table_flag, "--list", "--create");
627       CHECK_USAGE(unconditional_flag, "--unconditional", "--create");
628       CHECK_USAGE(link_flag, "--link", "--create");
629       CHECK_USAGE(retain_time_flag, "--preserve-modification-time",
630                   "--create");
631       CHECK_USAGE(no_chown_flag, "--no-preserve-owner", "--create");
632       CHECK_USAGE(set_owner_flag||set_group_flag, "--owner", "--create");
633       CHECK_USAGE(swap_bytes_flag, "--swap-bytes (--swap)", "--create");
634       CHECK_USAGE(swap_halfwords_flag, "--swap-halfwords (--swap)",
635                   "--create");
636       CHECK_USAGE(to_stdout_option, "--to-stdout", "--create");
637       
638       if (append_flag && !(archive_name || output_archive_name))
639         USAGE_ERROR ((0, 0,
640                       _("--append is used but no archive file name is given (use -F or -O options")));
641
642       CHECK_USAGE(rename_batch_file, "--rename-batch-file", "--create");
643       CHECK_USAGE(abs_paths_flag, "--absolute-pathnames", "--create");
644       CHECK_USAGE(input_archive_name, "-I", "--create");
645       if (archive_name && output_archive_name)
646         USAGE_ERROR ((0, 0, _("Both -O and -F are used in copy-out mode")));
647
648       if (archive_format == arf_unknown)
649         archive_format = arf_binary;
650       if (output_archive_name)
651         archive_name = output_archive_name;
652     }
653   else
654     {
655       /* Copy pass.  */
656       if (index != argc - 1)
657         USAGE_ERROR ((0, 0, _("Too many arguments")));
658
659       if (archive_format != arf_unknown)
660         USAGE_ERROR((0, 0,
661                      _("Archive format is not specified in copy-pass mode (use --format option)")));
662
663       CHECK_USAGE(swap_bytes_flag, "--swap-bytes (--swap)", "--pass-through");
664       CHECK_USAGE(swap_halfwords_flag, "--swap-halfwords (--swap)",
665                   "--pass-through");
666       CHECK_USAGE(table_flag, "--list", "--pass-through");
667       CHECK_USAGE(rename_flag, "--rename", "--pass-through");
668       CHECK_USAGE(append_flag, "--append", "--pass-through");
669       CHECK_USAGE(rename_batch_file, "--rename-batch-file", "--pass-through");
670       CHECK_USAGE(abs_paths_flag, "--absolute-pathnames",
671                   "--pass-through");
672       CHECK_USAGE(to_stdout_option, "--to-stdout", "--pass-through");
673       
674       directory_name = argv[index];
675     }
676
677   if (archive_name)
678     {
679       if (copy_function != copy_in && copy_function != copy_out)
680         USAGE_ERROR ((0, 0,
681                       _("-F can be used only with --create or --extract")));
682       archive_des = open_archive (archive_name);
683       if (archive_des < 0)
684         error (1, errno, "%s", archive_name);
685     }
686                      
687   /* Prevent SysV non-root users from giving away files inadvertantly.
688      This happens automatically on BSD, where only root can give
689      away files.  */
690   if (set_owner_flag == false && set_group_flag == false && geteuid ())
691     no_chown_flag = true;
692 }
693
694 /* Initialize the input and output buffers to their proper size and
695    initialize all variables associated with the input and output
696    buffers.  */
697
698 void
699 initialize_buffers ()
700 {
701   int in_buf_size, out_buf_size;
702
703   if (copy_function == process_copy_in)
704     {
705       /* Make sure the input buffer can always hold 2 blocks and that it
706          is big enough to hold 1 tar record (512 bytes) even if it
707          is not aligned on a block boundary.  The extra buffer space
708          is needed by process_copyin and peek_in_buf to automatically
709          figure out what kind of archive it is reading.  */
710       if (io_block_size >= 512)
711         in_buf_size = 2 * io_block_size;
712       else
713         in_buf_size = 1024;
714       out_buf_size = DISK_IO_BLOCK_SIZE;
715     }
716   else if (copy_function == process_copy_out)
717     {
718       in_buf_size = DISK_IO_BLOCK_SIZE;
719       out_buf_size = io_block_size;
720     }
721   else
722     {
723       in_buf_size = DISK_IO_BLOCK_SIZE;
724       out_buf_size = DISK_IO_BLOCK_SIZE;
725     }
726
727   input_buffer = (char *) xmalloc (in_buf_size);
728   in_buff = input_buffer;
729   input_buffer_size = in_buf_size;
730   input_size = 0;
731   input_bytes = 0;
732
733   output_buffer = (char *) xmalloc (out_buf_size);
734   out_buff = output_buffer;
735   output_size = 0;
736   output_bytes = 0;
737
738   /* Clear the block of zeros.  */
739   bzero (zeros_512, 512);
740 }
741
742 int
743 main (int argc, char *argv[])
744 {
745 #ifdef HAVE_LOCALE_H
746   setlocale (LC_ALL, "");
747 #endif
748   bindtextdomain (PACKAGE, LOCALEDIR);
749   textdomain (PACKAGE);
750
751   program_name = argv[0];
752   
753 #ifdef __TURBOC__
754   _fmode = O_BINARY;            /* Put stdin and stdout in binary mode.  */
755 #endif
756 #ifdef __EMX__                  /* gcc on OS/2.  */
757   _response (&argc, &argv);
758   _wildcard (&argc, &argv);
759 #endif
760
761   process_args (argc, argv);
762   umask (0);
763
764   initialize_buffers ();
765
766   (*copy_function) ();
767
768   if (archive_des >= 0 && rmtclose (archive_des) == -1)
769     error (1, errno, _("error closing archive"));
770
771   exit (0);
772 }