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