1b4bb70ccSBruce Evans /*-
28a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
38a16b7a1SPedro F. Giffuni *
44b88c807SRodney W. Grimes * Copyright (c) 1992 Keith Muller.
54b88c807SRodney W. Grimes * Copyright (c) 1992, 1993
64b88c807SRodney W. Grimes * The Regents of the University of California. All rights reserved.
74b88c807SRodney W. Grimes *
84b88c807SRodney W. Grimes * This code is derived from software contributed to Berkeley by
94b88c807SRodney W. Grimes * Keith Muller of the University of California, San Diego.
104b88c807SRodney W. Grimes *
114b88c807SRodney W. Grimes * Redistribution and use in source and binary forms, with or without
124b88c807SRodney W. Grimes * modification, are permitted provided that the following conditions
134b88c807SRodney W. Grimes * are met:
144b88c807SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright
154b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer.
164b88c807SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright
174b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the
184b88c807SRodney W. Grimes * documentation and/or other materials provided with the distribution.
19fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors
204b88c807SRodney W. Grimes * may be used to endorse or promote products derived from this software
214b88c807SRodney W. Grimes * without specific prior written permission.
224b88c807SRodney W. Grimes *
234b88c807SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
244b88c807SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
254b88c807SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
264b88c807SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
274b88c807SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
284b88c807SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
294b88c807SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
304b88c807SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
314b88c807SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
324b88c807SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
334b88c807SRodney W. Grimes * SUCH DAMAGE.
344b88c807SRodney W. Grimes */
354b88c807SRodney W. Grimes
364b88c807SRodney W. Grimes #include <sys/types.h>
374b88c807SRodney W. Grimes #include <sys/stat.h>
384b88c807SRodney W. Grimes #include <sys/mtio.h>
394b88c807SRodney W. Grimes #include <stdio.h>
404b88c807SRodney W. Grimes #include <string.h>
41b1787decSKris Kennaway #include <errno.h>
424b88c807SRodney W. Grimes #include <unistd.h>
434b88c807SRodney W. Grimes #include <stdlib.h>
444b88c807SRodney W. Grimes #include <limits.h>
45b1787decSKris Kennaway #include <paths.h>
464b88c807SRodney W. Grimes #include "pax.h"
474b88c807SRodney W. Grimes #include "options.h"
484b88c807SRodney W. Grimes #include "cpio.h"
494b88c807SRodney W. Grimes #include "tar.h"
504b88c807SRodney W. Grimes #include "extern.h"
514b88c807SRodney W. Grimes
524b88c807SRodney W. Grimes /*
534b88c807SRodney W. Grimes * Routines which handle command line options
544b88c807SRodney W. Grimes */
554b88c807SRodney W. Grimes
564b88c807SRodney W. Grimes static char flgch[] = FLGCH; /* list of all possible flags */
574b88c807SRodney W. Grimes static OPLIST *ophead = NULL; /* head for format specific options -x */
584b88c807SRodney W. Grimes static OPLIST *optail = NULL; /* option tail */
594b88c807SRodney W. Grimes
6046251ddeSWarner Losh static int no_op(void);
6146251ddeSWarner Losh static void printflg(unsigned int);
6246251ddeSWarner Losh static int c_frmt(const void *, const void *);
6346251ddeSWarner Losh static off_t str_offt(char *);
64a651f2bcSBaptiste Daroussin static char *get_line(FILE *fp);
65f789b261SWarner Losh static void pax_options(int, char **);
6646251ddeSWarner Losh static void pax_usage(void);
67f789b261SWarner Losh static void tar_options(int, char **);
6846251ddeSWarner Losh static void tar_usage(void);
69f789b261SWarner Losh static void cpio_options(int, char **);
7046251ddeSWarner Losh static void cpio_usage(void);
71b1787decSKris Kennaway
72a651f2bcSBaptiste Daroussin /* errors from get_line */
73b1787decSKris Kennaway #define GETLINE_FILE_CORRUPT 1
74b1787decSKris Kennaway #define GETLINE_OUT_OF_MEM 2
75a651f2bcSBaptiste Daroussin static int get_line_error;
76b1787decSKris Kennaway
77ae824d80SEd Schouten char *chdname;
784b88c807SRodney W. Grimes
791192d531SKris Kennaway #define GZIP_CMD "gzip" /* command to run as gzip */
801192d531SKris Kennaway #define COMPRESS_CMD "compress" /* command to run as compress */
810266a5d6SDag-Erling Smørgrav #define BZIP2_CMD "bzip2" /* command to run as bzip2 */
821192d531SKris Kennaway
834b88c807SRodney W. Grimes /*
844b88c807SRodney W. Grimes * Format specific routine table - MUST BE IN SORTED ORDER BY NAME
854b88c807SRodney W. Grimes * (see pax.h for description of each function)
864b88c807SRodney W. Grimes *
874b88c807SRodney W. Grimes * name, blksz, hdsz, udev, hlk, blkagn, inhead, id, st_read,
884b88c807SRodney W. Grimes * read, end_read, st_write, write, end_write, trail,
894b88c807SRodney W. Grimes * rd_data, wr_data, options
904b88c807SRodney W. Grimes */
914b88c807SRodney W. Grimes
924b88c807SRodney W. Grimes FSUB fsub[] = {
934b88c807SRodney W. Grimes /* 0: OLD BINARY CPIO */
940fd510b7SJoerg Wunsch {"bcpio", 5120, sizeof(HD_BCPIO), 1, 0, 0, 1, bcpio_id, cpio_strd,
954b88c807SRodney W. Grimes bcpio_rd, bcpio_endrd, cpio_stwr, bcpio_wr, cpio_endwr, cpio_trail,
9640feca3aSMark Murray NULL, rd_wrfile, wr_rdfile, bad_opt},
974b88c807SRodney W. Grimes
984b88c807SRodney W. Grimes /* 1: OLD OCTAL CHARACTER CPIO */
990fd510b7SJoerg Wunsch {"cpio", 5120, sizeof(HD_CPIO), 1, 0, 0, 1, cpio_id, cpio_strd,
1004b88c807SRodney W. Grimes cpio_rd, cpio_endrd, cpio_stwr, cpio_wr, cpio_endwr, cpio_trail,
10140feca3aSMark Murray NULL, rd_wrfile, wr_rdfile, bad_opt},
1024b88c807SRodney W. Grimes
1034b88c807SRodney W. Grimes /* 2: SVR4 HEX CPIO */
1040fd510b7SJoerg Wunsch {"sv4cpio", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, vcpio_id, cpio_strd,
1054b88c807SRodney W. Grimes vcpio_rd, vcpio_endrd, cpio_stwr, vcpio_wr, cpio_endwr, cpio_trail,
10640feca3aSMark Murray NULL, rd_wrfile, wr_rdfile, bad_opt},
1074b88c807SRodney W. Grimes
1084b88c807SRodney W. Grimes /* 3: SVR4 HEX CPIO WITH CRC */
1090fd510b7SJoerg Wunsch {"sv4crc", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd,
1104b88c807SRodney W. Grimes vcpio_rd, vcpio_endrd, crc_stwr, vcpio_wr, cpio_endwr, cpio_trail,
11140feca3aSMark Murray NULL, rd_wrfile, wr_rdfile, bad_opt},
1124b88c807SRodney W. Grimes
1134b88c807SRodney W. Grimes /* 4: OLD TAR */
1140fd510b7SJoerg Wunsch {"tar", 10240, BLKMULT, 0, 1, BLKMULT, 0, tar_id, no_op,
11540feca3aSMark Murray tar_rd, tar_endrd, no_op, tar_wr, tar_endwr, NULL, tar_trail,
1160fd510b7SJoerg Wunsch rd_wrfile, wr_rdfile, tar_opt},
1174b88c807SRodney W. Grimes
1184b88c807SRodney W. Grimes /* 5: POSIX USTAR */
1190fd510b7SJoerg Wunsch {"ustar", 10240, BLKMULT, 0, 1, BLKMULT, 0, ustar_id, ustar_strd,
12040feca3aSMark Murray ustar_rd, tar_endrd, ustar_stwr, ustar_wr, tar_endwr, NULL, tar_trail,
1210fd510b7SJoerg Wunsch rd_wrfile, wr_rdfile, bad_opt},
1224b88c807SRodney W. Grimes };
123b1787decSKris Kennaway #define F_OCPIO 0 /* format when called as cpio -6 */
124b1787decSKris Kennaway #define F_ACPIO 1 /* format when called as cpio -c */
125*a8e8a914SDag-Erling Smørgrav #define F_SCPIO 2 /* format when called with -x sv4cpio */
126b1787decSKris Kennaway #define F_CPIO 3 /* format when called as cpio */
127b1787decSKris Kennaway #define F_OTAR 4 /* format when called as tar -o */
128b1787decSKris Kennaway #define F_TAR 5 /* format when called as tar */
129*a8e8a914SDag-Erling Smørgrav #define DEFLT F_TAR /* default write format from list above */
1304b88c807SRodney W. Grimes
1314b88c807SRodney W. Grimes /*
1324b88c807SRodney W. Grimes * ford is the archive search order used by get_arc() to determine what kind
1334b88c807SRodney W. Grimes * of archive we are dealing with. This helps to properly id archive formats
1344b88c807SRodney W. Grimes * some formats may be subsets of others....
1354b88c807SRodney W. Grimes */
136*a8e8a914SDag-Erling Smørgrav int ford[] = {F_TAR, F_OTAR, F_CPIO, F_SCPIO, F_ACPIO, F_OCPIO, -1 };
1374b88c807SRodney W. Grimes
1384b88c807SRodney W. Grimes /*
1394b88c807SRodney W. Grimes * options()
1404b88c807SRodney W. Grimes * figure out if we are pax, tar or cpio. Call the appropriate options
1414b88c807SRodney W. Grimes * parser
1424b88c807SRodney W. Grimes */
1434b88c807SRodney W. Grimes
1444b88c807SRodney W. Grimes void
options(int argc,char ** argv)145f789b261SWarner Losh options(int argc, char **argv)
1464b88c807SRodney W. Grimes {
1474b88c807SRodney W. Grimes
1484b88c807SRodney W. Grimes /*
1494b88c807SRodney W. Grimes * Are we acting like pax, tar or cpio (based on argv[0])
1504b88c807SRodney W. Grimes */
1514b88c807SRodney W. Grimes if ((argv0 = strrchr(argv[0], '/')) != NULL)
1524b88c807SRodney W. Grimes argv0++;
1534b88c807SRodney W. Grimes else
1544b88c807SRodney W. Grimes argv0 = argv[0];
1554b88c807SRodney W. Grimes
156c113db69SPhilippe Charnier if (strcmp(NM_TAR, argv0) == 0) {
157c113db69SPhilippe Charnier tar_options(argc, argv);
158c113db69SPhilippe Charnier return;
159c113db69SPhilippe Charnier }
160c113db69SPhilippe Charnier else if (strcmp(NM_CPIO, argv0) == 0) {
161c113db69SPhilippe Charnier cpio_options(argc, argv);
162c113db69SPhilippe Charnier return;
163c113db69SPhilippe Charnier }
1644b88c807SRodney W. Grimes /*
1654b88c807SRodney W. Grimes * assume pax as the default
1664b88c807SRodney W. Grimes */
1674b88c807SRodney W. Grimes argv0 = NM_PAX;
168c113db69SPhilippe Charnier pax_options(argc, argv);
169c113db69SPhilippe Charnier return;
1704b88c807SRodney W. Grimes }
1714b88c807SRodney W. Grimes
1724b88c807SRodney W. Grimes /*
1734b88c807SRodney W. Grimes * pax_options()
1744b88c807SRodney W. Grimes * look at the user specified flags. set globals as required and check if
1754b88c807SRodney W. Grimes * the user specified a legal set of flags. If not, complain and exit
1764b88c807SRodney W. Grimes */
1774b88c807SRodney W. Grimes
1784b88c807SRodney W. Grimes static void
pax_options(int argc,char ** argv)179f789b261SWarner Losh pax_options(int argc, char **argv)
1804b88c807SRodney W. Grimes {
181f789b261SWarner Losh int c;
182cee22cbdSDavid E. O'Brien size_t i;
1834b88c807SRodney W. Grimes unsigned int flg = 0;
1844b88c807SRodney W. Grimes unsigned int bflg = 0;
185f789b261SWarner Losh char *pt;
1864b88c807SRodney W. Grimes FSUB tmp;
1874b88c807SRodney W. Grimes
1884b88c807SRodney W. Grimes /*
1894b88c807SRodney W. Grimes * process option flags
1904b88c807SRodney W. Grimes */
191d6e1f8d7SEitan Adler while ((c=getopt(argc,argv,"ab:cdf:iklno:p:rs:tuvwx:zB:DE:G:HLOPT:U:XYZ"))
19293ef08afSWarner Losh != -1) {
1934b88c807SRodney W. Grimes switch (c) {
1944b88c807SRodney W. Grimes case 'a':
1954b88c807SRodney W. Grimes /*
1964b88c807SRodney W. Grimes * append
1974b88c807SRodney W. Grimes */
1984b88c807SRodney W. Grimes flg |= AF;
1994b88c807SRodney W. Grimes break;
2004b88c807SRodney W. Grimes case 'b':
2014b88c807SRodney W. Grimes /*
2024b88c807SRodney W. Grimes * specify blocksize
2034b88c807SRodney W. Grimes */
2044b88c807SRodney W. Grimes flg |= BF;
2054b88c807SRodney W. Grimes if ((wrblksz = (int)str_offt(optarg)) <= 0) {
206778766feSKris Kennaway paxwarn(1, "Invalid block size %s", optarg);
2074b88c807SRodney W. Grimes pax_usage();
2084b88c807SRodney W. Grimes }
2094b88c807SRodney W. Grimes break;
2104b88c807SRodney W. Grimes case 'c':
2114b88c807SRodney W. Grimes /*
2124b88c807SRodney W. Grimes * inverse match on patterns
2134b88c807SRodney W. Grimes */
2144b88c807SRodney W. Grimes cflag = 1;
2154b88c807SRodney W. Grimes flg |= CF;
2164b88c807SRodney W. Grimes break;
2174b88c807SRodney W. Grimes case 'd':
2184b88c807SRodney W. Grimes /*
2194b88c807SRodney W. Grimes * match only dir on extract, not the subtree at dir
2204b88c807SRodney W. Grimes */
2214b88c807SRodney W. Grimes dflag = 1;
2224b88c807SRodney W. Grimes flg |= DF;
2234b88c807SRodney W. Grimes break;
2244b88c807SRodney W. Grimes case 'f':
2254b88c807SRodney W. Grimes /*
2264b88c807SRodney W. Grimes * filename where the archive is stored
2274b88c807SRodney W. Grimes */
2284b88c807SRodney W. Grimes arcname = optarg;
2294b88c807SRodney W. Grimes flg |= FF;
2304b88c807SRodney W. Grimes break;
2314b88c807SRodney W. Grimes case 'i':
2324b88c807SRodney W. Grimes /*
2334b88c807SRodney W. Grimes * interactive file rename
2344b88c807SRodney W. Grimes */
2354b88c807SRodney W. Grimes iflag = 1;
2364b88c807SRodney W. Grimes flg |= IF;
2374b88c807SRodney W. Grimes break;
2384b88c807SRodney W. Grimes case 'k':
2394b88c807SRodney W. Grimes /*
2404b88c807SRodney W. Grimes * do not clobber files that exist
2414b88c807SRodney W. Grimes */
2424b88c807SRodney W. Grimes kflag = 1;
2434b88c807SRodney W. Grimes flg |= KF;
2444b88c807SRodney W. Grimes break;
2454b88c807SRodney W. Grimes case 'l':
2464b88c807SRodney W. Grimes /*
2474b88c807SRodney W. Grimes * try to link src to dest with copy (-rw)
2484b88c807SRodney W. Grimes */
2494b88c807SRodney W. Grimes lflag = 1;
2504b88c807SRodney W. Grimes flg |= LF;
2514b88c807SRodney W. Grimes break;
2524b88c807SRodney W. Grimes case 'n':
2534b88c807SRodney W. Grimes /*
2544b88c807SRodney W. Grimes * select first match for a pattern only
2554b88c807SRodney W. Grimes */
2564b88c807SRodney W. Grimes nflag = 1;
2574b88c807SRodney W. Grimes flg |= NF;
2584b88c807SRodney W. Grimes break;
2594b88c807SRodney W. Grimes case 'o':
2604b88c807SRodney W. Grimes /*
2614b88c807SRodney W. Grimes * pass format specific options
2624b88c807SRodney W. Grimes */
2634b88c807SRodney W. Grimes flg |= OF;
2644b88c807SRodney W. Grimes if (opt_add(optarg) < 0)
2654b88c807SRodney W. Grimes pax_usage();
2664b88c807SRodney W. Grimes break;
2674b88c807SRodney W. Grimes case 'p':
2684b88c807SRodney W. Grimes /*
2694b88c807SRodney W. Grimes * specify file characteristic options
2704b88c807SRodney W. Grimes */
2714b88c807SRodney W. Grimes for (pt = optarg; *pt != '\0'; ++pt) {
2724b88c807SRodney W. Grimes switch(*pt) {
2734b88c807SRodney W. Grimes case 'a':
2744b88c807SRodney W. Grimes /*
2754b88c807SRodney W. Grimes * do not preserve access time
2764b88c807SRodney W. Grimes */
2774b88c807SRodney W. Grimes patime = 0;
2784b88c807SRodney W. Grimes break;
2794b88c807SRodney W. Grimes case 'e':
2804b88c807SRodney W. Grimes /*
2814b88c807SRodney W. Grimes * preserve user id, group id, file
2824b88c807SRodney W. Grimes * mode, access/modification times
2834b88c807SRodney W. Grimes */
2844b88c807SRodney W. Grimes pids = 1;
2854b88c807SRodney W. Grimes pmode = 1;
2864b88c807SRodney W. Grimes patime = 1;
2874b88c807SRodney W. Grimes pmtime = 1;
2884b88c807SRodney W. Grimes break;
2894b88c807SRodney W. Grimes case 'm':
2904b88c807SRodney W. Grimes /*
2914b88c807SRodney W. Grimes * do not preserve modification time
2924b88c807SRodney W. Grimes */
2934b88c807SRodney W. Grimes pmtime = 0;
2944b88c807SRodney W. Grimes break;
2954b88c807SRodney W. Grimes case 'o':
2964b88c807SRodney W. Grimes /*
2974b88c807SRodney W. Grimes * preserve uid/gid
2984b88c807SRodney W. Grimes */
2994b88c807SRodney W. Grimes pids = 1;
3004b88c807SRodney W. Grimes break;
3014b88c807SRodney W. Grimes case 'p':
3024b88c807SRodney W. Grimes /*
3030266a5d6SDag-Erling Smørgrav * preserve file mode bits
3044b88c807SRodney W. Grimes */
3054b88c807SRodney W. Grimes pmode = 1;
3064b88c807SRodney W. Grimes break;
3074b88c807SRodney W. Grimes default:
308778766feSKris Kennaway paxwarn(1, "Invalid -p string: %c", *pt);
3094b88c807SRodney W. Grimes pax_usage();
3104b88c807SRodney W. Grimes break;
3114b88c807SRodney W. Grimes }
3124b88c807SRodney W. Grimes }
3134b88c807SRodney W. Grimes flg |= PF;
3144b88c807SRodney W. Grimes break;
3154b88c807SRodney W. Grimes case 'r':
3164b88c807SRodney W. Grimes /*
3174b88c807SRodney W. Grimes * read the archive
3184b88c807SRodney W. Grimes */
3194b88c807SRodney W. Grimes flg |= RF;
3204b88c807SRodney W. Grimes break;
3214b88c807SRodney W. Grimes case 's':
3224b88c807SRodney W. Grimes /*
3234b88c807SRodney W. Grimes * file name substitution name pattern
3244b88c807SRodney W. Grimes */
3254b88c807SRodney W. Grimes if (rep_add(optarg) < 0) {
3264b88c807SRodney W. Grimes pax_usage();
3274b88c807SRodney W. Grimes break;
3284b88c807SRodney W. Grimes }
3294b88c807SRodney W. Grimes flg |= SF;
3304b88c807SRodney W. Grimes break;
3314b88c807SRodney W. Grimes case 't':
3324b88c807SRodney W. Grimes /*
3334b88c807SRodney W. Grimes * preserve access time on file system nodes we read
3344b88c807SRodney W. Grimes */
3354b88c807SRodney W. Grimes tflag = 1;
3364b88c807SRodney W. Grimes flg |= TF;
3374b88c807SRodney W. Grimes break;
3384b88c807SRodney W. Grimes case 'u':
3394b88c807SRodney W. Grimes /*
3404b88c807SRodney W. Grimes * ignore those older files
3414b88c807SRodney W. Grimes */
3424b88c807SRodney W. Grimes uflag = 1;
3434b88c807SRodney W. Grimes flg |= UF;
3444b88c807SRodney W. Grimes break;
3454b88c807SRodney W. Grimes case 'v':
3464b88c807SRodney W. Grimes /*
3474b88c807SRodney W. Grimes * verbose operation mode
3484b88c807SRodney W. Grimes */
3494b88c807SRodney W. Grimes vflag = 1;
3504b88c807SRodney W. Grimes flg |= VF;
3514b88c807SRodney W. Grimes break;
3524b88c807SRodney W. Grimes case 'w':
3534b88c807SRodney W. Grimes /*
3544b88c807SRodney W. Grimes * write an archive
3554b88c807SRodney W. Grimes */
3564b88c807SRodney W. Grimes flg |= WF;
3574b88c807SRodney W. Grimes break;
3584b88c807SRodney W. Grimes case 'x':
3594b88c807SRodney W. Grimes /*
3604b88c807SRodney W. Grimes * specify an archive format on write
3614b88c807SRodney W. Grimes */
3624b88c807SRodney W. Grimes tmp.name = optarg;
3630fd510b7SJoerg Wunsch if ((frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
364b1787decSKris Kennaway sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt)) != NULL) {
3654b88c807SRodney W. Grimes flg |= XF;
3664b88c807SRodney W. Grimes break;
3674b88c807SRodney W. Grimes }
368778766feSKris Kennaway paxwarn(1, "Unknown -x format: %s", optarg);
3694b88c807SRodney W. Grimes (void)fputs("pax: Known -x formats are:", stderr);
3704b88c807SRodney W. Grimes for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
3714b88c807SRodney W. Grimes (void)fprintf(stderr, " %s", fsub[i].name);
3724b88c807SRodney W. Grimes (void)fputs("\n\n", stderr);
3734b88c807SRodney W. Grimes pax_usage();
3744b88c807SRodney W. Grimes break;
3751192d531SKris Kennaway case 'z':
3761192d531SKris Kennaway /*
3771192d531SKris Kennaway * use gzip. Non standard option.
3781192d531SKris Kennaway */
3791192d531SKris Kennaway gzip_program = GZIP_CMD;
3801192d531SKris Kennaway break;
3814b88c807SRodney W. Grimes case 'B':
3824b88c807SRodney W. Grimes /*
3834b88c807SRodney W. Grimes * non-standard option on number of bytes written on a
3844b88c807SRodney W. Grimes * single archive volume.
3854b88c807SRodney W. Grimes */
3864b88c807SRodney W. Grimes if ((wrlimit = str_offt(optarg)) <= 0) {
387778766feSKris Kennaway paxwarn(1, "Invalid write limit %s", optarg);
3884b88c807SRodney W. Grimes pax_usage();
3894b88c807SRodney W. Grimes }
3904b88c807SRodney W. Grimes if (wrlimit % BLKMULT) {
391778766feSKris Kennaway paxwarn(1, "Write limit is not a %d byte multiple",
3924b88c807SRodney W. Grimes BLKMULT);
3934b88c807SRodney W. Grimes pax_usage();
3944b88c807SRodney W. Grimes }
3954b88c807SRodney W. Grimes flg |= CBF;
3964b88c807SRodney W. Grimes break;
3974b88c807SRodney W. Grimes case 'D':
3984b88c807SRodney W. Grimes /*
3994b88c807SRodney W. Grimes * On extraction check file inode change time before the
4004b88c807SRodney W. Grimes * modification of the file name. Non standard option.
4014b88c807SRodney W. Grimes */
4024b88c807SRodney W. Grimes Dflag = 1;
4034b88c807SRodney W. Grimes flg |= CDF;
4044b88c807SRodney W. Grimes break;
4054b88c807SRodney W. Grimes case 'E':
4064b88c807SRodney W. Grimes /*
4074b88c807SRodney W. Grimes * non-standard limit on read faults
4084b88c807SRodney W. Grimes * 0 indicates stop after first error, values
4094b88c807SRodney W. Grimes * indicate a limit, "NONE" try forever
4104b88c807SRodney W. Grimes */
4114b88c807SRodney W. Grimes flg |= CEF;
4124b88c807SRodney W. Grimes if (strcmp(NONE, optarg) == 0)
4134b88c807SRodney W. Grimes maxflt = -1;
4144b88c807SRodney W. Grimes else if ((maxflt = atoi(optarg)) < 0) {
415778766feSKris Kennaway paxwarn(1, "Error count value must be positive");
4164b88c807SRodney W. Grimes pax_usage();
4174b88c807SRodney W. Grimes }
4184b88c807SRodney W. Grimes break;
4194b88c807SRodney W. Grimes case 'G':
4204b88c807SRodney W. Grimes /*
4214b88c807SRodney W. Grimes * non-standard option for selecting files within an
4224b88c807SRodney W. Grimes * archive by group (gid or name)
4234b88c807SRodney W. Grimes */
4244b88c807SRodney W. Grimes if (grp_add(optarg) < 0) {
4254b88c807SRodney W. Grimes pax_usage();
4264b88c807SRodney W. Grimes break;
4274b88c807SRodney W. Grimes }
4284b88c807SRodney W. Grimes flg |= CGF;
4294b88c807SRodney W. Grimes break;
4304b88c807SRodney W. Grimes case 'H':
4314b88c807SRodney W. Grimes /*
4324b88c807SRodney W. Grimes * follow command line symlinks only
4334b88c807SRodney W. Grimes */
4344b88c807SRodney W. Grimes Hflag = 1;
4354b88c807SRodney W. Grimes flg |= CHF;
4364b88c807SRodney W. Grimes break;
4374b88c807SRodney W. Grimes case 'L':
4384b88c807SRodney W. Grimes /*
4394b88c807SRodney W. Grimes * follow symlinks
4404b88c807SRodney W. Grimes */
4414b88c807SRodney W. Grimes Lflag = 1;
4424b88c807SRodney W. Grimes flg |= CLF;
4434b88c807SRodney W. Grimes break;
444d6e1f8d7SEitan Adler case 'O':
445d6e1f8d7SEitan Adler /*
446d6e1f8d7SEitan Adler * Force one volume. Non standard option.
447d6e1f8d7SEitan Adler */
448d6e1f8d7SEitan Adler Oflag = 1;
449d6e1f8d7SEitan Adler break;
4504b88c807SRodney W. Grimes case 'P':
4514b88c807SRodney W. Grimes /*
4524b88c807SRodney W. Grimes * do NOT follow symlinks (default)
4534b88c807SRodney W. Grimes */
4544b88c807SRodney W. Grimes Lflag = 0;
4554b88c807SRodney W. Grimes flg |= CPF;
4564b88c807SRodney W. Grimes break;
4574b88c807SRodney W. Grimes case 'T':
4584b88c807SRodney W. Grimes /*
4594b88c807SRodney W. Grimes * non-standard option for selecting files within an
4604b88c807SRodney W. Grimes * archive by modification time range (lower,upper)
4614b88c807SRodney W. Grimes */
4624b88c807SRodney W. Grimes if (trng_add(optarg) < 0) {
4634b88c807SRodney W. Grimes pax_usage();
4644b88c807SRodney W. Grimes break;
4654b88c807SRodney W. Grimes }
4664b88c807SRodney W. Grimes flg |= CTF;
4674b88c807SRodney W. Grimes break;
4684b88c807SRodney W. Grimes case 'U':
4694b88c807SRodney W. Grimes /*
4704b88c807SRodney W. Grimes * non-standard option for selecting files within an
4714b88c807SRodney W. Grimes * archive by user (uid or name)
4724b88c807SRodney W. Grimes */
4734b88c807SRodney W. Grimes if (usr_add(optarg) < 0) {
4744b88c807SRodney W. Grimes pax_usage();
4754b88c807SRodney W. Grimes break;
4764b88c807SRodney W. Grimes }
4774b88c807SRodney W. Grimes flg |= CUF;
4784b88c807SRodney W. Grimes break;
4794b88c807SRodney W. Grimes case 'X':
4804b88c807SRodney W. Grimes /*
4814b88c807SRodney W. Grimes * do not pass over mount points in the file system
4824b88c807SRodney W. Grimes */
4834b88c807SRodney W. Grimes Xflag = 1;
4844b88c807SRodney W. Grimes flg |= CXF;
4854b88c807SRodney W. Grimes break;
4864b88c807SRodney W. Grimes case 'Y':
4874b88c807SRodney W. Grimes /*
4884b88c807SRodney W. Grimes * On extraction check file inode change time after the
4894b88c807SRodney W. Grimes * modification of the file name. Non standard option.
4904b88c807SRodney W. Grimes */
4914b88c807SRodney W. Grimes Yflag = 1;
4924b88c807SRodney W. Grimes flg |= CYF;
4934b88c807SRodney W. Grimes break;
4944b88c807SRodney W. Grimes case 'Z':
4954b88c807SRodney W. Grimes /*
4964b88c807SRodney W. Grimes * On extraction check modification time after the
4974b88c807SRodney W. Grimes * modification of the file name. Non standard option.
4984b88c807SRodney W. Grimes */
4994b88c807SRodney W. Grimes Zflag = 1;
5004b88c807SRodney W. Grimes flg |= CZF;
5014b88c807SRodney W. Grimes break;
5024b88c807SRodney W. Grimes default:
5034b88c807SRodney W. Grimes pax_usage();
5044b88c807SRodney W. Grimes break;
5054b88c807SRodney W. Grimes }
5064b88c807SRodney W. Grimes }
5074b88c807SRodney W. Grimes
5084b88c807SRodney W. Grimes /*
5094b88c807SRodney W. Grimes * figure out the operation mode of pax read,write,extract,copy,append
5104b88c807SRodney W. Grimes * or list. check that we have not been given a bogus set of flags
5114b88c807SRodney W. Grimes * for the operation mode.
5124b88c807SRodney W. Grimes */
5134b88c807SRodney W. Grimes if (ISLIST(flg)) {
5144b88c807SRodney W. Grimes act = LIST;
515b1787decSKris Kennaway listf = stdout;
5164b88c807SRodney W. Grimes bflg = flg & BDLIST;
5174b88c807SRodney W. Grimes } else if (ISEXTRACT(flg)) {
5184b88c807SRodney W. Grimes act = EXTRACT;
5194b88c807SRodney W. Grimes bflg = flg & BDEXTR;
5204b88c807SRodney W. Grimes } else if (ISARCHIVE(flg)) {
5214b88c807SRodney W. Grimes act = ARCHIVE;
5224b88c807SRodney W. Grimes bflg = flg & BDARCH;
5234b88c807SRodney W. Grimes } else if (ISAPPND(flg)) {
5244b88c807SRodney W. Grimes act = APPND;
5254b88c807SRodney W. Grimes bflg = flg & BDARCH;
5264b88c807SRodney W. Grimes } else if (ISCOPY(flg)) {
5274b88c807SRodney W. Grimes act = COPY;
5284b88c807SRodney W. Grimes bflg = flg & BDCOPY;
5294b88c807SRodney W. Grimes } else
5304b88c807SRodney W. Grimes pax_usage();
5314b88c807SRodney W. Grimes if (bflg) {
5324b88c807SRodney W. Grimes printflg(flg);
5334b88c807SRodney W. Grimes pax_usage();
5344b88c807SRodney W. Grimes }
5354b88c807SRodney W. Grimes
5364b88c807SRodney W. Grimes /*
5374b88c807SRodney W. Grimes * if we are writing (ARCHIVE) we use the default format if the user
5384b88c807SRodney W. Grimes * did not specify a format. when we write during an APPEND, we will
5394b88c807SRodney W. Grimes * adopt the format of the existing archive if none was supplied.
5404b88c807SRodney W. Grimes */
5414b88c807SRodney W. Grimes if (!(flg & XF) && (act == ARCHIVE))
5424b88c807SRodney W. Grimes frmt = &(fsub[DEFLT]);
5434b88c807SRodney W. Grimes
5444b88c807SRodney W. Grimes /*
5454b88c807SRodney W. Grimes * process the args as they are interpreted by the operation mode
5464b88c807SRodney W. Grimes */
5474b88c807SRodney W. Grimes switch (act) {
5484b88c807SRodney W. Grimes case LIST:
5494b88c807SRodney W. Grimes case EXTRACT:
5504b88c807SRodney W. Grimes for (; optind < argc; optind++)
551b1787decSKris Kennaway if (pat_add(argv[optind], NULL) < 0)
5524b88c807SRodney W. Grimes pax_usage();
5534b88c807SRodney W. Grimes break;
5544b88c807SRodney W. Grimes case COPY:
5554b88c807SRodney W. Grimes if (optind >= argc) {
556778766feSKris Kennaway paxwarn(0, "Destination directory was not supplied");
5574b88c807SRodney W. Grimes pax_usage();
5584b88c807SRodney W. Grimes }
5594b88c807SRodney W. Grimes --argc;
5604b88c807SRodney W. Grimes dirptr = argv[argc];
5614b88c807SRodney W. Grimes /* FALLTHROUGH */
5624b88c807SRodney W. Grimes case ARCHIVE:
5634b88c807SRodney W. Grimes case APPND:
5644b88c807SRodney W. Grimes for (; optind < argc; optind++)
565b1787decSKris Kennaway if (ftree_add(argv[optind], 0) < 0)
5664b88c807SRodney W. Grimes pax_usage();
5674b88c807SRodney W. Grimes /*
5684b88c807SRodney W. Grimes * no read errors allowed on updates/append operation!
5694b88c807SRodney W. Grimes */
5704b88c807SRodney W. Grimes maxflt = 0;
5714b88c807SRodney W. Grimes break;
5724b88c807SRodney W. Grimes }
5734b88c807SRodney W. Grimes }
5744b88c807SRodney W. Grimes
5754b88c807SRodney W. Grimes
5764b88c807SRodney W. Grimes /*
5774b88c807SRodney W. Grimes * tar_options()
5784b88c807SRodney W. Grimes * look at the user specified flags. set globals as required and check if
5794b88c807SRodney W. Grimes * the user specified a legal set of flags. If not, complain and exit
5804b88c807SRodney W. Grimes */
5814b88c807SRodney W. Grimes
5824b88c807SRodney W. Grimes static void
tar_options(int argc,char ** argv)583f789b261SWarner Losh tar_options(int argc, char **argv)
5844b88c807SRodney W. Grimes {
585f789b261SWarner Losh int c;
5864b88c807SRodney W. Grimes int fstdin = 0;
587d6e1f8d7SEitan Adler int tar_Oflag = 0;
588b1787decSKris Kennaway int nincfiles = 0;
589b1787decSKris Kennaway int incfiles_max = 0;
590b1787decSKris Kennaway struct incfile {
591b1787decSKris Kennaway char *file;
592b1787decSKris Kennaway char *dir;
593b1787decSKris Kennaway };
594b1787decSKris Kennaway struct incfile *incfiles = NULL;
5954b88c807SRodney W. Grimes
596b1787decSKris Kennaway /*
597b1787decSKris Kennaway * Set default values.
598b1787decSKris Kennaway */
599b1787decSKris Kennaway rmleadslash = 1;
600b1787decSKris Kennaway
6014b88c807SRodney W. Grimes /*
6024b88c807SRodney W. Grimes * process option flags
6034b88c807SRodney W. Grimes */
604b1787decSKris Kennaway while ((c = getoldopt(argc, argv,
605b1787decSKris Kennaway "b:cef:hjmopqruts:vwxyzBC:HI:LOPXZ014578")) != -1) {
606b1787decSKris Kennaway switch(c) {
6074b88c807SRodney W. Grimes case 'b':
6084b88c807SRodney W. Grimes /*
609b1787decSKris Kennaway * specify blocksize in 512-byte blocks
6104b88c807SRodney W. Grimes */
611b1787decSKris Kennaway if ((wrblksz = (int)str_offt(optarg)) <= 0) {
612b1787decSKris Kennaway paxwarn(1, "Invalid block size %s", optarg);
6134b88c807SRodney W. Grimes tar_usage();
6144b88c807SRodney W. Grimes }
615b1787decSKris Kennaway wrblksz *= 512; /* XXX - check for int oflow */
6164b88c807SRodney W. Grimes break;
6174b88c807SRodney W. Grimes case 'c':
6184b88c807SRodney W. Grimes /*
6194b88c807SRodney W. Grimes * create an archive
6204b88c807SRodney W. Grimes */
6214b88c807SRodney W. Grimes act = ARCHIVE;
6224b88c807SRodney W. Grimes break;
6234b88c807SRodney W. Grimes case 'e':
6244b88c807SRodney W. Grimes /*
6254b88c807SRodney W. Grimes * stop after first error
6264b88c807SRodney W. Grimes */
6274b88c807SRodney W. Grimes maxflt = 0;
6284b88c807SRodney W. Grimes break;
6294b88c807SRodney W. Grimes case 'f':
6304b88c807SRodney W. Grimes /*
6314b88c807SRodney W. Grimes * filename where the archive is stored
6324b88c807SRodney W. Grimes */
633b1787decSKris Kennaway if ((optarg[0] == '-') && (optarg[1]== '\0')) {
6344b88c807SRodney W. Grimes /*
6354b88c807SRodney W. Grimes * treat a - as stdin
6364b88c807SRodney W. Grimes */
637b1787decSKris Kennaway fstdin = 1;
638b1787decSKris Kennaway arcname = NULL;
6394b88c807SRodney W. Grimes break;
6404b88c807SRodney W. Grimes }
6414b88c807SRodney W. Grimes fstdin = 0;
642b1787decSKris Kennaway arcname = optarg;
643b1787decSKris Kennaway break;
644b1787decSKris Kennaway case 'h':
645b1787decSKris Kennaway /*
646b1787decSKris Kennaway * follow symlinks
647b1787decSKris Kennaway */
648b1787decSKris Kennaway Lflag = 1;
649b1787decSKris Kennaway break;
650b1787decSKris Kennaway case 'j':
651b1787decSKris Kennaway case 'y':
652b1787decSKris Kennaway /*
653b1787decSKris Kennaway * use bzip2. Non standard option.
654b1787decSKris Kennaway */
655b1787decSKris Kennaway gzip_program = BZIP2_CMD;
6564b88c807SRodney W. Grimes break;
6574b88c807SRodney W. Grimes case 'm':
6584b88c807SRodney W. Grimes /*
6594b88c807SRodney W. Grimes * do not preserve modification time
6604b88c807SRodney W. Grimes */
6614b88c807SRodney W. Grimes pmtime = 0;
6624b88c807SRodney W. Grimes break;
6634b88c807SRodney W. Grimes case 'o':
6644b88c807SRodney W. Grimes if (opt_add("write_opt=nodir") < 0)
6654b88c807SRodney W. Grimes tar_usage();
666b1787decSKris Kennaway case 'O':
667d6e1f8d7SEitan Adler tar_Oflag = 1;
6684b88c807SRodney W. Grimes break;
6694b88c807SRodney W. Grimes case 'p':
6704b88c807SRodney W. Grimes /*
671b1787decSKris Kennaway * preserve uid/gid and file mode, regardless of umask
6724b88c807SRodney W. Grimes */
6734b88c807SRodney W. Grimes pmode = 1;
674b1787decSKris Kennaway pids = 1;
675b1787decSKris Kennaway break;
676b1787decSKris Kennaway case 'q':
677b1787decSKris Kennaway /*
678b1787decSKris Kennaway * select first match for a pattern only
679b1787decSKris Kennaway */
680b1787decSKris Kennaway nflag = 1;
6814b88c807SRodney W. Grimes break;
6824b88c807SRodney W. Grimes case 'r':
6834b88c807SRodney W. Grimes case 'u':
6844b88c807SRodney W. Grimes /*
6854b88c807SRodney W. Grimes * append to the archive
6864b88c807SRodney W. Grimes */
6874b88c807SRodney W. Grimes act = APPND;
6884b88c807SRodney W. Grimes break;
689b1787decSKris Kennaway case 's':
690b1787decSKris Kennaway /*
691b1787decSKris Kennaway * file name substitution name pattern
692b1787decSKris Kennaway */
693b1787decSKris Kennaway if (rep_add(optarg) < 0) {
694b1787decSKris Kennaway tar_usage();
695b1787decSKris Kennaway break;
696b1787decSKris Kennaway }
697b1787decSKris Kennaway break;
6984b88c807SRodney W. Grimes case 't':
6994b88c807SRodney W. Grimes /*
7004b88c807SRodney W. Grimes * list contents of the tape
7014b88c807SRodney W. Grimes */
7024b88c807SRodney W. Grimes act = LIST;
7034b88c807SRodney W. Grimes break;
7044b88c807SRodney W. Grimes case 'v':
7054b88c807SRodney W. Grimes /*
7064b88c807SRodney W. Grimes * verbose operation mode
7074b88c807SRodney W. Grimes */
708b1787decSKris Kennaway vflag++;
7094b88c807SRodney W. Grimes break;
7104b88c807SRodney W. Grimes case 'w':
7114b88c807SRodney W. Grimes /*
7124b88c807SRodney W. Grimes * interactive file rename
7134b88c807SRodney W. Grimes */
7144b88c807SRodney W. Grimes iflag = 1;
7154b88c807SRodney W. Grimes break;
7164b88c807SRodney W. Grimes case 'x':
7174b88c807SRodney W. Grimes /*
718b1787decSKris Kennaway * extract an archive, preserving mode,
719b1787decSKris Kennaway * and mtime if possible.
7204b88c807SRodney W. Grimes */
7214b88c807SRodney W. Grimes act = EXTRACT;
722b1787decSKris Kennaway pmtime = 1;
7234b88c807SRodney W. Grimes break;
7241192d531SKris Kennaway case 'z':
7251192d531SKris Kennaway /*
7261192d531SKris Kennaway * use gzip. Non standard option.
7271192d531SKris Kennaway */
7281192d531SKris Kennaway gzip_program = GZIP_CMD;
7291192d531SKris Kennaway break;
7304b88c807SRodney W. Grimes case 'B':
7314b88c807SRodney W. Grimes /*
7324b88c807SRodney W. Grimes * Nothing to do here, this is pax default
7334b88c807SRodney W. Grimes */
7344b88c807SRodney W. Grimes break;
735b1787decSKris Kennaway case 'C':
736b1787decSKris Kennaway chdname = optarg;
737b1787decSKris Kennaway break;
7384b88c807SRodney W. Grimes case 'H':
7394b88c807SRodney W. Grimes /*
7404b88c807SRodney W. Grimes * follow command line symlinks only
7414b88c807SRodney W. Grimes */
7424b88c807SRodney W. Grimes Hflag = 1;
7434b88c807SRodney W. Grimes break;
744b1787decSKris Kennaway case 'I':
745b1787decSKris Kennaway if (++nincfiles > incfiles_max) {
746b1787decSKris Kennaway incfiles_max = nincfiles + 3;
747b1787decSKris Kennaway incfiles = realloc(incfiles,
748b1787decSKris Kennaway sizeof(*incfiles) * incfiles_max);
749b1787decSKris Kennaway if (incfiles == NULL) {
750b1787decSKris Kennaway paxwarn(0, "Unable to allocate space "
751b1787decSKris Kennaway "for option list");
752b1787decSKris Kennaway exit(1);
753b1787decSKris Kennaway }
754b1787decSKris Kennaway }
755b1787decSKris Kennaway incfiles[nincfiles - 1].file = optarg;
756b1787decSKris Kennaway incfiles[nincfiles - 1].dir = chdname;
757b1787decSKris Kennaway break;
7584b88c807SRodney W. Grimes case 'L':
7594b88c807SRodney W. Grimes /*
7604b88c807SRodney W. Grimes * follow symlinks
7614b88c807SRodney W. Grimes */
7624b88c807SRodney W. Grimes Lflag = 1;
7634b88c807SRodney W. Grimes break;
7644b88c807SRodney W. Grimes case 'P':
7654b88c807SRodney W. Grimes /*
766b1787decSKris Kennaway * do not remove leading '/' from pathnames
7674b88c807SRodney W. Grimes */
768b1787decSKris Kennaway rmleadslash = 0;
7694b88c807SRodney W. Grimes break;
7704b88c807SRodney W. Grimes case 'X':
7714b88c807SRodney W. Grimes /*
7724b88c807SRodney W. Grimes * do not pass over mount points in the file system
7734b88c807SRodney W. Grimes */
7744b88c807SRodney W. Grimes Xflag = 1;
7754b88c807SRodney W. Grimes break;
7761192d531SKris Kennaway case 'Z':
7771192d531SKris Kennaway /*
7781192d531SKris Kennaway * use compress.
7791192d531SKris Kennaway */
7801192d531SKris Kennaway gzip_program = COMPRESS_CMD;
7811192d531SKris Kennaway break;
7824b88c807SRodney W. Grimes case '0':
7834b88c807SRodney W. Grimes arcname = DEV_0;
7844b88c807SRodney W. Grimes break;
7854b88c807SRodney W. Grimes case '1':
7864b88c807SRodney W. Grimes arcname = DEV_1;
7874b88c807SRodney W. Grimes break;
7884b88c807SRodney W. Grimes case '4':
7894b88c807SRodney W. Grimes arcname = DEV_4;
7904b88c807SRodney W. Grimes break;
7914b88c807SRodney W. Grimes case '5':
7924b88c807SRodney W. Grimes arcname = DEV_5;
7934b88c807SRodney W. Grimes break;
7944b88c807SRodney W. Grimes case '7':
7954b88c807SRodney W. Grimes arcname = DEV_7;
7964b88c807SRodney W. Grimes break;
7974b88c807SRodney W. Grimes case '8':
7984b88c807SRodney W. Grimes arcname = DEV_8;
7994b88c807SRodney W. Grimes break;
8004b88c807SRodney W. Grimes default:
8014b88c807SRodney W. Grimes tar_usage();
8024b88c807SRodney W. Grimes break;
8034b88c807SRodney W. Grimes }
8044b88c807SRodney W. Grimes }
805b1787decSKris Kennaway argc -= optind;
806b1787decSKris Kennaway argv += optind;
807b1787decSKris Kennaway
808b1787decSKris Kennaway /* Traditional tar behaviour (pax uses stderr unless in list mode) */
809b1787decSKris Kennaway if (fstdin == 1 && act == ARCHIVE)
810b1787decSKris Kennaway listf = stderr;
811b1787decSKris Kennaway else
812b1787decSKris Kennaway listf = stdout;
813b1787decSKris Kennaway
814b1787decSKris Kennaway /* Traditional tar behaviour (pax wants to read file list from stdin) */
815b1787decSKris Kennaway if ((act == ARCHIVE || act == APPND) && argc == 0 && nincfiles == 0)
816b1787decSKris Kennaway exit(0);
8174b88c807SRodney W. Grimes
8184b88c807SRodney W. Grimes /*
8194b88c807SRodney W. Grimes * if we are writing (ARCHIVE) specify tar, otherwise run like pax
820b1787decSKris Kennaway * (unless -o specified)
8214b88c807SRodney W. Grimes */
822b1787decSKris Kennaway if (act == ARCHIVE || act == APPND)
823d6e1f8d7SEitan Adler frmt = &(fsub[tar_Oflag ? F_OTAR : F_TAR]);
824d6e1f8d7SEitan Adler else if (tar_Oflag) {
825b1787decSKris Kennaway paxwarn(1, "The -O/-o options are only valid when writing an archive");
826b1787decSKris Kennaway tar_usage(); /* only valid when writing */
827b1787decSKris Kennaway }
8284b88c807SRodney W. Grimes
8294b88c807SRodney W. Grimes /*
8304b88c807SRodney W. Grimes * process the args as they are interpreted by the operation mode
8314b88c807SRodney W. Grimes */
8324b88c807SRodney W. Grimes switch (act) {
8334b88c807SRodney W. Grimes case LIST:
8344b88c807SRodney W. Grimes case EXTRACT:
8354b88c807SRodney W. Grimes default:
836b1787decSKris Kennaway {
837b1787decSKris Kennaway int sawpat = 0;
838b1787decSKris Kennaway char *file, *dir = NULL;
839b1787decSKris Kennaway
840b1787decSKris Kennaway while (nincfiles || *argv != NULL) {
841b1787decSKris Kennaway /*
842b1787decSKris Kennaway * If we queued up any include files,
843b1787decSKris Kennaway * pull them in now. Otherwise, check
844b1787decSKris Kennaway * for -I and -C positional flags.
845b1787decSKris Kennaway * Anything else must be a file to
846b1787decSKris Kennaway * extract.
847b1787decSKris Kennaway */
848b1787decSKris Kennaway if (nincfiles) {
849b1787decSKris Kennaway file = incfiles->file;
850b1787decSKris Kennaway dir = incfiles->dir;
851b1787decSKris Kennaway incfiles++;
852b1787decSKris Kennaway nincfiles--;
853b1787decSKris Kennaway } else if (strcmp(*argv, "-I") == 0) {
854b1787decSKris Kennaway if (*++argv == NULL)
855b1787decSKris Kennaway break;
856b1787decSKris Kennaway file = *argv++;
857b1787decSKris Kennaway dir = chdname;
858b1787decSKris Kennaway } else
859b1787decSKris Kennaway file = NULL;
860b1787decSKris Kennaway if (file != NULL) {
861b1787decSKris Kennaway FILE *fp;
862b1787decSKris Kennaway char *str;
863b1787decSKris Kennaway
864b1787decSKris Kennaway if (strcmp(file, "-") == 0)
865b1787decSKris Kennaway fp = stdin;
866b1787decSKris Kennaway else if ((fp = fopen(file, "r")) == NULL) {
867b1787decSKris Kennaway paxwarn(1, "Unable to open file '%s' for read", file);
8684b88c807SRodney W. Grimes tar_usage();
869b1787decSKris Kennaway }
870a651f2bcSBaptiste Daroussin while ((str = get_line(fp)) != NULL) {
871b1787decSKris Kennaway if (pat_add(str, dir) < 0)
872b1787decSKris Kennaway tar_usage();
873b1787decSKris Kennaway sawpat = 1;
874b1787decSKris Kennaway }
875b1787decSKris Kennaway if (strcmp(file, "-") != 0)
876b1787decSKris Kennaway fclose(fp);
877a651f2bcSBaptiste Daroussin if (get_line_error) {
878b1787decSKris Kennaway paxwarn(1, "Problem with file '%s'", file);
879b1787decSKris Kennaway tar_usage();
880b1787decSKris Kennaway }
881b1787decSKris Kennaway } else if (strcmp(*argv, "-C") == 0) {
882b1787decSKris Kennaway if (*++argv == NULL)
883b1787decSKris Kennaway break;
884b1787decSKris Kennaway chdname = *argv++;
885b1787decSKris Kennaway } else if (pat_add(*argv++, chdname) < 0)
886b1787decSKris Kennaway tar_usage();
887b1787decSKris Kennaway else
888b1787decSKris Kennaway sawpat = 1;
889b1787decSKris Kennaway }
890b1787decSKris Kennaway /*
891b1787decSKris Kennaway * if patterns were added, we are doing chdir()
892b1787decSKris Kennaway * on a file-by-file basis, else, just one
893b1787decSKris Kennaway * global chdir (if any) after opening input.
894b1787decSKris Kennaway */
895b1787decSKris Kennaway if (sawpat > 0)
896b1787decSKris Kennaway chdname = NULL;
897b1787decSKris Kennaway }
8984b88c807SRodney W. Grimes break;
8994b88c807SRodney W. Grimes case ARCHIVE:
9004b88c807SRodney W. Grimes case APPND:
901b1787decSKris Kennaway if (chdname != NULL) { /* initial chdir() */
902b1787decSKris Kennaway if (ftree_add(chdname, 1) < 0)
9034b88c807SRodney W. Grimes tar_usage();
904b1787decSKris Kennaway }
905b1787decSKris Kennaway
906b1787decSKris Kennaway while (nincfiles || *argv != NULL) {
907b1787decSKris Kennaway char *file, *dir = NULL;
908b1787decSKris Kennaway
909b1787decSKris Kennaway /*
910b1787decSKris Kennaway * If we queued up any include files, pull them in
911b1787decSKris Kennaway * now. Otherwise, check for -I and -C positional
912b1787decSKris Kennaway * flags. Anything else must be a file to include
913b1787decSKris Kennaway * in the archive.
914b1787decSKris Kennaway */
915b1787decSKris Kennaway if (nincfiles) {
916b1787decSKris Kennaway file = incfiles->file;
917b1787decSKris Kennaway dir = incfiles->dir;
918b1787decSKris Kennaway incfiles++;
919b1787decSKris Kennaway nincfiles--;
920b1787decSKris Kennaway } else if (strcmp(*argv, "-I") == 0) {
921b1787decSKris Kennaway if (*++argv == NULL)
922b1787decSKris Kennaway break;
923b1787decSKris Kennaway file = *argv++;
924b1787decSKris Kennaway dir = NULL;
925b1787decSKris Kennaway } else
926b1787decSKris Kennaway file = NULL;
927b1787decSKris Kennaway if (file != NULL) {
928b1787decSKris Kennaway FILE *fp;
929b1787decSKris Kennaway char *str;
930b1787decSKris Kennaway
931b1787decSKris Kennaway /* Set directory if needed */
932b1787decSKris Kennaway if (dir) {
933b1787decSKris Kennaway if (ftree_add(dir, 1) < 0)
934b1787decSKris Kennaway tar_usage();
935b1787decSKris Kennaway }
936b1787decSKris Kennaway
937b1787decSKris Kennaway if (strcmp(file, "-") == 0)
938b1787decSKris Kennaway fp = stdin;
939b1787decSKris Kennaway else if ((fp = fopen(file, "r")) == NULL) {
940b1787decSKris Kennaway paxwarn(1, "Unable to open file '%s' for read", file);
941b1787decSKris Kennaway tar_usage();
942b1787decSKris Kennaway }
943a651f2bcSBaptiste Daroussin while ((str = get_line(fp)) != NULL) {
944b1787decSKris Kennaway if (ftree_add(str, 0) < 0)
945b1787decSKris Kennaway tar_usage();
946b1787decSKris Kennaway }
947b1787decSKris Kennaway if (strcmp(file, "-") != 0)
948b1787decSKris Kennaway fclose(fp);
949a651f2bcSBaptiste Daroussin if (get_line_error) {
950b1787decSKris Kennaway paxwarn(1, "Problem with file '%s'",
951b1787decSKris Kennaway file);
952b1787decSKris Kennaway tar_usage();
953b1787decSKris Kennaway }
954b1787decSKris Kennaway } else if (strcmp(*argv, "-C") == 0) {
955b1787decSKris Kennaway if (*++argv == NULL)
956b1787decSKris Kennaway break;
957b1787decSKris Kennaway if (ftree_add(*argv++, 1) < 0)
958b1787decSKris Kennaway tar_usage();
959b1787decSKris Kennaway } else if (ftree_add(*argv++, 0) < 0)
960b1787decSKris Kennaway tar_usage();
961b1787decSKris Kennaway }
9624b88c807SRodney W. Grimes /*
9634b88c807SRodney W. Grimes * no read errors allowed on updates/append operation!
9644b88c807SRodney W. Grimes */
9654b88c807SRodney W. Grimes maxflt = 0;
9664b88c807SRodney W. Grimes break;
9674b88c807SRodney W. Grimes }
968778766feSKris Kennaway if (!fstdin && ((arcname == NULL) || (*arcname == '\0'))) {
9694b88c807SRodney W. Grimes arcname = getenv("TAPE");
970778766feSKris Kennaway if ((arcname == NULL) || (*arcname == '\0'))
971b1787decSKris Kennaway arcname = _PATH_DEFTAPE;
9724b88c807SRodney W. Grimes }
9734b88c807SRodney W. Grimes }
9744b88c807SRodney W. Grimes
97540feca3aSMark Murray static int
mkpath(char * path)97640feca3aSMark Murray mkpath(char *path)
977b1787decSKris Kennaway {
978b1787decSKris Kennaway struct stat sb;
979f789b261SWarner Losh char *slash;
980b1787decSKris Kennaway int done = 0;
981b1787decSKris Kennaway
982b1787decSKris Kennaway slash = path;
983b1787decSKris Kennaway
984b1787decSKris Kennaway while (!done) {
985b1787decSKris Kennaway slash += strspn(slash, "/");
986b1787decSKris Kennaway slash += strcspn(slash, "/");
987b1787decSKris Kennaway
988b1787decSKris Kennaway done = (*slash == '\0');
989b1787decSKris Kennaway *slash = '\0';
990b1787decSKris Kennaway
991b1787decSKris Kennaway if (stat(path, &sb)) {
992b1787decSKris Kennaway if (errno != ENOENT || mkdir(path, 0777)) {
993b1787decSKris Kennaway paxwarn(1, "%s", path);
994b1787decSKris Kennaway return (-1);
995b1787decSKris Kennaway }
996b1787decSKris Kennaway } else if (!S_ISDIR(sb.st_mode)) {
997b1787decSKris Kennaway syswarn(1, ENOTDIR, "%s", path);
998b1787decSKris Kennaway return (-1);
999b1787decSKris Kennaway }
1000b1787decSKris Kennaway
1001b1787decSKris Kennaway if (!done)
1002b1787decSKris Kennaway *slash = '/';
1003b1787decSKris Kennaway }
1004b1787decSKris Kennaway
1005b1787decSKris Kennaway return (0);
1006b1787decSKris Kennaway }
10074b88c807SRodney W. Grimes /*
10084b88c807SRodney W. Grimes * cpio_options()
10094b88c807SRodney W. Grimes * look at the user specified flags. set globals as required and check if
10104b88c807SRodney W. Grimes * the user specified a legal set of flags. If not, complain and exit
10114b88c807SRodney W. Grimes */
10124b88c807SRodney W. Grimes
10134b88c807SRodney W. Grimes static void
cpio_options(int argc,char ** argv)1014f789b261SWarner Losh cpio_options(int argc, char **argv)
10154b88c807SRodney W. Grimes {
1016cee22cbdSDavid E. O'Brien int c;
1017cee22cbdSDavid E. O'Brien size_t i;
1018b1787decSKris Kennaway char *str;
1019b1787decSKris Kennaway FSUB tmp;
1020b1787decSKris Kennaway FILE *fp;
1021b1787decSKris Kennaway
1022b1787decSKris Kennaway kflag = 1;
1023b1787decSKris Kennaway pids = 1;
1024b1787decSKris Kennaway pmode = 1;
1025b1787decSKris Kennaway pmtime = 0;
1026b1787decSKris Kennaway arcname = NULL;
1027b1787decSKris Kennaway dflag = 1;
1028b1787decSKris Kennaway act = -1;
1029b1787decSKris Kennaway nodirs = 1;
1030b1787decSKris Kennaway while ((c=getopt(argc,argv,"abcdfiklmoprstuvzABC:E:F:H:I:LO:SZ6")) != -1)
1031b1787decSKris Kennaway switch (c) {
1032b1787decSKris Kennaway case 'a':
1033b1787decSKris Kennaway /*
1034b1787decSKris Kennaway * preserve access time on files read
1035b1787decSKris Kennaway */
1036b1787decSKris Kennaway tflag = 1;
1037b1787decSKris Kennaway break;
1038b1787decSKris Kennaway case 'b':
1039b1787decSKris Kennaway /*
1040b1787decSKris Kennaway * swap bytes and half-words when reading data
1041b1787decSKris Kennaway */
1042b1787decSKris Kennaway break;
1043b1787decSKris Kennaway case 'c':
1044b1787decSKris Kennaway /*
1045b1787decSKris Kennaway * ASCII cpio header
1046b1787decSKris Kennaway */
1047b1787decSKris Kennaway frmt = &(fsub[F_ACPIO]);
1048b1787decSKris Kennaway break;
1049b1787decSKris Kennaway case 'd':
1050b1787decSKris Kennaway /*
1051b1787decSKris Kennaway * create directories as needed
1052b1787decSKris Kennaway */
1053b1787decSKris Kennaway nodirs = 0;
1054b1787decSKris Kennaway break;
1055b1787decSKris Kennaway case 'f':
1056b1787decSKris Kennaway /*
1057b1787decSKris Kennaway * invert meaning of pattern list
1058b1787decSKris Kennaway */
1059b1787decSKris Kennaway cflag = 1;
1060b1787decSKris Kennaway break;
1061b1787decSKris Kennaway case 'i':
1062b1787decSKris Kennaway /*
1063b1787decSKris Kennaway * restore an archive
1064b1787decSKris Kennaway */
1065b1787decSKris Kennaway act = EXTRACT;
1066b1787decSKris Kennaway break;
1067b1787decSKris Kennaway case 'k':
1068b1787decSKris Kennaway break;
1069b1787decSKris Kennaway case 'l':
1070b1787decSKris Kennaway /*
1071b1787decSKris Kennaway * use links instead of copies when possible
1072b1787decSKris Kennaway */
1073b1787decSKris Kennaway lflag = 1;
1074b1787decSKris Kennaway break;
1075b1787decSKris Kennaway case 'm':
1076b1787decSKris Kennaway /*
1077b1787decSKris Kennaway * preserve modification time
1078b1787decSKris Kennaway */
1079b1787decSKris Kennaway pmtime = 1;
1080b1787decSKris Kennaway break;
1081b1787decSKris Kennaway case 'o':
1082b1787decSKris Kennaway /*
1083b1787decSKris Kennaway * create an archive
1084b1787decSKris Kennaway */
1085b1787decSKris Kennaway act = ARCHIVE;
1086b1787decSKris Kennaway frmt = &(fsub[F_CPIO]);
1087b1787decSKris Kennaway break;
1088b1787decSKris Kennaway case 'p':
1089b1787decSKris Kennaway /*
1090b1787decSKris Kennaway * copy-pass mode
1091b1787decSKris Kennaway */
1092b1787decSKris Kennaway act = COPY;
1093b1787decSKris Kennaway break;
1094b1787decSKris Kennaway case 'r':
1095b1787decSKris Kennaway /*
1096b1787decSKris Kennaway * interactively rename files
1097b1787decSKris Kennaway */
1098b1787decSKris Kennaway iflag = 1;
1099b1787decSKris Kennaway break;
1100b1787decSKris Kennaway case 's':
1101b1787decSKris Kennaway /*
1102b1787decSKris Kennaway * swap bytes after reading data
1103b1787decSKris Kennaway */
1104b1787decSKris Kennaway break;
1105b1787decSKris Kennaway case 't':
1106b1787decSKris Kennaway /*
1107b1787decSKris Kennaway * list contents of archive
1108b1787decSKris Kennaway */
1109b1787decSKris Kennaway act = LIST;
1110b1787decSKris Kennaway listf = stdout;
1111b1787decSKris Kennaway break;
1112b1787decSKris Kennaway case 'u':
1113b1787decSKris Kennaway /*
1114b1787decSKris Kennaway * replace newer files
1115b1787decSKris Kennaway */
1116b1787decSKris Kennaway kflag = 0;
1117b1787decSKris Kennaway break;
1118b1787decSKris Kennaway case 'v':
1119b1787decSKris Kennaway /*
1120b1787decSKris Kennaway * verbose operation mode
1121b1787decSKris Kennaway */
1122b1787decSKris Kennaway vflag = 1;
1123b1787decSKris Kennaway break;
1124b1787decSKris Kennaway case 'z':
1125b1787decSKris Kennaway /*
1126b1787decSKris Kennaway * use gzip. Non standard option.
1127b1787decSKris Kennaway */
1128b1787decSKris Kennaway gzip_program = GZIP_CMD;
1129b1787decSKris Kennaway break;
1130b1787decSKris Kennaway case 'A':
1131b1787decSKris Kennaway /*
1132b1787decSKris Kennaway * append mode
1133b1787decSKris Kennaway */
1134b1787decSKris Kennaway act = APPND;
1135b1787decSKris Kennaway break;
1136b1787decSKris Kennaway case 'B':
1137b1787decSKris Kennaway /*
1138b1787decSKris Kennaway * Use 5120 byte block size
1139b1787decSKris Kennaway */
1140b1787decSKris Kennaway wrblksz = 5120;
1141b1787decSKris Kennaway break;
1142b1787decSKris Kennaway case 'C':
1143b1787decSKris Kennaway /*
1144b1787decSKris Kennaway * set block size in bytes
1145b1787decSKris Kennaway */
1146b1787decSKris Kennaway wrblksz = atoi(optarg);
1147b1787decSKris Kennaway break;
1148b1787decSKris Kennaway case 'E':
1149b1787decSKris Kennaway /*
1150b1787decSKris Kennaway * file with patterns to extract or list
1151b1787decSKris Kennaway */
1152b1787decSKris Kennaway if ((fp = fopen(optarg, "r")) == NULL) {
1153b1787decSKris Kennaway paxwarn(1, "Unable to open file '%s' for read", optarg);
1154b1787decSKris Kennaway cpio_usage();
11554b88c807SRodney W. Grimes }
1156a651f2bcSBaptiste Daroussin while ((str = get_line(fp)) != NULL) {
1157b1787decSKris Kennaway pat_add(str, NULL);
1158b1787decSKris Kennaway }
1159b1787decSKris Kennaway fclose(fp);
1160a651f2bcSBaptiste Daroussin if (get_line_error) {
1161b1787decSKris Kennaway paxwarn(1, "Problem with file '%s'", optarg);
1162b1787decSKris Kennaway cpio_usage();
1163b1787decSKris Kennaway }
1164b1787decSKris Kennaway break;
1165b1787decSKris Kennaway case 'F':
1166b1787decSKris Kennaway case 'I':
1167b1787decSKris Kennaway case 'O':
1168b1787decSKris Kennaway /*
1169b1787decSKris Kennaway * filename where the archive is stored
1170b1787decSKris Kennaway */
1171b1787decSKris Kennaway if ((optarg[0] == '-') && (optarg[1]== '\0')) {
1172b1787decSKris Kennaway /*
1173b1787decSKris Kennaway * treat a - as stdin
1174b1787decSKris Kennaway */
1175b1787decSKris Kennaway arcname = NULL;
1176b1787decSKris Kennaway break;
1177b1787decSKris Kennaway }
1178b1787decSKris Kennaway arcname = optarg;
1179b1787decSKris Kennaway break;
1180b1787decSKris Kennaway case 'H':
1181b1787decSKris Kennaway /*
1182b1787decSKris Kennaway * specify an archive format on write
1183b1787decSKris Kennaway */
1184b1787decSKris Kennaway tmp.name = optarg;
1185b1787decSKris Kennaway if ((frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
1186b1787decSKris Kennaway sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt)) != NULL)
1187b1787decSKris Kennaway break;
1188b1787decSKris Kennaway paxwarn(1, "Unknown -H format: %s", optarg);
1189b1787decSKris Kennaway (void)fputs("cpio: Known -H formats are:", stderr);
1190b1787decSKris Kennaway for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
1191b1787decSKris Kennaway (void)fprintf(stderr, " %s", fsub[i].name);
1192b1787decSKris Kennaway (void)fputs("\n\n", stderr);
1193b1787decSKris Kennaway cpio_usage();
1194b1787decSKris Kennaway break;
1195b1787decSKris Kennaway case 'L':
1196b1787decSKris Kennaway /*
1197b1787decSKris Kennaway * follow symbolic links
1198b1787decSKris Kennaway */
1199b1787decSKris Kennaway Lflag = 1;
1200b1787decSKris Kennaway break;
1201b1787decSKris Kennaway case 'S':
1202b1787decSKris Kennaway /*
1203b1787decSKris Kennaway * swap halfwords after reading data
1204b1787decSKris Kennaway */
1205b1787decSKris Kennaway break;
1206b1787decSKris Kennaway case 'Z':
1207b1787decSKris Kennaway /*
1208b1787decSKris Kennaway * use compress. Non standard option.
1209b1787decSKris Kennaway */
1210b1787decSKris Kennaway gzip_program = COMPRESS_CMD;
1211b1787decSKris Kennaway break;
1212b1787decSKris Kennaway case '6':
1213b1787decSKris Kennaway /*
1214b1787decSKris Kennaway * process Version 6 cpio format
1215b1787decSKris Kennaway */
1216b1787decSKris Kennaway frmt = &(fsub[F_OCPIO]);
1217b1787decSKris Kennaway break;
1218b1787decSKris Kennaway case '?':
1219b1787decSKris Kennaway default:
1220b1787decSKris Kennaway cpio_usage();
1221b1787decSKris Kennaway break;
1222b1787decSKris Kennaway }
1223b1787decSKris Kennaway argc -= optind;
1224b1787decSKris Kennaway argv += optind;
1225b1787decSKris Kennaway
1226b1787decSKris Kennaway /*
1227b1787decSKris Kennaway * process the args as they are interpreted by the operation mode
1228b1787decSKris Kennaway */
1229b1787decSKris Kennaway switch (act) {
1230b1787decSKris Kennaway case LIST:
1231b1787decSKris Kennaway case EXTRACT:
1232b1787decSKris Kennaway while (*argv != NULL)
1233b1787decSKris Kennaway if (pat_add(*argv++, NULL) < 0)
1234b1787decSKris Kennaway cpio_usage();
1235b1787decSKris Kennaway break;
1236b1787decSKris Kennaway case COPY:
1237b1787decSKris Kennaway if (*argv == NULL) {
1238b1787decSKris Kennaway paxwarn(0, "Destination directory was not supplied");
1239b1787decSKris Kennaway cpio_usage();
1240b1787decSKris Kennaway }
1241b1787decSKris Kennaway dirptr = *argv;
1242b1787decSKris Kennaway if (mkpath(dirptr) < 0)
1243b1787decSKris Kennaway cpio_usage();
1244b1787decSKris Kennaway --argc;
1245b1787decSKris Kennaway ++argv;
1246b1787decSKris Kennaway /* FALLTHROUGH */
1247b1787decSKris Kennaway case ARCHIVE:
1248b1787decSKris Kennaway case APPND:
1249b1787decSKris Kennaway if (*argv != NULL)
1250b1787decSKris Kennaway cpio_usage();
1251b1787decSKris Kennaway /*
1252b1787decSKris Kennaway * no read errors allowed on updates/append operation!
1253b1787decSKris Kennaway */
1254b1787decSKris Kennaway maxflt = 0;
1255a651f2bcSBaptiste Daroussin while ((str = get_line(stdin)) != NULL) {
125616fc3635SMark Murray ftree_add(str, 0);
1257b1787decSKris Kennaway }
1258a651f2bcSBaptiste Daroussin if (get_line_error) {
1259b1787decSKris Kennaway paxwarn(1, "Problem while reading stdin");
1260b1787decSKris Kennaway cpio_usage();
1261b1787decSKris Kennaway }
1262b1787decSKris Kennaway break;
1263b1787decSKris Kennaway default:
1264b1787decSKris Kennaway cpio_usage();
1265b1787decSKris Kennaway break;
1266b1787decSKris Kennaway }
1267b1787decSKris Kennaway }
12684b88c807SRodney W. Grimes
12694b88c807SRodney W. Grimes /*
12704b88c807SRodney W. Grimes * printflg()
12714b88c807SRodney W. Grimes * print out those invalid flag sets found to the user
12724b88c807SRodney W. Grimes */
12734b88c807SRodney W. Grimes
12744b88c807SRodney W. Grimes static void
printflg(unsigned int flg)12754b88c807SRodney W. Grimes printflg(unsigned int flg)
12764b88c807SRodney W. Grimes {
12774b88c807SRodney W. Grimes int nxt;
12784b88c807SRodney W. Grimes int pos = 0;
12794b88c807SRodney W. Grimes
12804b88c807SRodney W. Grimes (void)fprintf(stderr,"%s: Invalid combination of options:", argv0);
1281b1787decSKris Kennaway while ((nxt = ffs(flg)) != 0) {
12824b88c807SRodney W. Grimes flg = flg >> nxt;
12834b88c807SRodney W. Grimes pos += nxt;
12844b88c807SRodney W. Grimes (void)fprintf(stderr, " -%c", flgch[pos-1]);
12854b88c807SRodney W. Grimes }
12864b88c807SRodney W. Grimes (void)putc('\n', stderr);
12874b88c807SRodney W. Grimes }
12884b88c807SRodney W. Grimes
12894b88c807SRodney W. Grimes /*
12904b88c807SRodney W. Grimes * c_frmt()
12914b88c807SRodney W. Grimes * comparison routine used by bsearch to find the format specified
12924b88c807SRodney W. Grimes * by the user
12934b88c807SRodney W. Grimes */
12944b88c807SRodney W. Grimes
12954b88c807SRodney W. Grimes static int
c_frmt(const void * a,const void * b)12964b88c807SRodney W. Grimes c_frmt(const void *a, const void *b)
12974b88c807SRodney W. Grimes {
129840feca3aSMark Murray return(strcmp(((const FSUB *)a)->name, ((const FSUB *)b)->name));
12994b88c807SRodney W. Grimes }
13004b88c807SRodney W. Grimes
13014b88c807SRodney W. Grimes /*
13024b88c807SRodney W. Grimes * opt_next()
13034b88c807SRodney W. Grimes * called by format specific options routines to get each format specific
13044b88c807SRodney W. Grimes * flag and value specified with -o
13054b88c807SRodney W. Grimes * Return:
13064b88c807SRodney W. Grimes * pointer to next OPLIST entry or NULL (end of list).
13074b88c807SRodney W. Grimes */
13084b88c807SRodney W. Grimes
13094b88c807SRodney W. Grimes OPLIST *
opt_next(void)13104b88c807SRodney W. Grimes opt_next(void)
13114b88c807SRodney W. Grimes {
13124b88c807SRodney W. Grimes OPLIST *opt;
13134b88c807SRodney W. Grimes
13144b88c807SRodney W. Grimes if ((opt = ophead) != NULL)
13154b88c807SRodney W. Grimes ophead = ophead->fow;
13164b88c807SRodney W. Grimes return(opt);
13174b88c807SRodney W. Grimes }
13184b88c807SRodney W. Grimes
13194b88c807SRodney W. Grimes /*
13204b88c807SRodney W. Grimes * bad_opt()
13214b88c807SRodney W. Grimes * generic routine used to complain about a format specific options
13224b88c807SRodney W. Grimes * when the format does not support options.
13234b88c807SRodney W. Grimes */
13244b88c807SRodney W. Grimes
13254b88c807SRodney W. Grimes int
bad_opt(void)13264b88c807SRodney W. Grimes bad_opt(void)
13274b88c807SRodney W. Grimes {
1328f789b261SWarner Losh OPLIST *opt;
13294b88c807SRodney W. Grimes
13304b88c807SRodney W. Grimes if (ophead == NULL)
13314b88c807SRodney W. Grimes return(0);
13324b88c807SRodney W. Grimes /*
13334b88c807SRodney W. Grimes * print all we were given
13344b88c807SRodney W. Grimes */
1335778766feSKris Kennaway paxwarn(1,"These format options are not supported");
13364b88c807SRodney W. Grimes while ((opt = opt_next()) != NULL)
13374b88c807SRodney W. Grimes (void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value);
13384b88c807SRodney W. Grimes pax_usage();
13394b88c807SRodney W. Grimes return(0);
13404b88c807SRodney W. Grimes }
13414b88c807SRodney W. Grimes
13424b88c807SRodney W. Grimes /*
13434b88c807SRodney W. Grimes * opt_add()
13449d5abbddSJens Schweikhardt * breaks the value supplied to -o into an option name and value. Options
13454b88c807SRodney W. Grimes * are given to -o in the form -o name-value,name=value
134646be34b9SKris Kennaway * multiple -o may be specified.
13474b88c807SRodney W. Grimes * Return:
13489d5abbddSJens Schweikhardt * 0 if format in name=value format, -1 if -o is passed junk.
13494b88c807SRodney W. Grimes */
13504b88c807SRodney W. Grimes
13514b88c807SRodney W. Grimes int
opt_add(const char * str)135240feca3aSMark Murray opt_add(const char *str)
13534b88c807SRodney W. Grimes {
1354f789b261SWarner Losh OPLIST *opt;
1355f789b261SWarner Losh char *frpt;
1356f789b261SWarner Losh char *pt;
1357f789b261SWarner Losh char *endpt;
135840feca3aSMark Murray char *lstr;
13594b88c807SRodney W. Grimes
13604b88c807SRodney W. Grimes if ((str == NULL) || (*str == '\0')) {
1361778766feSKris Kennaway paxwarn(0, "Invalid option name");
13624b88c807SRodney W. Grimes return(-1);
13634b88c807SRodney W. Grimes }
136440feca3aSMark Murray if ((lstr = strdup(str)) == NULL) {
1365b1787decSKris Kennaway paxwarn(0, "Unable to allocate space for option list");
1366b1787decSKris Kennaway return(-1);
1367b1787decSKris Kennaway }
136840feca3aSMark Murray frpt = endpt = lstr;
13694b88c807SRodney W. Grimes
13704b88c807SRodney W. Grimes /*
13714b88c807SRodney W. Grimes * break into name and values pieces and stuff each one into a
13724b88c807SRodney W. Grimes * OPLIST structure. When we know the format, the format specific
13734b88c807SRodney W. Grimes * option function will go through this list
13744b88c807SRodney W. Grimes */
13754b88c807SRodney W. Grimes while ((frpt != NULL) && (*frpt != '\0')) {
13764b88c807SRodney W. Grimes if ((endpt = strchr(frpt, ',')) != NULL)
13774b88c807SRodney W. Grimes *endpt = '\0';
13784b88c807SRodney W. Grimes if ((pt = strchr(frpt, '=')) == NULL) {
1379778766feSKris Kennaway paxwarn(0, "Invalid options format");
138040feca3aSMark Murray free(lstr);
13814b88c807SRodney W. Grimes return(-1);
13824b88c807SRodney W. Grimes }
13834b88c807SRodney W. Grimes if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
1384778766feSKris Kennaway paxwarn(0, "Unable to allocate space for option list");
138540feca3aSMark Murray free(lstr);
13864b88c807SRodney W. Grimes return(-1);
13874b88c807SRodney W. Grimes }
1388248825e5SKevin Lo lstr = NULL; /* parts of string going onto the OPLIST */
13894b88c807SRodney W. Grimes *pt++ = '\0';
13904b88c807SRodney W. Grimes opt->name = frpt;
13914b88c807SRodney W. Grimes opt->value = pt;
13924b88c807SRodney W. Grimes opt->fow = NULL;
13934b88c807SRodney W. Grimes if (endpt != NULL)
13944b88c807SRodney W. Grimes frpt = endpt + 1;
13954b88c807SRodney W. Grimes else
13964b88c807SRodney W. Grimes frpt = NULL;
13974b88c807SRodney W. Grimes if (ophead == NULL) {
13984b88c807SRodney W. Grimes optail = ophead = opt;
13994b88c807SRodney W. Grimes continue;
14004b88c807SRodney W. Grimes }
14014b88c807SRodney W. Grimes optail->fow = opt;
14024b88c807SRodney W. Grimes optail = opt;
14034b88c807SRodney W. Grimes }
1404248825e5SKevin Lo free(lstr);
14054b88c807SRodney W. Grimes return(0);
14064b88c807SRodney W. Grimes }
14074b88c807SRodney W. Grimes
14084b88c807SRodney W. Grimes /*
14094b88c807SRodney W. Grimes * str_offt()
14104b88c807SRodney W. Grimes * Convert an expression of the following forms to an off_t > 0.
14114b88c807SRodney W. Grimes * 1) A positive decimal number.
14124b88c807SRodney W. Grimes * 2) A positive decimal number followed by a b (mult by 512).
14134b88c807SRodney W. Grimes * 3) A positive decimal number followed by a k (mult by 1024).
14144b88c807SRodney W. Grimes * 4) A positive decimal number followed by a m (mult by 512).
14154b88c807SRodney W. Grimes * 5) A positive decimal number followed by a w (mult by sizeof int)
14164b88c807SRodney W. Grimes * 6) Two or more positive decimal numbers (with/without k,b or w).
14179a01d32bSJeroen Ruigrok van der Werven * separated by x (also * for backwards compatibility), specifying
14184b88c807SRodney W. Grimes * the product of the indicated values.
14194b88c807SRodney W. Grimes * Return:
14204b88c807SRodney W. Grimes * 0 for an error, a positive value o.w.
14214b88c807SRodney W. Grimes */
14224b88c807SRodney W. Grimes
14234b88c807SRodney W. Grimes static off_t
str_offt(char * val)14244b88c807SRodney W. Grimes str_offt(char *val)
14254b88c807SRodney W. Grimes {
14264b88c807SRodney W. Grimes char *expr;
14274b88c807SRodney W. Grimes off_t num, t;
14284b88c807SRodney W. Grimes
14294b88c807SRodney W. Grimes num = strtoq(val, &expr, 0);
14304b88c807SRodney W. Grimes if ((num == QUAD_MAX) || (num <= 0) || (expr == val))
14314b88c807SRodney W. Grimes return(0);
14324b88c807SRodney W. Grimes
14334b88c807SRodney W. Grimes switch(*expr) {
14344b88c807SRodney W. Grimes case 'b':
14354b88c807SRodney W. Grimes t = num;
14364b88c807SRodney W. Grimes num *= 512;
14374b88c807SRodney W. Grimes if (t > num)
14384b88c807SRodney W. Grimes return(0);
14394b88c807SRodney W. Grimes ++expr;
14404b88c807SRodney W. Grimes break;
14414b88c807SRodney W. Grimes case 'k':
14424b88c807SRodney W. Grimes t = num;
14434b88c807SRodney W. Grimes num *= 1024;
14444b88c807SRodney W. Grimes if (t > num)
14454b88c807SRodney W. Grimes return(0);
14464b88c807SRodney W. Grimes ++expr;
14474b88c807SRodney W. Grimes break;
14484b88c807SRodney W. Grimes case 'm':
14494b88c807SRodney W. Grimes t = num;
14504b88c807SRodney W. Grimes num *= 1048576;
14514b88c807SRodney W. Grimes if (t > num)
14524b88c807SRodney W. Grimes return(0);
14534b88c807SRodney W. Grimes ++expr;
14544b88c807SRodney W. Grimes break;
14554b88c807SRodney W. Grimes case 'w':
14564b88c807SRodney W. Grimes t = num;
14574b88c807SRodney W. Grimes num *= sizeof(int);
14584b88c807SRodney W. Grimes if (t > num)
14594b88c807SRodney W. Grimes return(0);
14604b88c807SRodney W. Grimes ++expr;
14614b88c807SRodney W. Grimes break;
14624b88c807SRodney W. Grimes }
14634b88c807SRodney W. Grimes
14644b88c807SRodney W. Grimes switch(*expr) {
14654b88c807SRodney W. Grimes case '\0':
14664b88c807SRodney W. Grimes break;
14674b88c807SRodney W. Grimes case '*':
14684b88c807SRodney W. Grimes case 'x':
14694b88c807SRodney W. Grimes t = num;
14704b88c807SRodney W. Grimes num *= str_offt(expr + 1);
14714b88c807SRodney W. Grimes if (t > num)
14724b88c807SRodney W. Grimes return(0);
14734b88c807SRodney W. Grimes break;
14744b88c807SRodney W. Grimes default:
14754b88c807SRodney W. Grimes return(0);
14764b88c807SRodney W. Grimes }
14774b88c807SRodney W. Grimes return(num);
14784b88c807SRodney W. Grimes }
14794b88c807SRodney W. Grimes
1480b1787decSKris Kennaway char *
get_line(FILE * f)1481a651f2bcSBaptiste Daroussin get_line(FILE *f)
1482b1787decSKris Kennaway {
1483b1787decSKris Kennaway char *name, *temp;
1484b1787decSKris Kennaway size_t len;
1485b1787decSKris Kennaway
1486b1787decSKris Kennaway name = fgetln(f, &len);
1487b1787decSKris Kennaway if (!name) {
1488a651f2bcSBaptiste Daroussin get_line_error = ferror(f) ? GETLINE_FILE_CORRUPT : 0;
1489b1787decSKris Kennaway return(0);
1490b1787decSKris Kennaway }
1491b1787decSKris Kennaway if (name[len-1] != '\n')
1492b1787decSKris Kennaway len++;
1493b1787decSKris Kennaway temp = malloc(len);
1494b1787decSKris Kennaway if (!temp) {
1495a651f2bcSBaptiste Daroussin get_line_error = GETLINE_OUT_OF_MEM;
1496b1787decSKris Kennaway return(0);
1497b1787decSKris Kennaway }
1498b1787decSKris Kennaway memcpy(temp, name, len-1);
1499b1787decSKris Kennaway temp[len-1] = 0;
1500b1787decSKris Kennaway return(temp);
1501b1787decSKris Kennaway }
1502b1787decSKris Kennaway
15034b88c807SRodney W. Grimes /*
15044b88c807SRodney W. Grimes * no_op()
15054b88c807SRodney W. Grimes * for those option functions where the archive format has nothing to do.
15064b88c807SRodney W. Grimes * Return:
15074b88c807SRodney W. Grimes * 0
15084b88c807SRodney W. Grimes */
15094b88c807SRodney W. Grimes
15104b88c807SRodney W. Grimes static int
no_op(void)15114b88c807SRodney W. Grimes no_op(void)
15124b88c807SRodney W. Grimes {
15134b88c807SRodney W. Grimes return(0);
15144b88c807SRodney W. Grimes }
15154b88c807SRodney W. Grimes
15164b88c807SRodney W. Grimes /*
15174b88c807SRodney W. Grimes * pax_usage()
15184b88c807SRodney W. Grimes * print the usage summary to the user
15194b88c807SRodney W. Grimes */
15204b88c807SRodney W. Grimes
15214b88c807SRodney W. Grimes void
pax_usage(void)15224b88c807SRodney W. Grimes pax_usage(void)
15234b88c807SRodney W. Grimes {
1524d6e1f8d7SEitan Adler (void)fputs("usage: pax [-cdnOvz] [-E limit] [-f archive] ", stderr);
15254b88c807SRodney W. Grimes (void)fputs("[-s replstr] ... [-U user] ...", stderr);
15264b88c807SRodney W. Grimes (void)fputs("\n [-G group] ... ", stderr);
15274b88c807SRodney W. Grimes (void)fputs("[-T [from_date][,to_date]] ... ", stderr);
15284b88c807SRodney W. Grimes (void)fputs("[pattern ...]\n", stderr);
1529d6e1f8d7SEitan Adler (void)fputs(" pax -r [-cdiknOuvzDYZ] [-E limit] ", stderr);
15304b88c807SRodney W. Grimes (void)fputs("[-f archive] [-o options] ... \n", stderr);
15314b88c807SRodney W. Grimes (void)fputs(" [-p string] ... [-s replstr] ... ", stderr);
15324b88c807SRodney W. Grimes (void)fputs("[-U user] ... [-G group] ...\n ", stderr);
15334b88c807SRodney W. Grimes (void)fputs("[-T [from_date][,to_date]] ... ", stderr);
15344b88c807SRodney W. Grimes (void)fputs(" [pattern ...]\n", stderr);
1535d6e1f8d7SEitan Adler (void)fputs(" pax -w [-dituvzHLOPX] [-b blocksize] ", stderr);
15364b88c807SRodney W. Grimes (void)fputs("[ [-a] [-f archive] ] [-x format] \n", stderr);
15374b88c807SRodney W. Grimes (void)fputs(" [-B bytes] [-s replstr] ... ", stderr);
15384b88c807SRodney W. Grimes (void)fputs("[-o options] ... [-U user] ...", stderr);
15394b88c807SRodney W. Grimes (void)fputs("\n [-G group] ... ", stderr);
15404b88c807SRodney W. Grimes (void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
15414b88c807SRodney W. Grimes (void)fputs("[file ...]\n", stderr);
1542d6e1f8d7SEitan Adler (void)fputs(" pax -r -w [-diklntuvDHLOPXYZ] ", stderr);
15434b88c807SRodney W. Grimes (void)fputs("[-p string] ... [-s replstr] ...", stderr);
15444b88c807SRodney W. Grimes (void)fputs("\n [-U user] ... [-G group] ... ", stderr);
15454b88c807SRodney W. Grimes (void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
15464b88c807SRodney W. Grimes (void)fputs("\n [file ...] directory\n", stderr);
15474b88c807SRodney W. Grimes exit(1);
15484b88c807SRodney W. Grimes }
15494b88c807SRodney W. Grimes
15504b88c807SRodney W. Grimes /*
15514b88c807SRodney W. Grimes * tar_usage()
15524b88c807SRodney W. Grimes * print the usage summary to the user
15534b88c807SRodney W. Grimes */
15544b88c807SRodney W. Grimes
15554b88c807SRodney W. Grimes void
tar_usage(void)15564b88c807SRodney W. Grimes tar_usage(void)
15574b88c807SRodney W. Grimes {
1558b1787decSKris Kennaway (void)fputs("usage: tar [-]{crtux}[-befhjmopqsvwyzHLOPXZ014578] [blocksize] ",
15594b88c807SRodney W. Grimes stderr);
1560b1787decSKris Kennaway (void)fputs("[archive] [replstr] [-C directory] [-I file] [file ...]\n",
1561b1787decSKris Kennaway stderr);
15624b88c807SRodney W. Grimes exit(1);
15634b88c807SRodney W. Grimes }
15644b88c807SRodney W. Grimes
15654b88c807SRodney W. Grimes /*
15664b88c807SRodney W. Grimes * cpio_usage()
15674b88c807SRodney W. Grimes * print the usage summary to the user
15684b88c807SRodney W. Grimes */
15694b88c807SRodney W. Grimes
15704b88c807SRodney W. Grimes void
cpio_usage(void)15714b88c807SRodney W. Grimes cpio_usage(void)
15724b88c807SRodney W. Grimes {
1573b1787decSKris Kennaway (void)fputs("usage: cpio -o [-aABcLvVzZ] [-C bytes] [-H format] [-O archive]\n", stderr);
1574b1787decSKris Kennaway (void)fputs(" [-F archive] < name-list [> archive]\n", stderr);
1575b1787decSKris Kennaway (void)fputs(" cpio -i [-bBcdfmnrsStuvVzZ6] [-C bytes] [-E file] [-H format]\n", stderr);
1576b1787decSKris Kennaway (void)fputs(" [-I archive] [-F archive] [pattern...] [< archive]\n", stderr);
1577b1787decSKris Kennaway (void)fputs(" cpio -p [-adlLmuvV] destination-directory < name-list\n", stderr);
15784b88c807SRodney W. Grimes exit(1);
15794b88c807SRodney W. Grimes }
1580