Imported Debian patch 1.5-16
[debian/pax] / options.c
1 /*      $OpenBSD: options.c,v 1.34 1998/09/20 02:22:22 millert Exp $    */
2 /*      $NetBSD: options.c,v 1.6 1996/03/26 23:54:18 mrg Exp $  */
3
4 /*-
5  * Copyright (c) 1992 Keith Muller.
6  * Copyright (c) 1992, 1993
7  *      The Regents of the University of California.  All rights reserved.
8  *
9  * This code is derived from software contributed to Berkeley by
10  * Keith Muller of the University of California, San Diego.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:
22  *      This product includes software developed by the University of
23  *      California, Berkeley and its contributors.
24  * 4. Neither the name of the University nor the names of its contributors
25  *    may be used to endorse or promote products derived from this software
26  *    without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38  * SUCH DAMAGE.
39  */
40
41 #ifndef lint
42 #if 0
43 static char sccsid[] = "@(#)options.c   8.2 (Berkeley) 4/18/94";
44 #else
45 static char rcsid[] = "$OpenBSD: options.c,v 1.34 1998/09/20 02:22:22 millert Exp $";
46 #endif
47 #endif /* not lint */
48
49 #include <sys/types.h>
50 #include <sys/time.h>
51 #include <sys/stat.h>
52 #include <sys/mtio.h>
53 #include <sys/param.h>
54 #include <stdio.h>
55 #include <string.h>
56 #include <errno.h>
57 #include <unistd.h>
58 #include <stdlib.h>
59 #include <limits.h>
60 #include <paths.h>
61 #include "pax.h"
62 #include "options.h"
63 #include "cpio.h"
64 #include "tar.h"
65 #include "extern.h"
66
67 #include "fgetln.h"    /* added, David */
68
69 /*
70  * Routines which handle command line options
71  */
72
73 static char flgch[] = FLGCH;    /* list of all possible flags */
74 static OPLIST *ophead = NULL;   /* head for format specific options -x */
75 static OPLIST *optail = NULL;   /* option tail */
76
77 static int no_op __P((void));
78 static void printflg __P((unsigned int));
79 static int c_frmt __P((const void *, const void *));
80 static off_t str_offt __P((char *));
81 static void pax_options __P((register int, register char **));
82 static void pax_usage __P((void));
83 static void tar_options __P((register int, register char **));
84 static void tar_usage __P((void));
85 static void cpio_options __P((register int, register char **));
86 static void cpio_usage __P((void));
87
88 #define GZIP_CMD        "gzip"          /* command to run as gzip */
89 #define COMPRESS_CMD    "compress"      /* command to run as compress */
90 #define BZIP2_CMD       "bzip2"         /* command to run as bzip2 */
91
92 /*
93  *      Format specific routine table - MUST BE IN SORTED ORDER BY NAME
94  *      (see pax.h for description of each function)
95  *
96  *      name, blksz, hdsz, udev, hlk, blkagn, inhead, id, st_read,
97  *      read, end_read, st_write, write, end_write, trail,
98  *      rd_data, wr_data, options
99  */
100
101 FSUB fsub[] = {
102 /* 0: OLD BINARY CPIO */
103         {"bcpio", 5120, sizeof(HD_BCPIO), 1, 0, 0, 1, bcpio_id, cpio_strd,
104         bcpio_rd, bcpio_endrd, cpio_stwr, bcpio_wr, cpio_endwr, cpio_trail,
105         rd_wrfile, wr_rdfile, bad_opt},
106
107 /* 1: OLD OCTAL CHARACTER CPIO */
108         {"cpio", 5120, sizeof(HD_CPIO), 1, 0, 0, 1, cpio_id, cpio_strd,
109         cpio_rd, cpio_endrd, cpio_stwr, cpio_wr, cpio_endwr, cpio_trail,
110         rd_wrfile, wr_rdfile, bad_opt},
111
112 /* 2: SVR4 HEX CPIO */
113         {"sv4cpio", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, vcpio_id, cpio_strd,
114         vcpio_rd, vcpio_endrd, cpio_stwr, vcpio_wr, cpio_endwr, cpio_trail,
115         rd_wrfile, wr_rdfile, bad_opt},
116
117 /* 3: SVR4 HEX CPIO WITH CRC */
118         {"sv4crc", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd,
119         vcpio_rd, vcpio_endrd, crc_stwr, vcpio_wr, cpio_endwr, cpio_trail,
120         rd_wrfile, wr_rdfile, bad_opt},
121
122 /* 4: OLD TAR */
123         {"tar", 10240, BLKMULT, 0, 1, BLKMULT, 0, tar_id, no_op,
124         tar_rd, tar_endrd, no_op, tar_wr, tar_endwr, tar_trail,
125         rd_wrfile, wr_rdfile, tar_opt},
126
127 /* 5: POSIX USTAR */
128         {"ustar", 10240, BLKMULT, 0, 1, BLKMULT, 0, ustar_id, ustar_strd,
129         ustar_rd, tar_endrd, ustar_stwr, ustar_wr, tar_endwr, tar_trail,
130         rd_wrfile, wr_rdfile, bad_opt},
131 };
132 #define F_OCPIO 0       /* format when called as cpio -6 */
133 #define F_ACPIO 1       /* format when called as cpio -c */
134 #define F_CPIO  3       /* format when called as cpio */
135 #define F_OTAR  4       /* format when called as tar -o */
136 #define F_TAR   5       /* format when called as tar */
137 #define DEFLT   5       /* default write format from list above */
138
139 /*
140  * ford is the archive search order used by get_arc() to determine what kind
141  * of archive we are dealing with. This helps to properly id  archive formats
142  * some formats may be subsets of others....
143  */
144 int ford[] = {5, 4, 3, 2, 1, 0, -1 };
145
146 /*
147  * options()
148  *      figure out if we are pax, tar or cpio. Call the appropriate options
149  *      parser
150  */
151
152 #ifdef __STDC__
153 void
154 options(register int argc, register char **argv)
155 #else
156 void
157 options(argc, argv)
158         register int argc;
159         register char **argv;
160 #endif
161 {
162
163         /*
164          * Are we acting like pax, tar or cpio (based on argv[0])
165          */
166         if ((argv0 = strrchr(argv[0], '/')) != NULL)
167                 argv0++;
168         else
169                 argv0 = argv[0];
170
171         if (strcmp(NM_TAR, argv0) == 0)
172                 return(tar_options(argc, argv));
173         else if (strcmp(NM_CPIO, argv0) == 0)
174                 return(cpio_options(argc, argv));
175         /*
176          * assume pax as the default
177          */
178         argv0 = NM_PAX;
179         return(pax_options(argc, argv));
180 }
181
182 /*
183  * pax_options()
184  *      look at the user specified flags. set globals as required and check if
185  *      the user specified a legal set of flags. If not, complain and exit
186  */
187
188 #ifdef __STDC__
189 static void
190 pax_options(register int argc, register char **argv)
191 #else
192 static void
193 pax_options(argc, argv)
194         register int argc;
195         register char **argv;
196 #endif
197 {
198         register int c;
199         register int i;
200         unsigned int flg = 0;
201         unsigned int bflg = 0;
202         register char *pt;
203         FSUB tmp;
204         extern char *optarg;
205         extern int optind;
206
207         /*
208          * process option flags
209          */
210         while ((c=getopt(argc,argv,"ab:cdf:ijklno:p:rs:tuvwx:zB:DE:G:HLPT:U:XYZ"))
211             != EOF) {
212                 switch (c) {
213                 case 'a':
214                         /*
215                          * append
216                          */
217                         flg |= AF;
218                         break;
219                 case 'b':
220                         /*
221                          * specify blocksize
222                          */
223                         flg |= BF;
224                         if ((wrblksz = (int)str_offt(optarg)) <= 0) {
225                                 paxwarn(1, "Invalid block size %s", optarg);
226                                 pax_usage();
227                         }
228                         break;
229                 case 'c':
230                         /*
231                          * inverse match on patterns
232                          */
233                         cflag = 1;
234                         flg |= CF;
235                         break;
236                 case 'd':
237                         /*
238                          * match only dir on extract, not the subtree at dir
239                          */
240                         dflag = 1;
241                         flg |= DF;
242                         break;
243                 case 'f':
244                         /*
245                          * filename where the archive is stored
246                          */
247                         arcname = optarg;
248                         flg |= FF;
249                         break;
250                 case 'i':
251                         /*
252                          * interactive file rename
253                          */
254                         iflag = 1;
255                         flg |= IF;
256                         break;
257                 case 'j':
258                         /*
259                          * use bzip2.  Non standard option.
260                          */
261                         zflag = 1;
262                         gzip_program = BZIP2_CMD;
263                         break;
264                 case 'k':
265                         /*
266                          * do not clobber files that exist
267                          */
268                         kflag = 1;
269                         flg |= KF;
270                         break;
271                 case 'l':
272                         /*
273                          * try to link src to dest with copy (-rw)
274                          */
275                         lflag = 1;
276                         flg |= LF;
277                         break;
278                 case 'n':
279                         /*
280                          * select first match for a pattern only
281                          */
282                         nflag = 1;
283                         flg |= NF;
284                         break;
285                 case 'o':
286                         /*
287                          * pass format specific options
288                          */
289                         flg |= OF;
290                         if (opt_add(optarg) < 0)
291                                 pax_usage();
292                         break;
293                 case 'p':
294                         /*
295                          * specify file characteristic options
296                          */
297                         for (pt = optarg; *pt != '\0'; ++pt) {
298                                 switch(*pt) {
299                                 case 'a':
300                                         /*
301                                          * do not preserve access time
302                                          */
303                                         patime = 0;
304                                         break;
305                                 case 'e':
306                                         /*
307                                          * preserve user id, group id, file
308                                          * mode, access/modification times
309                                          */
310                                         pids = 1;
311                                         pmode = 1;
312                                         patime = 1;
313                                         pmtime = 1;
314                                         break;
315                                 case 'm':
316                                         /*
317                                          * do not preserve modification time
318                                          */
319                                         pmtime = 0;
320                                         break;
321                                 case 'o':
322                                         /*
323                                          * preserve uid/gid
324                                          */
325                                         pids = 1;
326                                         break;
327                                 case 'p':
328                                         /*
329                                          * preserver file mode bits
330                                          */
331                                         pmode = 1;
332                                         break;
333                                 default:
334                                         paxwarn(1, "Invalid -p string: %c", *pt);
335                                         pax_usage();
336                                         break;
337                                 }
338                         }
339                         flg |= PF;
340                         break;
341                 case 'r':
342                         /*
343                          * read the archive
344                          */
345                         flg |= RF;
346                         break;
347                 case 's':
348                         /*
349                          * file name substitution name pattern
350                          */
351                         if (rep_add(optarg) < 0) {
352                                 pax_usage();
353                                 break;
354                         }
355                         flg |= SF;
356                         break;
357                 case 't':
358                         /*
359                          * preserve access time on filesystem nodes we read
360                          */
361                         tflag = 1;
362                         flg |= TF;
363                         break;
364                 case 'u':
365                         /*
366                          * ignore those older files
367                          */
368                         uflag = 1;
369                         flg |= UF;
370                         break;
371                 case 'v':
372                         /*
373                          * verbose operation mode
374                          */
375                         vflag = 1;
376                         flg |= VF;
377                         break;
378                 case 'w':
379                         /*
380                          * write an archive
381                          */
382                         flg |= WF;
383                         break;
384                 case 'x':
385                         /*
386                          * specify an archive format on write
387                          */
388                         tmp.name = optarg;
389                         if ((frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
390                             sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt)) != NULL) {
391                                 flg |= XF;
392                                 break;
393                         }
394                         paxwarn(1, "Unknown -x format: %s", optarg);
395                         (void)fputs("pax: Known -x formats are:", stderr);
396                         for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
397                                 (void)fprintf(stderr, " %s", fsub[i].name);
398                         (void)fputs("\n\n", stderr);
399                         pax_usage();
400                         break;
401                 case 'z':
402                         /*
403                          * use gzip.  Non standard option.
404                          */
405                         zflag = 1;
406                         gzip_program = GZIP_CMD;
407                         break;
408                 case 'B':
409                         /*
410                          * non-standard option on number of bytes written on a
411                          * single archive volume.
412                          */
413                         if ((wrlimit = str_offt(optarg)) <= 0) {
414                                 paxwarn(1, "Invalid write limit %s", optarg);
415                                 pax_usage();
416                         }
417                         if (wrlimit % BLKMULT) {
418                                 paxwarn(1, "Write limit is not a %d byte multiple",
419                                     BLKMULT);
420                                 pax_usage();
421                         }
422                         flg |= CBF;
423                         break;
424                 case 'D':
425                         /*
426                          * On extraction check file inode change time before the
427                          * modification of the file name. Non standard option.
428                          */
429                         Dflag = 1;
430                         flg |= CDF;
431                         break;
432                 case 'E':
433                         /*
434                          * non-standard limit on read faults
435                          * 0 indicates stop after first error, values
436                          * indicate a limit, "NONE" try forever
437                          */
438                         flg |= CEF;
439                         if (strcmp(NONE, optarg) == 0)
440                                 maxflt = -1;
441                         else if ((maxflt = atoi(optarg)) < 0) {
442                                 paxwarn(1, "Error count value must be positive");
443                                 pax_usage();
444                         }
445                         break;
446                 case 'G':
447                         /*
448                          * non-standard option for selecting files within an
449                          * archive by group (gid or name)
450                          */
451                         if (grp_add(optarg) < 0) {
452                                 pax_usage();
453                                 break;
454                         }
455                         flg |= CGF;
456                         break;
457                 case 'H':
458                         /*
459                          * follow command line symlinks only
460                          */
461                         Hflag = 1;
462                         flg |= CHF;
463                         break;
464                 case 'L':
465                         /*
466                          * follow symlinks
467                          */
468                         Lflag = 1;
469                         flg |= CLF;
470                         break;
471                 case 'P':
472                         /*
473                          * do NOT follow symlinks (default)
474                          */
475                         Lflag = 0;
476                         flg |= CPF;
477                         break;
478                 case 'T':
479                         /*
480                          * non-standard option for selecting files within an
481                          * archive by modification time range (lower,upper)
482                          */
483                         if (trng_add(optarg) < 0) {
484                                 pax_usage();
485                                 break;
486                         }
487                         flg |= CTF;
488                         break;
489                 case 'U':
490                         /*
491                          * non-standard option for selecting files within an
492                          * archive by user (uid or name)
493                          */
494                         if (usr_add(optarg) < 0) {
495                                 pax_usage();
496                                 break;
497                         }
498                         flg |= CUF;
499                         break;
500                 case 'X':
501                         /*
502                          * do not pass over mount points in the file system
503                          */
504                         Xflag = 1;
505                         flg |= CXF;
506                         break;
507                 case 'Y':
508                         /*
509                          * On extraction check file inode change time after the
510                          * modification of the file name. Non standard option.
511                          */
512                         Yflag = 1;
513                         flg |= CYF;
514                         break;
515                 case 'Z':
516                         /*
517                          * On extraction check modification time after the
518                          * modification of the file name. Non standard option.
519                          */
520                         Zflag = 1;
521                         flg |= CZF;
522                         break;
523                 default:
524                         pax_usage();
525                         break;
526                 }
527         }
528
529         /*
530          * figure out the operation mode of pax read,write,extract,copy,append
531          * or list. check that we have not been given a bogus set of flags
532          * for the operation mode.
533          */
534         if (ISLIST(flg)) {
535                 act = LIST;
536                 listf = stdout;
537                 bflg = flg & BDLIST;
538         } else if (ISEXTRACT(flg)) {
539                 act = EXTRACT;
540                 bflg = flg & BDEXTR;
541         } else if (ISARCHIVE(flg)) {
542                 act = ARCHIVE;
543                 bflg = flg & BDARCH;
544         } else if (ISAPPND(flg)) {
545                 act = APPND;
546                 bflg = flg & BDARCH;
547         } else if (ISCOPY(flg)) {
548                 act = COPY;
549                 bflg = flg & BDCOPY;
550         } else
551                 pax_usage();
552         if (bflg) {
553                 printflg(flg);
554                 pax_usage();
555         }
556
557         /*
558          * if we are writing (ARCHIVE) we use the default format if the user
559          * did not specify a format. when we write during an APPEND, we will
560          * adopt the format of the existing archive if none was supplied.
561          */
562         if (!(flg & XF) && (act == ARCHIVE))
563                 frmt = &(fsub[DEFLT]);
564
565         /*
566          * process the args as they are interpreted by the operation mode
567          */
568         switch (act) {
569         case LIST:
570         case EXTRACT:
571                 for (; optind < argc; optind++)
572                         if (pat_add(argv[optind], NULL) < 0)
573                                 pax_usage();
574                 break;
575         case COPY:
576                 if (optind >= argc) {
577                         paxwarn(0, "Destination directory was not supplied");
578                         pax_usage();
579                 }
580                 --argc;
581                 dirptr = argv[argc];
582                 /* FALL THROUGH */
583         case ARCHIVE:
584         case APPND:
585                 for (; optind < argc; optind++)
586                         if (ftree_add(argv[optind], 0) < 0)
587                                 pax_usage();
588                 /*
589                  * no read errors allowed on updates/append operation!
590                  */
591                 maxflt = 0;
592                 break;
593         }
594 }
595
596
597 /*
598  * tar_options()
599  *      look at the user specified flags. set globals as required and check if
600  *      the user specified a legal set of flags. If not, complain and exit
601  */
602
603 #ifdef __STDC__
604 static void
605 tar_options(register int argc, register char **argv)
606 #else
607 static void
608 tar_options(argc, argv)
609         register int argc;
610         register char **argv;
611 #endif
612 {
613         register int c;
614         int fstdin = 0;
615         int Oflag = 0;
616
617         /*
618          * Set default values.
619          */
620         rmleadslash = 1;
621
622         /*
623          * process option flags
624          */
625         while ((c = getoldopt(argc, argv,
626             "b:cef:hjmopruts:vwxzBC:HLOPXZ014578"))
627             != EOF) {
628                 switch(c) {
629                 case 'b':
630                         /*
631                          * specify blocksize in 512-byte blocks
632                          */
633                         if ((wrblksz = (int)str_offt(optarg)) <= 0) {
634                                 paxwarn(1, "Invalid block size %s", optarg);
635                                 tar_usage();
636                         }
637                         wrblksz *= 512;         /* XXX - check for int oflow */
638                         break;
639                 case 'c':
640                         /*
641                          * create an archive
642                          */
643                         act = ARCHIVE;
644                         break;
645                 case 'e':
646                         /*
647                          * stop after first error
648                          */
649                         maxflt = 0;
650                         break;
651                 case 'f':
652                         /*
653                          * filename where the archive is stored
654                          */
655                         if ((optarg[0] == '-') && (optarg[1]== '\0')) {
656                                 /*
657                                  * treat a - as stdin
658                                  */
659                                 fstdin = 1;
660                                 arcname = NULL;
661                                 break;
662                         }
663                         fstdin = 0;
664                         arcname = optarg;
665                         break;
666                 case 'h':
667                         /*
668                          * follow symlinks
669                          */
670                         Lflag = 1;
671                         break;
672                 case 'j':
673                         /*
674                          * use bzip2.  Non standard option.
675                          */
676                         zflag = 1;
677                         gzip_program = BZIP2_CMD;
678                         break;
679                 case 'm':
680                         /*
681                          * do not preserve modification time
682                          */
683                         pmtime = 0;
684                         break;
685                 case 'o':
686                         if (opt_add("write_opt=nodir") < 0)
687                                 tar_usage();
688                 case 'O':
689                         Oflag = 1;
690                         break;
691                 case 'p':
692                         /*
693                          * preserve uid/gid and file mode, regardless of umask
694                          */
695                         pmode = 1;
696                         pids = 1;
697                         break;
698                 case 'r':
699                 case 'u':
700                         /*
701                          * append to the archive
702                          */
703                         act = APPND;
704                         break;
705                 case 's':
706                         /*
707                          * file name substitution name pattern
708                          */
709                         if (rep_add(optarg) < 0) {
710                                 tar_usage();
711                                 break;
712                         }
713                         break;
714                 case 't':
715                         /*
716                          * list contents of the tape
717                          */
718                         act = LIST;
719                         break;
720                 case 'v':
721                         /*
722                          * verbose operation mode
723                          */
724                         vflag++;
725                         break;
726                 case 'w':
727                         /*
728                          * interactive file rename
729                          */
730                         iflag = 1;
731                         break;
732                 case 'x':
733                         /*
734                          * extract an archive, preserving mode,
735                          * and mtime if possible.
736                          */
737                         act = EXTRACT;
738                         pmtime = 1;
739                         break;
740                 case 'z':
741                         /*
742                          * use gzip.  Non standard option.
743                          */
744                         zflag = 1;
745                         gzip_program = GZIP_CMD;
746                         break;
747                 case 'B':
748                         /*
749                          * Nothing to do here, this is pax default
750                          */
751                         break;
752                 case 'C':
753                         chdname = optarg;
754                         break;
755                 case 'H':
756                         /*
757                          * follow command line symlinks only
758                          */
759                         Hflag = 1;
760                         break;
761                 case 'L':
762                         /*
763                          * follow symlinks
764                          */
765                         Lflag = 1;
766                         break;
767                 case 'P':
768                         /*
769                          * do not remove leading '/' from pathnames
770                          */
771                         rmleadslash = 0;
772                         break;
773                 case 'X':
774                         /*
775                          * do not pass over mount points in the file system
776                          */
777                         Xflag = 1;
778                         break;
779                 case 'Z':
780                         /*
781                          * use compress.
782                          */
783                         zflag = 1;
784                         gzip_program = COMPRESS_CMD;
785                         break;
786                 case '0':
787                         arcname = DEV_0;
788                         break;
789                 case '1':
790                         arcname = DEV_1;
791                         break;
792                 case '4':
793                         arcname = DEV_4;
794                         break;
795                 case '5':
796                         arcname = DEV_5;
797                         break;
798                 case '7':
799                         arcname = DEV_7;
800                         break;
801                 case '8':
802                         arcname = DEV_8;
803                         break;
804                 default:
805                         tar_usage();
806                         break;
807                 }
808         }
809         argc -= optind;
810         argv += optind;
811
812         /* Traditional tar behaviour (pax uses stderr unless in list mode) */
813         if (fstdin == 1 && act == ARCHIVE)
814                 listf = stderr;
815         else
816                 listf = stdout;
817
818         /* Traditional tar behaviour (pax wants to read filelist from stdin) */
819         if ((act == ARCHIVE || act == APPND) && argc == 0)
820                 exit(0);
821
822         /*
823          * if we are writing (ARCHIVE) specify tar, otherwise run like pax
824          * (unless -o specified)
825          */
826         if (act == ARCHIVE || act == APPND)
827                 frmt = &(fsub[Oflag ? F_OTAR : F_TAR]);
828         else if (Oflag) {
829                 paxwarn(1, "The -O/-o options are only valid when writing an archive");
830                 tar_usage();            /* only valid when writing */
831         }
832
833         /*
834          * process the args as they are interpreted by the operation mode
835          */
836         switch (act) {
837         case LIST:
838         case EXTRACT:
839         default:
840                 {
841                         int sawpat = 0;
842
843                         while (*argv != NULL) {
844                                 if (strcmp(*argv, "-C") == 0) {
845                                         if(*++argv == NULL)
846                                                 break;
847                                         chdname = *argv++;
848
849                                         continue;
850                                 }
851                                 if (pat_add(*argv++, chdname) < 0)
852                                         tar_usage();
853                                 sawpat++;
854                         }
855                         /*
856                          * if patterns were added, we are doing chdir()
857                          * on a file-by-file basis, else, just one 
858                          * global chdir (if any) after opening input.
859                          */
860                         if (sawpat > 0)
861                                 chdname = NULL;
862                 }
863                 break;
864         case ARCHIVE:
865         case APPND:
866                 if (chdname != NULL) {  /* initial chdir() */
867                         if (ftree_add(chdname, 1) < 0)
868                                 tar_usage();
869                 }
870
871                 while (*argv != NULL) {
872                         if (!strcmp(*argv, "-C")) {
873                                 if (*++argv == NULL)
874                                         break;
875                                 if (ftree_add(*argv++, 1) < 0)
876                                         tar_usage();
877                         } else {
878                                 if (ftree_add(*argv++, 0) < 0)
879                                         tar_usage();
880                         }
881                 }
882                 /*
883                  * no read errors allowed on updates/append operation!
884                  */
885                 maxflt = 0;
886                 break;
887         }
888         if (!fstdin && ((arcname == NULL) || (*arcname == '\0'))) {
889                 arcname = getenv("TAPE");
890                 if ((arcname == NULL) || (*arcname == '\0'))
891                         arcname = _PATH_DEFTAPE;
892         }
893 }
894
895 int
896 mkpath(path)
897         char *path;
898 {
899         struct stat sb;
900         register char *slash;
901         int done = 0;
902
903         slash = path;
904
905         while (!done) {
906                 slash += strspn(slash, "/");
907                 slash += strcspn(slash, "/");
908
909                 done = (*slash == '\0');
910                 *slash = '\0';
911
912                 if (stat(path, &sb)) {
913                         if (errno != ENOENT || mkdir(path, 0777)) {
914                                 paxwarn(1, "%s", path);
915                                 return (-1);
916                         }
917                 } else if (!S_ISDIR(sb.st_mode)) {
918                         syswarn(1, ENOTDIR, "%s", path);
919                         return (-1);
920                 }
921
922                 if (!done)
923                         *slash = '/';
924         }
925
926         return (0);
927 }
928 /*
929  * cpio_options()
930  *      look at the user specified flags. set globals as required and check if
931  *      the user specified a legal set of flags. If not, complain and exit
932  */
933
934 #ifdef __STDC__
935 static void
936 cpio_options(register int argc, register char **argv)
937 #else
938 static void
939 cpio_options(argc, argv)
940         register int argc;
941         register char **argv;
942 #endif
943 {
944         register int c, i;
945         size_t len;
946         char *str;
947         FSUB tmp;
948         FILE *fp;
949
950         kflag = 1;
951         pids = 1;
952         pmode = 1;
953         pmtime = 0;
954         arcname = NULL;
955         dflag = 1;
956         act = -1;
957         nodirs = 1;
958         while ((c=getopt(argc,argv,"abcdfijklmoprstuvzABC:E:F:H:I:LO:SZ6")) != EOF)
959                 switch (c) {
960                         case 'a':
961                                 /*
962                                  * preserve access time on files read
963                                  */
964                                 tflag = 1;
965                                 break;
966                         case 'b':
967                                 /*
968                                  * swap bytes and half-words when reading data
969                                  */
970                                 break;
971                         case 'c':
972                                 /*
973                                  * ASCII cpio header
974                                  */
975                                 frmt = &(fsub[F_ACPIO]);
976                                 break;
977                         case 'd':
978                                 /*
979                                  * create directories as needed
980                                  */
981                                 nodirs = 0;
982                                 break;
983                         case 'f':
984                                 /*
985                                  * invert meaning of pattern list
986                                  */
987                                 cflag = 1;
988                                 break;
989                         case 'i':
990                                 /*
991                                  * restore an archive
992                                  */
993                                 act = EXTRACT;
994                                 break;
995                         case 'j':
996                                 /*
997                                  * use bzip2.  Non standard option.
998                                  */
999                                 zflag = 1;
1000                                 gzip_program = BZIP2_CMD;
1001                                 break;
1002                         case 'k':
1003                                 break;
1004                         case 'l':
1005                                 /*
1006                                  * use links instead of copies when possible
1007                                  */
1008                                 lflag = 1;
1009                                 break;
1010                         case 'm':
1011                                 /*
1012                                  * preserve modification time
1013                                  */
1014                                 pmtime = 1;
1015                                 break;
1016                         case 'o':
1017                                 /*
1018                                  * create an archive
1019                                  */
1020                                 act = ARCHIVE;
1021                                 frmt = &(fsub[F_CPIO]);
1022                                 break;
1023                         case 'p':
1024                                 /*
1025                                  * copy-pass mode
1026                                  */
1027                                 act = COPY;
1028                                 break;
1029                         case 'r':
1030                                 /*
1031                                  * interactively rename files
1032                                  */
1033                                 iflag = 1;
1034                                 break;
1035                         case 's':
1036                                 /*
1037                                  * swap bytes after reading data
1038                                  */
1039                                 break;
1040                         case 't':
1041                                 /*
1042                                  * list contents of archive
1043                                  */
1044                                 act = LIST;
1045                                 listf = stdout;
1046                                 break;
1047                         case 'u':
1048                                 /*
1049                                  * replace newer files
1050                                  */
1051                                 kflag = 0;
1052                                 break;
1053                         case 'v':
1054                                 /*
1055                                  * verbose operation mode
1056                                  */
1057                                 vflag = 1;
1058                                 break;
1059                         case 'z':
1060                                 /*
1061                                  * use gzip.  Non standard option.
1062                                  */
1063                                 zflag = 1;
1064                                 gzip_program = GZIP_CMD;
1065                                 break;
1066                         case 'A':
1067                                 /*
1068                                  * append mode
1069                                  */
1070                                 act = APPND;
1071                                 break;
1072                         case 'B':
1073                                 /*
1074                                  * Use 5120 byte block size
1075                                  */
1076                                 wrblksz = 5120;
1077                                 break;
1078                         case 'C':
1079                                 /*
1080                                  * set block size in bytes
1081                                  */
1082                                 wrblksz = atoi(optarg);
1083                                 break;
1084                         case 'E':
1085                                 /*
1086                                  * file with patterns to extract or list
1087                                  */
1088                                 if ((fp = fopen(optarg, "r")) == NULL) {
1089                                         paxwarn(1, "Unable to open file '%s' for read", optarg);
1090                                         cpio_usage();
1091                                 }
1092                                 while ((str = fgetln(fp, &len)) != NULL) {
1093                                         str[len - 1] = '\0';
1094                                         pat_add(str, NULL);
1095                                 }
1096                                 fclose(fp);
1097                                 break;
1098                         case 'F':
1099                         case 'I':
1100                         case 'O':
1101                                 /*
1102                                  * filename where the archive is stored
1103                                  */
1104                                 if ((optarg[0] == '-') && (optarg[1]== '\0')) {
1105                                         /*
1106                                          * treat a - as stdin
1107                                          */
1108                                         arcname = NULL;
1109                                         break;
1110                                 }
1111                                 arcname = optarg;
1112                                 break;
1113                         case 'H':
1114                                 /*
1115                                  * specify an archive format on write
1116                                  */
1117                                 tmp.name = optarg;
1118                                 if ((frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
1119                                     sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt)) != NULL)
1120                                         break;
1121                                 paxwarn(1, "Unknown -H format: %s", optarg);
1122                                 (void)fputs("cpio: Known -H formats are:", stderr);
1123                                 for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
1124                                         (void)fprintf(stderr, " %s", fsub[i].name);
1125                                 (void)fputs("\n\n", stderr);
1126                                 cpio_usage();
1127                                 break;
1128                         case 'L':
1129                                 /*
1130                                  * follow symbolic links
1131                                  */
1132                                 Lflag = 1;
1133                                 break;
1134                         case 'S':
1135                                 /*
1136                                  * swap halfwords after reading data
1137                                  */
1138                                 break;
1139                         case 'Z':
1140                                 /*
1141                                  * use compress.  Non standard option.
1142                                  */
1143                                 zflag = 1;
1144                                 gzip_program = COMPRESS_CMD;
1145                                 break;
1146                         case '6':
1147                                 /*
1148                                  * process Version 6 cpio format
1149                                  */
1150                                 frmt = &(fsub[F_OCPIO]);
1151                                 break;
1152                         case '?':
1153                         default:
1154                                 cpio_usage();
1155                                 break;
1156                 }
1157         argc -= optind;
1158         argv += optind;
1159
1160         /*
1161          * process the args as they are interpreted by the operation mode
1162          */
1163         switch (act) {
1164                 case LIST:
1165                 case EXTRACT:
1166                         while (*argv != NULL)
1167                                 if (pat_add(*argv++, NULL) < 0)
1168                                         cpio_usage();
1169                         break;
1170                 case COPY:
1171                         if (*argv == NULL) {
1172                                 paxwarn(0, "Destination directory was not supplied");
1173                                 cpio_usage();
1174                         }
1175                         dirptr = *argv;
1176                         if (mkpath(dirptr) < 0)
1177                                 cpio_usage();
1178                         --argc;
1179                         ++argv;
1180                         /* FALL THROUGH */
1181                 case ARCHIVE:
1182                 case APPND:
1183                         if (*argv != NULL)
1184                                 cpio_usage();
1185                         /*
1186                          * no read errors allowed on updates/append operation!
1187                          */
1188                         maxflt = 0;
1189                         while ((str = fgetln(stdin, &len)) != NULL) {
1190                                 str[len - 1] = '\0';
1191                                 ftree_add(strdup(str), NULL);
1192                         }
1193                         break;
1194                 default:
1195                         cpio_usage();
1196                         break;
1197         }
1198 }
1199
1200 /*
1201  * printflg()
1202  *      print out those invalid flag sets found to the user
1203  */
1204
1205 #ifdef __STDC__
1206 static void
1207 printflg(unsigned int flg)
1208 #else
1209 static void
1210 printflg(flg)
1211         unsigned int flg;
1212 #endif
1213 {
1214         int nxt;
1215         int pos = 0;
1216
1217         (void)fprintf(stderr,"%s: Invalid combination of options:", argv0);
1218         while ((nxt = ffs(flg)) != 0) {
1219                 flg = flg >> nxt;
1220                 pos += nxt;
1221                 (void)fprintf(stderr, " -%c", flgch[pos-1]);
1222         }
1223         (void)putc('\n', stderr);
1224 }
1225
1226 /*
1227  * c_frmt()
1228  *      comparison routine used by bsearch to find the format specified
1229  *      by the user
1230  */
1231
1232 #ifdef __STDC__
1233 static int
1234 c_frmt(const void *a, const void *b)
1235 #else
1236 static int
1237 c_frmt(a, b)
1238         void *a;
1239         void *b;
1240 #endif
1241 {
1242         return(strcmp(((FSUB *)a)->name, ((FSUB *)b)->name));
1243 }
1244
1245 /*
1246  * opt_next()
1247  *      called by format specific options routines to get each format specific
1248  *      flag and value specified with -o
1249  * Return:
1250  *      pointer to next OPLIST entry or NULL (end of list).
1251  */
1252
1253 #ifdef __STDC__
1254 OPLIST *
1255 opt_next(void)
1256 #else
1257 OPLIST *
1258 opt_next()
1259 #endif
1260 {
1261         OPLIST *opt;
1262
1263         if ((opt = ophead) != NULL)
1264                 ophead = ophead->fow;
1265         return(opt);
1266 }
1267
1268 /*
1269  * bad_opt()
1270  *      generic routine used to complain about a format specific options
1271  *      when the format does not support options.
1272  */
1273
1274 #ifdef __STDC__
1275 int
1276 bad_opt(void)
1277 #else
1278 int
1279 bad_opt()
1280 #endif
1281 {
1282         register OPLIST *opt;
1283
1284         if (ophead == NULL)
1285                 return(0);
1286         /*
1287          * print all we were given
1288          */
1289         paxwarn(1,"These format options are not supported");
1290         while ((opt = opt_next()) != NULL)
1291                 (void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value);
1292         pax_usage();
1293         return(0);
1294 }
1295
1296 /*
1297  * opt_add()
1298  *      breaks the value supplied to -o into a option name and value. options
1299  *      are given to -o in the form -o name-value,name=value
1300  *      mulltiple -o may be specified.
1301  * Return:
1302  *      0 if format in name=value format, -1 if -o is passed junk
1303  */
1304
1305 #ifdef __STDC__
1306 int
1307 opt_add(register char *str)
1308 #else
1309 int
1310 opt_add(str)
1311         register char *str;
1312 #endif
1313 {
1314         register OPLIST *opt;
1315         register char *frpt;
1316         register char *pt;
1317         register char *endpt;
1318
1319         if ((str == NULL) || (*str == '\0')) {
1320                 paxwarn(0, "Invalid option name");
1321                 return(-1);
1322         }
1323         if ((str = strdup(str)) == NULL) {
1324                 paxwarn(0, "Unable to allocate space for option list");
1325                 return(-1);
1326         }
1327         frpt = endpt = str;
1328
1329         /*
1330          * break into name and values pieces and stuff each one into a
1331          * OPLIST structure. When we know the format, the format specific
1332          * option function will go through this list
1333          */
1334         while ((frpt != NULL) && (*frpt != '\0')) {
1335                 if ((endpt = strchr(frpt, ',')) != NULL)
1336                         *endpt = '\0';
1337                 if ((pt = strchr(frpt, '=')) == NULL) {
1338                         paxwarn(0, "Invalid options format");
1339                         free(str);
1340                         return(-1);
1341                 }
1342                 if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
1343                         paxwarn(0, "Unable to allocate space for option list");
1344                         free(str);
1345                         return(-1);
1346                 }
1347                 *pt++ = '\0';
1348                 opt->name = frpt;
1349                 opt->value = pt;
1350                 opt->fow = NULL;
1351                 if (endpt != NULL)
1352                         frpt = endpt + 1;
1353                 else
1354                         frpt = NULL;
1355                 if (ophead == NULL) {
1356                         optail = ophead = opt;
1357                         continue;
1358                 }
1359                 optail->fow = opt;
1360                 optail = opt;
1361         }
1362         return(0);
1363 }
1364
1365 /*
1366  * str_offt()
1367  *      Convert an expression of the following forms to an off_t > 0.
1368  *      1) A positive decimal number.
1369  *      2) A positive decimal number followed by a b (mult by 512).
1370  *      3) A positive decimal number followed by a k (mult by 1024).
1371  *      4) A positive decimal number followed by a m (mult by 512).
1372  *      5) A positive decimal number followed by a w (mult by sizeof int)
1373  *      6) Two or more positive decimal numbers (with/without k,b or w).
1374  *         seperated by x (also * for backwards compatibility), specifying
1375  *         the product of the indicated values.
1376  * Return:
1377  *      0 for an error, a positive value o.w.
1378  */
1379
1380 #ifdef __STDC__
1381 static off_t
1382 str_offt(char *val)
1383 #else
1384 static off_t
1385 str_offt(val)
1386         char *val;
1387 #endif
1388 {
1389         char *expr;
1390         off_t num, t;
1391
1392 #       ifdef NET2_STAT
1393         num = strtol(val, &expr, 0);
1394         if ((num == LONG_MAX) || (num <= 0) || (expr == val))
1395 #       else
1396         num = strtoq(val, &expr, 0);
1397         if ((num == QUAD_MAX) || (num <= 0) || (expr == val))
1398 #       endif
1399                 return(0);
1400
1401         switch(*expr) {
1402         case 'b':
1403                 t = num;
1404                 num *= 512;
1405                 if (t > num)
1406                         return(0);
1407                 ++expr;
1408                 break;
1409         case 'k':
1410                 t = num;
1411                 num *= 1024;
1412                 if (t > num)
1413                         return(0);
1414                 ++expr;
1415                 break;
1416         case 'm':
1417                 t = num;
1418                 num *= 1048576;
1419                 if (t > num)
1420                         return(0);
1421                 ++expr;
1422                 break;
1423         case 'w':
1424                 t = num;
1425                 num *= sizeof(int);
1426                 if (t > num)
1427                         return(0);
1428                 ++expr;
1429                 break;
1430         }
1431
1432         switch(*expr) {
1433                 case '\0':
1434                         break;
1435                 case '*':
1436                 case 'x':
1437                         t = num;
1438                         num *= str_offt(expr + 1);
1439                         if (t > num)
1440                                 return(0);
1441                         break;
1442                 default:
1443                         return(0);
1444         }
1445         return(num);
1446 }
1447
1448 /*
1449  * no_op()
1450  *      for those option functions where the archive format has nothing to do.
1451  * Return:
1452  *      0
1453  */
1454
1455 #ifdef __STDC__
1456 static int
1457 no_op(void)
1458 #else
1459 static int
1460 no_op()
1461 #endif
1462 {
1463         return(0);
1464 }
1465
1466 /*
1467  * pax_usage()
1468  *      print the usage summary to the user
1469  */
1470
1471 #ifdef __STDC__
1472 void
1473 pax_usage(void)
1474 #else
1475 void
1476 pax_usage()
1477 #endif
1478 {
1479         (void)fputs("usage: pax [-cdjnvz] [-E limit] [-f archive] ", stderr);
1480         (void)fputs("[-s replstr] ... [-U user] ...", stderr);
1481         (void)fputs("\n           [-G group] ... ", stderr);
1482         (void)fputs("[-T [from_date][,to_date]] ... ", stderr);
1483         (void)fputs("[pattern ...]\n", stderr);
1484         (void)fputs("       pax -r [-cdijknuvzDYZ] [-E limit] ", stderr);
1485         (void)fputs("[-f archive] [-o options] ... \n", stderr);
1486         (void)fputs("           [-p string] ... [-s replstr] ... ", stderr);
1487         (void)fputs("[-U user] ... [-G group] ...\n           ", stderr);
1488         (void)fputs("[-T [from_date][,to_date]] ... ", stderr);
1489         (void)fputs(" [pattern ...]\n", stderr);
1490         (void)fputs("       pax -w [-dijtuvzHLPX] [-b blocksize] ", stderr);
1491         (void)fputs("[ [-a] [-f archive] ] [-x format] \n", stderr);
1492         (void)fputs("           [-B bytes] [-s replstr] ... ", stderr);
1493         (void)fputs("[-o options] ... [-U user] ...", stderr);
1494         (void)fputs("\n           [-G group] ... ", stderr);
1495         (void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
1496         (void)fputs("[file ...]\n", stderr);
1497         (void)fputs("       pax -r -w [-diklntuvDHLPXYZ] ", stderr);
1498         (void)fputs("[-p string] ... [-s replstr] ...", stderr);
1499         (void)fputs("\n           [-U user] ... [-G group] ... ", stderr);
1500         (void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
1501         (void)fputs("\n           [file ...] directory\n", stderr);
1502         exit(1);
1503 }
1504
1505 /*
1506  * tar_usage()
1507  *      print the usage summary to the user
1508  */
1509
1510 #ifdef __STDC__
1511 void
1512 tar_usage(void)
1513 #else
1514 void
1515 tar_usage()
1516 #endif
1517 {
1518         (void)fputs("usage: tar -{txru}[cevfbjmopswzBHLPXZ014578] [tapefile] ",
1519                  stderr);
1520         (void)fputs("[blocksize] [replstr] [-C directory] file1 file2...\n",
1521             stderr);
1522         exit(1);
1523 }
1524
1525 /*
1526  * cpio_usage()
1527  *      print the usage summary to the user
1528  */
1529
1530 #ifdef __STDC__
1531 void
1532 cpio_usage(void)
1533 #else
1534 void
1535 cpio_usage()
1536 #endif
1537 {
1538         (void)fputs("usage: cpio -o [-aABcjLvVzZ] [-C bytes] [-H format] [-O archive]\n", stderr);
1539         (void)fputs("               [-F archive] < name-list [> archive]\n", stderr);
1540         (void)fputs("       cpio -i [-bBcdfjmnrsStuvVzZ6] [-C bytes] [-E file] [-H format]\n", stderr);
1541         (void)fputs("               [-I archive] [-F archive] [pattern...] [< archive]\n", stderr);
1542         (void)fputs("       cpio -p [-adlLmuvV] destination-directory < name-list\n", stderr);
1543         exit(1);
1544 }