Home | History | Annotate | Line # | Download | only in pax
options.c revision 1.39.2.2
      1  1.39.2.2       jmc /*	$NetBSD: options.c,v 1.39.2.2 2004/06/16 01:27:38 jmc Exp $	*/
      2       1.5       cgd 
      3       1.1       jtc /*-
      4       1.1       jtc  * Copyright (c) 1992 Keith Muller.
      5       1.1       jtc  * Copyright (c) 1992, 1993
      6       1.1       jtc  *	The Regents of the University of California.  All rights reserved.
      7       1.1       jtc  *
      8       1.1       jtc  * This code is derived from software contributed to Berkeley by
      9       1.1       jtc  * Keith Muller of the University of California, San Diego.
     10       1.1       jtc  *
     11       1.1       jtc  * Redistribution and use in source and binary forms, with or without
     12       1.1       jtc  * modification, are permitted provided that the following conditions
     13       1.1       jtc  * are met:
     14       1.1       jtc  * 1. Redistributions of source code must retain the above copyright
     15       1.1       jtc  *    notice, this list of conditions and the following disclaimer.
     16       1.1       jtc  * 2. Redistributions in binary form must reproduce the above copyright
     17       1.1       jtc  *    notice, this list of conditions and the following disclaimer in the
     18       1.1       jtc  *    documentation and/or other materials provided with the distribution.
     19  1.39.2.1       jmc  * 3. Neither the name of the University nor the names of its contributors
     20       1.1       jtc  *    may be used to endorse or promote products derived from this software
     21       1.1       jtc  *    without specific prior written permission.
     22       1.1       jtc  *
     23       1.1       jtc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24       1.1       jtc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25       1.1       jtc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26       1.1       jtc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27       1.1       jtc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28       1.1       jtc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29       1.1       jtc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30       1.1       jtc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31       1.1       jtc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32       1.1       jtc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33       1.1       jtc  * SUCH DAMAGE.
     34       1.1       jtc  */
     35       1.1       jtc 
     36  1.39.2.2       jmc #if HAVE_CONFIG_H
     37  1.39.2.2       jmc #include "config.h"
     38  1.39.2.1       jmc #endif
     39  1.39.2.1       jmc 
     40       1.8  christos #include <sys/cdefs.h>
     41  1.39.2.1       jmc #if !defined(lint)
     42       1.5       cgd #if 0
     43       1.5       cgd static char sccsid[] = "@(#)options.c	8.2 (Berkeley) 4/18/94";
     44       1.5       cgd #else
     45  1.39.2.2       jmc __RCSID("$NetBSD: options.c,v 1.39.2.2 2004/06/16 01:27:38 jmc Exp $");
     46       1.5       cgd #endif
     47       1.1       jtc #endif /* not lint */
     48       1.1       jtc 
     49       1.1       jtc #include <sys/types.h>
     50       1.1       jtc #include <sys/time.h>
     51       1.1       jtc #include <sys/stat.h>
     52       1.1       jtc #include <sys/mtio.h>
     53       1.1       jtc #include <sys/param.h>
     54      1.38        tv #include <ctype.h>
     55  1.39.2.1       jmc #include <errno.h>
     56      1.38        tv #include <getopt.h>
     57      1.38        tv #include <limits.h>
     58       1.1       jtc #include <stdio.h>
     59      1.38        tv #include <stdlib.h>
     60       1.1       jtc #include <string.h>
     61       1.1       jtc #include <unistd.h>
     62  1.39.2.1       jmc #include <paths.h>
     63       1.1       jtc #include "pax.h"
     64       1.1       jtc #include "options.h"
     65       1.1       jtc #include "cpio.h"
     66       1.1       jtc #include "tar.h"
     67       1.1       jtc #include "extern.h"
     68      1.39     lukem #ifndef SMALL
     69      1.35     lukem #include "mtree.h"
     70      1.39     lukem #endif	/* SMALL */
     71       1.1       jtc 
     72       1.1       jtc /*
     73       1.1       jtc  * Routines which handle command line options
     74       1.1       jtc  */
     75       1.1       jtc 
     76      1.18        tv static int nopids;		/* tar mode: suppress "pids" for -p option */
     77      1.10       mrg static char *flgch = FLGCH;	/* list of all possible flags (pax) */
     78       1.1       jtc static OPLIST *ophead = NULL;	/* head for format specific options -x */
     79       1.1       jtc static OPLIST *optail = NULL;	/* option tail */
     80       1.1       jtc 
     81      1.33     lukem static int no_op(void);
     82      1.33     lukem static void printflg(unsigned int);
     83      1.33     lukem static int c_frmt(const void *, const void *);
     84      1.33     lukem static off_t str_offt(char *);
     85  1.39.2.1       jmc static char *getline(FILE *fp);
     86      1.33     lukem static void pax_options(int, char **);
     87      1.33     lukem static void pax_usage(void);
     88      1.33     lukem static void tar_options(int, char **);
     89      1.33     lukem static void tar_usage(void);
     90      1.33     lukem static void cpio_options(int, char **);
     91      1.33     lukem static void cpio_usage(void);
     92       1.1       jtc 
     93  1.39.2.1       jmc /* errors from getline */
     94  1.39.2.1       jmc #define GETLINE_FILE_CORRUPT 1
     95  1.39.2.1       jmc #define GETLINE_OUT_OF_MEM 2
     96  1.39.2.1       jmc static int getline_error;
     97      1.23        is 
     98  1.39.2.1       jmc #define BZIP2_CMD	"bzip2"		/* command to run as bzip2 */
     99       1.6       mrg #define GZIP_CMD	"gzip"		/* command to run as gzip */
    100       1.6       mrg #define COMPRESS_CMD	"compress"	/* command to run as compress */
    101       1.6       mrg 
    102       1.1       jtc /*
    103  1.39.2.1       jmc  * Long options.
    104  1.39.2.1       jmc  */
    105  1.39.2.1       jmc #define	OPT_USE_COMPRESS_PROGRAM	0
    106  1.39.2.1       jmc #define	OPT_CHECKPOINT			1
    107  1.39.2.1       jmc #define	OPT_UNLINK			2
    108  1.39.2.1       jmc #define	OPT_HELP			3
    109  1.39.2.1       jmc #define	OPT_ATIME_PRESERVE		4
    110  1.39.2.1       jmc #define	OPT_IGNORE_FAILED_READ		5
    111  1.39.2.1       jmc #define	OPT_REMOVE_FILES		6
    112  1.39.2.1       jmc #define	OPT_NULL			7
    113  1.39.2.1       jmc #define	OPT_TOTALS			8
    114  1.39.2.1       jmc #define	OPT_VERSION			9
    115  1.39.2.1       jmc #define	OPT_EXCLUDE			10
    116  1.39.2.1       jmc #define	OPT_BLOCK_COMPRESS		11
    117  1.39.2.1       jmc #define	OPT_NORECURSE			12
    118  1.39.2.1       jmc #define	OPT_FORCE_LOCAL			13
    119  1.39.2.1       jmc #define	OPT_INSECURE			14
    120  1.39.2.1       jmc #define	OPT_STRICT			15
    121  1.39.2.1       jmc 
    122  1.39.2.1       jmc /*
    123       1.1       jtc  *	Format specific routine table - MUST BE IN SORTED ORDER BY NAME
    124       1.1       jtc  *	(see pax.h for description of each function)
    125       1.1       jtc  *
    126      1.26     itohy  *	name, blksz, hdsz, udev, hlk, blkagn, inhead, id, st_read,
    127       1.1       jtc  *	read, end_read, st_write, write, end_write, trail,
    128       1.1       jtc  *	rd_data, wr_data, options
    129       1.1       jtc  */
    130       1.1       jtc 
    131       1.1       jtc FSUB fsub[] = {
    132       1.1       jtc /* 0: OLD BINARY CPIO */
    133       1.8  christos 	{ "bcpio", 5120, sizeof(HD_BCPIO), 1, 0, 0, 1, bcpio_id, cpio_strd,
    134       1.8  christos 	bcpio_rd, bcpio_endrd, cpio_stwr, bcpio_wr, cpio_endwr, NULL,
    135       1.8  christos 	cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt },
    136       1.1       jtc 
    137       1.1       jtc /* 1: OLD OCTAL CHARACTER CPIO */
    138       1.8  christos 	{ "cpio", 5120, sizeof(HD_CPIO), 1, 0, 0, 1, cpio_id, cpio_strd,
    139       1.8  christos 	cpio_rd, cpio_endrd, cpio_stwr, cpio_wr, cpio_endwr, NULL,
    140       1.8  christos 	cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt },
    141       1.1       jtc 
    142       1.1       jtc /* 2: SVR4 HEX CPIO */
    143       1.8  christos 	{ "sv4cpio", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, vcpio_id, cpio_strd,
    144       1.8  christos 	vcpio_rd, vcpio_endrd, cpio_stwr, vcpio_wr, cpio_endwr, NULL,
    145       1.8  christos 	cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt },
    146       1.1       jtc 
    147       1.1       jtc /* 3: SVR4 HEX CPIO WITH CRC */
    148       1.8  christos 	{ "sv4crc", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd,
    149       1.8  christos 	vcpio_rd, vcpio_endrd, crc_stwr, vcpio_wr, cpio_endwr, NULL,
    150       1.8  christos 	cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt },
    151       1.1       jtc 
    152       1.1       jtc /* 4: OLD TAR */
    153       1.8  christos 	{ "tar", 10240, BLKMULT, 0, 1, BLKMULT, 0, tar_id, no_op,
    154       1.1       jtc 	tar_rd, tar_endrd, no_op, tar_wr, tar_endwr, tar_trail,
    155       1.8  christos 	NULL, rd_wrfile, wr_rdfile, tar_opt },
    156       1.1       jtc 
    157       1.1       jtc /* 5: POSIX USTAR */
    158       1.8  christos 	{ "ustar", 10240, BLKMULT, 0, 1, BLKMULT, 0, ustar_id, ustar_strd,
    159       1.1       jtc 	ustar_rd, tar_endrd, ustar_stwr, ustar_wr, tar_endwr, tar_trail,
    160       1.8  christos 	NULL, rd_wrfile, wr_rdfile, bad_opt }
    161       1.1       jtc };
    162      1.10       mrg #define F_BCPIO		0	/* old binary cpio format */
    163      1.10       mrg #define F_CPIO		1	/* old octal character cpio format */
    164      1.10       mrg #define F_SV4CPIO	2	/* SVR4 hex cpio format */
    165      1.10       mrg #define F_SV4CRC	3	/* SVR4 hex with crc cpio format */
    166      1.18        tv #define F_TAR		4	/* old V7 UNIX tar format */
    167      1.10       mrg #define F_USTAR		5	/* ustar format */
    168      1.10       mrg #define DEFLT		F_USTAR	/* default write format from list above */
    169       1.1       jtc 
    170       1.1       jtc /*
    171       1.1       jtc  * ford is the archive search order used by get_arc() to determine what kind
    172  1.39.2.1       jmc  * of archive we are dealing with. This helps to properly id archive formats
    173       1.1       jtc  * some formats may be subsets of others....
    174       1.1       jtc  */
    175      1.10       mrg int ford[] = {F_USTAR, F_TAR, F_SV4CRC, F_SV4CPIO, F_CPIO, F_BCPIO, -1};
    176       1.1       jtc 
    177       1.1       jtc /*
    178       1.1       jtc  * options()
    179       1.1       jtc  *	figure out if we are pax, tar or cpio. Call the appropriate options
    180       1.1       jtc  *	parser
    181       1.1       jtc  */
    182       1.1       jtc 
    183       1.1       jtc void
    184       1.7       tls options(int argc, char **argv)
    185       1.1       jtc {
    186       1.1       jtc 
    187       1.1       jtc 	/*
    188       1.1       jtc 	 * Are we acting like pax, tar or cpio (based on argv[0])
    189       1.1       jtc 	 */
    190       1.1       jtc 	if ((argv0 = strrchr(argv[0], '/')) != NULL)
    191       1.1       jtc 		argv0++;
    192       1.1       jtc 	else
    193       1.1       jtc 		argv0 = argv[0];
    194       1.1       jtc 
    195       1.1       jtc 	if (strcmp(NM_TAR, argv0) == 0)
    196      1.13   mycroft 		tar_options(argc, argv);
    197       1.1       jtc 	else if (strcmp(NM_CPIO, argv0) == 0)
    198      1.13   mycroft 		cpio_options(argc, argv);
    199      1.13   mycroft 	else {
    200      1.13   mycroft 		argv0 = NM_PAX;
    201      1.13   mycroft 		pax_options(argc, argv);
    202      1.13   mycroft 	}
    203       1.1       jtc }
    204       1.1       jtc 
    205  1.39.2.1       jmc struct option pax_longopts[] = {
    206  1.39.2.1       jmc 	{ "insecure",		no_argument,		0,
    207  1.39.2.1       jmc 						OPT_INSECURE },
    208  1.39.2.1       jmc 	{ "force-local",	no_argument,		0,
    209  1.39.2.1       jmc 						OPT_FORCE_LOCAL },
    210  1.39.2.1       jmc };
    211  1.39.2.1       jmc 
    212       1.1       jtc /*
    213       1.1       jtc  * pax_options()
    214       1.1       jtc  *	look at the user specified flags. set globals as required and check if
    215       1.1       jtc  *	the user specified a legal set of flags. If not, complain and exit
    216       1.1       jtc  */
    217       1.1       jtc 
    218       1.1       jtc static void
    219       1.7       tls pax_options(int argc, char **argv)
    220       1.1       jtc {
    221       1.7       tls 	int c;
    222       1.7       tls 	int i;
    223       1.1       jtc 	unsigned int flg = 0;
    224       1.1       jtc 	unsigned int bflg = 0;
    225       1.7       tls 	char *pt;
    226      1.26     itohy 	FSUB tmp;
    227       1.1       jtc 
    228       1.1       jtc 	/*
    229       1.1       jtc 	 * process option flags
    230       1.1       jtc 	 */
    231  1.39.2.1       jmc 	while ((c = getopt_long(argc, argv,
    232  1.39.2.1       jmc 	    "ab:cdf:ijklno:p:rs:tuvwx:zAB:DE:G:HLMN:OPT:U:XYZ",
    233  1.39.2.1       jmc 	    pax_longopts, NULL)) != -1) {
    234       1.1       jtc 		switch (c) {
    235       1.1       jtc 		case 'a':
    236       1.1       jtc 			/*
    237       1.1       jtc 			 * append
    238       1.1       jtc 			 */
    239       1.1       jtc 			flg |= AF;
    240       1.1       jtc 			break;
    241       1.1       jtc 		case 'b':
    242       1.1       jtc 			/*
    243       1.1       jtc 			 * specify blocksize
    244       1.1       jtc 			 */
    245       1.1       jtc 			flg |= BF;
    246       1.1       jtc 			if ((wrblksz = (int)str_offt(optarg)) <= 0) {
    247       1.8  christos 				tty_warn(1, "Invalid block size %s", optarg);
    248       1.1       jtc 				pax_usage();
    249       1.1       jtc 			}
    250       1.1       jtc 			break;
    251       1.1       jtc 		case 'c':
    252       1.1       jtc 			/*
    253       1.1       jtc 			 * inverse match on patterns
    254       1.1       jtc 			 */
    255       1.1       jtc 			cflag = 1;
    256       1.1       jtc 			flg |= CF;
    257       1.1       jtc 			break;
    258       1.1       jtc 		case 'd':
    259       1.1       jtc 			/*
    260       1.1       jtc 			 * match only dir on extract, not the subtree at dir
    261       1.1       jtc 			 */
    262       1.1       jtc 			dflag = 1;
    263       1.1       jtc 			flg |= DF;
    264       1.1       jtc 			break;
    265       1.1       jtc 		case 'f':
    266       1.1       jtc 			/*
    267       1.1       jtc 			 * filename where the archive is stored
    268       1.1       jtc 			 */
    269       1.1       jtc 			arcname = optarg;
    270       1.1       jtc 			flg |= FF;
    271       1.1       jtc 			break;
    272       1.1       jtc 		case 'i':
    273       1.1       jtc 			/*
    274       1.1       jtc 			 * interactive file rename
    275       1.1       jtc 			 */
    276       1.1       jtc 			iflag = 1;
    277       1.1       jtc 			flg |= IF;
    278       1.1       jtc 			break;
    279  1.39.2.1       jmc 		case 'j':
    280  1.39.2.1       jmc 			/*
    281  1.39.2.1       jmc 			 * pass through bzip2
    282  1.39.2.1       jmc 			 */
    283  1.39.2.1       jmc 			jflag = 1;
    284  1.39.2.1       jmc 			gzip_program = BZIP2_CMD;
    285  1.39.2.1       jmc 			break;
    286       1.1       jtc 		case 'k':
    287       1.1       jtc 			/*
    288       1.1       jtc 			 * do not clobber files that exist
    289       1.1       jtc 			 */
    290       1.1       jtc 			kflag = 1;
    291       1.1       jtc 			flg |= KF;
    292       1.1       jtc 			break;
    293       1.1       jtc 		case 'l':
    294       1.1       jtc 			/*
    295       1.1       jtc 			 * try to link src to dest with copy (-rw)
    296       1.1       jtc 			 */
    297       1.1       jtc 			lflag = 1;
    298       1.1       jtc 			flg |= LF;
    299       1.1       jtc 			break;
    300       1.1       jtc 		case 'n':
    301       1.1       jtc 			/*
    302       1.1       jtc 			 * select first match for a pattern only
    303       1.1       jtc 			 */
    304       1.1       jtc 			nflag = 1;
    305       1.1       jtc 			flg |= NF;
    306       1.1       jtc 			break;
    307       1.1       jtc 		case 'o':
    308       1.1       jtc 			/*
    309       1.1       jtc 			 * pass format specific options
    310       1.1       jtc 			 */
    311       1.1       jtc 			flg |= OF;
    312       1.1       jtc 			if (opt_add(optarg) < 0)
    313       1.1       jtc 				pax_usage();
    314       1.1       jtc 			break;
    315       1.1       jtc 		case 'p':
    316       1.1       jtc 			/*
    317       1.1       jtc 			 * specify file characteristic options
    318       1.1       jtc 			 */
    319       1.1       jtc 			for (pt = optarg; *pt != '\0'; ++pt) {
    320       1.1       jtc 				switch(*pt) {
    321       1.1       jtc 				case 'a':
    322       1.1       jtc 					/*
    323       1.1       jtc 					 * do not preserve access time
    324       1.1       jtc 					 */
    325       1.1       jtc 					patime = 0;
    326       1.1       jtc 					break;
    327       1.1       jtc 				case 'e':
    328       1.1       jtc 					/*
    329       1.1       jtc 					 * preserve user id, group id, file
    330       1.1       jtc 					 * mode, access/modification times
    331      1.24       mrg 					 * and file flags.
    332       1.1       jtc 					 */
    333       1.1       jtc 					pids = 1;
    334       1.1       jtc 					pmode = 1;
    335       1.1       jtc 					patime = 1;
    336       1.1       jtc 					pmtime = 1;
    337      1.24       mrg 					pfflags = 1;
    338      1.24       mrg 					break;
    339      1.25   mycroft #if 0
    340      1.24       mrg 				case 'f':
    341      1.24       mrg 					/*
    342      1.24       mrg 					 * do not preserve file flags
    343      1.24       mrg 					 */
    344      1.24       mrg 					pfflags = 0;
    345       1.1       jtc 					break;
    346      1.25   mycroft #endif
    347       1.1       jtc 				case 'm':
    348       1.1       jtc 					/*
    349       1.1       jtc 					 * do not preserve modification time
    350       1.1       jtc 					 */
    351       1.1       jtc 					pmtime = 0;
    352       1.1       jtc 					break;
    353       1.1       jtc 				case 'o':
    354       1.1       jtc 					/*
    355       1.1       jtc 					 * preserve uid/gid
    356       1.1       jtc 					 */
    357       1.1       jtc 					pids = 1;
    358       1.1       jtc 					break;
    359       1.1       jtc 				case 'p':
    360       1.1       jtc 					/*
    361      1.35     lukem 					 * preserve file mode bits
    362       1.1       jtc 					 */
    363       1.1       jtc 					pmode = 1;
    364       1.1       jtc 					break;
    365       1.1       jtc 				default:
    366  1.39.2.1       jmc 					tty_warn(1, "Invalid -p string: %c",
    367  1.39.2.1       jmc 					    *pt);
    368       1.1       jtc 					pax_usage();
    369       1.1       jtc 					break;
    370       1.1       jtc 				}
    371       1.1       jtc 			}
    372       1.1       jtc 			flg |= PF;
    373       1.1       jtc 			break;
    374       1.1       jtc 		case 'r':
    375       1.1       jtc 			/*
    376       1.1       jtc 			 * read the archive
    377       1.1       jtc 			 */
    378       1.1       jtc 			flg |= RF;
    379       1.1       jtc 			break;
    380       1.1       jtc 		case 's':
    381       1.1       jtc 			/*
    382       1.1       jtc 			 * file name substitution name pattern
    383       1.1       jtc 			 */
    384       1.1       jtc 			if (rep_add(optarg) < 0) {
    385       1.1       jtc 				pax_usage();
    386       1.1       jtc 				break;
    387       1.1       jtc 			}
    388       1.1       jtc 			flg |= SF;
    389       1.1       jtc 			break;
    390       1.1       jtc 		case 't':
    391       1.1       jtc 			/*
    392       1.1       jtc 			 * preserve access time on filesystem nodes we read
    393       1.1       jtc 			 */
    394       1.1       jtc 			tflag = 1;
    395       1.1       jtc 			flg |= TF;
    396       1.1       jtc 			break;
    397       1.1       jtc 		case 'u':
    398       1.1       jtc 			/*
    399       1.1       jtc 			 * ignore those older files
    400       1.1       jtc 			 */
    401       1.1       jtc 			uflag = 1;
    402       1.1       jtc 			flg |= UF;
    403       1.1       jtc 			break;
    404       1.1       jtc 		case 'v':
    405       1.1       jtc 			/*
    406       1.1       jtc 			 * verbose operation mode
    407       1.1       jtc 			 */
    408       1.1       jtc 			vflag = 1;
    409       1.1       jtc 			flg |= VF;
    410       1.1       jtc 			break;
    411       1.1       jtc 		case 'w':
    412       1.1       jtc 			/*
    413       1.1       jtc 			 * write an archive
    414       1.1       jtc 			 */
    415       1.1       jtc 			flg |= WF;
    416       1.1       jtc 			break;
    417       1.1       jtc 		case 'x':
    418       1.1       jtc 			/*
    419       1.1       jtc 			 * specify an archive format on write
    420       1.1       jtc 			 */
    421       1.1       jtc 			tmp.name = optarg;
    422       1.8  christos 			frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
    423       1.8  christos 			    sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt);
    424       1.8  christos 			if (frmt != NULL) {
    425       1.1       jtc 				flg |= XF;
    426       1.1       jtc 				break;
    427       1.1       jtc 			}
    428       1.8  christos 			tty_warn(1, "Unknown -x format: %s", optarg);
    429       1.1       jtc 			(void)fputs("pax: Known -x formats are:", stderr);
    430       1.1       jtc 			for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
    431       1.1       jtc 				(void)fprintf(stderr, " %s", fsub[i].name);
    432       1.1       jtc 			(void)fputs("\n\n", stderr);
    433       1.1       jtc 			pax_usage();
    434       1.1       jtc 			break;
    435       1.6       mrg 		case 'z':
    436       1.6       mrg 			/*
    437       1.6       mrg 			 * use gzip.  Non standard option.
    438       1.6       mrg 			 */
    439       1.6       mrg 			gzip_program = GZIP_CMD;
    440      1.20      tron 			break;
    441      1.20      tron 		case 'A':
    442      1.20      tron 			Aflag = 1;
    443      1.20      tron 			flg |= CAF;
    444       1.6       mrg 			break;
    445       1.1       jtc 		case 'B':
    446       1.1       jtc 			/*
    447       1.1       jtc 			 * non-standard option on number of bytes written on a
    448       1.1       jtc 			 * single archive volume.
    449       1.1       jtc 			 */
    450       1.1       jtc 			if ((wrlimit = str_offt(optarg)) <= 0) {
    451       1.8  christos 				tty_warn(1, "Invalid write limit %s", optarg);
    452       1.1       jtc 				pax_usage();
    453       1.1       jtc 			}
    454       1.1       jtc 			if (wrlimit % BLKMULT) {
    455       1.8  christos 				tty_warn(1,
    456       1.8  christos 				    "Write limit is not a %d byte multiple",
    457       1.1       jtc 				    BLKMULT);
    458       1.1       jtc 				pax_usage();
    459       1.1       jtc 			}
    460       1.1       jtc 			flg |= CBF;
    461       1.1       jtc 			break;
    462       1.1       jtc 		case 'D':
    463       1.1       jtc 			/*
    464       1.1       jtc 			 * On extraction check file inode change time before the
    465       1.1       jtc 			 * modification of the file name. Non standard option.
    466       1.1       jtc 			 */
    467       1.1       jtc 			Dflag = 1;
    468       1.1       jtc 			flg |= CDF;
    469       1.1       jtc 			break;
    470       1.1       jtc 		case 'E':
    471       1.1       jtc 			/*
    472       1.1       jtc 			 * non-standard limit on read faults
    473       1.1       jtc 			 * 0 indicates stop after first error, values
    474       1.1       jtc 			 * indicate a limit, "NONE" try forever
    475       1.1       jtc 			 */
    476       1.1       jtc 			flg |= CEF;
    477       1.1       jtc 			if (strcmp(NONE, optarg) == 0)
    478       1.1       jtc 				maxflt = -1;
    479       1.1       jtc 			else if ((maxflt = atoi(optarg)) < 0) {
    480       1.8  christos 				tty_warn(1,
    481       1.8  christos 				    "Error count value must be positive");
    482       1.1       jtc 				pax_usage();
    483       1.1       jtc 			}
    484       1.1       jtc 			break;
    485       1.1       jtc 		case 'G':
    486       1.1       jtc 			/*
    487       1.1       jtc 			 * non-standard option for selecting files within an
    488       1.1       jtc 			 * archive by group (gid or name)
    489       1.1       jtc 			 */
    490       1.1       jtc 			if (grp_add(optarg) < 0) {
    491       1.1       jtc 				pax_usage();
    492       1.1       jtc 				break;
    493       1.1       jtc 			}
    494       1.1       jtc 			flg |= CGF;
    495       1.1       jtc 			break;
    496       1.1       jtc 		case 'H':
    497       1.1       jtc 			/*
    498       1.1       jtc 			 * follow command line symlinks only
    499       1.1       jtc 			 */
    500       1.1       jtc 			Hflag = 1;
    501       1.1       jtc 			flg |= CHF;
    502       1.1       jtc 			break;
    503       1.1       jtc 		case 'L':
    504       1.1       jtc 			/*
    505       1.1       jtc 			 * follow symlinks
    506       1.1       jtc 			 */
    507       1.1       jtc 			Lflag = 1;
    508       1.1       jtc 			flg |= CLF;
    509      1.27   thorpej 			break;
    510      1.39     lukem #ifdef SMALL
    511      1.39     lukem 		case 'M':
    512      1.39     lukem 		case 'N':
    513      1.39     lukem 			tty_warn(1, "Support for -%c is not compiled in", c);
    514      1.39     lukem 			exit(1);
    515      1.39     lukem #else	/* !SMALL */
    516      1.34     lukem 		case 'M':
    517      1.34     lukem 			/*
    518      1.34     lukem 			 * Treat list of filenames on stdin as an
    519      1.34     lukem 			 * mtree(8) specfile.  Non standard option.
    520      1.34     lukem 			 */
    521      1.34     lukem 			Mflag = 1;
    522      1.34     lukem 			flg |= CMF;
    523      1.34     lukem 			break;
    524      1.35     lukem 		case 'N':
    525      1.35     lukem 			/*
    526      1.35     lukem 			 * Use alternative directory for user db lookups.
    527      1.35     lukem 			 */
    528      1.36     lukem 			if (!setup_getid(optarg)) {
    529      1.36     lukem 				tty_warn(1,
    530      1.36     lukem 			    "Unable to use user and group databases in `%s'",
    531      1.36     lukem 				    optarg);
    532      1.35     lukem 				pax_usage();
    533      1.36     lukem 			}
    534      1.35     lukem 			break;
    535      1.39     lukem #endif	/* !SMALL */
    536      1.27   thorpej 		case 'O':
    537      1.27   thorpej 			/*
    538      1.27   thorpej 			 * Force one volume.  Non standard option.
    539      1.27   thorpej 			 */
    540      1.27   thorpej 			force_one_volume = 1;
    541       1.1       jtc 			break;
    542       1.1       jtc 		case 'P':
    543       1.1       jtc 			/*
    544       1.1       jtc 			 * do NOT follow symlinks (default)
    545       1.1       jtc 			 */
    546       1.1       jtc 			Lflag = 0;
    547       1.1       jtc 			flg |= CPF;
    548       1.1       jtc 			break;
    549       1.1       jtc 		case 'T':
    550       1.1       jtc 			/*
    551       1.1       jtc 			 * non-standard option for selecting files within an
    552       1.1       jtc 			 * archive by modification time range (lower,upper)
    553       1.1       jtc 			 */
    554       1.1       jtc 			if (trng_add(optarg) < 0) {
    555       1.1       jtc 				pax_usage();
    556       1.1       jtc 				break;
    557       1.1       jtc 			}
    558       1.1       jtc 			flg |= CTF;
    559       1.1       jtc 			break;
    560       1.1       jtc 		case 'U':
    561       1.1       jtc 			/*
    562       1.1       jtc 			 * non-standard option for selecting files within an
    563       1.1       jtc 			 * archive by user (uid or name)
    564       1.1       jtc 			 */
    565       1.1       jtc 			if (usr_add(optarg) < 0) {
    566       1.1       jtc 				pax_usage();
    567       1.1       jtc 				break;
    568       1.1       jtc 			}
    569       1.1       jtc 			flg |= CUF;
    570       1.1       jtc 			break;
    571       1.1       jtc 		case 'X':
    572       1.1       jtc 			/*
    573       1.1       jtc 			 * do not pass over mount points in the file system
    574       1.1       jtc 			 */
    575       1.1       jtc 			Xflag = 1;
    576       1.1       jtc 			flg |= CXF;
    577       1.1       jtc 			break;
    578       1.1       jtc 		case 'Y':
    579       1.1       jtc 			/*
    580       1.1       jtc 			 * On extraction check file inode change time after the
    581       1.1       jtc 			 * modification of the file name. Non standard option.
    582       1.1       jtc 			 */
    583       1.1       jtc 			Yflag = 1;
    584       1.1       jtc 			flg |= CYF;
    585       1.1       jtc 			break;
    586       1.1       jtc 		case 'Z':
    587       1.1       jtc 			/*
    588       1.1       jtc 			 * On extraction check modification time after the
    589       1.1       jtc 			 * modification of the file name. Non standard option.
    590       1.1       jtc 			 */
    591       1.1       jtc 			Zflag = 1;
    592       1.1       jtc 			flg |= CZF;
    593       1.1       jtc 			break;
    594  1.39.2.1       jmc 		case OPT_INSECURE:
    595  1.39.2.1       jmc 			secure = 0;
    596  1.39.2.1       jmc 			break;
    597  1.39.2.1       jmc 		case OPT_FORCE_LOCAL:
    598  1.39.2.1       jmc 			forcelocal = 0;
    599  1.39.2.1       jmc 			break;
    600       1.1       jtc 		case '?':
    601       1.1       jtc 		default:
    602       1.1       jtc 			pax_usage();
    603       1.1       jtc 			break;
    604       1.1       jtc 		}
    605       1.1       jtc 	}
    606       1.1       jtc 
    607       1.1       jtc 	/*
    608       1.1       jtc 	 * figure out the operation mode of pax read,write,extract,copy,append
    609       1.1       jtc 	 * or list. check that we have not been given a bogus set of flags
    610       1.1       jtc 	 * for the operation mode.
    611       1.1       jtc 	 */
    612       1.1       jtc 	if (ISLIST(flg)) {
    613       1.1       jtc 		act = LIST;
    614  1.39.2.1       jmc 		listf = stdout;
    615       1.1       jtc 		bflg = flg & BDLIST;
    616       1.1       jtc 	} else if (ISEXTRACT(flg)) {
    617       1.1       jtc 		act = EXTRACT;
    618       1.1       jtc 		bflg = flg & BDEXTR;
    619       1.1       jtc 	} else if (ISARCHIVE(flg)) {
    620       1.1       jtc 		act = ARCHIVE;
    621       1.1       jtc 		bflg = flg & BDARCH;
    622       1.1       jtc 	} else if (ISAPPND(flg)) {
    623       1.1       jtc 		act = APPND;
    624       1.1       jtc 		bflg = flg & BDARCH;
    625       1.1       jtc 	} else if (ISCOPY(flg)) {
    626       1.1       jtc 		act = COPY;
    627       1.1       jtc 		bflg = flg & BDCOPY;
    628       1.1       jtc 	} else
    629       1.1       jtc 		pax_usage();
    630       1.1       jtc 	if (bflg) {
    631       1.1       jtc 		printflg(flg);
    632       1.1       jtc 		pax_usage();
    633       1.1       jtc 	}
    634       1.1       jtc 
    635       1.1       jtc 	/*
    636       1.1       jtc 	 * if we are writing (ARCHIVE) we use the default format if the user
    637       1.1       jtc 	 * did not specify a format. when we write during an APPEND, we will
    638       1.1       jtc 	 * adopt the format of the existing archive if none was supplied.
    639       1.1       jtc 	 */
    640       1.1       jtc 	if (!(flg & XF) && (act == ARCHIVE))
    641       1.1       jtc 		frmt = &(fsub[DEFLT]);
    642       1.1       jtc 
    643       1.1       jtc 	/*
    644       1.1       jtc 	 * process the args as they are interpreted by the operation mode
    645       1.1       jtc 	 */
    646       1.1       jtc 	switch (act) {
    647       1.1       jtc 	case LIST:
    648       1.1       jtc 	case EXTRACT:
    649       1.1       jtc 		for (; optind < argc; optind++)
    650  1.39.2.1       jmc 			if (pat_add(argv[optind], NULL) < 0)
    651       1.1       jtc 				pax_usage();
    652       1.1       jtc 		break;
    653       1.1       jtc 	case COPY:
    654       1.1       jtc 		if (optind >= argc) {
    655       1.8  christos 			tty_warn(0, "Destination directory was not supplied");
    656       1.1       jtc 			pax_usage();
    657       1.1       jtc 		}
    658       1.1       jtc 		--argc;
    659       1.1       jtc 		dirptr = argv[argc];
    660  1.39.2.1       jmc 		if (mkpath(dirptr) < 0)
    661  1.39.2.1       jmc 			pax_usage();
    662      1.14   mycroft 		/* FALLTHROUGH */
    663       1.1       jtc 	case ARCHIVE:
    664       1.1       jtc 	case APPND:
    665       1.1       jtc 		for (; optind < argc; optind++)
    666      1.23        is 			if (ftree_add(argv[optind], 0) < 0)
    667       1.1       jtc 				pax_usage();
    668       1.1       jtc 		/*
    669       1.1       jtc 		 * no read errors allowed on updates/append operation!
    670       1.1       jtc 		 */
    671       1.1       jtc 		maxflt = 0;
    672       1.1       jtc 		break;
    673       1.1       jtc 	}
    674       1.1       jtc }
    675       1.1       jtc 
    676       1.1       jtc 
    677       1.1       jtc /*
    678       1.1       jtc  * tar_options()
    679       1.1       jtc  *	look at the user specified flags. set globals as required and check if
    680       1.1       jtc  *	the user specified a legal set of flags. If not, complain and exit
    681       1.1       jtc  */
    682       1.1       jtc 
    683      1.29   thorpej struct option tar_longopts[] = {
    684      1.29   thorpej 	{ "block-size",		required_argument,	0,	'b' },
    685  1.39.2.1       jmc 	{ "bunzip2",		no_argument,		0,	'j' },
    686  1.39.2.1       jmc 	{ "bzip2",		no_argument,		0,	'j' },
    687      1.29   thorpej 	{ "create",		no_argument,		0,	'c' },	/* F */
    688      1.29   thorpej 	/* -e -- no corresponding long option */
    689      1.29   thorpej 	{ "file",		required_argument,	0,	'f' },
    690      1.29   thorpej 	{ "dereference",	no_argument,		0,	'h' },
    691  1.39.2.1       jmc 	{ "keep-old-files",	no_argument,		0,	'k' },
    692      1.29   thorpej 	{ "one-file-system",	no_argument,		0,	'l' },
    693      1.29   thorpej 	{ "modification-time",	no_argument,		0,	'm' },
    694      1.29   thorpej 	{ "old-archive",	no_argument,		0,	'o' },
    695      1.29   thorpej 	{ "portability",	no_argument,		0,	'o' },
    696      1.29   thorpej 	{ "same-permissions",	no_argument,		0,	'p' },
    697      1.29   thorpej 	{ "preserve-permissions", no_argument,		0,	'p' },
    698      1.29   thorpej 	{ "preserve",		no_argument,		0,	'p' },
    699  1.39.2.1       jmc 	{ "fast-read",		no_argument,		0,	'q' },
    700      1.29   thorpej 	{ "append",		no_argument,		0,	'r' },	/* F */
    701      1.29   thorpej 	{ "update",		no_argument,		0,	'u' },	/* F */
    702      1.29   thorpej 	{ "list",		no_argument,		0,	't' },	/* F */
    703      1.29   thorpej 	{ "verbose",		no_argument,		0,	'v' },
    704      1.29   thorpej 	{ "interactive",	no_argument,		0,	'w' },
    705      1.29   thorpej 	{ "confirmation",	no_argument,		0,	'w' },
    706      1.29   thorpej 	{ "extract",		no_argument,		0,	'x' },	/* F */
    707      1.29   thorpej 	{ "get",		no_argument,		0,	'x' },	/* F */
    708      1.29   thorpej 	{ "gzip",		no_argument,		0,	'z' },
    709      1.29   thorpej 	{ "gunzip",		no_argument,		0,	'z' },
    710      1.29   thorpej 	{ "read-full-blocks",	no_argument,		0,	'B' },
    711      1.29   thorpej 	{ "directory",		required_argument,	0,	'C' },
    712  1.39.2.1       jmc 	{ "to-stdout",		no_argument,		0,	'O' },
    713      1.29   thorpej 	{ "absolute-paths",	no_argument,		0,	'P' },
    714  1.39.2.1       jmc 	{ "files-from",		required_argument,	0,	'T' },
    715      1.29   thorpej 	{ "exclude-from",	required_argument,	0,	'X' },
    716      1.29   thorpej 	{ "compress",		no_argument,		0,	'Z' },
    717      1.29   thorpej 	{ "uncompress",		no_argument,		0,	'Z' },
    718  1.39.2.1       jmc 	{ "strict",		no_argument,		0,
    719  1.39.2.1       jmc 						OPT_STRICT },
    720      1.31   thorpej 	{ "atime-preserve",	no_argument,		0,
    721      1.31   thorpej 						OPT_ATIME_PRESERVE },
    722      1.29   thorpej 	{ "unlink",		no_argument,		0,
    723      1.29   thorpej 						OPT_UNLINK },
    724      1.30   thorpej 	{ "use-compress-program", required_argument,	0,
    725      1.30   thorpej 						OPT_USE_COMPRESS_PROGRAM },
    726  1.39.2.1       jmc 	{ "force-local",	no_argument,		0,
    727  1.39.2.1       jmc 						OPT_FORCE_LOCAL },
    728  1.39.2.1       jmc 	{ "insecure",		no_argument,		0,
    729  1.39.2.1       jmc 						OPT_INSECURE },
    730  1.39.2.1       jmc 	{ "exclude",		required_argument,	0,
    731  1.39.2.1       jmc 						OPT_EXCLUDE },
    732      1.29   thorpej #if 0 /* Not implemented */
    733      1.29   thorpej 	{ "catenate",		no_argument,		0,	'A' },	/* F */
    734      1.29   thorpej 	{ "concatenate",	no_argument,		0,	'A' },	/* F */
    735      1.29   thorpej 	{ "diff",		no_argument,		0,	'd' },	/* F */
    736      1.29   thorpej 	{ "compare",		no_argument,		0,	'd' },	/* F */
    737      1.29   thorpej 	{ "checkpoint",		no_argument,		0,
    738      1.29   thorpej 						OPT_CHECKPOINT },
    739      1.31   thorpej 	{ "help",		no_argument,		0,
    740      1.29   thorpej 						OPT_HELP },
    741      1.29   thorpej 	{ "info-script",	required_argument,	0,	'F' },
    742      1.29   thorpej 	{ "new-volume-script",	required_argument,	0,	'F' },
    743      1.29   thorpej 	{ "incremental",	no_argument,		0,	'G' },
    744      1.29   thorpej 	{ "listed-incremental",	required_argument,	0,	'g' },
    745      1.29   thorpej 	{ "ignore-zeros",	no_argument,		0,	'i' },
    746      1.29   thorpej 	{ "ignore-failed-read",	no_argument,		0,
    747      1.29   thorpej 						OPT_IGNORE_FAILED_READ },
    748      1.29   thorpej 	{ "starting-file",	no_argument,		0,	'K' },
    749  1.39.2.1       jmc 	{ "tape-length",	required_argument,	0,	'L' },
    750      1.29   thorpej 	{ "multi-volume",	no_argument,		0,	'M' },
    751      1.29   thorpej 	{ "after-date",		required_argument,	0,	'N' },
    752      1.29   thorpej 	{ "newer",		required_argument,	0,	'N' },
    753      1.29   thorpej 	{ "record-number",	no_argument,		0,	'R' },
    754      1.29   thorpej 	{ "remove-files",	no_argument,		0,
    755      1.29   thorpej 						OPT_REMOVE_FILES },
    756      1.29   thorpej 	{ "same-order",		no_argument,		0,	's' },
    757      1.29   thorpej 	{ "preserve-order",	no_argument,		0,	's' },
    758      1.29   thorpej 	{ "sparse",		no_argument,		0,	'S' },
    759      1.29   thorpej 	{ "null",		no_argument,		0,
    760      1.29   thorpej 						OPT_NULL },
    761      1.29   thorpej 	{ "totals",		no_argument,		0,
    762      1.29   thorpej 						OPT_TOTALS },
    763      1.29   thorpej 	{ "volume-name",	required_argument,	0,	'V' },
    764      1.29   thorpej 	{ "label",		required_argument,	0,	'V' },
    765      1.29   thorpej 	{ "version",		no_argument,		0,
    766      1.29   thorpej 						OPT_VERSION },
    767      1.29   thorpej 	{ "verify",		no_argument,		0,	'W' },
    768      1.29   thorpej 	{ "block-compress",	no_argument,		0,
    769      1.29   thorpej 						OPT_BLOCK_COMPRESS },
    770      1.29   thorpej 	{ "norecurse",		no_argument,		0,
    771      1.29   thorpej 						OPT_NORECURSE },
    772      1.29   thorpej #endif
    773      1.29   thorpej 	{ 0,			0,			0,	0 },
    774      1.29   thorpej };
    775      1.29   thorpej 
    776       1.1       jtc static void
    777       1.7       tls tar_options(int argc, char **argv)
    778       1.1       jtc {
    779       1.7       tls 	int c;
    780       1.1       jtc 	int fstdin = 0;
    781  1.39.2.1       jmc 	int Oflag = 0;
    782  1.39.2.1       jmc 	int nincfiles = 0;
    783  1.39.2.1       jmc 	int incfiles_max = 0;
    784  1.39.2.1       jmc 	struct incfile {
    785  1.39.2.1       jmc 		char *file;
    786  1.39.2.1       jmc 		char *dir;
    787  1.39.2.1       jmc 	};
    788  1.39.2.1       jmc 	struct incfile *incfiles = NULL;
    789  1.39.2.1       jmc 
    790  1.39.2.1       jmc 	/*
    791  1.39.2.1       jmc 	 * Set default values.
    792  1.39.2.1       jmc 	 */
    793  1.39.2.1       jmc 	rmleadslash = 1;
    794  1.39.2.1       jmc 	is_gnutar = 1;
    795       1.1       jtc 
    796       1.1       jtc 	/*
    797       1.1       jtc 	 * process option flags
    798       1.1       jtc 	 */
    799  1.39.2.1       jmc 	while ((c = getoldopt(argc, argv,
    800  1.39.2.1       jmc 	    "+b:cef:hjklmopqrs:tuvwxzBC:HI:OPT:X:Z014578",
    801      1.29   thorpej 	    tar_longopts, NULL))
    802       1.9     lukem 	    != -1)  {
    803       1.4       jtc 		switch(c) {
    804       1.1       jtc 		case 'b':
    805       1.1       jtc 			/*
    806  1.39.2.1       jmc 			 * specify blocksize in 512-byte blocks
    807       1.1       jtc 			 */
    808       1.4       jtc 			if ((wrblksz = (int)str_offt(optarg)) <= 0) {
    809       1.8  christos 				tty_warn(1, "Invalid block size %s", optarg);
    810       1.1       jtc 				tar_usage();
    811       1.1       jtc 			}
    812  1.39.2.1       jmc 			wrblksz *= 512;		/* XXX - check for int oflow */
    813       1.1       jtc 			break;
    814       1.1       jtc 		case 'c':
    815       1.1       jtc 			/*
    816       1.1       jtc 			 * create an archive
    817       1.1       jtc 			 */
    818       1.1       jtc 			act = ARCHIVE;
    819       1.1       jtc 			break;
    820       1.1       jtc 		case 'e':
    821       1.1       jtc 			/*
    822       1.1       jtc 			 * stop after first error
    823       1.1       jtc 			 */
    824       1.1       jtc 			maxflt = 0;
    825       1.1       jtc 			break;
    826       1.1       jtc 		case 'f':
    827       1.1       jtc 			/*
    828       1.1       jtc 			 * filename where the archive is stored
    829       1.1       jtc 			 */
    830       1.4       jtc 			if ((optarg[0] == '-') && (optarg[1]== '\0')) {
    831       1.1       jtc 				/*
    832       1.1       jtc 				 * treat a - as stdin
    833       1.1       jtc 				 */
    834       1.4       jtc 				fstdin = 1;
    835  1.39.2.1       jmc 				arcname = NULL;
    836       1.1       jtc 				break;
    837       1.1       jtc 			}
    838       1.1       jtc 			fstdin = 0;
    839       1.4       jtc 			arcname = optarg;
    840       1.1       jtc 			break;
    841      1.21      tron 		case 'h':
    842      1.21      tron 			/*
    843  1.39.2.1       jmc 			 * follow symlinks
    844      1.21      tron 			 */
    845  1.39.2.1       jmc 			Lflag = 1;
    846  1.39.2.1       jmc 			break;
    847  1.39.2.1       jmc 		case 'j':
    848  1.39.2.1       jmc 			/*
    849  1.39.2.1       jmc 			 * pass through bzip2. not a standard option
    850  1.39.2.1       jmc 			 */
    851  1.39.2.1       jmc 			jflag = 1;
    852  1.39.2.1       jmc 			gzip_program = BZIP2_CMD;
    853  1.39.2.1       jmc 			break;
    854  1.39.2.1       jmc 		case 'k':
    855  1.39.2.1       jmc 			/*
    856  1.39.2.1       jmc 			 * do not clobber files that exist
    857  1.39.2.1       jmc 			 */
    858  1.39.2.1       jmc 			kflag = 1;
    859      1.21      tron 			break;
    860      1.10       mrg 		case 'l':
    861      1.10       mrg 			/*
    862      1.10       mrg 			 * do not pass over mount points in the file system
    863      1.10       mrg 			 */
    864      1.10       mrg 			Xflag = 1;
    865      1.10       mrg 			break;
    866       1.1       jtc 		case 'm':
    867       1.1       jtc 			/*
    868       1.1       jtc 			 * do not preserve modification time
    869       1.1       jtc 			 */
    870       1.1       jtc 			pmtime = 0;
    871       1.1       jtc 			break;
    872       1.1       jtc 		case 'o':
    873      1.18        tv 			/*
    874      1.18        tv 			 * This option does several things based on whether
    875      1.18        tv 			 * this is a create or extract operation.
    876      1.18        tv 			 */
    877      1.18        tv 			if (act == ARCHIVE) {
    878  1.39.2.1       jmc 				/* GNU tar: write V7 format archives. */
    879  1.39.2.1       jmc 				Oflag = 1;
    880      1.18        tv 				/* 4.2BSD: don't add directory entries. */
    881      1.18        tv 				if (opt_add("write_opt=nodir") < 0)
    882      1.18        tv 					tar_usage();
    883      1.18        tv 
    884      1.18        tv 			} else {
    885      1.18        tv 				/* SUS: don't preserve owner/group. */
    886      1.18        tv 				pids = 0;
    887      1.18        tv 				nopids = 1;
    888      1.18        tv 			}
    889       1.1       jtc 			break;
    890  1.39.2.1       jmc 		case 'O':
    891  1.39.2.1       jmc 			Oflag = 1;
    892  1.39.2.1       jmc 			break;
    893       1.1       jtc 		case 'p':
    894       1.1       jtc 			/*
    895       1.1       jtc 			 * preserve user id, group id, file
    896       1.1       jtc 			 * mode, access/modification times
    897       1.1       jtc 			 */
    898      1.18        tv 			if (!nopids)
    899      1.18        tv 				pids = 1;
    900       1.1       jtc 			pmode = 1;
    901       1.1       jtc 			patime = 1;
    902       1.1       jtc 			pmtime = 1;
    903       1.1       jtc 			break;
    904  1.39.2.1       jmc 		case 'q':
    905  1.39.2.1       jmc 			/*
    906  1.39.2.1       jmc 			 * select first match for a pattern only
    907  1.39.2.1       jmc 			 */
    908  1.39.2.1       jmc 			nflag = 1;
    909  1.39.2.1       jmc 			break;
    910       1.1       jtc 		case 'r':
    911       1.1       jtc 		case 'u':
    912       1.1       jtc 			/*
    913       1.1       jtc 			 * append to the archive
    914       1.1       jtc 			 */
    915       1.1       jtc 			act = APPND;
    916       1.1       jtc 			break;
    917  1.39.2.1       jmc 		case 's':
    918  1.39.2.1       jmc 			/*
    919  1.39.2.1       jmc 			 * file name substitution name pattern
    920  1.39.2.1       jmc 			 */
    921  1.39.2.1       jmc 			if (rep_add(optarg) < 0) {
    922  1.39.2.1       jmc 				tar_usage();
    923  1.39.2.1       jmc 				break;
    924  1.39.2.1       jmc 			}
    925  1.39.2.1       jmc 			break;
    926       1.1       jtc 		case 't':
    927       1.1       jtc 			/*
    928       1.1       jtc 			 * list contents of the tape
    929       1.1       jtc 			 */
    930       1.1       jtc 			act = LIST;
    931       1.1       jtc 			break;
    932       1.1       jtc 		case 'v':
    933       1.1       jtc 			/*
    934       1.1       jtc 			 * verbose operation mode
    935       1.1       jtc 			 */
    936       1.1       jtc 			vflag = 1;
    937       1.1       jtc 			break;
    938       1.1       jtc 		case 'w':
    939       1.1       jtc 			/*
    940       1.1       jtc 			 * interactive file rename
    941       1.1       jtc 			 */
    942       1.1       jtc 			iflag = 1;
    943       1.1       jtc 			break;
    944       1.1       jtc 		case 'x':
    945       1.1       jtc 			/*
    946  1.39.2.1       jmc 			 * extract an archive, preserving mode,
    947  1.39.2.1       jmc 			 * and mtime if possible.
    948       1.1       jtc 			 */
    949       1.1       jtc 			act = EXTRACT;
    950  1.39.2.1       jmc 			pmtime = 1;
    951       1.1       jtc 			break;
    952       1.6       mrg 		case 'z':
    953       1.6       mrg 			/*
    954       1.6       mrg 			 * use gzip.  Non standard option.
    955       1.6       mrg 			 */
    956       1.6       mrg 			zflag = 1;
    957       1.6       mrg 			gzip_program = GZIP_CMD;
    958       1.6       mrg 			break;
    959       1.1       jtc 		case 'B':
    960       1.1       jtc 			/*
    961       1.1       jtc 			 * Nothing to do here, this is pax default
    962       1.1       jtc 			 */
    963       1.1       jtc 			break;
    964  1.39.2.1       jmc 		case 'C':
    965  1.39.2.1       jmc 			chdname = optarg;
    966  1.39.2.1       jmc 			break;
    967  1.39.2.1       jmc 		case 'H':
    968       1.1       jtc 			/*
    969  1.39.2.1       jmc 			 * follow command line symlinks only
    970       1.1       jtc 			 */
    971  1.39.2.1       jmc 			Hflag = 1;
    972  1.39.2.1       jmc 			break;
    973  1.39.2.1       jmc 		case 'I':
    974  1.39.2.1       jmc 		case 'T':
    975  1.39.2.1       jmc 			if (++nincfiles > incfiles_max) {
    976  1.39.2.1       jmc 				incfiles_max = nincfiles + 3;
    977  1.39.2.1       jmc 				incfiles = realloc(incfiles,
    978  1.39.2.1       jmc 				    sizeof(*incfiles) * incfiles_max);
    979  1.39.2.1       jmc 				if (incfiles == NULL) {
    980  1.39.2.1       jmc 					tty_warn(0, "Unable to allocate space "
    981  1.39.2.1       jmc 					    "for option list");
    982  1.39.2.1       jmc 					exit(1);
    983  1.39.2.1       jmc 				}
    984  1.39.2.1       jmc 			}
    985  1.39.2.1       jmc 			incfiles[nincfiles - 1].file = optarg;
    986  1.39.2.1       jmc 			incfiles[nincfiles - 1].dir = chdname;
    987       1.1       jtc 			break;
    988       1.1       jtc 		case 'P':
    989  1.39.2.1       jmc 			/*
    990  1.39.2.1       jmc 			 * do not remove leading '/' from pathnames
    991  1.39.2.1       jmc 			 */
    992  1.39.2.1       jmc 			rmleadslash = 0;
    993      1.21      tron 			Aflag = 1;
    994       1.1       jtc 			break;
    995       1.1       jtc 		case 'X':
    996       1.1       jtc 			/*
    997      1.15       mrg 			 * GNU tar compat: exclude the files listed in optarg
    998       1.1       jtc 			 */
    999      1.15       mrg 			if (tar_gnutar_X_compat(optarg) != 0)
   1000      1.15       mrg 				tar_usage();
   1001       1.6       mrg 			break;
   1002       1.6       mrg 		case 'Z':
   1003       1.6       mrg 			/*
   1004       1.6       mrg 			 * use compress.
   1005       1.6       mrg 			 */
   1006       1.6       mrg 			zflag = 1;
   1007       1.6       mrg 			gzip_program = COMPRESS_CMD;
   1008       1.1       jtc 			break;
   1009       1.1       jtc 		case '0':
   1010       1.1       jtc 			arcname = DEV_0;
   1011       1.1       jtc 			break;
   1012       1.1       jtc 		case '1':
   1013       1.1       jtc 			arcname = DEV_1;
   1014       1.1       jtc 			break;
   1015       1.1       jtc 		case '4':
   1016       1.1       jtc 			arcname = DEV_4;
   1017       1.1       jtc 			break;
   1018       1.1       jtc 		case '5':
   1019       1.1       jtc 			arcname = DEV_5;
   1020       1.1       jtc 			break;
   1021       1.1       jtc 		case '7':
   1022       1.1       jtc 			arcname = DEV_7;
   1023       1.1       jtc 			break;
   1024       1.1       jtc 		case '8':
   1025       1.1       jtc 			arcname = DEV_8;
   1026      1.31   thorpej 			break;
   1027      1.31   thorpej 		case OPT_ATIME_PRESERVE:
   1028      1.31   thorpej 			patime = 1;
   1029       1.1       jtc 			break;
   1030      1.29   thorpej 		case OPT_UNLINK:
   1031      1.29   thorpej 			/* Just ignore -- we always unlink first. */
   1032      1.30   thorpej 			break;
   1033      1.30   thorpej 		case OPT_USE_COMPRESS_PROGRAM:
   1034      1.30   thorpej 			zflag = 1;
   1035      1.30   thorpej 			gzip_program = optarg;
   1036      1.29   thorpej 			break;
   1037  1.39.2.1       jmc 		case OPT_FORCE_LOCAL:
   1038  1.39.2.1       jmc 			forcelocal = 1;
   1039  1.39.2.1       jmc 			break;
   1040  1.39.2.1       jmc 		case OPT_INSECURE:
   1041  1.39.2.1       jmc 			secure = 0;
   1042  1.39.2.1       jmc 			break;
   1043  1.39.2.1       jmc 		case OPT_STRICT:
   1044  1.39.2.1       jmc 			/* disable gnu extensions */
   1045  1.39.2.1       jmc 			is_gnutar = 0;
   1046  1.39.2.1       jmc 			break;
   1047  1.39.2.1       jmc 		case OPT_EXCLUDE:
   1048  1.39.2.1       jmc 			if (tar_gnutar_minus_minus_exclude(optarg) != 0)
   1049  1.39.2.1       jmc 				tar_usage();
   1050  1.39.2.1       jmc 			break;
   1051       1.1       jtc 		default:
   1052       1.1       jtc 			tar_usage();
   1053       1.1       jtc 			break;
   1054       1.1       jtc 		}
   1055       1.1       jtc 	}
   1056       1.4       jtc 	argc -= optind;
   1057       1.4       jtc 	argv += optind;
   1058      1.17        tv 
   1059  1.39.2.1       jmc 	/* Tar requires an action. */
   1060  1.39.2.1       jmc 	if (act == ERROR)
   1061  1.39.2.1       jmc 		tar_usage();
   1062  1.39.2.1       jmc 
   1063  1.39.2.1       jmc 	/* Traditional tar behaviour (pax uses stderr unless in list mode) */
   1064  1.39.2.1       jmc 	if (fstdin == 1 && act == ARCHIVE)
   1065  1.39.2.1       jmc 		listf = stderr;
   1066  1.39.2.1       jmc 	else
   1067  1.39.2.1       jmc 		listf = stdout;
   1068      1.23        is 
   1069  1.39.2.1       jmc 	/* Traditional tar behaviour (pax wants to read file list from stdin) */
   1070  1.39.2.1       jmc 	if ((act == ARCHIVE || act == APPND) && argc == 0 && nincfiles == 0)
   1071  1.39.2.1       jmc 		exit(0);
   1072      1.17        tv 	/*
   1073      1.17        tv 	 * if we are writing (ARCHIVE) specify tar, otherwise run like pax
   1074  1.39.2.1       jmc 	 * (unless -o specified)
   1075      1.17        tv 	 */
   1076  1.39.2.1       jmc 	if (act == ARCHIVE || act == APPND)
   1077  1.39.2.1       jmc 		frmt = &(fsub[Oflag ? F_TAR : F_USTAR]);
   1078  1.39.2.1       jmc 	else if (Oflag) {
   1079  1.39.2.1       jmc 		if (act == EXTRACT)
   1080  1.39.2.1       jmc 			to_stdout = 1;
   1081  1.39.2.1       jmc 		else {
   1082  1.39.2.1       jmc 			tty_warn(1, "The -O/-o options are only valid when "
   1083  1.39.2.1       jmc 			    "writing or extracting an archive");
   1084  1.39.2.1       jmc 			tar_usage();
   1085  1.39.2.1       jmc 		}
   1086  1.39.2.1       jmc 	}
   1087       1.1       jtc 
   1088       1.1       jtc 	/*
   1089       1.1       jtc 	 * process the args as they are interpreted by the operation mode
   1090       1.1       jtc 	 */
   1091       1.1       jtc 	switch (act) {
   1092       1.1       jtc 	case LIST:
   1093      1.23        is 	case EXTRACT:
   1094  1.39.2.1       jmc 	default:
   1095  1.39.2.1       jmc 		{
   1096  1.39.2.1       jmc 			int sawpat = 0;
   1097  1.39.2.1       jmc 			int dirisnext = 0;
   1098  1.39.2.1       jmc 			char *file, *dir;
   1099  1.39.2.1       jmc 
   1100  1.39.2.1       jmc 			while (nincfiles || *argv != NULL) {
   1101  1.39.2.1       jmc 				/*
   1102  1.39.2.1       jmc 				 * If we queued up any include files,
   1103  1.39.2.1       jmc 				 * pull them in now.  Otherwise, check
   1104  1.39.2.1       jmc 				 * for -I and -C positional flags.
   1105  1.39.2.1       jmc 				 * Anything else must be a file to
   1106  1.39.2.1       jmc 				 * extract.
   1107  1.39.2.1       jmc 				 */
   1108  1.39.2.1       jmc 				if (nincfiles) {
   1109  1.39.2.1       jmc 					file = incfiles->file;
   1110  1.39.2.1       jmc 					dir = incfiles->dir;
   1111  1.39.2.1       jmc 					incfiles++;
   1112  1.39.2.1       jmc 					nincfiles--;
   1113  1.39.2.1       jmc 				} else if (strcmp(*argv, "-I") == 0) {
   1114  1.39.2.1       jmc 					if (*++argv == NULL)
   1115  1.39.2.1       jmc 						break;
   1116  1.39.2.1       jmc 					file = *argv++;
   1117  1.39.2.1       jmc 					dir = chdname;
   1118  1.39.2.1       jmc 				} else
   1119  1.39.2.1       jmc 					file = NULL;
   1120  1.39.2.1       jmc 				if (file != NULL) {
   1121  1.39.2.1       jmc 					FILE *fp;
   1122  1.39.2.1       jmc 					char *str;
   1123  1.39.2.1       jmc 
   1124  1.39.2.1       jmc 					if (strcmp(file, "-") == 0)
   1125  1.39.2.1       jmc 						fp = stdin;
   1126  1.39.2.1       jmc 					else if ((fp = fopen(file, "r")) == NULL) {
   1127  1.39.2.1       jmc 						tty_warn(1, "Unable to open file '%s' for read", file);
   1128  1.39.2.1       jmc 						tar_usage();
   1129  1.39.2.1       jmc 					}
   1130  1.39.2.1       jmc 					while ((str = getline(fp)) != NULL) {
   1131  1.39.2.1       jmc 						if (dirisnext) {
   1132  1.39.2.1       jmc 							dir = str;
   1133  1.39.2.1       jmc 							dirisnext = 0;
   1134  1.39.2.1       jmc 							continue;
   1135  1.39.2.1       jmc 						}
   1136  1.39.2.1       jmc 						if (strcmp(str, "-C") == 0) {
   1137  1.39.2.1       jmc 							dirisnext = 1;
   1138  1.39.2.1       jmc 							continue;
   1139  1.39.2.1       jmc 						}
   1140  1.39.2.1       jmc 						if (pat_add(str, dir) < 0)
   1141  1.39.2.1       jmc 							tar_usage();
   1142  1.39.2.1       jmc 						sawpat = 1;
   1143  1.39.2.1       jmc 					}
   1144  1.39.2.1       jmc 					/* Bomb if given -C w/out a dir. */
   1145  1.39.2.1       jmc 					if (dirisnext)
   1146  1.39.2.1       jmc 						tar_usage();
   1147  1.39.2.1       jmc 					if (strcmp(file, "-") != 0)
   1148  1.39.2.1       jmc 						fclose(fp);
   1149  1.39.2.1       jmc 					if (getline_error) {
   1150  1.39.2.1       jmc 						tty_warn(1, "Problem with file '%s'", file);
   1151  1.39.2.1       jmc 						tar_usage();
   1152  1.39.2.1       jmc 					}
   1153  1.39.2.1       jmc 				} else if (strcmp(*argv, "-C") == 0) {
   1154  1.39.2.1       jmc 					if (*++argv == NULL)
   1155  1.39.2.1       jmc  						break;
   1156  1.39.2.1       jmc 					chdname = *argv++;
   1157  1.39.2.1       jmc 				} else if (pat_add(*argv++, chdname) < 0)
   1158  1.39.2.1       jmc 					tar_usage();
   1159  1.39.2.1       jmc 				else
   1160  1.39.2.1       jmc 					sawpat = 1;
   1161  1.39.2.1       jmc 			}
   1162  1.39.2.1       jmc 			/*
   1163  1.39.2.1       jmc 			 * if patterns were added, we are doing	chdir()
   1164  1.39.2.1       jmc 			 * on a file-by-file basis, else, just one
   1165  1.39.2.1       jmc 			 * global chdir (if any) after opening input.
   1166  1.39.2.1       jmc 			 */
   1167  1.39.2.1       jmc 			if (sawpat > 0)
   1168  1.39.2.1       jmc 				chdname = NULL;
   1169  1.39.2.1       jmc 		}
   1170      1.23        is 		break;
   1171       1.1       jtc 	case ARCHIVE:
   1172       1.1       jtc 	case APPND:
   1173  1.39.2.1       jmc 		if (chdname != NULL) {	/* initial chdir() */
   1174  1.39.2.1       jmc 			if (ftree_add(chdname, 1) < 0)
   1175  1.39.2.1       jmc 				tar_usage();
   1176  1.39.2.1       jmc 		}
   1177  1.39.2.1       jmc 
   1178  1.39.2.1       jmc 		while (nincfiles || *argv != NULL) {
   1179  1.39.2.1       jmc 			char *file, *dir;
   1180  1.39.2.1       jmc 
   1181  1.39.2.1       jmc 			/*
   1182  1.39.2.1       jmc 			 * If we queued up any include files, pull them in
   1183  1.39.2.1       jmc 			 * now.  Otherwise, check for -I and -C positional
   1184  1.39.2.1       jmc 			 * flags.  Anything else must be a file to include
   1185  1.39.2.1       jmc 			 * in the archive.
   1186  1.39.2.1       jmc 			 */
   1187  1.39.2.1       jmc 			if (nincfiles) {
   1188  1.39.2.1       jmc 				file = incfiles->file;
   1189  1.39.2.1       jmc 				dir = incfiles->dir;
   1190  1.39.2.1       jmc 				incfiles++;
   1191  1.39.2.1       jmc 				nincfiles--;
   1192  1.39.2.1       jmc 			} else if (strcmp(*argv, "-I") == 0) {
   1193  1.39.2.1       jmc 				if (*++argv == NULL)
   1194  1.39.2.1       jmc 					break;
   1195  1.39.2.1       jmc 				file = *argv++;
   1196  1.39.2.1       jmc 				dir = NULL;
   1197  1.39.2.1       jmc 			} else
   1198  1.39.2.1       jmc 				file = NULL;
   1199  1.39.2.1       jmc 			if (file != NULL) {
   1200  1.39.2.1       jmc 				FILE *fp;
   1201  1.39.2.1       jmc 				char *str;
   1202  1.39.2.1       jmc 				int dirisnext = 0;
   1203  1.39.2.1       jmc 
   1204  1.39.2.1       jmc 				/* Set directory if needed */
   1205  1.39.2.1       jmc 				if (dir) {
   1206  1.39.2.1       jmc 					if (ftree_add(dir, 1) < 0)
   1207  1.39.2.1       jmc 						tar_usage();
   1208  1.39.2.1       jmc 				}
   1209  1.39.2.1       jmc 
   1210  1.39.2.1       jmc 				if (strcmp(file, "-") == 0)
   1211  1.39.2.1       jmc 					fp = stdin;
   1212  1.39.2.1       jmc 				else if ((fp = fopen(file, "r")) == NULL) {
   1213  1.39.2.1       jmc 					tty_warn(1, "Unable to open file '%s' for read", file);
   1214  1.39.2.1       jmc 					tar_usage();
   1215  1.39.2.1       jmc 				}
   1216  1.39.2.1       jmc 				while ((str = getline(fp)) != NULL) {
   1217  1.39.2.1       jmc 					if (dirisnext) {
   1218  1.39.2.1       jmc 						if (ftree_add(str, 1) < 0)
   1219  1.39.2.1       jmc 							tar_usage();
   1220  1.39.2.1       jmc 						dirisnext = 0;
   1221  1.39.2.1       jmc 						continue;
   1222  1.39.2.1       jmc 					}
   1223  1.39.2.1       jmc 					if (strcmp(str, "-C") == 0) {
   1224  1.39.2.1       jmc 						dirisnext = 1;
   1225  1.39.2.1       jmc 						continue;
   1226  1.39.2.1       jmc 					}
   1227  1.39.2.1       jmc 					if (ftree_add(str, 0) < 0)
   1228  1.39.2.1       jmc 						tar_usage();
   1229  1.39.2.1       jmc 				}
   1230  1.39.2.1       jmc 				/* Bomb if given -C w/out a dir. */
   1231  1.39.2.1       jmc 				if (dirisnext)
   1232  1.39.2.1       jmc 					tar_usage();
   1233  1.39.2.1       jmc 				if (strcmp(file, "-") != 0)
   1234  1.39.2.1       jmc 					fclose(fp);
   1235  1.39.2.1       jmc 				if (getline_error) {
   1236  1.39.2.1       jmc 					tty_warn(1, "Problem with file '%s'",
   1237  1.39.2.1       jmc 					    file);
   1238  1.39.2.1       jmc 					tar_usage();
   1239  1.39.2.1       jmc 				}
   1240  1.39.2.1       jmc 			} else if (strcmp(*argv, "-C") == 0) {
   1241  1.39.2.1       jmc 				if (*++argv == NULL)
   1242  1.39.2.1       jmc 					break;
   1243  1.39.2.1       jmc 				if (ftree_add(*argv++, 1) < 0)
   1244  1.39.2.1       jmc 					tar_usage();
   1245  1.39.2.1       jmc 			} else if (ftree_add(*argv++, 0) < 0)
   1246  1.39.2.1       jmc 				tar_usage();
   1247  1.39.2.1       jmc 		}
   1248       1.1       jtc 		/*
   1249       1.1       jtc 		 * no read errors allowed on updates/append operation!
   1250       1.1       jtc 		 */
   1251       1.1       jtc 		maxflt = 0;
   1252       1.1       jtc 		break;
   1253       1.1       jtc 	}
   1254       1.1       jtc 	if (!fstdin && ((arcname == (char *)NULL) || (*arcname == '\0'))) {
   1255       1.1       jtc 		arcname = getenv("TAPE");
   1256  1.39.2.1       jmc 		if ((arcname == NULL) || (*arcname == '\0'))
   1257  1.39.2.1       jmc 			arcname = _PATH_DEFTAPE;
   1258       1.1       jtc 	}
   1259       1.1       jtc }
   1260       1.1       jtc 
   1261  1.39.2.1       jmc int
   1262  1.39.2.1       jmc mkpath(path)
   1263  1.39.2.1       jmc 	char *path;
   1264  1.39.2.1       jmc {
   1265  1.39.2.1       jmc 	struct stat sb;
   1266  1.39.2.1       jmc 	char *slash;
   1267  1.39.2.1       jmc 	int done = 0;
   1268  1.39.2.1       jmc 
   1269  1.39.2.1       jmc 	slash = path;
   1270  1.39.2.1       jmc 
   1271  1.39.2.1       jmc 	while (!done) {
   1272  1.39.2.1       jmc 		slash += strspn(slash, "/");
   1273  1.39.2.1       jmc 		slash += strcspn(slash, "/");
   1274  1.39.2.1       jmc 
   1275  1.39.2.1       jmc 		done = (*slash == '\0');
   1276  1.39.2.1       jmc 		*slash = '\0';
   1277  1.39.2.1       jmc 
   1278  1.39.2.1       jmc 		if (stat(path, &sb)) {
   1279  1.39.2.1       jmc 			if (errno != ENOENT || mkdir(path, 0777)) {
   1280  1.39.2.1       jmc 				tty_warn(1, "%s", path);
   1281  1.39.2.1       jmc 				return (-1);
   1282  1.39.2.1       jmc 			}
   1283  1.39.2.1       jmc 		} else if (!S_ISDIR(sb.st_mode)) {
   1284  1.39.2.1       jmc 			syswarn(1, ENOTDIR, "%s", path);
   1285  1.39.2.1       jmc 			return (-1);
   1286  1.39.2.1       jmc 		}
   1287  1.39.2.1       jmc 
   1288  1.39.2.1       jmc 		if (!done)
   1289  1.39.2.1       jmc 			*slash = '/';
   1290  1.39.2.1       jmc 	}
   1291  1.39.2.1       jmc 
   1292  1.39.2.1       jmc 	return (0);
   1293  1.39.2.1       jmc }
   1294  1.39.2.1       jmc 
   1295  1.39.2.1       jmc 
   1296  1.39.2.1       jmc struct option cpio_longopts[] = {
   1297  1.39.2.1       jmc 	{ "reset-access-time",	no_argument,		0,	'a' },
   1298  1.39.2.1       jmc 	{ "make-directories",	no_argument,		0, 	'd' },
   1299  1.39.2.1       jmc 	{ "nonmatching",	no_argument,		0,	'f' },
   1300  1.39.2.1       jmc 	{ "extract",		no_argument,		0,	'i' },
   1301  1.39.2.1       jmc 	{ "link",		no_argument,		0,	'l' },
   1302  1.39.2.1       jmc 	{ "preserve-modification-time", no_argument,	0,	'm' },
   1303  1.39.2.1       jmc 	{ "create",		no_argument,		0,	'o' },
   1304  1.39.2.1       jmc 	{ "pass-through",	no_argument,		0,	'p' },
   1305  1.39.2.1       jmc 	{ "rename",		no_argument,		0,	'r' },
   1306  1.39.2.1       jmc 	{ "list",		no_argument,		0,	't' },
   1307  1.39.2.1       jmc 	{ "unconditional",	no_argument,		0,	'u' },
   1308  1.39.2.1       jmc 	{ "verbose",		no_argument,		0,	'v' },
   1309  1.39.2.1       jmc 	{ "append",		no_argument,		0,	'A' },
   1310  1.39.2.1       jmc 	{ "pattern-file",	required_argument,	0,	'E' },
   1311  1.39.2.1       jmc 	{ "file",		required_argument,	0,	'F' },
   1312  1.39.2.1       jmc 	{ "force-local",	no_argument,		0,
   1313  1.39.2.1       jmc 						OPT_FORCE_LOCAL },
   1314  1.39.2.1       jmc 	{ "format",		required_argument,	0,	'H' },
   1315  1.39.2.1       jmc 	{ "dereference",	no_argument,		0,	'L' },
   1316  1.39.2.1       jmc 	{ "swap-halfwords",	no_argument,		0,	'S' },
   1317  1.39.2.1       jmc 	{ "insecure",		no_argument,		0,
   1318  1.39.2.1       jmc 						OPT_INSECURE },
   1319  1.39.2.1       jmc 
   1320  1.39.2.1       jmc #ifdef notyet
   1321  1.39.2.1       jmc /* Not implemented */
   1322  1.39.2.1       jmc 	{ "null",		no_argument,		0,	'0' },
   1323  1.39.2.1       jmc 	{ "swap",		no_argument,		0,	'b' },
   1324  1.39.2.1       jmc 	{ "numeric-uid-gid",	no_argument,		0,	'n' },
   1325  1.39.2.1       jmc 	{ "swap-bytes",		no_argument,		0,	's' },
   1326  1.39.2.1       jmc 	{ "message",		required_argument,	0,	'M' },
   1327  1.39.2.1       jmc 	{ "owner",		required_argument,	0	'R' },
   1328  1.39.2.1       jmc 	{ "dot",		no_argument,		0,	'V' },
   1329  1.39.2.1       jmc 	{ "block-size",		required_argument,	0,
   1330  1.39.2.1       jmc 						OPT_BLOCK_SIZE },
   1331  1.39.2.1       jmc 	{ "no-absolute-pathnames", no_argument,		0,
   1332  1.39.2.1       jmc 						OPT_NO_ABSOLUTE_PATHNAMES },
   1333  1.39.2.1       jmc 	{ "no-preserve-owner",	no_argument,		0,
   1334  1.39.2.1       jmc 						OPT_NO_PRESERVE_OWNER },
   1335  1.39.2.1       jmc 	{ "only-verify-crc",	no_argument,		0,
   1336  1.39.2.1       jmc 						OPT_ONLY_VERIFY_CRC },
   1337  1.39.2.1       jmc 	{ "rsh-command",	required_argument,	0,
   1338  1.39.2.1       jmc 						OPT_RSH_COMMAND },
   1339  1.39.2.1       jmc 	{ "sparce",		no_argument,		0,
   1340  1.39.2.1       jmc 						OPT_SPARSE },
   1341  1.39.2.1       jmc 	{ "version",		no_argument,		0,
   1342  1.39.2.1       jmc 						OPT_VERSION },
   1343  1.39.2.1       jmc #endif
   1344  1.39.2.1       jmc };
   1345  1.39.2.1       jmc 
   1346       1.1       jtc /*
   1347       1.1       jtc  * cpio_options()
   1348       1.1       jtc  *	look at the user specified flags. set globals as required and check if
   1349       1.1       jtc  *	the user specified a legal set of flags. If not, complain and exit
   1350       1.1       jtc  */
   1351       1.1       jtc 
   1352       1.1       jtc static void
   1353       1.7       tls cpio_options(int argc, char **argv)
   1354       1.1       jtc {
   1355      1.26     itohy 	FSUB tmp;
   1356      1.10       mrg 	unsigned int flg = 0;
   1357      1.10       mrg 	unsigned int bflg = 0;
   1358      1.10       mrg 	int c, i;
   1359  1.39.2.1       jmc 	FILE *fp;
   1360  1.39.2.1       jmc 	char *str;
   1361      1.10       mrg 
   1362  1.39.2.1       jmc 	uflag = 1;
   1363  1.39.2.1       jmc 	kflag = 1;
   1364  1.39.2.1       jmc 	pids = 1;
   1365  1.39.2.1       jmc 	pmode = 1;
   1366  1.39.2.1       jmc 	pmtime = 0;
   1367  1.39.2.1       jmc 	arcname = NULL;
   1368  1.39.2.1       jmc 	dflag = 1;
   1369  1.39.2.1       jmc 	nodirs = 1;
   1370      1.10       mrg 	/*
   1371      1.10       mrg 	 * process option flags
   1372      1.10       mrg 	 */
   1373      1.29   thorpej 	while ((c = getoldopt(argc, argv,
   1374  1.39.2.1       jmc 	    "+abcdfiklmoprstuvzABC:E:F:H:I:LM:O:R:SVZ6",
   1375  1.39.2.1       jmc 	    cpio_longopts, NULL)) != -1) {
   1376      1.10       mrg 		switch(c) {
   1377      1.10       mrg 		case 'a':
   1378      1.10       mrg 			/*
   1379      1.10       mrg 			 * preserve access time on filesystem nodes we read
   1380      1.10       mrg 			 */
   1381      1.10       mrg 			tflag = 1;
   1382      1.10       mrg 			flg |= TF;
   1383      1.10       mrg 			break;
   1384      1.10       mrg #ifdef notyet
   1385      1.10       mrg 		case 'b':
   1386  1.39.2.1       jmc 			/*
   1387  1.39.2.1       jmc 			 * swap bytes and half-words when reading data
   1388  1.39.2.1       jmc 			 */
   1389      1.10       mrg 			break;
   1390      1.10       mrg #endif
   1391      1.10       mrg 		case 'c':
   1392  1.39.2.1       jmc 			/*
   1393  1.39.2.1       jmc 			 * ASCII cpio header
   1394  1.39.2.1       jmc 			 */
   1395      1.10       mrg 			frmt = &fsub[F_SV4CPIO];
   1396      1.10       mrg 			break;
   1397      1.10       mrg 		case 'd':
   1398      1.10       mrg 			/*
   1399  1.39.2.1       jmc 			 * create directories as needed
   1400      1.10       mrg 			 * pax does this by default ..
   1401      1.10       mrg 			 */
   1402  1.39.2.1       jmc 			nodirs = 0;
   1403      1.10       mrg 			flg |= RF;
   1404      1.10       mrg 			break;
   1405      1.10       mrg 		case 'f':
   1406      1.10       mrg 			/*
   1407      1.10       mrg 			 * inverse match on patterns
   1408      1.10       mrg 			 */
   1409      1.10       mrg 			cflag = 1;
   1410      1.10       mrg 			flg |= CF;
   1411      1.10       mrg 			break;
   1412      1.10       mrg 		case 'i':
   1413      1.10       mrg 			/*
   1414      1.10       mrg 			 * read the archive
   1415      1.10       mrg 			 */
   1416  1.39.2.1       jmc 			act = EXTRACT;
   1417      1.10       mrg 			flg |= RF;
   1418      1.10       mrg 			break;
   1419      1.10       mrg #ifdef notyet
   1420      1.10       mrg 		case 'k':
   1421      1.10       mrg 			break;
   1422      1.10       mrg #endif
   1423      1.10       mrg 		case 'l':
   1424      1.10       mrg 			/*
   1425      1.10       mrg 			 * try to link src to dest with copy (-rw)
   1426      1.10       mrg 			 */
   1427      1.10       mrg 			lflag = 1;
   1428      1.10       mrg 			flg |= LF;
   1429      1.10       mrg 			break;
   1430      1.10       mrg 		case 'm':
   1431      1.10       mrg 			/*
   1432      1.10       mrg 			 * preserve mtime
   1433      1.10       mrg 			 */
   1434      1.10       mrg 			flg |= PF;
   1435      1.10       mrg 			pmtime = 1;
   1436      1.10       mrg 			break;
   1437      1.10       mrg 		case 'o':
   1438      1.10       mrg 			/*
   1439      1.10       mrg 			 * write an archive
   1440      1.10       mrg 			 */
   1441  1.39.2.1       jmc 			act = ARCHIVE;
   1442  1.39.2.1       jmc 			frmt = &(fsub[F_SV4CRC]);
   1443      1.10       mrg 			flg |= WF;
   1444      1.10       mrg 			break;
   1445      1.10       mrg 		case 'p':
   1446      1.10       mrg 			/*
   1447      1.10       mrg 			 * cpio -p is like pax -rw
   1448      1.10       mrg 			 */
   1449  1.39.2.1       jmc 			act = COPY;
   1450      1.10       mrg 			flg |= RF | WF;
   1451      1.10       mrg 			break;
   1452      1.10       mrg 		case 'r':
   1453      1.10       mrg 			/*
   1454      1.10       mrg 			 * interactive file rename
   1455      1.10       mrg 			 */
   1456      1.10       mrg 			iflag = 1;
   1457      1.10       mrg 			flg |= IF;
   1458      1.10       mrg 			break;
   1459      1.10       mrg #ifdef notyet
   1460      1.10       mrg 		case 's':
   1461  1.39.2.1       jmc 			/*
   1462  1.39.2.1       jmc 			 * swap bytes after reading data
   1463  1.39.2.1       jmc 			 */
   1464      1.10       mrg 			break;
   1465      1.10       mrg #endif
   1466      1.10       mrg 		case 't':
   1467  1.39.2.1       jmc 			/*
   1468  1.39.2.1       jmc 			 * list contents of archive
   1469  1.39.2.1       jmc 			 */
   1470      1.10       mrg 			act = LIST;
   1471  1.39.2.1       jmc 			listf = stdout;
   1472      1.10       mrg 			break;
   1473      1.10       mrg 		case 'u':
   1474      1.10       mrg 			/*
   1475      1.10       mrg 			 * don't ignore those older files
   1476      1.10       mrg 			 */
   1477      1.10       mrg 			uflag = 0;
   1478  1.39.2.1       jmc 			kflag = 0;
   1479      1.10       mrg 			flg |= UF;
   1480      1.10       mrg 			break;
   1481      1.10       mrg 		case 'v':
   1482      1.10       mrg 			/*
   1483      1.10       mrg 			 * verbose operation mode
   1484      1.10       mrg 			 */
   1485      1.10       mrg 			vflag = 1;
   1486      1.10       mrg 			flg |= VF;
   1487      1.10       mrg 			break;
   1488  1.39.2.1       jmc 		case 'z':
   1489  1.39.2.1       jmc 			/*
   1490  1.39.2.1       jmc 			 * use gzip.  Non standard option.
   1491  1.39.2.1       jmc 			 */
   1492  1.39.2.1       jmc 			gzip_program = GZIP_CMD;
   1493  1.39.2.1       jmc 			break;
   1494  1.39.2.1       jmc 		case 'A':
   1495  1.39.2.1       jmc 			/*
   1496  1.39.2.1       jmc 			 * append to an archive
   1497  1.39.2.1       jmc 			 */
   1498  1.39.2.1       jmc 			act = APPND;
   1499  1.39.2.1       jmc 			flg |= AF;
   1500  1.39.2.1       jmc 			break;
   1501  1.39.2.1       jmc 		case 'B':
   1502  1.39.2.1       jmc 			/*
   1503  1.39.2.1       jmc 			 * set blocksize to 5120
   1504  1.39.2.1       jmc 			 */
   1505  1.39.2.1       jmc 			blksz = 5120;
   1506  1.39.2.1       jmc 			break;
   1507  1.39.2.1       jmc 		case 'C':
   1508  1.39.2.1       jmc 			/*
   1509  1.39.2.1       jmc 			 * specify blocksize
   1510  1.39.2.1       jmc 			 */
   1511  1.39.2.1       jmc 			if ((blksz = (int)str_offt(optarg)) <= 0) {
   1512  1.39.2.1       jmc 				tty_warn(1, "Invalid block size %s", optarg);
   1513  1.39.2.1       jmc 				cpio_usage();
   1514  1.39.2.1       jmc 			}
   1515  1.39.2.1       jmc 			break;
   1516  1.39.2.1       jmc 		case 'E':
   1517  1.39.2.1       jmc 			/*
   1518  1.39.2.1       jmc 			 * file with patterns to extract or list
   1519  1.39.2.1       jmc 			 */
   1520  1.39.2.1       jmc 			if ((fp = fopen(optarg, "r")) == NULL) {
   1521  1.39.2.1       jmc 				tty_warn(1, "Unable to open file '%s' for read",
   1522  1.39.2.1       jmc 				    optarg);
   1523  1.39.2.1       jmc 				cpio_usage();
   1524  1.39.2.1       jmc 			}
   1525  1.39.2.1       jmc 			while ((str = getline(fp)) != NULL) {
   1526  1.39.2.1       jmc 				pat_add(str, NULL);
   1527  1.39.2.1       jmc 			}
   1528  1.39.2.1       jmc 			fclose(fp);
   1529  1.39.2.1       jmc 			if (getline_error) {
   1530  1.39.2.1       jmc 				tty_warn(1, "Problem with file '%s'", optarg);
   1531  1.39.2.1       jmc 				cpio_usage();
   1532  1.39.2.1       jmc 			}
   1533  1.39.2.1       jmc 			break;
   1534  1.39.2.1       jmc 		case 'H':
   1535  1.39.2.1       jmc 			/*
   1536  1.39.2.1       jmc 			 * specify an archive format on write
   1537  1.39.2.1       jmc 			 */
   1538  1.39.2.1       jmc 			tmp.name = optarg;
   1539  1.39.2.1       jmc 			frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
   1540  1.39.2.1       jmc 			    sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt);
   1541  1.39.2.1       jmc 			if (frmt != NULL) {
   1542  1.39.2.1       jmc 				flg |= XF;
   1543  1.39.2.1       jmc 				break;
   1544  1.39.2.1       jmc 			}
   1545  1.39.2.1       jmc 			tty_warn(1, "Unknown -H format: %s", optarg);
   1546  1.39.2.1       jmc 			(void)fputs("cpio: Known -H formats are:", stderr);
   1547  1.39.2.1       jmc 			for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
   1548  1.39.2.1       jmc 				(void)fprintf(stderr, " %s", fsub[i].name);
   1549  1.39.2.1       jmc 			(void)fputs("\n\n", stderr);
   1550  1.39.2.1       jmc 			cpio_usage();
   1551  1.39.2.1       jmc 			break;
   1552  1.39.2.1       jmc 		case 'I':
   1553  1.39.2.1       jmc 		case 'O':
   1554  1.39.2.1       jmc 			/*
   1555  1.39.2.1       jmc 			 * filename where the archive is stored
   1556  1.39.2.1       jmc 			 */
   1557  1.39.2.1       jmc 			if ((optarg[0] == '-') && (optarg[1]== '\0')) {
   1558  1.39.2.1       jmc 				/*
   1559  1.39.2.1       jmc 				 * treat a - as stdin
   1560  1.39.2.1       jmc 				 */
   1561  1.39.2.1       jmc 				arcname = NULL;
   1562  1.39.2.1       jmc 				break;
   1563  1.39.2.1       jmc 			}
   1564  1.39.2.1       jmc 			arcname = optarg;
   1565  1.39.2.1       jmc 			break;
   1566  1.39.2.1       jmc 		case 'L':
   1567  1.39.2.1       jmc 			/*
   1568  1.39.2.1       jmc 			 * follow symlinks
   1569  1.39.2.1       jmc 			 */
   1570  1.39.2.1       jmc 			Lflag = 1;
   1571  1.39.2.1       jmc 			flg |= CLF;
   1572  1.39.2.1       jmc 			break;
   1573  1.39.2.1       jmc #ifdef notyet
   1574  1.39.2.1       jmc 		case 'M':
   1575  1.39.2.1       jmc 			arg = optarg;
   1576  1.39.2.1       jmc 			break;
   1577  1.39.2.1       jmc 		case 'R':
   1578  1.39.2.1       jmc 			arg = optarg;
   1579  1.39.2.1       jmc 			break;
   1580  1.39.2.1       jmc #endif
   1581  1.39.2.1       jmc 		case 'S':
   1582  1.39.2.1       jmc 			/*
   1583  1.39.2.1       jmc 			 * swap halfwords after reading data
   1584  1.39.2.1       jmc 			 */
   1585  1.39.2.1       jmc 			cpio_swp_head = 1;
   1586  1.39.2.1       jmc 			break;
   1587  1.39.2.1       jmc #ifdef notyet
   1588  1.39.2.1       jmc 		case 'V':
   1589  1.39.2.1       jmc 			break;
   1590  1.39.2.1       jmc #endif
   1591  1.39.2.1       jmc 		case 'Z':
   1592  1.39.2.1       jmc 			/*
   1593  1.39.2.1       jmc 			 * use compress.  Non standard option.
   1594  1.39.2.1       jmc 			 */
   1595  1.39.2.1       jmc 			gzip_program = COMPRESS_CMD;
   1596  1.39.2.1       jmc 			break;
   1597  1.39.2.1       jmc 		case '6':
   1598  1.39.2.1       jmc 			/*
   1599  1.39.2.1       jmc 			 * process Version 6 cpio format
   1600  1.39.2.1       jmc 			 */
   1601  1.39.2.1       jmc 			frmt = &(fsub[F_BCPIO]);
   1602  1.39.2.1       jmc 		case OPT_FORCE_LOCAL:
   1603  1.39.2.1       jmc 			forcelocal = 1;
   1604  1.39.2.1       jmc 			break;
   1605  1.39.2.1       jmc 		case OPT_INSECURE:
   1606  1.39.2.1       jmc 			secure = 0;
   1607  1.39.2.1       jmc 			break;
   1608      1.10       mrg 		default:
   1609      1.10       mrg 			cpio_usage();
   1610      1.10       mrg 			break;
   1611      1.10       mrg 		}
   1612      1.10       mrg 	}
   1613      1.10       mrg 
   1614      1.10       mrg 	/*
   1615      1.10       mrg 	 * figure out the operation mode of cpio. check that we have not been
   1616      1.10       mrg 	 * given a bogus set of flags for the operation mode.
   1617      1.10       mrg 	 */
   1618      1.10       mrg 	if (ISLIST(flg)) {
   1619      1.10       mrg 		act = LIST;
   1620      1.10       mrg 		bflg = flg & BDLIST;
   1621      1.10       mrg 	} else if (ISEXTRACT(flg)) {
   1622      1.10       mrg 		act = EXTRACT;
   1623      1.10       mrg 		bflg = flg & BDEXTR;
   1624      1.10       mrg 	} else if (ISARCHIVE(flg)) {
   1625      1.10       mrg 		act = ARCHIVE;
   1626      1.10       mrg 		bflg = flg & BDARCH;
   1627      1.10       mrg 	} else if (ISAPPND(flg)) {
   1628      1.10       mrg 		act = APPND;
   1629      1.10       mrg 		bflg = flg & BDARCH;
   1630      1.10       mrg 	} else if (ISCOPY(flg)) {
   1631      1.10       mrg 		act = COPY;
   1632      1.10       mrg 		bflg = flg & BDCOPY;
   1633      1.10       mrg 	} else
   1634      1.10       mrg 		cpio_usage();
   1635      1.10       mrg 	if (bflg) {
   1636      1.10       mrg 		cpio_usage();
   1637      1.10       mrg 	}
   1638      1.10       mrg 
   1639      1.10       mrg 	/*
   1640      1.10       mrg 	 * if we are writing (ARCHIVE) we use the default format if the user
   1641      1.10       mrg 	 * did not specify a format. when we write during an APPEND, we will
   1642      1.10       mrg 	 * adopt the format of the existing archive if none was supplied.
   1643      1.10       mrg 	 */
   1644      1.10       mrg 	if (!(flg & XF) && (act == ARCHIVE))
   1645      1.10       mrg 		frmt = &(fsub[F_BCPIO]);
   1646      1.10       mrg 
   1647      1.10       mrg 	/*
   1648      1.10       mrg 	 * process the args as they are interpreted by the operation mode
   1649      1.10       mrg 	 */
   1650      1.10       mrg 	switch (act) {
   1651      1.10       mrg 	case LIST:
   1652      1.10       mrg 	case EXTRACT:
   1653      1.10       mrg 		for (; optind < argc; optind++)
   1654      1.23        is 			if (pat_add(argv[optind], 0) < 0)
   1655      1.10       mrg 				cpio_usage();
   1656      1.10       mrg 		break;
   1657      1.10       mrg 	case COPY:
   1658      1.10       mrg 		if (optind >= argc) {
   1659      1.10       mrg 			tty_warn(0, "Destination directory was not supplied");
   1660      1.10       mrg 			cpio_usage();
   1661      1.10       mrg 		}
   1662      1.10       mrg 		--argc;
   1663      1.10       mrg 		dirptr = argv[argc];
   1664      1.14   mycroft 		/* FALLTHROUGH */
   1665      1.10       mrg 	case ARCHIVE:
   1666      1.10       mrg 	case APPND:
   1667  1.39.2.1       jmc 		if (argc != optind) {
   1668  1.39.2.1       jmc 			for (; optind < argc; optind++)
   1669  1.39.2.1       jmc 				if (ftree_add(argv[optind], 0) < 0)
   1670  1.39.2.1       jmc 					cpio_usage();
   1671  1.39.2.1       jmc 			break;
   1672  1.39.2.1       jmc 		}
   1673      1.10       mrg 		/*
   1674      1.10       mrg 		 * no read errors allowed on updates/append operation!
   1675      1.10       mrg 		 */
   1676      1.10       mrg 		maxflt = 0;
   1677  1.39.2.1       jmc 		while ((str = getline(stdin)) != NULL) {
   1678  1.39.2.1       jmc 			ftree_add(str, 0);
   1679  1.39.2.1       jmc 		}
   1680  1.39.2.1       jmc 		if (getline_error) {
   1681  1.39.2.1       jmc 			tty_warn(1, "Problem while reading stdin");
   1682  1.39.2.1       jmc 			cpio_usage();
   1683  1.39.2.1       jmc 		}
   1684  1.39.2.1       jmc 		break;
   1685  1.39.2.1       jmc 	default:
   1686  1.39.2.1       jmc 		cpio_usage();
   1687      1.10       mrg 		break;
   1688      1.10       mrg 	}
   1689       1.1       jtc }
   1690       1.1       jtc 
   1691       1.1       jtc /*
   1692       1.1       jtc  * printflg()
   1693       1.1       jtc  *	print out those invalid flag sets found to the user
   1694       1.1       jtc  */
   1695       1.1       jtc 
   1696       1.1       jtc static void
   1697       1.1       jtc printflg(unsigned int flg)
   1698       1.1       jtc {
   1699       1.1       jtc 	int nxt;
   1700       1.1       jtc 
   1701       1.1       jtc 	(void)fprintf(stderr,"%s: Invalid combination of options:", argv0);
   1702       1.8  christos 	while ((nxt = ffs(flg)) != 0) {
   1703  1.39.2.1       jmc 		flg &= ~(1 << (nxt - 1));
   1704  1.39.2.1       jmc 		(void)fprintf(stderr, " -%c", flgch[nxt - 1]);
   1705       1.1       jtc 	}
   1706       1.1       jtc 	(void)putc('\n', stderr);
   1707       1.1       jtc }
   1708       1.1       jtc 
   1709       1.1       jtc /*
   1710       1.1       jtc  * c_frmt()
   1711       1.1       jtc  *	comparison routine used by bsearch to find the format specified
   1712       1.1       jtc  *	by the user
   1713       1.1       jtc  */
   1714       1.1       jtc 
   1715       1.1       jtc static int
   1716       1.1       jtc c_frmt(const void *a, const void *b)
   1717       1.1       jtc {
   1718      1.26     itohy 	return(strcmp(((FSUB *)a)->name, ((FSUB *)b)->name));
   1719       1.1       jtc }
   1720       1.1       jtc 
   1721       1.1       jtc /*
   1722       1.1       jtc  * opt_next()
   1723       1.1       jtc  *	called by format specific options routines to get each format specific
   1724       1.1       jtc  *	flag and value specified with -o
   1725       1.1       jtc  * Return:
   1726       1.1       jtc  *	pointer to next OPLIST entry or NULL (end of list).
   1727       1.1       jtc  */
   1728       1.1       jtc 
   1729       1.1       jtc OPLIST *
   1730       1.1       jtc opt_next(void)
   1731       1.1       jtc {
   1732       1.1       jtc 	OPLIST *opt;
   1733       1.1       jtc 
   1734       1.1       jtc 	if ((opt = ophead) != NULL)
   1735       1.1       jtc 		ophead = ophead->fow;
   1736       1.1       jtc 	return(opt);
   1737       1.1       jtc }
   1738       1.1       jtc 
   1739       1.1       jtc /*
   1740       1.1       jtc  * bad_opt()
   1741       1.1       jtc  *	generic routine used to complain about a format specific options
   1742       1.1       jtc  *	when the format does not support options.
   1743       1.1       jtc  */
   1744       1.1       jtc 
   1745       1.1       jtc int
   1746       1.1       jtc bad_opt(void)
   1747       1.1       jtc {
   1748       1.7       tls 	OPLIST *opt;
   1749       1.1       jtc 
   1750       1.1       jtc 	if (ophead == NULL)
   1751       1.1       jtc 		return(0);
   1752       1.1       jtc 	/*
   1753       1.1       jtc 	 * print all we were given
   1754       1.1       jtc 	 */
   1755  1.39.2.1       jmc 	tty_warn(1," These format options are not supported for %s",
   1756  1.39.2.1       jmc 	    frmt->name);
   1757       1.1       jtc 	while ((opt = opt_next()) != NULL)
   1758       1.1       jtc 		(void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value);
   1759  1.39.2.1       jmc 	if (strcmp(NM_TAR, argv0) == 0)
   1760  1.39.2.1       jmc 		tar_usage();
   1761  1.39.2.1       jmc 	else if (strcmp(NM_CPIO, argv0) == 0)
   1762  1.39.2.1       jmc 		cpio_usage();
   1763  1.39.2.1       jmc 	else
   1764  1.39.2.1       jmc 		pax_usage();
   1765       1.1       jtc 	return(0);
   1766       1.1       jtc }
   1767       1.1       jtc 
   1768       1.1       jtc /*
   1769       1.1       jtc  * opt_add()
   1770       1.1       jtc  *	breaks the value supplied to -o into a option name and value. options
   1771       1.1       jtc  *	are given to -o in the form -o name-value,name=value
   1772      1.26     itohy  *	multiple -o may be specified.
   1773       1.1       jtc  * Return:
   1774       1.1       jtc  *	0 if format in name=value format, -1 if -o is passed junk
   1775       1.1       jtc  */
   1776       1.1       jtc 
   1777       1.1       jtc int
   1778      1.18        tv opt_add(const char *str)
   1779       1.1       jtc {
   1780       1.7       tls 	OPLIST *opt;
   1781       1.7       tls 	char *frpt;
   1782       1.7       tls 	char *pt;
   1783       1.7       tls 	char *endpt;
   1784  1.39.2.1       jmc 	char *dstr;
   1785       1.1       jtc 
   1786       1.1       jtc 	if ((str == NULL) || (*str == '\0')) {
   1787       1.8  christos 		tty_warn(0, "Invalid option name");
   1788       1.1       jtc 		return(-1);
   1789       1.1       jtc 	}
   1790  1.39.2.1       jmc 	if ((dstr = strdup(str)) == NULL) {
   1791  1.39.2.1       jmc 		tty_warn(0, "Unable to allocate space for option list");
   1792  1.39.2.1       jmc 		return(-1);
   1793  1.39.2.1       jmc 	}
   1794  1.39.2.1       jmc 	frpt = endpt = dstr;
   1795       1.1       jtc 
   1796       1.1       jtc 	/*
   1797       1.1       jtc 	 * break into name and values pieces and stuff each one into a
   1798       1.1       jtc 	 * OPLIST structure. When we know the format, the format specific
   1799       1.1       jtc 	 * option function will go through this list
   1800       1.1       jtc 	 */
   1801       1.1       jtc 	while ((frpt != NULL) && (*frpt != '\0')) {
   1802       1.1       jtc 		if ((endpt = strchr(frpt, ',')) != NULL)
   1803       1.1       jtc 			*endpt = '\0';
   1804       1.1       jtc 		if ((pt = strchr(frpt, '=')) == NULL) {
   1805       1.8  christos 			tty_warn(0, "Invalid options format");
   1806  1.39.2.1       jmc 			free(dstr);
   1807       1.1       jtc 			return(-1);
   1808       1.1       jtc 		}
   1809       1.1       jtc 		if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
   1810       1.8  christos 			tty_warn(0, "Unable to allocate space for option list");
   1811  1.39.2.1       jmc 			free(dstr);
   1812       1.1       jtc 			return(-1);
   1813       1.1       jtc 		}
   1814       1.1       jtc 		*pt++ = '\0';
   1815       1.1       jtc 		opt->name = frpt;
   1816       1.1       jtc 		opt->value = pt;
   1817       1.1       jtc 		opt->fow = NULL;
   1818       1.1       jtc 		if (endpt != NULL)
   1819       1.1       jtc 			frpt = endpt + 1;
   1820       1.1       jtc 		else
   1821       1.1       jtc 			frpt = NULL;
   1822       1.1       jtc 		if (ophead == NULL) {
   1823       1.1       jtc 			optail = ophead = opt;
   1824       1.1       jtc 			continue;
   1825       1.1       jtc 		}
   1826       1.1       jtc 		optail->fow = opt;
   1827       1.1       jtc 		optail = opt;
   1828       1.1       jtc 	}
   1829       1.1       jtc 	return(0);
   1830       1.1       jtc }
   1831       1.1       jtc 
   1832       1.1       jtc /*
   1833       1.1       jtc  * str_offt()
   1834       1.1       jtc  *	Convert an expression of the following forms to an off_t > 0.
   1835      1.26     itohy  *	1) A positive decimal number.
   1836       1.1       jtc  *	2) A positive decimal number followed by a b (mult by 512).
   1837       1.1       jtc  *	3) A positive decimal number followed by a k (mult by 1024).
   1838       1.1       jtc  *	4) A positive decimal number followed by a m (mult by 512).
   1839       1.1       jtc  *	5) A positive decimal number followed by a w (mult by sizeof int)
   1840       1.1       jtc  *	6) Two or more positive decimal numbers (with/without k,b or w).
   1841      1.32       wiz  *	   separated by x (also * for backwards compatibility), specifying
   1842       1.1       jtc  *	   the product of the indicated values.
   1843       1.1       jtc  * Return:
   1844       1.1       jtc  *	0 for an error, a positive value o.w.
   1845       1.1       jtc  */
   1846       1.1       jtc 
   1847       1.1       jtc static off_t
   1848       1.1       jtc str_offt(char *val)
   1849       1.1       jtc {
   1850       1.1       jtc 	char *expr;
   1851       1.1       jtc 	off_t num, t;
   1852       1.1       jtc 
   1853      1.33     lukem 	num = STRTOOFFT(val, &expr, 0);
   1854      1.33     lukem 	if ((num == OFFT_MAX) || (num <= 0) || (expr == val))
   1855       1.1       jtc 		return(0);
   1856       1.1       jtc 
   1857       1.1       jtc 	switch(*expr) {
   1858       1.1       jtc 	case 'b':
   1859       1.1       jtc 		t = num;
   1860       1.1       jtc 		num *= 512;
   1861       1.1       jtc 		if (t > num)
   1862       1.1       jtc 			return(0);
   1863       1.1       jtc 		++expr;
   1864       1.1       jtc 		break;
   1865       1.1       jtc 	case 'k':
   1866       1.1       jtc 		t = num;
   1867       1.1       jtc 		num *= 1024;
   1868       1.1       jtc 		if (t > num)
   1869       1.1       jtc 			return(0);
   1870       1.1       jtc 		++expr;
   1871       1.1       jtc 		break;
   1872       1.1       jtc 	case 'm':
   1873       1.1       jtc 		t = num;
   1874       1.1       jtc 		num *= 1048576;
   1875       1.1       jtc 		if (t > num)
   1876       1.1       jtc 			return(0);
   1877       1.1       jtc 		++expr;
   1878       1.1       jtc 		break;
   1879       1.1       jtc 	case 'w':
   1880       1.1       jtc 		t = num;
   1881       1.1       jtc 		num *= sizeof(int);
   1882       1.1       jtc 		if (t > num)
   1883       1.1       jtc 			return(0);
   1884       1.1       jtc 		++expr;
   1885       1.1       jtc 		break;
   1886       1.1       jtc 	}
   1887       1.1       jtc 
   1888       1.1       jtc 	switch(*expr) {
   1889       1.1       jtc 		case '\0':
   1890       1.1       jtc 			break;
   1891       1.1       jtc 		case '*':
   1892       1.1       jtc 		case 'x':
   1893       1.1       jtc 			t = num;
   1894       1.1       jtc 			num *= str_offt(expr + 1);
   1895       1.1       jtc 			if (t > num)
   1896       1.1       jtc 				return(0);
   1897       1.1       jtc 			break;
   1898       1.1       jtc 		default:
   1899       1.1       jtc 			return(0);
   1900       1.1       jtc 	}
   1901       1.1       jtc 	return(num);
   1902       1.1       jtc }
   1903       1.1       jtc 
   1904  1.39.2.1       jmc char *
   1905  1.39.2.1       jmc getline(FILE *f)
   1906  1.39.2.1       jmc {
   1907  1.39.2.1       jmc 	char *name, *temp;
   1908  1.39.2.1       jmc 	size_t len;
   1909  1.39.2.1       jmc 
   1910  1.39.2.1       jmc 	name = fgetln(f, &len);
   1911  1.39.2.1       jmc 	if (!name) {
   1912  1.39.2.1       jmc 		getline_error = ferror(f) ? GETLINE_FILE_CORRUPT : 0;
   1913  1.39.2.1       jmc 		return(0);
   1914  1.39.2.1       jmc 	}
   1915  1.39.2.1       jmc 	if (name[len-1] != '\n')
   1916  1.39.2.1       jmc 		len++;
   1917  1.39.2.1       jmc 	temp = malloc(len);
   1918  1.39.2.1       jmc 	if (!temp) {
   1919  1.39.2.1       jmc 		getline_error = GETLINE_OUT_OF_MEM;
   1920  1.39.2.1       jmc 		return(0);
   1921  1.39.2.1       jmc 	}
   1922  1.39.2.1       jmc 	memcpy(temp, name, len-1);
   1923  1.39.2.1       jmc 	temp[len-1] = 0;
   1924  1.39.2.1       jmc 	return(temp);
   1925  1.39.2.1       jmc }
   1926  1.39.2.1       jmc 
   1927       1.1       jtc /*
   1928       1.1       jtc  * no_op()
   1929       1.1       jtc  *	for those option functions where the archive format has nothing to do.
   1930       1.1       jtc  * Return:
   1931       1.1       jtc  *	0
   1932       1.1       jtc  */
   1933       1.1       jtc 
   1934       1.1       jtc static int
   1935       1.1       jtc no_op(void)
   1936       1.1       jtc {
   1937       1.1       jtc 	return(0);
   1938       1.1       jtc }
   1939       1.1       jtc 
   1940       1.1       jtc /*
   1941       1.1       jtc  * pax_usage()
   1942       1.1       jtc  *	print the usage summary to the user
   1943       1.1       jtc  */
   1944       1.1       jtc 
   1945       1.1       jtc void
   1946       1.1       jtc pax_usage(void)
   1947       1.1       jtc {
   1948      1.35     lukem 	fprintf(stderr,
   1949  1.39.2.1       jmc "usage: pax [-cdjnvzO] [-E limit] [-f archive] [-N dbdir] [-s replstr] ...\n"
   1950      1.35     lukem "           [-U user] ... [-G group] ... [-T [from_date][,to_date]] ...\n"
   1951      1.35     lukem "           [pattern ...]\n");
   1952      1.35     lukem 	fprintf(stderr,
   1953  1.39.2.1       jmc "       pax -r [-cdijknuvzADOYZ] [-E limit] [-f archive] [-N dbdir]\n"
   1954      1.35     lukem "           [-o options] ... [-p string] ... [-s replstr] ... [-U user] ...\n"
   1955      1.35     lukem "           [-G group] ... [-T [from_date][,to_date]] ... [pattern ...]\n");
   1956      1.35     lukem 	fprintf(stderr,
   1957  1.39.2.1       jmc "       pax -w [-dijtuvzAHLMOPX] [-b blocksize] [[-a] [-f archive]] [-x format]\n"
   1958      1.35     lukem "           [-B bytes] [-N dbdir] [-o options] ... [-s replstr] ...\n"
   1959      1.35     lukem "           [-U user] ... [-G group] ...\n"
   1960      1.35     lukem "           [-T [from_date][,to_date][/[c][m]]] ... [file ...]\n");
   1961      1.35     lukem 	fprintf(stderr,
   1962  1.39.2.1       jmc "       pax -r -w [-dijklntuvzADHLMOPXYZ] [-N dbdir] [-p string] ...\n"
   1963      1.35     lukem "           [-s replstr] ... [-U user] ... [-G group] ...\n"
   1964      1.35     lukem "           [-T [from_date][,to_date][/[c][m]]] ... [file ...] directory\n");
   1965       1.1       jtc 	exit(1);
   1966      1.12   mycroft 	/* NOTREACHED */
   1967       1.1       jtc }
   1968       1.1       jtc 
   1969       1.1       jtc /*
   1970       1.1       jtc  * tar_usage()
   1971       1.1       jtc  *	print the usage summary to the user
   1972       1.1       jtc  */
   1973       1.1       jtc 
   1974       1.1       jtc void
   1975       1.1       jtc tar_usage(void)
   1976       1.1       jtc {
   1977  1.39.2.1       jmc 	(void)fputs("usage: tar [-]{crtux}[-befhjlmopqvwzHLOPXZ014578] [archive] "
   1978  1.39.2.1       jmc 		    "[blocksize]\n"
   1979  1.39.2.1       jmc 		    "           [-C directory] [-T file] [-s replstr] "
   1980  1.39.2.1       jmc 		    "[file ...]\n", stderr);
   1981       1.1       jtc 	exit(1);
   1982      1.12   mycroft 	/* NOTREACHED */
   1983       1.1       jtc }
   1984       1.1       jtc 
   1985       1.1       jtc /*
   1986       1.1       jtc  * cpio_usage()
   1987       1.1       jtc  *	print the usage summary to the user
   1988       1.1       jtc  */
   1989       1.1       jtc 
   1990       1.1       jtc void
   1991       1.1       jtc cpio_usage(void)
   1992       1.1       jtc {
   1993      1.10       mrg 
   1994  1.39.2.1       jmc 	(void)fputs("usage: cpio -o [-aABcLvzZ] [-C bytes] [-F archive] "
   1995  1.39.2.1       jmc 		    "[-H format] [-O archive]\n"
   1996  1.39.2.1       jmc 		    "               < name-list [> archive]\n"
   1997  1.39.2.1       jmc 		    "       cpio -i [-bBcdfmrsStuvzZ6] [-C bytes] [-E file] "
   1998  1.39.2.1       jmc 		    "[-F archive] [-H format] \n"
   1999  1.39.2.1       jmc 		    "               [-I archive] "
   2000  1.39.2.1       jmc 		    "[pattern ...] [< archive]\n"
   2001  1.39.2.1       jmc 		    "       cpio -p [-adlLmuv] destination-directory "
   2002  1.39.2.1       jmc 		    "< name-list\n", stderr);
   2003       1.1       jtc 	exit(1);
   2004      1.12   mycroft 	/* NOTREACHED */
   2005      1.23        is }
   2006