1*2b9c0f9fSriastradh /* $NetBSD: options.c,v 1.121 2024/08/05 13:37:27 riastradh Exp $ */ 2b5b29542Sagc 3b5b29542Sagc /*- 4ed6ed8e6Sagc * Copyright (c) 1992 Keith Muller. 5b5b29542Sagc * Copyright (c) 1992, 1993 6b5b29542Sagc * The Regents of the University of California. All rights reserved. 7b5b29542Sagc * 8b5b29542Sagc * This code is derived from software contributed to Berkeley by 9b5b29542Sagc * Keith Muller of the University of California, San Diego. 10b5b29542Sagc * 11b5b29542Sagc * Redistribution and use in source and binary forms, with or without 12b5b29542Sagc * modification, are permitted provided that the following conditions 13b5b29542Sagc * are met: 14b5b29542Sagc * 1. Redistributions of source code must retain the above copyright 15b5b29542Sagc * notice, this list of conditions and the following disclaimer. 16b5b29542Sagc * 2. Redistributions in binary form must reproduce the above copyright 17b5b29542Sagc * notice, this list of conditions and the following disclaimer in the 18b5b29542Sagc * documentation and/or other materials provided with the distribution. 19b5b29542Sagc * 3. Neither the name of the University nor the names of its contributors 20b5b29542Sagc * may be used to endorse or promote products derived from this software 21b5b29542Sagc * without specific prior written permission. 22b5b29542Sagc * 23b5b29542Sagc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24b5b29542Sagc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25b5b29542Sagc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26b5b29542Sagc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27b5b29542Sagc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28b5b29542Sagc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29b5b29542Sagc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30b5b29542Sagc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31b5b29542Sagc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32b5b29542Sagc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33b5b29542Sagc * SUCH DAMAGE. 34b5b29542Sagc */ 3549f0ad86Scgd 36171d6532Slukem #if HAVE_NBTOOL_CONFIG_H 37171d6532Slukem #include "nbtool_config.h" 38171d6532Slukem #endif 39171d6532Slukem 40f3cd6022Schristos #include <sys/cdefs.h> 41171d6532Slukem #if !defined(lint) 4249f0ad86Scgd #if 0 4349f0ad86Scgd static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 4/18/94"; 4449f0ad86Scgd #else 45*2b9c0f9fSriastradh __RCSID("$NetBSD: options.c,v 1.121 2024/08/05 13:37:27 riastradh Exp $"); 4649f0ad86Scgd #endif 478b35abe2Sjtc #endif /* not lint */ 488b35abe2Sjtc 498b35abe2Sjtc #include <sys/types.h> 508b35abe2Sjtc #include <sys/time.h> 518b35abe2Sjtc #include <sys/stat.h> 528b35abe2Sjtc #include <sys/param.h> 538b35abe2Sjtc #include <ctype.h> 540c612021Schristos #include <errno.h> 55b2f78261Sjmc #if HAVE_NBTOOL_CONFIG_H 56b2f78261Sjmc #include "compat_getopt.h" 57b2f78261Sjmc #else 589fbd8888Stv #include <getopt.h> 59b2f78261Sjmc #endif 609fbd8888Stv #include <limits.h> 619fbd8888Stv #include <stdio.h> 629fbd8888Stv #include <stdlib.h> 638b35abe2Sjtc #include <string.h> 6421fbd5bbSlukem #include <strings.h> 658b35abe2Sjtc #include <unistd.h> 666d8547fdSchristos #include <inttypes.h> 670c612021Schristos #include <paths.h> 689158fb65Schristos #include <util.h> 698b35abe2Sjtc #include "pax.h" 708b35abe2Sjtc #include "options.h" 718b35abe2Sjtc #include "cpio.h" 728b35abe2Sjtc #include "tar.h" 738b35abe2Sjtc #include "extern.h" 746ee4925cSlukem #ifndef SMALL 75ae5120dcSlukem #include "mtree.h" 766ee4925cSlukem #endif /* SMALL */ 778b35abe2Sjtc 78d79fbfb9Sjoerg char *chdname; 79d79fbfb9Sjoerg #if !HAVE_NBTOOL_CONFIG_H 80d79fbfb9Sjoerg int do_chroot; 81d79fbfb9Sjoerg #endif 82d79fbfb9Sjoerg 838b35abe2Sjtc /* 848b35abe2Sjtc * Routines which handle command line options 858b35abe2Sjtc */ 869158fb65Schristos struct stat tst; /* Timestamp to set if non-0 */ 878b35abe2Sjtc 884aa7016dStv static int nopids; /* tar mode: suppress "pids" for -p option */ 895820cbfaSchristos static char flgch[] = FLGCH; /* list of all possible flags (pax) */ 908b35abe2Sjtc static OPLIST *ophead = NULL; /* head for format specific options -x */ 918b35abe2Sjtc static OPLIST *optail = NULL; /* option tail */ 928b35abe2Sjtc 93074c0c6eSjoerg static int opt_add(const char *); 94c1bd745cSlukem static int no_op(void); 95c1bd745cSlukem static void printflg(unsigned int); 96c1bd745cSlukem static int c_frmt(const void *, const void *); 97c1bd745cSlukem static off_t str_offt(char *); 987027866aSroy static char *get_line(FILE *fp); 999158fb65Schristos #ifndef SMALL 1009158fb65Schristos static int set_tstamp(const char *, struct stat *); 1019158fb65Schristos #endif 102c1bd745cSlukem static void pax_options(int, char **); 103074c0c6eSjoerg __dead static void pax_usage(void); 104c1bd745cSlukem static void tar_options(int, char **); 105074c0c6eSjoerg __dead static void tar_usage(void); 106d7df71baSchristos #ifndef NO_CPIO 107c1bd745cSlukem static void cpio_options(int, char **); 108074c0c6eSjoerg __dead static void cpio_usage(void); 109d7df71baSchristos #endif 1108b35abe2Sjtc 1117027866aSroy /* errors from get_line */ 1120c612021Schristos #define GETLINE_FILE_CORRUPT 1 1130c612021Schristos #define GETLINE_OUT_OF_MEM 2 1147027866aSroy static int get_line_error; 115e413a4ffSis 116e04df3a3Swiz #define BZIP2_CMD "bzip2" /* command to run as bzip2 */ 1177f64ea03Smrg #define GZIP_CMD "gzip" /* command to run as gzip */ 118dbf8eeeeSchristos #define XZ_CMD "xz" /* command to run as xz */ 1197f64ea03Smrg #define COMPRESS_CMD "compress" /* command to run as compress */ 1207f64ea03Smrg 1218b35abe2Sjtc /* 122ca541391Schristos * Long options. 123ca541391Schristos */ 124ca541391Schristos #define OPT_USE_COMPRESS_PROGRAM 0 125ca541391Schristos #define OPT_CHECKPOINT 1 126ca541391Schristos #define OPT_UNLINK 2 127ca541391Schristos #define OPT_HELP 3 128ca541391Schristos #define OPT_ATIME_PRESERVE 4 129ca541391Schristos #define OPT_IGNORE_FAILED_READ 5 130ca541391Schristos #define OPT_REMOVE_FILES 6 131ca541391Schristos #define OPT_NULL 7 132ca541391Schristos #define OPT_TOTALS 8 133ca541391Schristos #define OPT_VERSION 9 134ca541391Schristos #define OPT_EXCLUDE 10 135ca541391Schristos #define OPT_BLOCK_COMPRESS 11 136ca541391Schristos #define OPT_NORECURSE 12 137ca541391Schristos #define OPT_FORCE_LOCAL 13 138ca541391Schristos #define OPT_INSECURE 14 139f70dfaafSchristos #define OPT_STRICT 15 14060cf1998Schristos #define OPT_SPARSE 16 141dbf8eeeeSchristos #define OPT_XZ 17 142e028f49dSchristos #define OPT_GNU 18 1439158fb65Schristos #define OPT_TIMESTAMP 19 14479308267Sjmc #if !HAVE_NBTOOL_CONFIG_H 1459158fb65Schristos #define OPT_CHROOT 20 14679308267Sjmc #endif 147ca541391Schristos 148ca541391Schristos /* 1498b35abe2Sjtc * Format specific routine table - MUST BE IN SORTED ORDER BY NAME 1508b35abe2Sjtc * (see pax.h for description of each function) 1518b35abe2Sjtc * 1528b35abe2Sjtc * name, blksz, hdsz, udev, hlk, blkagn, inhead, id, st_read, 1538b35abe2Sjtc * read, end_read, st_write, write, end_write, trail, 154d6bc453dSchristos * subtrail, rd_data, wr_data, options 1558b35abe2Sjtc */ 1568b35abe2Sjtc 1578b35abe2Sjtc FSUB fsub[] = { 158d7df71baSchristos #ifndef NO_CPIO 1598b35abe2Sjtc /* 0: OLD BINARY CPIO */ 160f3cd6022Schristos { "bcpio", 5120, sizeof(HD_BCPIO), 1, 0, 0, 1, bcpio_id, cpio_strd, 161f3cd6022Schristos bcpio_rd, bcpio_endrd, cpio_stwr, bcpio_wr, cpio_endwr, NULL, 162f3cd6022Schristos cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt }, 1638b35abe2Sjtc 1648b35abe2Sjtc /* 1: OLD OCTAL CHARACTER CPIO */ 165f3cd6022Schristos { "cpio", 5120, sizeof(HD_CPIO), 1, 0, 0, 1, cpio_id, cpio_strd, 166f3cd6022Schristos cpio_rd, cpio_endrd, cpio_stwr, cpio_wr, cpio_endwr, NULL, 167f3cd6022Schristos cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt }, 1688b35abe2Sjtc 1698b35abe2Sjtc /* 2: SVR4 HEX CPIO */ 170f3cd6022Schristos { "sv4cpio", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, vcpio_id, cpio_strd, 171f3cd6022Schristos vcpio_rd, vcpio_endrd, cpio_stwr, vcpio_wr, cpio_endwr, NULL, 172f3cd6022Schristos cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt }, 1738b35abe2Sjtc 1748b35abe2Sjtc /* 3: SVR4 HEX CPIO WITH CRC */ 175f3cd6022Schristos { "sv4crc", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd, 176f3cd6022Schristos vcpio_rd, vcpio_endrd, crc_stwr, vcpio_wr, cpio_endwr, NULL, 177f3cd6022Schristos cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt }, 178d7df71baSchristos #endif 1798b35abe2Sjtc /* 4: OLD TAR */ 180f3cd6022Schristos { "tar", 10240, BLKMULT, 0, 1, BLKMULT, 0, tar_id, no_op, 1818b35abe2Sjtc tar_rd, tar_endrd, no_op, tar_wr, tar_endwr, tar_trail, 182f3cd6022Schristos NULL, rd_wrfile, wr_rdfile, tar_opt }, 1838b35abe2Sjtc 1848b35abe2Sjtc /* 5: POSIX USTAR */ 185f3cd6022Schristos { "ustar", 10240, BLKMULT, 0, 1, BLKMULT, 0, ustar_id, ustar_strd, 1868b35abe2Sjtc ustar_rd, tar_endrd, ustar_stwr, ustar_wr, tar_endwr, tar_trail, 187f3cd6022Schristos NULL, rd_wrfile, wr_rdfile, bad_opt } 1888b35abe2Sjtc }; 189d7df71baSchristos #ifndef NO_CPIO 19051fc9487Smrg #define F_BCPIO 0 /* old binary cpio format */ 19151fc9487Smrg #define F_CPIO 1 /* old octal character cpio format */ 19251fc9487Smrg #define F_SV4CPIO 2 /* SVR4 hex cpio format */ 19351fc9487Smrg #define F_SV4CRC 3 /* SVR4 hex with crc cpio format */ 1944aa7016dStv #define F_TAR 4 /* old V7 UNIX tar format */ 19551fc9487Smrg #define F_USTAR 5 /* ustar format */ 196d7df71baSchristos #else 197d7df71baSchristos #define F_TAR 0 /* old V7 UNIX tar format */ 198d7df71baSchristos #define F_USTAR 1 /* ustar format */ 199d7df71baSchristos #endif 20051fc9487Smrg #define DEFLT F_USTAR /* default write format from list above */ 2018b35abe2Sjtc 2028b35abe2Sjtc /* 2038b35abe2Sjtc * ford is the archive search order used by get_arc() to determine what kind 2048b35abe2Sjtc * of archive we are dealing with. This helps to properly id archive formats 2058b35abe2Sjtc * some formats may be subsets of others.... 2068b35abe2Sjtc */ 207d7df71baSchristos int ford[] = {F_USTAR, F_TAR, 208d7df71baSchristos #ifndef NO_CPIO 209d7df71baSchristos F_SV4CRC, F_SV4CPIO, F_CPIO, F_BCPIO, 210d7df71baSchristos #endif 211d7df71baSchristos -1}; 2128b35abe2Sjtc 2138b35abe2Sjtc /* 21408df9f4cSchristos * filename record separator 21508df9f4cSchristos */ 21608df9f4cSchristos int sep = '\n'; 21708df9f4cSchristos 21808df9f4cSchristos /* 219c5d25686Schristos * Do we have -C anywhere? 220c5d25686Schristos */ 221c5d25686Schristos int havechd = 0; 222c5d25686Schristos 223c5d25686Schristos /* 2248b35abe2Sjtc * options() 2258b35abe2Sjtc * figure out if we are pax, tar or cpio. Call the appropriate options 2268b35abe2Sjtc * parser 2278b35abe2Sjtc */ 2288b35abe2Sjtc 2298b35abe2Sjtc void 23048250187Stls options(int argc, char **argv) 2318b35abe2Sjtc { 2328b35abe2Sjtc 2338b35abe2Sjtc /* 2348b35abe2Sjtc * Are we acting like pax, tar or cpio (based on argv[0]) 2358b35abe2Sjtc */ 2368b35abe2Sjtc if ((argv0 = strrchr(argv[0], '/')) != NULL) 2378b35abe2Sjtc argv0++; 2388b35abe2Sjtc else 2398b35abe2Sjtc argv0 = argv[0]; 2408b35abe2Sjtc 241a1484a99Schristos if (strstr(argv0, NM_TAR)) { 242a1484a99Schristos argv0 = NM_TAR; 2433c0fae1fSgrant tar_options(argc, argv); 244d7df71baSchristos #ifndef NO_CPIO 245a1484a99Schristos } else if (strstr(argv0, NM_CPIO)) { 246a1484a99Schristos argv0 = NM_CPIO; 2473c0fae1fSgrant cpio_options(argc, argv); 248d7df71baSchristos #endif 249a1484a99Schristos } else { 2508b35abe2Sjtc argv0 = NM_PAX; 2513c0fae1fSgrant pax_options(argc, argv); 252ee9e50eaSmycroft } 2538b35abe2Sjtc } 2548b35abe2Sjtc 255ca541391Schristos struct option pax_longopts[] = { 256ca541391Schristos { "insecure", no_argument, 0, 257ca541391Schristos OPT_INSECURE }, 258169f6258Schristos { "force-local", no_argument, 0, 259169f6258Schristos OPT_FORCE_LOCAL }, 2600ac48c3bSchristos { "use-compress-program", required_argument, 0, 2610ac48c3bSchristos OPT_USE_COMPRESS_PROGRAM }, 262dbf8eeeeSchristos { "xz", no_argument, 0, 263dbf8eeeeSchristos OPT_XZ }, 264e028f49dSchristos { "gnu", no_argument, 0, 265e028f49dSchristos OPT_GNU }, 266015658bfSchristos { "timestamp", required_argument, 0, 267015658bfSchristos OPT_TIMESTAMP }, 268573bd5e5Schristos { 0, 0, 0, 269573bd5e5Schristos 0 }, 270ca541391Schristos }; 271ca541391Schristos 2728b35abe2Sjtc /* 2738b35abe2Sjtc * pax_options() 2748b35abe2Sjtc * look at the user specified flags. set globals as required and check if 2758b35abe2Sjtc * the user specified a legal set of flags. If not, complain and exit 2768b35abe2Sjtc */ 2778b35abe2Sjtc 2788b35abe2Sjtc static void 27948250187Stls pax_options(int argc, char **argv) 2808b35abe2Sjtc { 28148250187Stls int c; 282990d25a9Slukem size_t i; 283702d1ca5Schristos u_int64_t flg = 0; 284702d1ca5Schristos u_int64_t bflg = 0; 28548250187Stls char *pt; 2868b35abe2Sjtc FSUB tmp; 2878b35abe2Sjtc 2888b35abe2Sjtc /* 2898b35abe2Sjtc * process option flags 2908b35abe2Sjtc */ 291ca541391Schristos while ((c = getopt_long(argc, argv, 292702d1ca5Schristos "0ab:cdf:ijklno:p:rs:tuvwx:zAB:DE:G:HLMN:OPT:U:VXYZ", 293ca541391Schristos pax_longopts, NULL)) != -1) { 2948b35abe2Sjtc switch (c) { 29508df9f4cSchristos case '0': 29608df9f4cSchristos sep = '\0'; 29708df9f4cSchristos break; 2988b35abe2Sjtc case 'a': 2998b35abe2Sjtc /* 3008b35abe2Sjtc * append 3018b35abe2Sjtc */ 3028b35abe2Sjtc flg |= AF; 3038b35abe2Sjtc break; 3048b35abe2Sjtc case 'b': 3058b35abe2Sjtc /* 3068b35abe2Sjtc * specify blocksize 3078b35abe2Sjtc */ 3088b35abe2Sjtc flg |= BF; 3098b35abe2Sjtc if ((wrblksz = (int)str_offt(optarg)) <= 0) { 310f3cd6022Schristos tty_warn(1, "Invalid block size %s", optarg); 3118b35abe2Sjtc pax_usage(); 3128b35abe2Sjtc } 3138b35abe2Sjtc break; 3148b35abe2Sjtc case 'c': 3158b35abe2Sjtc /* 3168b35abe2Sjtc * inverse match on patterns 3178b35abe2Sjtc */ 3188b35abe2Sjtc cflag = 1; 3198b35abe2Sjtc flg |= CF; 3208b35abe2Sjtc break; 3218b35abe2Sjtc case 'd': 3228b35abe2Sjtc /* 3238b35abe2Sjtc * match only dir on extract, not the subtree at dir 3248b35abe2Sjtc */ 3258b35abe2Sjtc dflag = 1; 3268b35abe2Sjtc flg |= DF; 3278b35abe2Sjtc break; 3288b35abe2Sjtc case 'f': 3298b35abe2Sjtc /* 3308b35abe2Sjtc * filename where the archive is stored 3318b35abe2Sjtc */ 3328b35abe2Sjtc arcname = optarg; 3338b35abe2Sjtc flg |= FF; 3348b35abe2Sjtc break; 3358b35abe2Sjtc case 'i': 3368b35abe2Sjtc /* 3378b35abe2Sjtc * interactive file rename 3388b35abe2Sjtc */ 3398b35abe2Sjtc iflag = 1; 3408b35abe2Sjtc flg |= IF; 3418b35abe2Sjtc break; 342a0dbdefcSchristos case 'j': 343a0dbdefcSchristos /* 344a0dbdefcSchristos * pass through bzip2 345a0dbdefcSchristos */ 346a0dbdefcSchristos gzip_program = BZIP2_CMD; 347a0dbdefcSchristos break; 3488b35abe2Sjtc case 'k': 3498b35abe2Sjtc /* 3508b35abe2Sjtc * do not clobber files that exist 3518b35abe2Sjtc */ 3528b35abe2Sjtc kflag = 1; 3538b35abe2Sjtc flg |= KF; 3548b35abe2Sjtc break; 3558b35abe2Sjtc case 'l': 3568b35abe2Sjtc /* 3578b35abe2Sjtc * try to link src to dest with copy (-rw) 3588b35abe2Sjtc */ 3598b35abe2Sjtc lflag = 1; 3608b35abe2Sjtc flg |= LF; 3618b35abe2Sjtc break; 3628b35abe2Sjtc case 'n': 3638b35abe2Sjtc /* 3648b35abe2Sjtc * select first match for a pattern only 3658b35abe2Sjtc */ 3668b35abe2Sjtc nflag = 1; 3678b35abe2Sjtc flg |= NF; 3688b35abe2Sjtc break; 3698b35abe2Sjtc case 'o': 3708b35abe2Sjtc /* 3718b35abe2Sjtc * pass format specific options 3728b35abe2Sjtc */ 3738b35abe2Sjtc flg |= OF; 3748b35abe2Sjtc if (opt_add(optarg) < 0) 3758b35abe2Sjtc pax_usage(); 3768b35abe2Sjtc break; 3778b35abe2Sjtc case 'p': 3788b35abe2Sjtc /* 3798b35abe2Sjtc * specify file characteristic options 3808b35abe2Sjtc */ 3818b35abe2Sjtc for (pt = optarg; *pt != '\0'; ++pt) { 3828b35abe2Sjtc switch(*pt) { 3838b35abe2Sjtc case 'a': 3848b35abe2Sjtc /* 3858b35abe2Sjtc * do not preserve access time 3868b35abe2Sjtc */ 3878b35abe2Sjtc patime = 0; 3888b35abe2Sjtc break; 3898b35abe2Sjtc case 'e': 3908b35abe2Sjtc /* 3918b35abe2Sjtc * preserve user id, group id, file 3928b35abe2Sjtc * mode, access/modification times 393b60cafe2Smrg * and file flags. 3948b35abe2Sjtc */ 3958b35abe2Sjtc pids = 1; 3968b35abe2Sjtc pmode = 1; 3978b35abe2Sjtc patime = 1; 3988b35abe2Sjtc pmtime = 1; 399b60cafe2Smrg pfflags = 1; 400b60cafe2Smrg break; 401e9e9dbbdSmycroft #if 0 402b60cafe2Smrg case 'f': 403b60cafe2Smrg /* 404b60cafe2Smrg * do not preserve file flags 405b60cafe2Smrg */ 406b60cafe2Smrg pfflags = 0; 4078b35abe2Sjtc break; 408e9e9dbbdSmycroft #endif 4098b35abe2Sjtc case 'm': 4108b35abe2Sjtc /* 4118b35abe2Sjtc * do not preserve modification time 4128b35abe2Sjtc */ 4138b35abe2Sjtc pmtime = 0; 4148b35abe2Sjtc break; 4158b35abe2Sjtc case 'o': 4168b35abe2Sjtc /* 4178b35abe2Sjtc * preserve uid/gid 4188b35abe2Sjtc */ 4198b35abe2Sjtc pids = 1; 4208b35abe2Sjtc break; 4218b35abe2Sjtc case 'p': 4228b35abe2Sjtc /* 423ae5120dcSlukem * preserve file mode bits 4248b35abe2Sjtc */ 4258b35abe2Sjtc pmode = 1; 4268b35abe2Sjtc break; 4278b35abe2Sjtc default: 4280c612021Schristos tty_warn(1, "Invalid -p string: %c", 4290c612021Schristos *pt); 4308b35abe2Sjtc pax_usage(); 4318b35abe2Sjtc break; 4328b35abe2Sjtc } 4338b35abe2Sjtc } 4348b35abe2Sjtc flg |= PF; 4358b35abe2Sjtc break; 4368b35abe2Sjtc case 'r': 4378b35abe2Sjtc /* 4388b35abe2Sjtc * read the archive 4398b35abe2Sjtc */ 4408b35abe2Sjtc flg |= RF; 4418b35abe2Sjtc break; 4428b35abe2Sjtc case 's': 4438b35abe2Sjtc /* 4448b35abe2Sjtc * file name substitution name pattern 4458b35abe2Sjtc */ 4468b35abe2Sjtc if (rep_add(optarg) < 0) { 4478b35abe2Sjtc pax_usage(); 4488b35abe2Sjtc break; 4498b35abe2Sjtc } 4508b35abe2Sjtc flg |= SF; 4518b35abe2Sjtc break; 4528b35abe2Sjtc case 't': 4538b35abe2Sjtc /* 4548b35abe2Sjtc * preserve access time on filesystem nodes we read 4558b35abe2Sjtc */ 4568b35abe2Sjtc tflag = 1; 4578b35abe2Sjtc flg |= TF; 4588b35abe2Sjtc break; 4598b35abe2Sjtc case 'u': 4608b35abe2Sjtc /* 4618b35abe2Sjtc * ignore those older files 4628b35abe2Sjtc */ 4638b35abe2Sjtc uflag = 1; 4648b35abe2Sjtc flg |= UF; 4658b35abe2Sjtc break; 4668b35abe2Sjtc case 'v': 4678b35abe2Sjtc /* 4688b35abe2Sjtc * verbose operation mode 4698b35abe2Sjtc */ 4708b35abe2Sjtc vflag = 1; 4718b35abe2Sjtc flg |= VF; 4728b35abe2Sjtc break; 4738b35abe2Sjtc case 'w': 4748b35abe2Sjtc /* 4758b35abe2Sjtc * write an archive 4768b35abe2Sjtc */ 4778b35abe2Sjtc flg |= WF; 4788b35abe2Sjtc break; 4798b35abe2Sjtc case 'x': 4808b35abe2Sjtc /* 4818b35abe2Sjtc * specify an archive format on write 4828b35abe2Sjtc */ 4838b35abe2Sjtc tmp.name = optarg; 484f3cd6022Schristos frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub, 485f3cd6022Schristos sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt); 486f3cd6022Schristos if (frmt != NULL) { 4878b35abe2Sjtc flg |= XF; 4888b35abe2Sjtc break; 4898b35abe2Sjtc } 490f3cd6022Schristos tty_warn(1, "Unknown -x format: %s", optarg); 4918b35abe2Sjtc (void)fputs("pax: Known -x formats are:", stderr); 4928b35abe2Sjtc for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i) 4938b35abe2Sjtc (void)fprintf(stderr, " %s", fsub[i].name); 4948b35abe2Sjtc (void)fputs("\n\n", stderr); 4958b35abe2Sjtc pax_usage(); 4968b35abe2Sjtc break; 4977f64ea03Smrg case 'z': 4987f64ea03Smrg /* 4997f64ea03Smrg * use gzip. Non standard option. 5007f64ea03Smrg */ 5017f64ea03Smrg gzip_program = GZIP_CMD; 5027f64ea03Smrg break; 5031fbe6b7eStron case 'A': 5041fbe6b7eStron Aflag = 1; 5051fbe6b7eStron flg |= CAF; 5061fbe6b7eStron break; 5078b35abe2Sjtc case 'B': 5088b35abe2Sjtc /* 5098b35abe2Sjtc * non-standard option on number of bytes written on a 5108b35abe2Sjtc * single archive volume. 5118b35abe2Sjtc */ 5128b35abe2Sjtc if ((wrlimit = str_offt(optarg)) <= 0) { 513f3cd6022Schristos tty_warn(1, "Invalid write limit %s", optarg); 5148b35abe2Sjtc pax_usage(); 5158b35abe2Sjtc } 5168b35abe2Sjtc if (wrlimit % BLKMULT) { 517f3cd6022Schristos tty_warn(1, 518f3cd6022Schristos "Write limit is not a %d byte multiple", 5198b35abe2Sjtc BLKMULT); 5208b35abe2Sjtc pax_usage(); 5218b35abe2Sjtc } 5228b35abe2Sjtc flg |= CBF; 5238b35abe2Sjtc break; 5248b35abe2Sjtc case 'D': 5258b35abe2Sjtc /* 5268b35abe2Sjtc * On extraction check file inode change time before the 5278b35abe2Sjtc * modification of the file name. Non standard option. 5288b35abe2Sjtc */ 5298b35abe2Sjtc Dflag = 1; 5308b35abe2Sjtc flg |= CDF; 5318b35abe2Sjtc break; 5328b35abe2Sjtc case 'E': 5338b35abe2Sjtc /* 5348b35abe2Sjtc * non-standard limit on read faults 5358b35abe2Sjtc * 0 indicates stop after first error, values 5365820cbfaSchristos * indicate a limit, "none" try forever 5378b35abe2Sjtc */ 5388b35abe2Sjtc flg |= CEF; 5395820cbfaSchristos if (strcmp(none, optarg) == 0) 5408b35abe2Sjtc maxflt = -1; 5418b35abe2Sjtc else if ((maxflt = atoi(optarg)) < 0) { 542f3cd6022Schristos tty_warn(1, 543f3cd6022Schristos "Error count value must be positive"); 5448b35abe2Sjtc pax_usage(); 5458b35abe2Sjtc } 5468b35abe2Sjtc break; 5478b35abe2Sjtc case 'G': 5488b35abe2Sjtc /* 5498b35abe2Sjtc * non-standard option for selecting files within an 5508b35abe2Sjtc * archive by group (gid or name) 5518b35abe2Sjtc */ 5528b35abe2Sjtc if (grp_add(optarg) < 0) { 5538b35abe2Sjtc pax_usage(); 5548b35abe2Sjtc break; 5558b35abe2Sjtc } 5568b35abe2Sjtc flg |= CGF; 5578b35abe2Sjtc break; 5588b35abe2Sjtc case 'H': 5598b35abe2Sjtc /* 5608b35abe2Sjtc * follow command line symlinks only 5618b35abe2Sjtc */ 5628b35abe2Sjtc Hflag = 1; 5638b35abe2Sjtc flg |= CHF; 5648b35abe2Sjtc break; 5658b35abe2Sjtc case 'L': 5668b35abe2Sjtc /* 5678b35abe2Sjtc * follow symlinks 5688b35abe2Sjtc */ 5698b35abe2Sjtc Lflag = 1; 5708b35abe2Sjtc flg |= CLF; 5718b35abe2Sjtc break; 5726ee4925cSlukem #ifdef SMALL 5736ee4925cSlukem case 'M': 5746ee4925cSlukem case 'N': 5756ee4925cSlukem tty_warn(1, "Support for -%c is not compiled in", c); 5766ee4925cSlukem exit(1); 5776ee4925cSlukem #else /* !SMALL */ 57855026d54Slukem case 'M': 57955026d54Slukem /* 58055026d54Slukem * Treat list of filenames on stdin as an 58155026d54Slukem * mtree(8) specfile. Non standard option. 58255026d54Slukem */ 58355026d54Slukem Mflag = 1; 58455026d54Slukem flg |= CMF; 58555026d54Slukem break; 586ae5120dcSlukem case 'N': 587ae5120dcSlukem /* 588ae5120dcSlukem * Use alternative directory for user db lookups. 589ae5120dcSlukem */ 5901a63c49aSlukem if (!setup_getid(optarg)) { 5911a63c49aSlukem tty_warn(1, 5921a63c49aSlukem "Unable to use user and group databases in `%s'", 5931a63c49aSlukem optarg); 594ae5120dcSlukem pax_usage(); 5951a63c49aSlukem } 596ae5120dcSlukem break; 5976ee4925cSlukem #endif /* !SMALL */ 598d0666190Sthorpej case 'O': 599d0666190Sthorpej /* 600d0666190Sthorpej * Force one volume. Non standard option. 601d0666190Sthorpej */ 602d0666190Sthorpej force_one_volume = 1; 603d0666190Sthorpej break; 6048b35abe2Sjtc case 'P': 6058b35abe2Sjtc /* 6068b35abe2Sjtc * do NOT follow symlinks (default) 6078b35abe2Sjtc */ 6088b35abe2Sjtc Lflag = 0; 6098b35abe2Sjtc flg |= CPF; 6108b35abe2Sjtc break; 6118b35abe2Sjtc case 'T': 6128b35abe2Sjtc /* 6138b35abe2Sjtc * non-standard option for selecting files within an 6148b35abe2Sjtc * archive by modification time range (lower,upper) 6158b35abe2Sjtc */ 6168b35abe2Sjtc if (trng_add(optarg) < 0) { 6178b35abe2Sjtc pax_usage(); 6188b35abe2Sjtc break; 6198b35abe2Sjtc } 6208b35abe2Sjtc flg |= CTF; 6218b35abe2Sjtc break; 6228b35abe2Sjtc case 'U': 6238b35abe2Sjtc /* 6248b35abe2Sjtc * non-standard option for selecting files within an 6258b35abe2Sjtc * archive by user (uid or name) 6268b35abe2Sjtc */ 6278b35abe2Sjtc if (usr_add(optarg) < 0) { 6288b35abe2Sjtc pax_usage(); 6298b35abe2Sjtc break; 6308b35abe2Sjtc } 6318b35abe2Sjtc flg |= CUF; 6328b35abe2Sjtc break; 633702d1ca5Schristos case 'V': 634702d1ca5Schristos /* 635702d1ca5Schristos * somewhat verbose operation mode (no listing) 636702d1ca5Schristos */ 637702d1ca5Schristos Vflag = 1; 638702d1ca5Schristos flg |= VSF; 639702d1ca5Schristos break; 6408b35abe2Sjtc case 'X': 6418b35abe2Sjtc /* 6428b35abe2Sjtc * do not pass over mount points in the file system 6438b35abe2Sjtc */ 6448b35abe2Sjtc Xflag = 1; 6458b35abe2Sjtc flg |= CXF; 6468b35abe2Sjtc break; 6478b35abe2Sjtc case 'Y': 6488b35abe2Sjtc /* 6498b35abe2Sjtc * On extraction check file inode change time after the 6508b35abe2Sjtc * modification of the file name. Non standard option. 6518b35abe2Sjtc */ 6528b35abe2Sjtc Yflag = 1; 6538b35abe2Sjtc flg |= CYF; 6548b35abe2Sjtc break; 6558b35abe2Sjtc case 'Z': 6568b35abe2Sjtc /* 6578b35abe2Sjtc * On extraction check modification time after the 6588b35abe2Sjtc * modification of the file name. Non standard option. 6598b35abe2Sjtc */ 6608b35abe2Sjtc Zflag = 1; 6618b35abe2Sjtc flg |= CZF; 6628b35abe2Sjtc break; 663ca541391Schristos case OPT_INSECURE: 664ca541391Schristos secure = 0; 665ca541391Schristos break; 666169f6258Schristos case OPT_FORCE_LOCAL: 66769536355Senami forcelocal = 1; 668169f6258Schristos break; 6690ac48c3bSchristos case OPT_USE_COMPRESS_PROGRAM: 6700ac48c3bSchristos gzip_program = optarg; 6710ac48c3bSchristos break; 672dbf8eeeeSchristos case OPT_XZ: 673dbf8eeeeSchristos gzip_program = XZ_CMD; 674dbf8eeeeSchristos break; 675e028f49dSchristos case OPT_GNU: 676e028f49dSchristos is_gnutar = 1; 677e028f49dSchristos break; 678015658bfSchristos #ifndef SMALL 679015658bfSchristos case OPT_TIMESTAMP: 680015658bfSchristos if (set_tstamp(optarg, &tst) == -1) { 681015658bfSchristos tty_warn(1, "Invalid timestamp `%s'", optarg); 682015658bfSchristos tar_usage(); 683015658bfSchristos } 684015658bfSchristos break; 685015658bfSchristos #endif 6868b35abe2Sjtc case '?': 6878b35abe2Sjtc default: 6888b35abe2Sjtc pax_usage(); 6898b35abe2Sjtc break; 6908b35abe2Sjtc } 6918b35abe2Sjtc } 6928b35abe2Sjtc 6938b35abe2Sjtc /* 6948b35abe2Sjtc * figure out the operation mode of pax read,write,extract,copy,append 6958b35abe2Sjtc * or list. check that we have not been given a bogus set of flags 6968b35abe2Sjtc * for the operation mode. 6978b35abe2Sjtc */ 6988b35abe2Sjtc if (ISLIST(flg)) { 6998b35abe2Sjtc act = LIST; 7000c612021Schristos listf = stdout; 7018b35abe2Sjtc bflg = flg & BDLIST; 7028b35abe2Sjtc } else if (ISEXTRACT(flg)) { 7038b35abe2Sjtc act = EXTRACT; 7048b35abe2Sjtc bflg = flg & BDEXTR; 7058b35abe2Sjtc } else if (ISARCHIVE(flg)) { 7068b35abe2Sjtc act = ARCHIVE; 7078b35abe2Sjtc bflg = flg & BDARCH; 7088b35abe2Sjtc } else if (ISAPPND(flg)) { 7098b35abe2Sjtc act = APPND; 7108b35abe2Sjtc bflg = flg & BDARCH; 7118b35abe2Sjtc } else if (ISCOPY(flg)) { 7128b35abe2Sjtc act = COPY; 7138b35abe2Sjtc bflg = flg & BDCOPY; 7148b35abe2Sjtc } else 7158b35abe2Sjtc pax_usage(); 7168b35abe2Sjtc if (bflg) { 7178b35abe2Sjtc printflg(flg); 7188b35abe2Sjtc pax_usage(); 7198b35abe2Sjtc } 7208b35abe2Sjtc 7218b35abe2Sjtc /* 7228b35abe2Sjtc * if we are writing (ARCHIVE) we use the default format if the user 7238b35abe2Sjtc * did not specify a format. when we write during an APPEND, we will 7248b35abe2Sjtc * adopt the format of the existing archive if none was supplied. 7258b35abe2Sjtc */ 7268b35abe2Sjtc if (!(flg & XF) && (act == ARCHIVE)) 7278b35abe2Sjtc frmt = &(fsub[DEFLT]); 7288b35abe2Sjtc 7298b35abe2Sjtc /* 7308b35abe2Sjtc * process the args as they are interpreted by the operation mode 7318b35abe2Sjtc */ 7328b35abe2Sjtc switch (act) { 7338b35abe2Sjtc case LIST: 7348b35abe2Sjtc case EXTRACT: 7358b35abe2Sjtc for (; optind < argc; optind++) 736c1bd5c17Sdholland if (pat_add(argv[optind], NULL, 0) < 0) 7378b35abe2Sjtc pax_usage(); 7388b35abe2Sjtc break; 7398b35abe2Sjtc case COPY: 7408b35abe2Sjtc if (optind >= argc) { 741f3cd6022Schristos tty_warn(0, "Destination directory was not supplied"); 7428b35abe2Sjtc pax_usage(); 7438b35abe2Sjtc } 744a9a7ae57Smrg --argc; 745a9a7ae57Smrg dirptr = argv[argc]; 7460c612021Schristos if (mkpath(dirptr) < 0) 74792982112Schristos exit(1); 7488b35abe2Sjtc /* FALLTHROUGH */ 7498b35abe2Sjtc case ARCHIVE: 7508b35abe2Sjtc case APPND: 7518b35abe2Sjtc for (; optind < argc; optind++) 752e413a4ffSis if (ftree_add(argv[optind], 0) < 0) 7538b35abe2Sjtc pax_usage(); 7548b35abe2Sjtc /* 7558b35abe2Sjtc * no read errors allowed on updates/append operation! 7568b35abe2Sjtc */ 7578b35abe2Sjtc maxflt = 0; 7588b35abe2Sjtc break; 7598b35abe2Sjtc } 7608b35abe2Sjtc } 7618b35abe2Sjtc 7628b35abe2Sjtc 7638b35abe2Sjtc /* 7648b35abe2Sjtc * tar_options() 7658b35abe2Sjtc * look at the user specified flags. set globals as required and check if 7668b35abe2Sjtc * the user specified a legal set of flags. If not, complain and exit 7678b35abe2Sjtc */ 7688b35abe2Sjtc 7694120b8a4Sthorpej struct option tar_longopts[] = { 7704120b8a4Sthorpej { "block-size", required_argument, 0, 'b' }, 771e04df3a3Swiz { "bunzip2", no_argument, 0, 'j' }, 772e04df3a3Swiz { "bzip2", no_argument, 0, 'j' }, 7734120b8a4Sthorpej { "create", no_argument, 0, 'c' }, /* F */ 7744120b8a4Sthorpej /* -e -- no corresponding long option */ 7754120b8a4Sthorpej { "file", required_argument, 0, 'f' }, 7764120b8a4Sthorpej { "dereference", no_argument, 0, 'h' }, 777c8921f64Schristos { "keep-old-files", no_argument, 0, 'k' }, 7784120b8a4Sthorpej { "one-file-system", no_argument, 0, 'l' }, 7794120b8a4Sthorpej { "modification-time", no_argument, 0, 'm' }, 7804120b8a4Sthorpej { "old-archive", no_argument, 0, 'o' }, 7814120b8a4Sthorpej { "portability", no_argument, 0, 'o' }, 7824120b8a4Sthorpej { "same-permissions", no_argument, 0, 'p' }, 7834120b8a4Sthorpej { "preserve-permissions", no_argument, 0, 'p' }, 7844120b8a4Sthorpej { "preserve", no_argument, 0, 'p' }, 785675306ebSchristos { "fast-read", no_argument, 0, 'q' }, 7864120b8a4Sthorpej { "append", no_argument, 0, 'r' }, /* F */ 7874120b8a4Sthorpej { "update", no_argument, 0, 'u' }, /* F */ 7884120b8a4Sthorpej { "list", no_argument, 0, 't' }, /* F */ 7894120b8a4Sthorpej { "verbose", no_argument, 0, 'v' }, 7904120b8a4Sthorpej { "interactive", no_argument, 0, 'w' }, 7914120b8a4Sthorpej { "confirmation", no_argument, 0, 'w' }, 7924120b8a4Sthorpej { "extract", no_argument, 0, 'x' }, /* F */ 7934120b8a4Sthorpej { "get", no_argument, 0, 'x' }, /* F */ 7944120b8a4Sthorpej { "gzip", no_argument, 0, 'z' }, 7954120b8a4Sthorpej { "gunzip", no_argument, 0, 'z' }, 7964120b8a4Sthorpej { "read-full-blocks", no_argument, 0, 'B' }, 7974120b8a4Sthorpej { "directory", required_argument, 0, 'C' }, 79823c362a5Schristos { "xz", no_argument, 0, 'J' }, 7991301238aSsimonb { "to-stdout", no_argument, 0, 'O' }, 8004120b8a4Sthorpej { "absolute-paths", no_argument, 0, 'P' }, 8018317fe12Sdsl { "sparse", no_argument, 0, 'S' }, 8020c612021Schristos { "files-from", required_argument, 0, 'T' }, 803702d1ca5Schristos { "summary", no_argument, 0, 'V' }, 804702d1ca5Schristos { "stats", no_argument, 0, 'V' }, 8054120b8a4Sthorpej { "exclude-from", required_argument, 0, 'X' }, 8064120b8a4Sthorpej { "compress", no_argument, 0, 'Z' }, 8074120b8a4Sthorpej { "uncompress", no_argument, 0, 'Z' }, 808f70dfaafSchristos { "strict", no_argument, 0, 809f70dfaafSchristos OPT_STRICT }, 810547c8911Sthorpej { "atime-preserve", no_argument, 0, 811547c8911Sthorpej OPT_ATIME_PRESERVE }, 8124120b8a4Sthorpej { "unlink", no_argument, 0, 8134120b8a4Sthorpej OPT_UNLINK }, 814a3a7c5ccSthorpej { "use-compress-program", required_argument, 0, 815a3a7c5ccSthorpej OPT_USE_COMPRESS_PROGRAM }, 8160c612021Schristos { "force-local", no_argument, 0, 8170c612021Schristos OPT_FORCE_LOCAL }, 818ca541391Schristos { "insecure", no_argument, 0, 819ca541391Schristos OPT_INSECURE }, 820c3510d14Smrg { "exclude", required_argument, 0, 821c3510d14Smrg OPT_EXCLUDE }, 8228dcba567Schristos { "no-recursion", no_argument, 0, 8238dcba567Schristos OPT_NORECURSE }, 82479308267Sjmc #if !HAVE_NBTOOL_CONFIG_H 8258317fe12Sdsl { "chroot", no_argument, 0, 8268317fe12Sdsl OPT_CHROOT }, 82779308267Sjmc #endif 8289158fb65Schristos { "timestamp", required_argument, 0, 8299158fb65Schristos OPT_TIMESTAMP }, 8304120b8a4Sthorpej #if 0 /* Not implemented */ 8314120b8a4Sthorpej { "catenate", no_argument, 0, 'A' }, /* F */ 8324120b8a4Sthorpej { "concatenate", no_argument, 0, 'A' }, /* F */ 8334120b8a4Sthorpej { "diff", no_argument, 0, 'd' }, /* F */ 8344120b8a4Sthorpej { "compare", no_argument, 0, 'd' }, /* F */ 8354120b8a4Sthorpej { "checkpoint", no_argument, 0, 8364120b8a4Sthorpej OPT_CHECKPOINT }, 837547c8911Sthorpej { "help", no_argument, 0, 8384120b8a4Sthorpej OPT_HELP }, 8394120b8a4Sthorpej { "info-script", required_argument, 0, 'F' }, 8404120b8a4Sthorpej { "new-volume-script", required_argument, 0, 'F' }, 8414120b8a4Sthorpej { "incremental", no_argument, 0, 'G' }, 8424120b8a4Sthorpej { "listed-incremental", required_argument, 0, 'g' }, 8434120b8a4Sthorpej { "ignore-zeros", no_argument, 0, 'i' }, 8444120b8a4Sthorpej { "ignore-failed-read", no_argument, 0, 8454120b8a4Sthorpej OPT_IGNORE_FAILED_READ }, 8464120b8a4Sthorpej { "starting-file", no_argument, 0, 'K' }, 847169f6258Schristos { "tape-length", required_argument, 0, 'L' }, 8484120b8a4Sthorpej { "multi-volume", no_argument, 0, 'M' }, 8494120b8a4Sthorpej { "after-date", required_argument, 0, 'N' }, 8504120b8a4Sthorpej { "newer", required_argument, 0, 'N' }, 8514120b8a4Sthorpej { "record-number", no_argument, 0, 'R' }, 8524120b8a4Sthorpej { "remove-files", no_argument, 0, 8534120b8a4Sthorpej OPT_REMOVE_FILES }, 8544120b8a4Sthorpej { "same-order", no_argument, 0, 's' }, 8554120b8a4Sthorpej { "preserve-order", no_argument, 0, 's' }, 8564120b8a4Sthorpej { "null", no_argument, 0, 8574120b8a4Sthorpej OPT_NULL }, 8584120b8a4Sthorpej { "totals", no_argument, 0, 8594120b8a4Sthorpej OPT_TOTALS }, 860702d1ca5Schristos { "volume-name", required_argument, 0, 'V' }, /* XXX */ 861702d1ca5Schristos { "label", required_argument, 0, 'V' }, /* XXX */ 8624120b8a4Sthorpej { "version", no_argument, 0, 8634120b8a4Sthorpej OPT_VERSION }, 8644120b8a4Sthorpej { "verify", no_argument, 0, 'W' }, 8654120b8a4Sthorpej { "block-compress", no_argument, 0, 8664120b8a4Sthorpej OPT_BLOCK_COMPRESS }, 8674120b8a4Sthorpej #endif 8684120b8a4Sthorpej { 0, 0, 0, 0 }, 8694120b8a4Sthorpej }; 8704120b8a4Sthorpej 8718b35abe2Sjtc static void 872e977a745Scbiere tar_set_action(int op) 873e977a745Scbiere { 874e977a745Scbiere if (act != ERROR && act != op) 875e977a745Scbiere tar_usage(); 876e977a745Scbiere act = op; 877e977a745Scbiere } 878e977a745Scbiere 879e977a745Scbiere static void 88048250187Stls tar_options(int argc, char **argv) 8818b35abe2Sjtc { 88248250187Stls int c; 8838b35abe2Sjtc int fstdin = 0; 8840c612021Schristos int Oflag = 0; 8850c612021Schristos int nincfiles = 0; 8860c612021Schristos int incfiles_max = 0; 8870c612021Schristos struct incfile { 8880c612021Schristos char *file; 8890c612021Schristos char *dir; 8900c612021Schristos }; 8910c612021Schristos struct incfile *incfiles = NULL; 8920c612021Schristos 8930c612021Schristos /* 8940c612021Schristos * Set default values. 8950c612021Schristos */ 8960c612021Schristos rmleadslash = 1; 897f830cb18Schristos is_gnutar = 1; 8988b35abe2Sjtc 8998b35abe2Sjtc /* 9008b35abe2Sjtc * process option flags 9018b35abe2Sjtc */ 9020c612021Schristos while ((c = getoldopt(argc, argv, 90323c362a5Schristos "+b:cef:hjklmopqrs:tuvwxzBC:HI:JOPST:X:Z014578", 9044120b8a4Sthorpej tar_longopts, NULL)) 905332c413bSlukem != -1) { 906eb066159Sjtc switch(c) { 9078b35abe2Sjtc case 'b': 9088b35abe2Sjtc /* 9090c612021Schristos * specify blocksize in 512-byte blocks 9108b35abe2Sjtc */ 911eb066159Sjtc if ((wrblksz = (int)str_offt(optarg)) <= 0) { 912f3cd6022Schristos tty_warn(1, "Invalid block size %s", optarg); 9138b35abe2Sjtc tar_usage(); 9148b35abe2Sjtc } 9150c612021Schristos wrblksz *= 512; /* XXX - check for int oflow */ 9168b35abe2Sjtc break; 9178b35abe2Sjtc case 'c': 9188b35abe2Sjtc /* 9198b35abe2Sjtc * create an archive 9208b35abe2Sjtc */ 921e977a745Scbiere tar_set_action(ARCHIVE); 9228b35abe2Sjtc break; 9238b35abe2Sjtc case 'e': 9248b35abe2Sjtc /* 9258b35abe2Sjtc * stop after first error 9268b35abe2Sjtc */ 9278b35abe2Sjtc maxflt = 0; 9288b35abe2Sjtc break; 9298b35abe2Sjtc case 'f': 9308b35abe2Sjtc /* 9318b35abe2Sjtc * filename where the archive is stored 9328b35abe2Sjtc */ 933eb066159Sjtc if ((optarg[0] == '-') && (optarg[1]== '\0')) { 9348b35abe2Sjtc /* 9358b35abe2Sjtc * treat a - as stdin 9368b35abe2Sjtc */ 937eb066159Sjtc fstdin = 1; 9380c612021Schristos arcname = NULL; 9398b35abe2Sjtc break; 9408b35abe2Sjtc } 9418b35abe2Sjtc fstdin = 0; 942eb066159Sjtc arcname = optarg; 9438b35abe2Sjtc break; 94462724fe7Stron case 'h': 94562724fe7Stron /* 946a86cae99Schristos * follow symlinks 94762724fe7Stron */ 948a86cae99Schristos Lflag = 1; 94962724fe7Stron break; 950e04df3a3Swiz case 'j': 951e04df3a3Swiz /* 952e04df3a3Swiz * pass through bzip2. not a standard option 953e04df3a3Swiz */ 954e04df3a3Swiz gzip_program = BZIP2_CMD; 955e04df3a3Swiz break; 956c8921f64Schristos case 'k': 957c8921f64Schristos /* 958c8921f64Schristos * do not clobber files that exist 959c8921f64Schristos */ 960c8921f64Schristos kflag = 1; 961c8921f64Schristos break; 96251fc9487Smrg case 'l': 96351fc9487Smrg /* 96451fc9487Smrg * do not pass over mount points in the file system 96551fc9487Smrg */ 96651fc9487Smrg Xflag = 1; 96751fc9487Smrg break; 9688b35abe2Sjtc case 'm': 9698b35abe2Sjtc /* 9708b35abe2Sjtc * do not preserve modification time 9718b35abe2Sjtc */ 9728b35abe2Sjtc pmtime = 0; 9738b35abe2Sjtc break; 9748b35abe2Sjtc case 'o': 9754aa7016dStv /* 9764aa7016dStv * This option does several things based on whether 9774aa7016dStv * this is a create or extract operation. 9784aa7016dStv */ 9794aa7016dStv if (act == ARCHIVE) { 980f70dfaafSchristos /* GNU tar: write V7 format archives. */ 981f70dfaafSchristos Oflag = 1; 9824aa7016dStv /* 4.2BSD: don't add directory entries. */ 9834aa7016dStv if (opt_add("write_opt=nodir") < 0) 9844aa7016dStv tar_usage(); 9854aa7016dStv 9864aa7016dStv } else { 9874aa7016dStv /* SUS: don't preserve owner/group. */ 9884aa7016dStv pids = 0; 9894aa7016dStv nopids = 1; 9904aa7016dStv } 9918b35abe2Sjtc break; 9928b35abe2Sjtc case 'p': 9938b35abe2Sjtc /* 9948b35abe2Sjtc * preserve user id, group id, file 9958b35abe2Sjtc * mode, access/modification times 9968b35abe2Sjtc */ 9974aa7016dStv if (!nopids) 9988b35abe2Sjtc pids = 1; 9998b35abe2Sjtc pmode = 1; 10008b35abe2Sjtc patime = 1; 10018b35abe2Sjtc pmtime = 1; 10028b35abe2Sjtc break; 10030c612021Schristos case 'q': 10040c612021Schristos /* 10050c612021Schristos * select first match for a pattern only 10060c612021Schristos */ 10070c612021Schristos nflag = 1; 10080c612021Schristos break; 10098b35abe2Sjtc case 'r': 10108b35abe2Sjtc case 'u': 10118b35abe2Sjtc /* 10128b35abe2Sjtc * append to the archive 10138b35abe2Sjtc */ 1014e977a745Scbiere tar_set_action(APPND); 10158b35abe2Sjtc break; 10160c612021Schristos case 's': 10170c612021Schristos /* 10180c612021Schristos * file name substitution name pattern 10190c612021Schristos */ 10200c612021Schristos if (rep_add(optarg) < 0) { 10210c612021Schristos tar_usage(); 10220c612021Schristos break; 10230c612021Schristos } 10240c612021Schristos break; 10258b35abe2Sjtc case 't': 10268b35abe2Sjtc /* 10278b35abe2Sjtc * list contents of the tape 10288b35abe2Sjtc */ 1029e977a745Scbiere tar_set_action(LIST); 10308b35abe2Sjtc break; 10318b35abe2Sjtc case 'v': 10328b35abe2Sjtc /* 10338b35abe2Sjtc * verbose operation mode 10348b35abe2Sjtc */ 10358b35abe2Sjtc vflag = 1; 10368b35abe2Sjtc break; 10378b35abe2Sjtc case 'w': 10388b35abe2Sjtc /* 10398b35abe2Sjtc * interactive file rename 10408b35abe2Sjtc */ 10418b35abe2Sjtc iflag = 1; 10428b35abe2Sjtc break; 10438b35abe2Sjtc case 'x': 10448b35abe2Sjtc /* 10450c612021Schristos * extract an archive, preserving mode, 10460c612021Schristos * and mtime if possible. 10478b35abe2Sjtc */ 1048e977a745Scbiere tar_set_action(EXTRACT); 10490c612021Schristos pmtime = 1; 10508b35abe2Sjtc break; 10517f64ea03Smrg case 'z': 10527f64ea03Smrg /* 10537f64ea03Smrg * use gzip. Non standard option. 10547f64ea03Smrg */ 10557f64ea03Smrg gzip_program = GZIP_CMD; 10567f64ea03Smrg break; 10578b35abe2Sjtc case 'B': 10588b35abe2Sjtc /* 10598b35abe2Sjtc * Nothing to do here, this is pax default 10608b35abe2Sjtc */ 10618b35abe2Sjtc break; 10620c612021Schristos case 'C': 1063c5d25686Schristos havechd++; 10640c612021Schristos chdname = optarg; 10650c612021Schristos break; 10660c612021Schristos case 'H': 10670c612021Schristos /* 10680c612021Schristos * follow command line symlinks only 10690c612021Schristos */ 10700c612021Schristos Hflag = 1; 10710c612021Schristos break; 10720c612021Schristos case 'I': 10730c612021Schristos case 'T': 10740c612021Schristos if (++nincfiles > incfiles_max) { 10750c612021Schristos incfiles_max = nincfiles + 3; 10760c612021Schristos incfiles = realloc(incfiles, 10770c612021Schristos sizeof(*incfiles) * incfiles_max); 10780c612021Schristos if (incfiles == NULL) { 10790c612021Schristos tty_warn(0, "Unable to allocate space " 10800c612021Schristos "for option list"); 10810c612021Schristos exit(1); 10820c612021Schristos } 10830c612021Schristos } 10840c612021Schristos incfiles[nincfiles - 1].file = optarg; 10850c612021Schristos incfiles[nincfiles - 1].dir = chdname; 10860c612021Schristos break; 108723c362a5Schristos case 'J': 108823c362a5Schristos gzip_program = XZ_CMD; 108923c362a5Schristos break; 109023c362a5Schristos case 'O': 109123c362a5Schristos Oflag = 1; 109223c362a5Schristos break; 10938b35abe2Sjtc case 'P': 10940c612021Schristos /* 10950c612021Schristos * do not remove leading '/' from pathnames 10960c612021Schristos */ 10970c612021Schristos rmleadslash = 0; 109862724fe7Stron Aflag = 1; 10998b35abe2Sjtc break; 110060cf1998Schristos case 'S': 110160cf1998Schristos /* do nothing; we already generate sparse files */ 110260cf1998Schristos break; 1103702d1ca5Schristos case 'V': 1104702d1ca5Schristos /* 1105702d1ca5Schristos * semi-verbose operation mode (no listing) 1106702d1ca5Schristos */ 1107702d1ca5Schristos Vflag = 1; 1108702d1ca5Schristos break; 11098b35abe2Sjtc case 'X': 11108b35abe2Sjtc /* 1111ce6b1876Smrg * GNU tar compat: exclude the files listed in optarg 11128b35abe2Sjtc */ 1113ce6b1876Smrg if (tar_gnutar_X_compat(optarg) != 0) 1114ce6b1876Smrg tar_usage(); 11158b35abe2Sjtc break; 11167f64ea03Smrg case 'Z': 11177f64ea03Smrg /* 11187f64ea03Smrg * use compress. 11197f64ea03Smrg */ 11207f64ea03Smrg gzip_program = COMPRESS_CMD; 11217f64ea03Smrg break; 11228b35abe2Sjtc case '0': 11238b35abe2Sjtc arcname = DEV_0; 11248b35abe2Sjtc break; 11258b35abe2Sjtc case '1': 11268b35abe2Sjtc arcname = DEV_1; 11278b35abe2Sjtc break; 11288b35abe2Sjtc case '4': 11298b35abe2Sjtc arcname = DEV_4; 11308b35abe2Sjtc break; 11318b35abe2Sjtc case '5': 11328b35abe2Sjtc arcname = DEV_5; 11338b35abe2Sjtc break; 11348b35abe2Sjtc case '7': 11358b35abe2Sjtc arcname = DEV_7; 11368b35abe2Sjtc break; 11378b35abe2Sjtc case '8': 11388b35abe2Sjtc arcname = DEV_8; 11398b35abe2Sjtc break; 1140547c8911Sthorpej case OPT_ATIME_PRESERVE: 1141547c8911Sthorpej patime = 1; 1142547c8911Sthorpej break; 11434120b8a4Sthorpej case OPT_UNLINK: 11444120b8a4Sthorpej /* Just ignore -- we always unlink first. */ 11454120b8a4Sthorpej break; 1146a3a7c5ccSthorpej case OPT_USE_COMPRESS_PROGRAM: 1147a3a7c5ccSthorpej gzip_program = optarg; 1148a3a7c5ccSthorpej break; 11490c612021Schristos case OPT_FORCE_LOCAL: 11500c612021Schristos forcelocal = 1; 11510c612021Schristos break; 1152ca541391Schristos case OPT_INSECURE: 1153ca541391Schristos secure = 0; 1154ca541391Schristos break; 1155f70dfaafSchristos case OPT_STRICT: 1156f70dfaafSchristos /* disable gnu extensions */ 1157f70dfaafSchristos is_gnutar = 0; 1158f70dfaafSchristos break; 1159c3510d14Smrg case OPT_EXCLUDE: 1160c3510d14Smrg if (tar_gnutar_minus_minus_exclude(optarg) != 0) 1161c3510d14Smrg tar_usage(); 1162c3510d14Smrg break; 11638dcba567Schristos case OPT_NORECURSE: 11648dcba567Schristos dflag = 1; 11658dcba567Schristos break; 116679308267Sjmc #if !HAVE_NBTOOL_CONFIG_H 11678317fe12Sdsl case OPT_CHROOT: 11688317fe12Sdsl do_chroot = 1; 11698317fe12Sdsl break; 117079308267Sjmc #endif 11719158fb65Schristos #ifndef SMALL 11729158fb65Schristos case OPT_TIMESTAMP: 11739158fb65Schristos if (set_tstamp(optarg, &tst) == -1) { 11749158fb65Schristos tty_warn(1, "Invalid timestamp `%s'", optarg); 11759158fb65Schristos tar_usage(); 11769158fb65Schristos } 11779158fb65Schristos break; 11789158fb65Schristos #endif 11798b35abe2Sjtc default: 11808b35abe2Sjtc tar_usage(); 11818b35abe2Sjtc break; 11828b35abe2Sjtc } 11838b35abe2Sjtc } 1184eb066159Sjtc argc -= optind; 1185eb066159Sjtc argv += optind; 11868b35abe2Sjtc 1187af892f93Ssoren /* Tar requires an action. */ 1188860d26c6Schristos if (act == ERROR) 1189af892f93Ssoren tar_usage(); 1190af892f93Ssoren 11910c612021Schristos /* Traditional tar behaviour (pax uses stderr unless in list mode) */ 11920c612021Schristos if (fstdin == 1 && act == ARCHIVE) 11930c612021Schristos listf = stderr; 11940c612021Schristos else 11950c612021Schristos listf = stdout; 1196e413a4ffSis 11970c612021Schristos /* Traditional tar behaviour (pax wants to read file list from stdin) */ 11980c612021Schristos if ((act == ARCHIVE || act == APPND) && argc == 0 && nincfiles == 0) 11990c612021Schristos exit(0); 12008b35abe2Sjtc /* 1201fb3e1197Stv * if we are writing (ARCHIVE) specify tar, otherwise run like pax 12020c612021Schristos * (unless -o specified) 1203fb3e1197Stv */ 12040c612021Schristos if (act == ARCHIVE || act == APPND) 12050c612021Schristos frmt = &(fsub[Oflag ? F_TAR : F_USTAR]); 12060c612021Schristos else if (Oflag) { 12071301238aSsimonb if (act == EXTRACT) 12081301238aSsimonb to_stdout = 1; 12091301238aSsimonb else { 12101301238aSsimonb tty_warn(1, "The -O/-o options are only valid when " 12111301238aSsimonb "writing or extracting an archive"); 12121301238aSsimonb tar_usage(); 12131301238aSsimonb } 12140c612021Schristos } 1215fb3e1197Stv 1216fb3e1197Stv /* 12178b35abe2Sjtc * process the args as they are interpreted by the operation mode 12188b35abe2Sjtc */ 12198b35abe2Sjtc switch (act) { 12208b35abe2Sjtc case LIST: 1221e413a4ffSis case EXTRACT: 12220c612021Schristos default: 12230c612021Schristos { 12240c612021Schristos int sawpat = 0; 1225ff3d818dSchristos int dirisnext = 0; 1226a8846ec5Schristos char *file, *dir = NULL; 1227afde5a17Sdholland int mustfreedir = 0; 12280c612021Schristos 12290c612021Schristos while (nincfiles || *argv != NULL) { 12300c612021Schristos /* 12310c612021Schristos * If we queued up any include files, 12320c612021Schristos * pull them in now. Otherwise, check 12330c612021Schristos * for -I and -C positional flags. 12340c612021Schristos * Anything else must be a file to 12350c612021Schristos * extract. 12360c612021Schristos */ 12370c612021Schristos if (nincfiles) { 12380c612021Schristos file = incfiles->file; 12390c612021Schristos dir = incfiles->dir; 1240afde5a17Sdholland mustfreedir = 0; 12410c612021Schristos incfiles++; 12420c612021Schristos nincfiles--; 12430c612021Schristos } else if (strcmp(*argv, "-I") == 0) { 12440c612021Schristos if (*++argv == NULL) 12450c612021Schristos break; 12460c612021Schristos file = *argv++; 12470c612021Schristos dir = chdname; 1248afde5a17Sdholland mustfreedir = 0; 1249aab85a0fSlukem } else { 12500c612021Schristos file = NULL; 1251aab85a0fSlukem dir = NULL; 1252afde5a17Sdholland mustfreedir = 0; 1253aab85a0fSlukem } 12540c612021Schristos if (file != NULL) { 12550c612021Schristos FILE *fp; 12560c612021Schristos char *str; 12570c612021Schristos 12580c612021Schristos if (strcmp(file, "-") == 0) 12590c612021Schristos fp = stdin; 12600c612021Schristos else if ((fp = fopen(file, "r")) == NULL) { 12610c612021Schristos tty_warn(1, "Unable to open file '%s' for read", file); 12620c612021Schristos tar_usage(); 12630c612021Schristos } 12647027866aSroy while ((str = get_line(fp)) != NULL) { 1265ff3d818dSchristos if (dirisnext) { 1266afde5a17Sdholland if (dir && mustfreedir) 1267a8846ec5Schristos free(dir); 1268ff3d818dSchristos dir = str; 1269afde5a17Sdholland mustfreedir = 1; 1270ff3d818dSchristos dirisnext = 0; 1271ff3d818dSchristos continue; 1272ff3d818dSchristos } 1273ff3d818dSchristos if (strcmp(str, "-C") == 0) { 1274c5d25686Schristos havechd++; 1275ff3d818dSchristos dirisnext = 1; 12762ed09657Schristos free(str); 1277ff3d818dSchristos continue; 1278ff3d818dSchristos } 12794fbd9df2Schristos if (strncmp(str, "-C ", 3) == 0) { 1280c5d25686Schristos havechd++; 1281afde5a17Sdholland if (dir && mustfreedir) 1282a8846ec5Schristos free(dir); 12832ed09657Schristos dir = strdup(str + 3); 1284afde5a17Sdholland mustfreedir = 1; 12852ed09657Schristos free(str); 12864fbd9df2Schristos continue; 12874fbd9df2Schristos } 1288a992ea79Sperry if (pat_add(str, dir, NOGLOB_MTCH) < 0) 12890c612021Schristos tar_usage(); 12900c612021Schristos sawpat = 1; 12910c612021Schristos } 1292ff3d818dSchristos /* Bomb if given -C w/out a dir. */ 1293ff3d818dSchristos if (dirisnext) 1294ff3d818dSchristos tar_usage(); 1295afde5a17Sdholland if (dir && mustfreedir) 1296a8846ec5Schristos free(dir); 12970c612021Schristos if (strcmp(file, "-") != 0) 12980c612021Schristos fclose(fp); 12997027866aSroy if (get_line_error) { 13000c612021Schristos tty_warn(1, "Problem with file '%s'", file); 13010c612021Schristos tar_usage(); 13020c612021Schristos } 13030c612021Schristos } else if (strcmp(*argv, "-C") == 0) { 13040c612021Schristos if (*++argv == NULL) 13050c612021Schristos break; 13060c612021Schristos chdname = *argv++; 1307c5d25686Schristos havechd++; 1308a992ea79Sperry } else if (pat_add(*argv++, chdname, 0) < 0) 13090c612021Schristos tar_usage(); 13100c612021Schristos else 13110c612021Schristos sawpat = 1; 13120c612021Schristos } 13130c612021Schristos /* 13140c612021Schristos * if patterns were added, we are doing chdir() 13150c612021Schristos * on a file-by-file basis, else, just one 13160c612021Schristos * global chdir (if any) after opening input. 13170c612021Schristos */ 13180c612021Schristos if (sawpat > 0) 13190c612021Schristos chdname = NULL; 13200c612021Schristos } 1321e413a4ffSis break; 13228b35abe2Sjtc case ARCHIVE: 13238b35abe2Sjtc case APPND: 13240c612021Schristos if (chdname != NULL) { /* initial chdir() */ 13250c612021Schristos if (ftree_add(chdname, 1) < 0) 13260c612021Schristos tar_usage(); 13270c612021Schristos } 13280c612021Schristos 13290c612021Schristos while (nincfiles || *argv != NULL) { 13300c612021Schristos char *file, *dir; 13310c612021Schristos 13320c612021Schristos /* 13330c612021Schristos * If we queued up any include files, pull them in 13340c612021Schristos * now. Otherwise, check for -I and -C positional 13350c612021Schristos * flags. Anything else must be a file to include 13360c612021Schristos * in the archive. 13370c612021Schristos */ 13380c612021Schristos if (nincfiles) { 13390c612021Schristos file = incfiles->file; 13400c612021Schristos dir = incfiles->dir; 13410c612021Schristos incfiles++; 13420c612021Schristos nincfiles--; 13430c612021Schristos } else if (strcmp(*argv, "-I") == 0) { 13440c612021Schristos if (*++argv == NULL) 13450c612021Schristos break; 13460c612021Schristos file = *argv++; 13470c612021Schristos dir = NULL; 1348aab85a0fSlukem } else { 13490c612021Schristos file = NULL; 1350aab85a0fSlukem dir = NULL; 1351aab85a0fSlukem } 13520c612021Schristos if (file != NULL) { 13530c612021Schristos FILE *fp; 13540c612021Schristos char *str; 1355ff3d818dSchristos int dirisnext = 0; 13560c612021Schristos 13570c612021Schristos /* Set directory if needed */ 13580c612021Schristos if (dir) { 13590c612021Schristos if (ftree_add(dir, 1) < 0) 13600c612021Schristos tar_usage(); 13610c612021Schristos } 13620c612021Schristos 13630c612021Schristos if (strcmp(file, "-") == 0) 13640c612021Schristos fp = stdin; 13650c612021Schristos else if ((fp = fopen(file, "r")) == NULL) { 13660c612021Schristos tty_warn(1, "Unable to open file '%s' for read", file); 13670c612021Schristos tar_usage(); 13680c612021Schristos } 13697027866aSroy while ((str = get_line(fp)) != NULL) { 1370ff3d818dSchristos if (dirisnext) { 1371ff3d818dSchristos if (ftree_add(str, 1) < 0) 1372ff3d818dSchristos tar_usage(); 1373ff3d818dSchristos dirisnext = 0; 1374ff3d818dSchristos continue; 1375ff3d818dSchristos } 1376ff3d818dSchristos if (strcmp(str, "-C") == 0) { 1377ff3d818dSchristos dirisnext = 1; 1378ff3d818dSchristos continue; 1379ff3d818dSchristos } 13804fbd9df2Schristos if (strncmp(str, "-C ", 3) == 0) { 13814fbd9df2Schristos if (ftree_add(str + 3, 1) < 0) 13824fbd9df2Schristos tar_usage(); 13834fbd9df2Schristos continue; 13844fbd9df2Schristos } 13850c612021Schristos if (ftree_add(str, 0) < 0) 13860c612021Schristos tar_usage(); 13870c612021Schristos } 1388ff3d818dSchristos /* Bomb if given -C w/out a dir. */ 1389ff3d818dSchristos if (dirisnext) 1390ff3d818dSchristos tar_usage(); 13910c612021Schristos if (strcmp(file, "-") != 0) 13920c612021Schristos fclose(fp); 13937027866aSroy if (get_line_error) { 13940c612021Schristos tty_warn(1, "Problem with file '%s'", 13950c612021Schristos file); 13960c612021Schristos tar_usage(); 13970c612021Schristos } 13980c612021Schristos } else if (strcmp(*argv, "-C") == 0) { 13990c612021Schristos if (*++argv == NULL) 14000c612021Schristos break; 14010c612021Schristos if (ftree_add(*argv++, 1) < 0) 14020c612021Schristos tar_usage(); 14030c612021Schristos } else if (ftree_add(*argv++, 0) < 0) 14040c612021Schristos tar_usage(); 14050c612021Schristos } 14068b35abe2Sjtc /* 14078b35abe2Sjtc * no read errors allowed on updates/append operation! 14088b35abe2Sjtc */ 14098b35abe2Sjtc maxflt = 0; 14108b35abe2Sjtc break; 14118b35abe2Sjtc } 14129f61b804Splunky if (!fstdin && ((arcname == NULL) || (*arcname == '\0'))) { 14138b35abe2Sjtc arcname = getenv("TAPE"); 14140c612021Schristos if ((arcname == NULL) || (*arcname == '\0')) 14150c612021Schristos arcname = _PATH_DEFTAPE; 14168b35abe2Sjtc } 14178b35abe2Sjtc } 14188b35abe2Sjtc 14190c612021Schristos int 1420da4f7877Smatt mkpath(char *path) 14210c612021Schristos { 14220c612021Schristos char *slash; 1423b60b306eSchristos int done = 0; 14240c612021Schristos 14250c612021Schristos slash = path; 14260c612021Schristos 14270c612021Schristos while (!done) { 14280c612021Schristos slash += strspn(slash, "/"); 14290c612021Schristos slash += strcspn(slash, "/"); 14300c612021Schristos 14310c612021Schristos done = (*slash == '\0'); 14320c612021Schristos *slash = '\0'; 14330c612021Schristos 1434b60b306eSchristos if (domkdir(path, 0777) == -1) 14350743a9e8Schristos goto out; 14360c612021Schristos 14370c612021Schristos if (!done) 14380c612021Schristos *slash = '/'; 14390c612021Schristos } 14400c612021Schristos 144192982112Schristos return 0; 14420743a9e8Schristos out: 14430743a9e8Schristos /* Can't create or or not a directory */ 1444b60b306eSchristos syswarn(1, errno, "Cannot create directory `%s'", path); 14450743a9e8Schristos return -1; 14460c612021Schristos } 14470c612021Schristos 14489a9c32e1Schristos 1449d7df71baSchristos #ifndef NO_CPIO 14509a9c32e1Schristos struct option cpio_longopts[] = { 14519a9c32e1Schristos { "reset-access-time", no_argument, 0, 'a' }, 14529a9c32e1Schristos { "make-directories", no_argument, 0, 'd' }, 14539a9c32e1Schristos { "nonmatching", no_argument, 0, 'f' }, 14549a9c32e1Schristos { "extract", no_argument, 0, 'i' }, 14559a9c32e1Schristos { "link", no_argument, 0, 'l' }, 14569a9c32e1Schristos { "preserve-modification-time", no_argument, 0, 'm' }, 14579a9c32e1Schristos { "create", no_argument, 0, 'o' }, 14589a9c32e1Schristos { "pass-through", no_argument, 0, 'p' }, 14599a9c32e1Schristos { "rename", no_argument, 0, 'r' }, 14609a9c32e1Schristos { "list", no_argument, 0, 't' }, 14619a9c32e1Schristos { "unconditional", no_argument, 0, 'u' }, 14629a9c32e1Schristos { "verbose", no_argument, 0, 'v' }, 14639a9c32e1Schristos { "append", no_argument, 0, 'A' }, 14649a9c32e1Schristos { "pattern-file", required_argument, 0, 'E' }, 14659a9c32e1Schristos { "file", required_argument, 0, 'F' }, 14669a9c32e1Schristos { "force-local", no_argument, 0, 14679a9c32e1Schristos OPT_FORCE_LOCAL }, 14689a9c32e1Schristos { "format", required_argument, 0, 'H' }, 14699a9c32e1Schristos { "dereference", no_argument, 0, 'L' }, 14709a9c32e1Schristos { "swap-halfwords", no_argument, 0, 'S' }, 1471702d1ca5Schristos { "summary", no_argument, 0, 'V' }, 1472702d1ca5Schristos { "stats", no_argument, 0, 'V' }, 1473ca541391Schristos { "insecure", no_argument, 0, 1474ca541391Schristos OPT_INSECURE }, 147560cf1998Schristos { "sparse", no_argument, 0, 147660cf1998Schristos OPT_SPARSE }, 1477dbf8eeeeSchristos { "xz", no_argument, 0, 1478dbf8eeeeSchristos OPT_XZ }, 14799a9c32e1Schristos 14809a9c32e1Schristos #ifdef notyet 14819a9c32e1Schristos /* Not implemented */ 14829a9c32e1Schristos { "null", no_argument, 0, '0' }, 14839a9c32e1Schristos { "swap", no_argument, 0, 'b' }, 14849a9c32e1Schristos { "numeric-uid-gid", no_argument, 0, 'n' }, 14859a9c32e1Schristos { "swap-bytes", no_argument, 0, 's' }, 14869a9c32e1Schristos { "message", required_argument, 0, 'M' }, 14879a9c32e1Schristos { "owner", required_argument, 0 'R' }, 1488702d1ca5Schristos { "dot", no_argument, 0, 'V' }, /* xxx */ 14899a9c32e1Schristos { "block-size", required_argument, 0, 14909a9c32e1Schristos OPT_BLOCK_SIZE }, 14919a9c32e1Schristos { "no-absolute-pathnames", no_argument, 0, 14929a9c32e1Schristos OPT_NO_ABSOLUTE_PATHNAMES }, 14939a9c32e1Schristos { "no-preserve-owner", no_argument, 0, 14949a9c32e1Schristos OPT_NO_PRESERVE_OWNER }, 14959a9c32e1Schristos { "only-verify-crc", no_argument, 0, 14969a9c32e1Schristos OPT_ONLY_VERIFY_CRC }, 14979a9c32e1Schristos { "rsh-command", required_argument, 0, 14989a9c32e1Schristos OPT_RSH_COMMAND }, 14999a9c32e1Schristos { "version", no_argument, 0, 15009a9c32e1Schristos OPT_VERSION }, 15019a9c32e1Schristos #endif 15024dca8bd5Sjmc { 0, 0, 0, 0 }, 15039a9c32e1Schristos }; 15049a9c32e1Schristos 1505e977a745Scbiere static void 1506e977a745Scbiere cpio_set_action(int op) 1507e977a745Scbiere { 1508e977a745Scbiere if ((act == APPND && op == ARCHIVE) || (act == ARCHIVE && op == APPND)) 1509e977a745Scbiere act = APPND; 15102ff6888cSsjg else if (act == EXTRACT && op == LIST) 15112ff6888cSsjg act = op; 1512e977a745Scbiere else if (act != ERROR && act != op) 1513e977a745Scbiere cpio_usage(); 1514e977a745Scbiere else 1515e977a745Scbiere act = op; 1516e977a745Scbiere } 1517e977a745Scbiere 15188b35abe2Sjtc /* 15198b35abe2Sjtc * cpio_options() 15208b35abe2Sjtc * look at the user specified flags. set globals as required and check if 15218b35abe2Sjtc * the user specified a legal set of flags. If not, complain and exit 15228b35abe2Sjtc */ 15238b35abe2Sjtc 15248b35abe2Sjtc static void 152548250187Stls cpio_options(int argc, char **argv) 15268b35abe2Sjtc { 152751fc9487Smrg FSUB tmp; 1528702d1ca5Schristos u_int64_t flg = 0; 1529702d1ca5Schristos u_int64_t bflg = 0; 1530990d25a9Slukem int c; 1531990d25a9Slukem size_t i; 15320c612021Schristos FILE *fp; 15330c612021Schristos char *str; 153451fc9487Smrg 15350c612021Schristos uflag = 1; 15360c612021Schristos kflag = 1; 15370c612021Schristos pids = 1; 15380c612021Schristos pmode = 1; 15390c612021Schristos pmtime = 0; 15400c612021Schristos arcname = NULL; 15410c612021Schristos dflag = 1; 15420c612021Schristos nodirs = 1; 154351fc9487Smrg /* 154451fc9487Smrg * process option flags 154551fc9487Smrg */ 15464120b8a4Sthorpej while ((c = getoldopt(argc, argv, 1547ca541391Schristos "+abcdfiklmoprstuvzABC:E:F:H:I:LM:O:R:SVZ6", 15489a9c32e1Schristos cpio_longopts, NULL)) != -1) { 154951fc9487Smrg switch(c) { 15500c612021Schristos case 'a': 15510c612021Schristos /* 15520c612021Schristos * preserve access time on filesystem nodes we read 15530c612021Schristos */ 15540c612021Schristos tflag = 1; 15550c612021Schristos flg |= TF; 15560c612021Schristos break; 15570c612021Schristos #ifdef notyet 15580c612021Schristos case 'b': 15590c612021Schristos /* 15600c612021Schristos * swap bytes and half-words when reading data 15610c612021Schristos */ 15620c612021Schristos break; 15630c612021Schristos #endif 15640c612021Schristos case 'c': 15650c612021Schristos /* 15660c612021Schristos * ASCII cpio header 15670c612021Schristos */ 15680c612021Schristos frmt = &fsub[F_SV4CPIO]; 15690c612021Schristos break; 15700c612021Schristos case 'd': 15710c612021Schristos /* 15720c612021Schristos * create directories as needed 15730c612021Schristos * pax does this by default .. 15740c612021Schristos */ 15750c612021Schristos nodirs = 0; 15760c612021Schristos break; 15770c612021Schristos case 'f': 15780c612021Schristos /* 15790c612021Schristos * inverse match on patterns 15800c612021Schristos */ 15810c612021Schristos cflag = 1; 15820c612021Schristos flg |= CF; 15830c612021Schristos break; 15840c612021Schristos case 'i': 15850c612021Schristos /* 15860c612021Schristos * read the archive 15870c612021Schristos */ 1588e977a745Scbiere cpio_set_action(EXTRACT); 15890c612021Schristos flg |= RF; 15900c612021Schristos break; 15910c612021Schristos #ifdef notyet 15920c612021Schristos case 'k': 15930c612021Schristos break; 15940c612021Schristos #endif 15950c612021Schristos case 'l': 15960c612021Schristos /* 15970c612021Schristos * try to link src to dest with copy (-rw) 15980c612021Schristos */ 15990c612021Schristos lflag = 1; 16000c612021Schristos flg |= LF; 16010c612021Schristos break; 16020c612021Schristos case 'm': 16030c612021Schristos /* 16040c612021Schristos * preserve mtime 16050c612021Schristos */ 16060c612021Schristos flg |= PF; 16070c612021Schristos pmtime = 1; 16080c612021Schristos break; 16090c612021Schristos case 'o': 16100c612021Schristos /* 16110c612021Schristos * write an archive 16120c612021Schristos */ 1613e977a745Scbiere cpio_set_action(ARCHIVE); 16140c612021Schristos frmt = &(fsub[F_SV4CRC]); 16150c612021Schristos flg |= WF; 16160c612021Schristos break; 16170c612021Schristos case 'p': 16180c612021Schristos /* 16190c612021Schristos * cpio -p is like pax -rw 16200c612021Schristos */ 1621e977a745Scbiere cpio_set_action(COPY); 16220c612021Schristos flg |= RF | WF; 16230c612021Schristos break; 16240c612021Schristos case 'r': 16250c612021Schristos /* 16260c612021Schristos * interactive file rename 16270c612021Schristos */ 16280c612021Schristos iflag = 1; 16290c612021Schristos flg |= IF; 16300c612021Schristos break; 16310c612021Schristos #ifdef notyet 16320c612021Schristos case 's': 16330c612021Schristos /* 16340c612021Schristos * swap bytes after reading data 16350c612021Schristos */ 16360c612021Schristos break; 16370c612021Schristos #endif 16380c612021Schristos case 't': 16390c612021Schristos /* 16400c612021Schristos * list contents of archive 16410c612021Schristos */ 1642e977a745Scbiere cpio_set_action(LIST); 16430c612021Schristos listf = stdout; 1644addf1a0fStron flg &= ~RF; 16450c612021Schristos break; 16460c612021Schristos case 'u': 16470c612021Schristos /* 16480c612021Schristos * don't ignore those older files 16490c612021Schristos */ 16500c612021Schristos uflag = 0; 16510c612021Schristos kflag = 0; 16520c612021Schristos flg |= UF; 16530c612021Schristos break; 16540c612021Schristos case 'v': 16550c612021Schristos /* 16560c612021Schristos * verbose operation mode 16570c612021Schristos */ 16580c612021Schristos vflag = 1; 16590c612021Schristos flg |= VF; 16600c612021Schristos break; 16610c612021Schristos case 'z': 16620c612021Schristos /* 16630c612021Schristos * use gzip. Non standard option. 16640c612021Schristos */ 16650c612021Schristos gzip_program = GZIP_CMD; 16660c612021Schristos break; 166751fc9487Smrg case 'A': 166851fc9487Smrg /* 166951fc9487Smrg * append to an archive 167051fc9487Smrg */ 1671e977a745Scbiere cpio_set_action(APPND); 167251fc9487Smrg flg |= AF; 167351fc9487Smrg break; 167451fc9487Smrg case 'B': 167551fc9487Smrg /* 167651fc9487Smrg * set blocksize to 5120 167751fc9487Smrg */ 167851fc9487Smrg blksz = 5120; 167951fc9487Smrg break; 168051fc9487Smrg case 'C': 168151fc9487Smrg /* 168251fc9487Smrg * specify blocksize 168351fc9487Smrg */ 168451fc9487Smrg if ((blksz = (int)str_offt(optarg)) <= 0) { 168551fc9487Smrg tty_warn(1, "Invalid block size %s", optarg); 16867b4c88f8Skristerw cpio_usage(); 16878b35abe2Sjtc } 168851fc9487Smrg break; 168951fc9487Smrg case 'E': 16900c612021Schristos /* 16910c612021Schristos * file with patterns to extract or list 16920c612021Schristos */ 16930c612021Schristos if ((fp = fopen(optarg, "r")) == NULL) { 16940c612021Schristos tty_warn(1, "Unable to open file '%s' for read", 16950c612021Schristos optarg); 16960c612021Schristos cpio_usage(); 16970c612021Schristos } 16987027866aSroy while ((str = get_line(fp)) != NULL) { 1699a992ea79Sperry pat_add(str, NULL, 0); 17000c612021Schristos } 17010c612021Schristos fclose(fp); 17027027866aSroy if (get_line_error) { 17030c612021Schristos tty_warn(1, "Problem with file '%s'", optarg); 17040c612021Schristos cpio_usage(); 17050c612021Schristos } 170651fc9487Smrg break; 170751fc9487Smrg case 'H': 170851fc9487Smrg /* 170951fc9487Smrg * specify an archive format on write 171051fc9487Smrg */ 171151fc9487Smrg tmp.name = optarg; 171251fc9487Smrg frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub, 171351fc9487Smrg sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt); 171451fc9487Smrg if (frmt != NULL) { 171551fc9487Smrg flg |= XF; 171651fc9487Smrg break; 171751fc9487Smrg } 171851fc9487Smrg tty_warn(1, "Unknown -H format: %s", optarg); 171951fc9487Smrg (void)fputs("cpio: Known -H formats are:", stderr); 172051fc9487Smrg for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i) 172151fc9487Smrg (void)fprintf(stderr, " %s", fsub[i].name); 172251fc9487Smrg (void)fputs("\n\n", stderr); 17237b4c88f8Skristerw cpio_usage(); 172451fc9487Smrg break; 172569536355Senami case 'F': 172651fc9487Smrg case 'I': 172751fc9487Smrg case 'O': 172851fc9487Smrg /* 172951fc9487Smrg * filename where the archive is stored 173051fc9487Smrg */ 173151fc9487Smrg if ((optarg[0] == '-') && (optarg[1]== '\0')) { 173251fc9487Smrg /* 173351fc9487Smrg * treat a - as stdin 173451fc9487Smrg */ 17350c612021Schristos arcname = NULL; 173651fc9487Smrg break; 173751fc9487Smrg } 173851fc9487Smrg arcname = optarg; 173951fc9487Smrg break; 174051fc9487Smrg case 'L': 174151fc9487Smrg /* 174251fc9487Smrg * follow symlinks 174351fc9487Smrg */ 174451fc9487Smrg Lflag = 1; 174551fc9487Smrg flg |= CLF; 174651fc9487Smrg break; 174751fc9487Smrg #ifdef notyet 174851fc9487Smrg case 'M': 174951fc9487Smrg arg = optarg; 175051fc9487Smrg break; 175151fc9487Smrg case 'R': 175251fc9487Smrg arg = optarg; 175351fc9487Smrg break; 175451fc9487Smrg #endif 175551fc9487Smrg case 'S': 17560c612021Schristos /* 17570c612021Schristos * swap halfwords after reading data 17580c612021Schristos */ 175951fc9487Smrg cpio_swp_head = 1; 176051fc9487Smrg break; 176151fc9487Smrg #ifdef notyet 1762702d1ca5Schristos case 'V': /* print a '.' for each file processed */ 176351fc9487Smrg break; 176451fc9487Smrg #endif 1765702d1ca5Schristos case 'V': 1766702d1ca5Schristos /* 1767702d1ca5Schristos * semi-verbose operation mode (no listing) 1768702d1ca5Schristos */ 1769702d1ca5Schristos Vflag = 1; 1770702d1ca5Schristos flg |= VF; 1771702d1ca5Schristos break; 17720c612021Schristos case 'Z': 177351fc9487Smrg /* 17740c612021Schristos * use compress. Non standard option. 177551fc9487Smrg */ 17760c612021Schristos gzip_program = COMPRESS_CMD; 177751fc9487Smrg break; 17780c612021Schristos case '6': 177951fc9487Smrg /* 17800c612021Schristos * process Version 6 cpio format 178151fc9487Smrg */ 17820c612021Schristos frmt = &(fsub[F_BCPIO]); 178369536355Senami break; 17849a9c32e1Schristos case OPT_FORCE_LOCAL: 17859a9c32e1Schristos forcelocal = 1; 17869a9c32e1Schristos break; 1787ca541391Schristos case OPT_INSECURE: 1788ca541391Schristos secure = 0; 1789ca541391Schristos break; 179060cf1998Schristos case OPT_SPARSE: 179160cf1998Schristos /* do nothing; we already generate sparse files */ 179260cf1998Schristos break; 1793dbf8eeeeSchristos case OPT_XZ: 1794dbf8eeeeSchristos gzip_program = XZ_CMD; 1795dbf8eeeeSchristos break; 179651fc9487Smrg default: 179751fc9487Smrg cpio_usage(); 179851fc9487Smrg break; 179951fc9487Smrg } 180051fc9487Smrg } 180151fc9487Smrg 180251fc9487Smrg /* 180351fc9487Smrg * figure out the operation mode of cpio. check that we have not been 180451fc9487Smrg * given a bogus set of flags for the operation mode. 180551fc9487Smrg */ 180651fc9487Smrg if (ISLIST(flg)) { 180751fc9487Smrg act = LIST; 180851fc9487Smrg bflg = flg & BDLIST; 180951fc9487Smrg } else if (ISEXTRACT(flg)) { 181051fc9487Smrg act = EXTRACT; 181151fc9487Smrg bflg = flg & BDEXTR; 181251fc9487Smrg } else if (ISARCHIVE(flg)) { 181351fc9487Smrg act = ARCHIVE; 181451fc9487Smrg bflg = flg & BDARCH; 181551fc9487Smrg } else if (ISAPPND(flg)) { 181651fc9487Smrg act = APPND; 181751fc9487Smrg bflg = flg & BDARCH; 181851fc9487Smrg } else if (ISCOPY(flg)) { 181951fc9487Smrg act = COPY; 182051fc9487Smrg bflg = flg & BDCOPY; 182151fc9487Smrg } else 182251fc9487Smrg cpio_usage(); 182351fc9487Smrg if (bflg) { 182451fc9487Smrg cpio_usage(); 182551fc9487Smrg } 182651fc9487Smrg 182751fc9487Smrg /* 182851fc9487Smrg * if we are writing (ARCHIVE) we use the default format if the user 182951fc9487Smrg * did not specify a format. when we write during an APPEND, we will 183051fc9487Smrg * adopt the format of the existing archive if none was supplied. 183151fc9487Smrg */ 183251fc9487Smrg if (!(flg & XF) && (act == ARCHIVE)) 183351fc9487Smrg frmt = &(fsub[F_BCPIO]); 183451fc9487Smrg 183551fc9487Smrg /* 183651fc9487Smrg * process the args as they are interpreted by the operation mode 183751fc9487Smrg */ 183851fc9487Smrg switch (act) { 183951fc9487Smrg case LIST: 184051fc9487Smrg case EXTRACT: 184151fc9487Smrg for (; optind < argc; optind++) 1842a992ea79Sperry if (pat_add(argv[optind], NULL, 0) < 0) 184351fc9487Smrg cpio_usage(); 184451fc9487Smrg break; 184551fc9487Smrg case COPY: 184651fc9487Smrg if (optind >= argc) { 184751fc9487Smrg tty_warn(0, "Destination directory was not supplied"); 184851fc9487Smrg cpio_usage(); 184951fc9487Smrg } 185051fc9487Smrg --argc; 185151fc9487Smrg dirptr = argv[argc]; 185251fc9487Smrg /* FALLTHROUGH */ 185351fc9487Smrg case ARCHIVE: 185451fc9487Smrg case APPND: 18550c612021Schristos if (argc != optind) { 185651fc9487Smrg for (; optind < argc; optind++) 1857e413a4ffSis if (ftree_add(argv[optind], 0) < 0) 185851fc9487Smrg cpio_usage(); 18590c612021Schristos break; 18600c612021Schristos } 186151fc9487Smrg /* 186251fc9487Smrg * no read errors allowed on updates/append operation! 186351fc9487Smrg */ 186451fc9487Smrg maxflt = 0; 18657027866aSroy while ((str = get_line(stdin)) != NULL) { 1866cf964629Sfvdl ftree_add(str, 0); 18670c612021Schristos } 18687027866aSroy if (get_line_error) { 18690c612021Schristos tty_warn(1, "Problem while reading stdin"); 18700c612021Schristos cpio_usage(); 18710c612021Schristos } 18720c612021Schristos break; 18730c612021Schristos default: 18740c612021Schristos cpio_usage(); 187551fc9487Smrg break; 187651fc9487Smrg } 187751fc9487Smrg } 1878d7df71baSchristos #endif 18798b35abe2Sjtc 18808b35abe2Sjtc /* 18818b35abe2Sjtc * printflg() 18828b35abe2Sjtc * print out those invalid flag sets found to the user 18838b35abe2Sjtc */ 18848b35abe2Sjtc 18858b35abe2Sjtc static void 18868b35abe2Sjtc printflg(unsigned int flg) 18878b35abe2Sjtc { 18888b35abe2Sjtc int nxt; 18898b35abe2Sjtc 18908b35abe2Sjtc (void)fprintf(stderr,"%s: Invalid combination of options:", argv0); 1891f3cd6022Schristos while ((nxt = ffs(flg)) != 0) { 1892b9173dc4Sjmmv flg &= ~(1 << (nxt - 1)); 1893b9173dc4Sjmmv (void)fprintf(stderr, " -%c", flgch[nxt - 1]); 18948b35abe2Sjtc } 18958b35abe2Sjtc (void)putc('\n', stderr); 18968b35abe2Sjtc } 18978b35abe2Sjtc 18988b35abe2Sjtc /* 18998b35abe2Sjtc * c_frmt() 19008b35abe2Sjtc * comparison routine used by bsearch to find the format specified 19018b35abe2Sjtc * by the user 19028b35abe2Sjtc */ 19038b35abe2Sjtc 19048b35abe2Sjtc static int 19058b35abe2Sjtc c_frmt(const void *a, const void *b) 19068b35abe2Sjtc { 1907cdec4ac1Sdsl return strcmp(((const FSUB *)a)->name, ((const FSUB *)b)->name); 19088b35abe2Sjtc } 19098b35abe2Sjtc 19108b35abe2Sjtc /* 19118b35abe2Sjtc * opt_next() 19128b35abe2Sjtc * called by format specific options routines to get each format specific 19138b35abe2Sjtc * flag and value specified with -o 19148b35abe2Sjtc * Return: 19158b35abe2Sjtc * pointer to next OPLIST entry or NULL (end of list). 19168b35abe2Sjtc */ 19178b35abe2Sjtc 19188b35abe2Sjtc OPLIST * 19198b35abe2Sjtc opt_next(void) 19208b35abe2Sjtc { 19218b35abe2Sjtc OPLIST *opt; 19228b35abe2Sjtc 19238b35abe2Sjtc if ((opt = ophead) != NULL) 19248b35abe2Sjtc ophead = ophead->fow; 1925cdec4ac1Sdsl return opt; 19268b35abe2Sjtc } 19278b35abe2Sjtc 19288b35abe2Sjtc /* 19298b35abe2Sjtc * bad_opt() 19308b35abe2Sjtc * generic routine used to complain about a format specific options 19318b35abe2Sjtc * when the format does not support options. 19328b35abe2Sjtc */ 19338b35abe2Sjtc 19348b35abe2Sjtc int 19358b35abe2Sjtc bad_opt(void) 19368b35abe2Sjtc { 193748250187Stls OPLIST *opt; 19388b35abe2Sjtc 19398b35abe2Sjtc if (ophead == NULL) 1940cdec4ac1Sdsl return 0; 19418b35abe2Sjtc /* 19428b35abe2Sjtc * print all we were given 19438b35abe2Sjtc */ 1944f70dfaafSchristos tty_warn(1," These format options are not supported for %s", 1945f70dfaafSchristos frmt->name); 19468b35abe2Sjtc while ((opt = opt_next()) != NULL) 19478b35abe2Sjtc (void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value); 1948f70dfaafSchristos if (strcmp(NM_TAR, argv0) == 0) 1949f70dfaafSchristos tar_usage(); 1950d7df71baSchristos #ifndef NO_CPIO 1951f70dfaafSchristos else if (strcmp(NM_CPIO, argv0) == 0) 1952f70dfaafSchristos cpio_usage(); 1953d7df71baSchristos #endif 1954f70dfaafSchristos else 19558b35abe2Sjtc pax_usage(); 1956cdec4ac1Sdsl return 0; 19578b35abe2Sjtc } 19588b35abe2Sjtc 19598b35abe2Sjtc /* 19608b35abe2Sjtc * opt_add() 19618b35abe2Sjtc * breaks the value supplied to -o into a option name and value. options 19628b35abe2Sjtc * are given to -o in the form -o name-value,name=value 1963f8adf56dSitohy * multiple -o may be specified. 19648b35abe2Sjtc * Return: 19658b35abe2Sjtc * 0 if format in name=value format, -1 if -o is passed junk 19668b35abe2Sjtc */ 19678b35abe2Sjtc 19688b35abe2Sjtc int 19694aa7016dStv opt_add(const char *str) 19708b35abe2Sjtc { 197148250187Stls OPLIST *opt; 197248250187Stls char *frpt; 197348250187Stls char *pt; 197448250187Stls char *endpt; 19750c612021Schristos char *dstr; 19768b35abe2Sjtc 19778b35abe2Sjtc if ((str == NULL) || (*str == '\0')) { 1978f3cd6022Schristos tty_warn(0, "Invalid option name"); 1979cdec4ac1Sdsl return -1; 19808b35abe2Sjtc } 19810c612021Schristos if ((dstr = strdup(str)) == NULL) { 19820c612021Schristos tty_warn(0, "Unable to allocate space for option list"); 1983cdec4ac1Sdsl return -1; 19840c612021Schristos } 19850c612021Schristos frpt = endpt = dstr; 19868b35abe2Sjtc 19878b35abe2Sjtc /* 19888b35abe2Sjtc * break into name and values pieces and stuff each one into a 19898b35abe2Sjtc * OPLIST structure. When we know the format, the format specific 19908b35abe2Sjtc * option function will go through this list 19918b35abe2Sjtc */ 19928b35abe2Sjtc while ((frpt != NULL) && (*frpt != '\0')) { 19938b35abe2Sjtc if ((endpt = strchr(frpt, ',')) != NULL) 19948b35abe2Sjtc *endpt = '\0'; 19958b35abe2Sjtc if ((pt = strchr(frpt, '=')) == NULL) { 1996f3cd6022Schristos tty_warn(0, "Invalid options format"); 19970c612021Schristos free(dstr); 1998cdec4ac1Sdsl return -1; 19998b35abe2Sjtc } 20008b35abe2Sjtc if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) { 2001f3cd6022Schristos tty_warn(0, "Unable to allocate space for option list"); 20020c612021Schristos free(dstr); 2003cdec4ac1Sdsl return -1; 20048b35abe2Sjtc } 20058b35abe2Sjtc *pt++ = '\0'; 20068b35abe2Sjtc opt->name = frpt; 20078b35abe2Sjtc opt->value = pt; 20088b35abe2Sjtc opt->fow = NULL; 20098b35abe2Sjtc if (endpt != NULL) 20108b35abe2Sjtc frpt = endpt + 1; 20118b35abe2Sjtc else 20128b35abe2Sjtc frpt = NULL; 20138b35abe2Sjtc if (ophead == NULL) { 20148b35abe2Sjtc optail = ophead = opt; 20158b35abe2Sjtc continue; 20168b35abe2Sjtc } 20178b35abe2Sjtc optail->fow = opt; 20188b35abe2Sjtc optail = opt; 20198b35abe2Sjtc } 2020cdec4ac1Sdsl return 0; 20218b35abe2Sjtc } 20228b35abe2Sjtc 20238b35abe2Sjtc /* 20248b35abe2Sjtc * str_offt() 20258b35abe2Sjtc * Convert an expression of the following forms to an off_t > 0. 20268b35abe2Sjtc * 1) A positive decimal number. 20278b35abe2Sjtc * 2) A positive decimal number followed by a b (mult by 512). 20288b35abe2Sjtc * 3) A positive decimal number followed by a k (mult by 1024). 20298b35abe2Sjtc * 4) A positive decimal number followed by a m (mult by 512). 20308b35abe2Sjtc * 5) A positive decimal number followed by a w (mult by sizeof int) 20318b35abe2Sjtc * 6) Two or more positive decimal numbers (with/without k,b or w). 2032a9356936Swiz * separated by x (also * for backwards compatibility), specifying 20338b35abe2Sjtc * the product of the indicated values. 20348b35abe2Sjtc * Return: 20358b35abe2Sjtc * 0 for an error, a positive value o.w. 20368b35abe2Sjtc */ 20378b35abe2Sjtc 20388b35abe2Sjtc static off_t 20398b35abe2Sjtc str_offt(char *val) 20408b35abe2Sjtc { 20418b35abe2Sjtc char *expr; 20428b35abe2Sjtc off_t num, t; 20438b35abe2Sjtc 2044c1bd745cSlukem num = STRTOOFFT(val, &expr, 0); 2045c1bd745cSlukem if ((num == OFFT_MAX) || (num <= 0) || (expr == val)) 2046cdec4ac1Sdsl return 0; 20478b35abe2Sjtc 20488b35abe2Sjtc switch(*expr) { 20498b35abe2Sjtc case 'b': 20508b35abe2Sjtc t = num; 20518b35abe2Sjtc num *= 512; 20528b35abe2Sjtc if (t > num) 2053cdec4ac1Sdsl return 0; 20548b35abe2Sjtc ++expr; 20558b35abe2Sjtc break; 20568b35abe2Sjtc case 'k': 20578b35abe2Sjtc t = num; 20588b35abe2Sjtc num *= 1024; 20598b35abe2Sjtc if (t > num) 2060cdec4ac1Sdsl return 0; 20618b35abe2Sjtc ++expr; 20628b35abe2Sjtc break; 20638b35abe2Sjtc case 'm': 20648b35abe2Sjtc t = num; 20658b35abe2Sjtc num *= 1048576; 20668b35abe2Sjtc if (t > num) 2067cdec4ac1Sdsl return 0; 20688b35abe2Sjtc ++expr; 20698b35abe2Sjtc break; 20708b35abe2Sjtc case 'w': 20718b35abe2Sjtc t = num; 20728b35abe2Sjtc num *= sizeof(int); 20738b35abe2Sjtc if (t > num) 2074cdec4ac1Sdsl return 0; 20758b35abe2Sjtc ++expr; 20768b35abe2Sjtc break; 20778b35abe2Sjtc } 20788b35abe2Sjtc 20798b35abe2Sjtc switch(*expr) { 20808b35abe2Sjtc case '\0': 20818b35abe2Sjtc break; 20828b35abe2Sjtc case '*': 20838b35abe2Sjtc case 'x': 20848b35abe2Sjtc t = num; 20858b35abe2Sjtc num *= str_offt(expr + 1); 20868b35abe2Sjtc if (t > num) 2087cdec4ac1Sdsl return 0; 20888b35abe2Sjtc break; 20898b35abe2Sjtc default: 2090cdec4ac1Sdsl return 0; 20918b35abe2Sjtc } 2092cdec4ac1Sdsl return num; 20938b35abe2Sjtc } 20948b35abe2Sjtc 2095074c0c6eSjoerg static char * 20967027866aSroy get_line(FILE *f) 20970c612021Schristos { 20980c612021Schristos char *name, *temp; 20990c612021Schristos size_t len; 21000c612021Schristos 21010c612021Schristos name = fgetln(f, &len); 21020c612021Schristos if (!name) { 21037027866aSroy get_line_error = ferror(f) ? GETLINE_FILE_CORRUPT : 0; 2104cdec4ac1Sdsl return 0; 21050c612021Schristos } 21060c612021Schristos if (name[len-1] != '\n') 21070c612021Schristos len++; 21080c612021Schristos temp = malloc(len); 21090c612021Schristos if (!temp) { 21107027866aSroy get_line_error = GETLINE_OUT_OF_MEM; 2111cdec4ac1Sdsl return 0; 21120c612021Schristos } 21130c612021Schristos memcpy(temp, name, len-1); 21140c612021Schristos temp[len-1] = 0; 2115cdec4ac1Sdsl return temp; 21160c612021Schristos } 21170c612021Schristos 21189158fb65Schristos #ifndef SMALL 21199158fb65Schristos /* 21209158fb65Schristos * set_tstamp() 21219158fb65Schristos * Use a specific timestamp for all individual files created in the 21229158fb65Schristos * archive 21239158fb65Schristos */ 21249158fb65Schristos static int 21259158fb65Schristos set_tstamp(const char *b, struct stat *st) 21269158fb65Schristos { 21279158fb65Schristos time_t when; 21289158fb65Schristos char *eb; 21299158fb65Schristos long long l; 21309158fb65Schristos 21319158fb65Schristos if (stat(b, st) != -1) 21329158fb65Schristos return 0; 21339158fb65Schristos 21349158fb65Schristos #ifndef HAVE_NBTOOL_CONFIG_H 21359158fb65Schristos errno = 0; 21369158fb65Schristos if ((when = parsedate(b, NULL, NULL)) == -1 && errno != 0) 21379158fb65Schristos #endif 21389158fb65Schristos { 21399158fb65Schristos errno = 0; 21409158fb65Schristos l = strtoll(b, &eb, 0); 21419158fb65Schristos if (b == eb || *eb || errno) 21429158fb65Schristos return -1; 21439158fb65Schristos when = (time_t)l; 21449158fb65Schristos } 21459158fb65Schristos 21469158fb65Schristos st->st_ino = 1; 21479158fb65Schristos #if HAVE_STRUCT_STAT_BIRTHTIME 21489158fb65Schristos st->st_birthtime = 21499158fb65Schristos #endif 21509158fb65Schristos st->st_mtime = st->st_ctime = st->st_atime = when; 21519158fb65Schristos return 0; 21529158fb65Schristos } 21539158fb65Schristos #endif 21549158fb65Schristos 21558b35abe2Sjtc /* 21568b35abe2Sjtc * no_op() 21578b35abe2Sjtc * for those option functions where the archive format has nothing to do. 21588b35abe2Sjtc * Return: 21598b35abe2Sjtc * 0 21608b35abe2Sjtc */ 21618b35abe2Sjtc 21628b35abe2Sjtc static int 21638b35abe2Sjtc no_op(void) 21648b35abe2Sjtc { 2165cdec4ac1Sdsl return 0; 21668b35abe2Sjtc } 21678b35abe2Sjtc 21688b35abe2Sjtc /* 21698b35abe2Sjtc * pax_usage() 21708b35abe2Sjtc * print the usage summary to the user 21718b35abe2Sjtc */ 21728b35abe2Sjtc 2173074c0c6eSjoerg static void 21748b35abe2Sjtc pax_usage(void) 21758b35abe2Sjtc { 2176ae5120dcSlukem fprintf(stderr, 21775952a904Shira "usage: pax [-0cdjnvzVO] [-E limit] [-f archive] [-N dbdir] [-s replstr] ...\n" 2178ae5120dcSlukem " [-U user] ... [-G group] ... [-T [from_date][,to_date]] ...\n" 2179ae5120dcSlukem " [pattern ...]\n"); 2180ae5120dcSlukem fprintf(stderr, 21815952a904Shira " pax -r [-cdijknuvzADOVYZ] [-E limit] [-f archive] [-N dbdir]\n" 2182ae5120dcSlukem " [-o options] ... [-p string] ... [-s replstr] ... [-U user] ...\n" 2183ae5120dcSlukem " [-G group] ... [-T [from_date][,to_date]] ... [pattern ...]\n"); 2184ae5120dcSlukem fprintf(stderr, 21855952a904Shira " pax -w [-dijtuvzAHLMOPVX] [-b blocksize] [[-a] [-f archive]] [-x format]\n" 2186ae5120dcSlukem " [-B bytes] [-N dbdir] [-o options] ... [-s replstr] ...\n" 2187ae5120dcSlukem " [-U user] ... [-G group] ...\n" 2188ae5120dcSlukem " [-T [from_date][,to_date][/[c][m]]] ... [file ...]\n"); 2189ae5120dcSlukem fprintf(stderr, 21905952a904Shira " pax -r -w [-dijklntuvzADHLMOPVXYZ] [-N dbdir] [-p string] ...\n" 2191ae5120dcSlukem " [-s replstr] ... [-U user] ... [-G group] ...\n" 2192ae5120dcSlukem " [-T [from_date][,to_date][/[c][m]]] ... [file ...] directory\n"); 21938b35abe2Sjtc exit(1); 21949dc385beSmycroft /* NOTREACHED */ 21958b35abe2Sjtc } 21968b35abe2Sjtc 21978b35abe2Sjtc /* 21988b35abe2Sjtc * tar_usage() 21998b35abe2Sjtc * print the usage summary to the user 22008b35abe2Sjtc */ 22018b35abe2Sjtc 2202074c0c6eSjoerg static void 22038b35abe2Sjtc tar_usage(void) 22048b35abe2Sjtc { 220523c362a5Schristos (void)fputs("usage: tar [-]{crtux}[-befhjklmopqvwzHJOPSXZ014578] " 220623c362a5Schristos "[archive] [blocksize]\n" 2207f05dd4bfSsoren " [-C directory] [-T file] [-s replstr] " 2208f05dd4bfSsoren "[file ...]\n", stderr); 22098b35abe2Sjtc exit(1); 22109dc385beSmycroft /* NOTREACHED */ 22118b35abe2Sjtc } 22128b35abe2Sjtc 2213d7df71baSchristos #ifndef NO_CPIO 22148b35abe2Sjtc /* 22158b35abe2Sjtc * cpio_usage() 22168b35abe2Sjtc * print the usage summary to the user 22178b35abe2Sjtc */ 22188b35abe2Sjtc 2219074c0c6eSjoerg static void 22208b35abe2Sjtc cpio_usage(void) 22218b35abe2Sjtc { 222251fc9487Smrg 2223b635f565Sjmmv (void)fputs("usage: cpio -o [-aABcLvzZ] [-C bytes] [-F archive] " 2224f9d57740Ssoren "[-H format] [-O archive]\n" 2225f9d57740Ssoren " < name-list [> archive]\n" 2226f9d57740Ssoren " cpio -i [-bBcdfmrsStuvzZ6] [-C bytes] [-E file] " 2227f9d57740Ssoren "[-F archive] [-H format] \n" 2228f9d57740Ssoren " [-I archive] " 2229f9d57740Ssoren "[pattern ...] [< archive]\n" 2230f9d57740Ssoren " cpio -p [-adlLmuv] destination-directory " 2231f9d57740Ssoren "< name-list\n", stderr); 22328b35abe2Sjtc exit(1); 22339dc385beSmycroft /* NOTREACHED */ 22348b35abe2Sjtc } 2235d7df71baSchristos #endif 2236