]> CyberLeo.Net >> Repos - FreeBSD/releng/8.0.git/blob - contrib/cpio/src/main.c
Adjust to reflect 8.0-RELEASE.
[FreeBSD/releng/8.0.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, 2005, 2006
5    Free Software Foundation, Inc.
6
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)
10    any later version.
11
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.
16
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.  */
21
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> */
26
27 #include <system.h>
28 #include <paxlib.h>
29
30 #include <stdio.h>
31 #include <getopt.h>
32 #include <argp.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35
36 #ifdef HAVE_LOCALE_H
37 # include <locale.h>
38 #endif
39
40 #include "filetypes.h"
41 #include "cpiohdr.h"
42 #include "dstring.h"
43 #include "extern.h"
44 #include <rmt.h>
45 #include <rmt-command.h>
46
47 enum cpio_options {
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,      
53   RSH_COMMAND_OPTION,            
54   QUIET_OPTION,                  
55   SPARSE_OPTION,                 
56   FORCE_LOCAL_OPTION,            
57   DEBUG_OPTION,                  
58   BLOCK_SIZE_OPTION,             
59   TO_STDOUT_OPTION,
60   
61   HANG_OPTION,
62   USAGE_OPTION,               
63   LICENSE_OPTION,             
64   VERSION_OPTION
65 };
66
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\
70 \n\
71 Examples:\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");
78
79 /*  Print usage error message and exit with error.  */
80
81 #define CHECK_USAGE(cond, opt, mode_opt) \
82  if (cond) \
83    ERROR((PAXEXIT_FAILURE, 0, _("%s is meaningless with %s"), opt, mode_opt));
84
85 static struct argp_option options[] = {
86   /* ********** */
87 #define GRID 10
88   {NULL, 0, NULL, 0,
89    N_("Main operation mode:"), GRID },
90   {"create", 'o', 0, 0,
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 },
96   {"list", 't', 0, 0,
97    N_("Print a table of contents of the input"), GRID },
98 #undef GRID
99   
100   /* ********** */
101 #define GRID 100  
102   {NULL, 0, NULL, 0,
103    N_("Operation modifiers valid in any mode:"), GRID },
104
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 },
111   {NULL, 'B', NULL, 0,
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 },
115   {NULL, 'c', NULL, 0,
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"),
123    GRID+1 },
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"),
128    GRID+1 },
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 },
135 #ifdef DEBUG_CPIO
136   {"debug", DEBUG_OPTION, NULL, 0,
137    N_("Enable debugging info"), GRID+1 },
138 #endif
139   {"warning", 'W', N_("FLAG"), 0,
140    N_("Control warning display. Currently FLAG is one of 'none', 'truncate', 'all'. Multiple options accumulate."), GRID+1 },
141 #undef GRID
142   
143   /* ********** */
144 #define GRID 200  
145   {NULL, 0, NULL, 0,
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,
156    "", GRID+1 },
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"),
163    GRID+1 },
164   {"to-stdout", TO_STDOUT_OPTION, NULL, 0,
165    N_("Extract files to standard output"), GRID+1 },
166 #undef GRID   
167
168   /* ********** */
169 #define GRID 300
170   {NULL, 0, NULL, 0,
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 },
176 #undef GRID
177   
178   /* ********** */
179 #define GRID 400
180   {NULL, 0, NULL, 0,
181    N_("Operation modifiers valid only in copy-pass mode:"), GRID},
182   {"link", 'l', 0, 0,
183    N_("Link files instead of copying them, when  possible"), GRID+1 },
184
185 #undef GRID
186   
187   /* ********** */
188 #define GRID 500
189   {NULL, 0, NULL, 0,
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"),
193    GRID+1 },
194   {"no-absolute-filenames", NO_ABSOLUTE_FILENAMES_OPTION, 0, 0,
195    N_("Create all files relative to the current directory"), GRID+1 },
196 #undef GRID  
197   /* ********** */
198 #define GRID 600
199   {NULL, 0, NULL, 0,
200    N_("Operation modifiers valid in copy-out and copy-pass modes:"), GRID },
201   {"null", '0', 0, 0,
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 },
211
212 #undef GRID   
213   /* ********** */
214 #define GRID 700
215   {NULL, 0, NULL, 0,
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 },
227 #undef GRID
228   
229   /* ********** */
230 #define GRID 800
231   {NULL, 0, NULL, 0,
232    N_("Informative options:"), GRID },
233
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
239      --version */
240   {"HANG",        HANG_OPTION,    "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
241    N_("hang for SECS seconds (default 3600)"), 0},
242 #undef GRID     
243   {0, 0, 0, 0}
244 };
245
246 static char *input_archive_name = 0;
247 static char *output_archive_name = 0;
248
249 static void
250 license ()
251 {
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"
258     "\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"
263     "\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"));
267   exit (0);
268 }
269
270 static int
271 warn_control (char *arg)
272 {
273   static struct warn_tab {
274     char *name;
275     int flag;
276   } warn_tab[] = {
277     { "none",       CPIO_WARN_ALL       },
278     { "truncate",   CPIO_WARN_TRUNCATE  },
279     { "all",        CPIO_WARN_ALL       },
280     { NULL }
281   };
282   struct warn_tab *wt;
283   int offset = 0;
284
285   if (strcmp (arg, "none") == 0)
286     {
287       warn_option = 0;
288       return 0;
289     }
290   
291   if (strlen (arg) > 2 && memcmp (arg, "no-", 3) == 0)
292     offset = 3;
293       
294   for (wt = warn_tab; wt->name; wt++)
295     if (strcmp (arg + offset, wt->name) == 0)
296       {
297         if (offset)
298           warn_option &= ~wt->flag;
299         else
300           warn_option |= wt->flag;
301         return 0;
302       }
303
304   return 1;
305 }
306
307 static error_t
308 parse_opt (int key, char *arg, struct argp_state *state)
309 {
310   static volatile int _argp_hang;
311   switch (key)
312     {
313     case '0':           /* Read null-terminated filenames.  */
314       name_end = '\0';
315       break;
316
317     case 'a':           /* Reset access times.  */
318       reset_time_flag = true;
319       break;
320
321     case 'A':           /* Append to the archive.  */
322       append_flag = true;
323       break;
324
325     case 'b':           /* Swap bytes and halfwords.  */
326       swap_bytes_flag = true;
327       swap_halfwords_flag = true;
328       break;
329
330     case 'B':           /* Set block size to 5120.  */
331       io_block_size = 5120;
332       break;
333
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;
339       break;
340
341     case 'c':           /* Use the old portable ASCII format.  */
342       if (archive_format != arf_unknown)
343         error (0, EXIT_FAILURE, _("Archive format multiply defined"));
344 #ifdef SVR4_COMPAT
345       archive_format = arf_newascii; /* -H newc.  */
346 #else
347       archive_format = arf_oldascii; /* -H odc.  */
348 #endif
349       break;
350
351     case 'C':           /* Block size.  */
352       io_block_size = atoi (arg);
353       if (io_block_size < 1)
354         error (2, 0, _("invalid block size"));
355       break;
356
357     case 'd':           /* Create directories where needed.  */
358       create_dir_flag = true;
359       break;
360
361     case 'f':           /* Only copy files not matching patterns.  */
362       copy_matching_files = false;
363       break;
364
365     case 'E':           /* Pattern file name.  */
366       pattern_file_name = arg;
367       break;
368
369     case 'F':           /* Archive file name.  */
370       archive_name = arg;
371       break;
372
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;
392       else
393         error (2, 0, _("\
394 invalid archive format `%s'; valid formats are:\n\
395 crc newc odc bin ustar tar (all-caps also recognized)"), arg);
396       break;
397           
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;
402       break;
403
404     case 'I':           /* Input archive file name.  */
405       input_archive_name = arg;
406       break;
407
408     case 'k':           /* Handle corrupted archives.  We always handle
409                            corrupted archives, but recognize this
410                            option for compatability.  */
411       break;
412
413     case 'l':           /* Link files when possible.  */
414       link_flag = true;
415       break;
416
417     case 'L':           /* Dereference symbolic links.  */
418       xstat = stat;
419       break;
420
421     case 'm':           /* Retain previous file modify times.  */
422       retain_time_flag = true;
423       break;
424
425     case 'M':           /* New media message.  */
426       set_new_media_message (arg);
427       break;
428
429     case 'n':           /* Long list owner and group as numbers.  */
430       numeric_uid = true;
431       break;
432
433     case NO_ABSOLUTE_FILENAMES_OPTION:          /* --no-absolute-filenames */
434       abs_paths_flag = false;
435       break;
436
437     case ABSOLUTE_FILENAMES_OPTION:             /* --absolute-filenames */
438       abs_paths_flag = true;
439       break;
440         
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;
446       break;
447
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;
452       break;
453
454     case 'O':           /* Output archive file name.  */
455       output_archive_name = arg;
456       break;
457
458     case ONLY_VERIFY_CRC_OPTION:
459       only_verify_crc_flag = true;
460       break;
461
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;
466       break;
467           
468     case RSH_COMMAND_OPTION:
469       rsh_command_option = arg;
470       break;
471
472     case 'r':           /* Interactively rename.  */
473       rename_flag = true;
474       break;
475
476     case RENAME_BATCH_FILE_OPTION:
477       rename_batch_file = arg;
478       break;
479
480     case QUIET_OPTION:
481       quiet_flag = true;
482       break;
483
484     case 'R':           /* Set the owner.  */
485       if (no_chown_flag)
486         error (PAXEXIT_FAILURE, 0, 
487                _("--owner cannot be used with --no-preserve-owner"));
488       else
489         {
490           char *e, *u, *g;
491           
492           e = parse_user_spec (arg, &set_owner, &set_group, &u, &g);
493           if (e)
494             error (PAXEXIT_FAILURE, 0, "%s: %s", arg, e);
495           if (u)
496             {
497               free (u);
498               set_owner_flag = true;
499             }
500           if (g)
501             {
502               free (g);
503               set_group_flag = true;
504             }
505         }
506       break;
507
508     case 's':           /* Swap bytes.  */
509       swap_bytes_flag = true;
510       break;
511
512     case 'S':           /* Swap halfwords.  */
513       swap_halfwords_flag = true;
514       break;
515
516     case 't':           /* Only print a list.  */
517       table_flag = true;
518       break;
519
520     case 'u':           /* Replace all!  Unconditionally!  */
521       unconditional_flag = true;
522       break;
523
524     case 'v':           /* Verbose!  */
525       verbose_flag = true;
526       break;
527
528     case 'V':           /* Print `.' for each file.  */
529       dot_flag = true;
530       break;
531
532     case 'W':
533       if (warn_control (arg))
534         argp_error (state, _("Invalid value for --warning option: %s"), arg);
535       break;
536       
537     case SPARSE_OPTION:
538       sparse_flag = true;
539       break;
540
541     case FORCE_LOCAL_OPTION:
542       force_local_option = 1;
543       break;
544
545 #ifdef DEBUG_CPIO
546     case DEBUG_OPTION:
547       debug_flag = true;
548       break;
549 #endif
550
551     case TO_STDOUT_OPTION:
552       to_stdout_option = true;
553       break;
554
555     case HANG_OPTION:
556       _argp_hang = atoi (arg ? arg : "3600");
557       while (_argp_hang-- > 0)
558         sleep (1);
559       break;
560       
561     case '?':
562       argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP);
563       break;
564
565     case USAGE_OPTION:
566       argp_state_help (state, state->out_stream,
567                        ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
568       break;
569
570     case VERSION_OPTION:
571       fprintf (state->out_stream, "%s\n", argp_program_version);
572       exit (0);
573
574     case LICENSE_OPTION:
575       license ();
576       break;
577
578     default:
579       return ARGP_ERR_UNKNOWN;
580     }
581   return 0;
582 }
583
584 static struct argp argp = {
585   options,
586   parse_opt,
587   N_("[destination-directory]"),
588   doc,
589   NULL,
590   NULL,
591   NULL
592 };
593
594 /* Process the arguments.  Set all options and set up the copy pass
595    directory or the copy in patterns.  */
596
597 void
598 process_args (int argc, char *argv[])
599 {
600   void (*copy_in) ();           /* Work around for pcc bug.  */
601   void (*copy_out) ();
602   int index;
603
604   if (argc < 2)
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);
608
609   xstat = lstat;
610
611   if (argp_parse (&argp, argc, argv, ARGP_IN_ORDER|ARGP_NO_HELP, &index, NULL))
612     exit (1); 
613
614   /* Do error checking and look at other args.  */
615
616   if (copy_function == 0)
617     {
618       if (table_flag)
619         copy_function = process_copy_in;
620       else
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);
624     }
625
626   /* Work around for pcc bug.  */
627   copy_in = process_copy_in;
628   copy_out = process_copy_out;
629
630   if (copy_function == copy_in)
631     {
632       archive_des = 0;
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)
639         {
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",
645                       "--to-stdout");
646         }
647       
648       if (archive_name && input_archive_name)
649         error (PAXEXIT_FAILURE, 0, 
650                _("Both -I and -F are used in copy-in mode"));
651
652       if (archive_format == arf_crcascii)
653         crc_i_flag = true;
654       num_patterns = argc - index;
655       save_patterns = &argv[index];
656       if (input_archive_name)
657         archive_name = input_archive_name;
658     }
659   else if (copy_function == copy_out)
660     {
661       if (index != argc)
662         error (PAXEXIT_FAILURE, 0, _("Too many arguments"));
663
664       archive_des = 1;
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",
672                   "--create");
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)",
676                   "--create");
677       CHECK_USAGE(to_stdout_option, "--to-stdout", "--create");
678       
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)"));
682
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"));
689
690       if (archive_format == arf_unknown)
691         archive_format = arf_binary;
692       if (output_archive_name)
693         archive_name = output_archive_name;
694     }
695   else
696     {
697       /* Copy pass.  */
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"));
702
703       if (archive_format != arf_unknown)
704         error (PAXEXIT_FAILURE, 0, 
705                _("Archive format is not specified in copy-pass mode (use --format option)"));
706
707       CHECK_USAGE(swap_bytes_flag, "--swap-bytes (--swap)", "--pass-through");
708       CHECK_USAGE(swap_halfwords_flag, "--swap-halfwords (--swap)",
709                   "--pass-through");
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",
715                   "--pass-through");
716       CHECK_USAGE(to_stdout_option, "--to-stdout", "--pass-through");
717       
718       directory_name = argv[index];
719     }
720
721   if (archive_name)
722     {
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);
727       if (archive_des < 0)
728         error (PAXEXIT_FAILURE, errno, _("Cannot open %s"), 
729                quotearg_colon (archive_name));
730     }
731                      
732   /* Prevent SysV non-root users from giving away files inadvertantly.
733      This happens automatically on BSD, where only root can give
734      away files.  */
735   if (set_owner_flag == false && set_group_flag == false && geteuid ())
736     no_chown_flag = true;
737 }
738
739 /* Initialize the input and output buffers to their proper size and
740    initialize all variables associated with the input and output
741    buffers.  */
742
743 void
744 initialize_buffers ()
745 {
746   int in_buf_size, out_buf_size;
747
748   if (copy_function == process_copy_in)
749     {
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;
757       else
758         in_buf_size = 1024;
759       out_buf_size = DISK_IO_BLOCK_SIZE;
760     }
761   else if (copy_function == process_copy_out)
762     {
763       in_buf_size = DISK_IO_BLOCK_SIZE;
764       out_buf_size = io_block_size;
765     }
766   else
767     {
768       in_buf_size = DISK_IO_BLOCK_SIZE;
769       out_buf_size = DISK_IO_BLOCK_SIZE;
770     }
771
772   input_buffer = (char *) xmalloc (in_buf_size);
773   in_buff = input_buffer;
774   input_buffer_size = in_buf_size;
775   input_size = 0;
776   input_bytes = 0;
777
778   output_buffer = (char *) xmalloc (out_buf_size);
779   out_buff = output_buffer;
780   output_size = 0;
781   output_bytes = 0;
782 }
783
784 int
785 main (int argc, char *argv[])
786 {
787   setlocale (LC_ALL, "");
788   bindtextdomain (PACKAGE, LOCALEDIR);
789   textdomain (PACKAGE);
790
791   program_name = argv[0];
792
793   process_args (argc, argv);
794   umask (0);
795
796   initialize_buffers ();
797
798   (*copy_function) ();
799
800   if (archive_des >= 0 && rmtclose (archive_des) == -1)
801     error (1, errno, _("error closing archive"));
802
803   exit (0);
804 }