2011-08-29 18:47:47 +04:00
|
|
|
/* $NetBSD: options.c,v 1.111 2011/08/29 14:47:47 joerg Exp $ */
|
1995-03-21 12:01:59 +03:00
|
|
|
|
1994-06-13 20:13:35 +04:00
|
|
|
/*-
|
2003-10-13 11:41:22 +04:00
|
|
|
* Copyright (c) 1992 Keith Muller.
|
1994-06-13 20:13:35 +04:00
|
|
|
* Copyright (c) 1992, 1993
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
|
|
|
*
|
|
|
|
* This code is derived from software contributed to Berkeley by
|
|
|
|
* Keith Muller of the University of California, San Diego.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
2003-08-07 13:05:01 +04:00
|
|
|
* 3. Neither the name of the University nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2003-10-27 03:12:41 +03:00
|
|
|
#if HAVE_NBTOOL_CONFIG_H
|
|
|
|
#include "nbtool_config.h"
|
|
|
|
#endif
|
|
|
|
|
1997-07-21 00:32:15 +04:00
|
|
|
#include <sys/cdefs.h>
|
2003-10-27 03:12:41 +03:00
|
|
|
#if !defined(lint)
|
1995-03-21 12:01:59 +03:00
|
|
|
#if 0
|
|
|
|
static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 4/18/94";
|
|
|
|
#else
|
2011-08-29 18:47:47 +04:00
|
|
|
__RCSID("$NetBSD: options.c,v 1.111 2011/08/29 14:47:47 joerg Exp $");
|
1995-03-21 12:01:59 +03:00
|
|
|
#endif
|
1994-06-13 20:13:35 +04:00
|
|
|
#endif /* not lint */
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <ctype.h>
|
2002-10-12 19:39:29 +04:00
|
|
|
#include <errno.h>
|
2004-06-21 02:20:14 +04:00
|
|
|
#if HAVE_NBTOOL_CONFIG_H
|
|
|
|
#include "compat_getopt.h"
|
|
|
|
#else
|
2002-02-01 01:43:33 +03:00
|
|
|
#include <getopt.h>
|
2004-06-21 02:20:14 +04:00
|
|
|
#endif
|
2002-02-01 01:43:33 +03:00
|
|
|
#include <limits.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
1994-06-13 20:13:35 +04:00
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
2002-10-12 19:39:29 +04:00
|
|
|
#include <paths.h>
|
1994-06-13 20:13:35 +04:00
|
|
|
#include "pax.h"
|
|
|
|
#include "options.h"
|
|
|
|
#include "cpio.h"
|
|
|
|
#include "tar.h"
|
|
|
|
#include "extern.h"
|
2002-02-02 15:34:39 +03:00
|
|
|
#ifndef SMALL
|
2002-01-24 10:45:33 +03:00
|
|
|
#include "mtree.h"
|
2002-02-02 15:34:39 +03:00
|
|
|
#endif /* SMALL */
|
1994-06-13 20:13:35 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Routines which handle command line options
|
|
|
|
*/
|
|
|
|
|
1999-02-07 03:56:55 +03:00
|
|
|
static int nopids; /* tar mode: suppress "pids" for -p option */
|
2004-05-11 21:12:26 +04:00
|
|
|
static char flgch[] = FLGCH; /* list of all possible flags (pax) */
|
1994-06-13 20:13:35 +04:00
|
|
|
static OPLIST *ophead = NULL; /* head for format specific options -x */
|
|
|
|
static OPLIST *optail = NULL; /* option tail */
|
|
|
|
|
2011-08-29 18:47:47 +04:00
|
|
|
static int opt_add(const char *);
|
2001-10-25 09:33:32 +04:00
|
|
|
static int no_op(void);
|
|
|
|
static void printflg(unsigned int);
|
|
|
|
static int c_frmt(const void *, const void *);
|
|
|
|
static off_t str_offt(char *);
|
2009-07-13 23:05:39 +04:00
|
|
|
static char *get_line(FILE *fp);
|
2001-10-25 09:33:32 +04:00
|
|
|
static void pax_options(int, char **);
|
2011-08-29 18:47:47 +04:00
|
|
|
__dead static void pax_usage(void);
|
2001-10-25 09:33:32 +04:00
|
|
|
static void tar_options(int, char **);
|
2011-08-29 18:47:47 +04:00
|
|
|
__dead static void tar_usage(void);
|
2005-06-29 06:21:27 +04:00
|
|
|
#ifndef NO_CPIO
|
2001-10-25 09:33:32 +04:00
|
|
|
static void cpio_options(int, char **);
|
2011-08-29 18:47:47 +04:00
|
|
|
__dead static void cpio_usage(void);
|
2005-06-29 06:21:27 +04:00
|
|
|
#endif
|
1994-06-13 20:13:35 +04:00
|
|
|
|
2009-07-13 23:05:39 +04:00
|
|
|
/* errors from get_line */
|
2002-10-12 19:39:29 +04:00
|
|
|
#define GETLINE_FILE_CORRUPT 1
|
|
|
|
#define GETLINE_OUT_OF_MEM 2
|
2009-07-13 23:05:39 +04:00
|
|
|
static int get_line_error;
|
1999-10-23 00:59:08 +04:00
|
|
|
|
2003-02-25 16:36:59 +03:00
|
|
|
#define BZIP2_CMD "bzip2" /* command to run as bzip2 */
|
1996-03-27 02:54:13 +03:00
|
|
|
#define GZIP_CMD "gzip" /* command to run as gzip */
|
2011-06-19 03:07:04 +04:00
|
|
|
#define XZ_CMD "xz" /* command to run as xz */
|
1996-03-27 02:54:13 +03:00
|
|
|
#define COMPRESS_CMD "compress" /* command to run as compress */
|
|
|
|
|
2002-10-15 20:16:29 +04:00
|
|
|
/*
|
|
|
|
* Long options.
|
|
|
|
*/
|
|
|
|
#define OPT_USE_COMPRESS_PROGRAM 0
|
|
|
|
#define OPT_CHECKPOINT 1
|
|
|
|
#define OPT_UNLINK 2
|
|
|
|
#define OPT_HELP 3
|
|
|
|
#define OPT_ATIME_PRESERVE 4
|
|
|
|
#define OPT_IGNORE_FAILED_READ 5
|
|
|
|
#define OPT_REMOVE_FILES 6
|
|
|
|
#define OPT_NULL 7
|
|
|
|
#define OPT_TOTALS 8
|
|
|
|
#define OPT_VERSION 9
|
|
|
|
#define OPT_EXCLUDE 10
|
|
|
|
#define OPT_BLOCK_COMPRESS 11
|
|
|
|
#define OPT_NORECURSE 12
|
|
|
|
#define OPT_FORCE_LOCAL 13
|
|
|
|
#define OPT_INSECURE 14
|
2002-10-16 07:46:07 +04:00
|
|
|
#define OPT_STRICT 15
|
2004-09-27 03:46:00 +04:00
|
|
|
#define OPT_SPARSE 16
|
2011-06-19 03:07:04 +04:00
|
|
|
#define OPT_XZ 17
|
2004-10-23 01:00:18 +04:00
|
|
|
#if !HAVE_NBTOOL_CONFIG_H
|
2011-06-19 03:07:04 +04:00
|
|
|
#define OPT_CHROOT 18
|
2004-10-23 01:00:18 +04:00
|
|
|
#endif
|
2002-10-15 20:16:29 +04:00
|
|
|
|
1994-06-13 20:13:35 +04:00
|
|
|
/*
|
|
|
|
* Format specific routine table - MUST BE IN SORTED ORDER BY NAME
|
|
|
|
* (see pax.h for description of each function)
|
|
|
|
*
|
2000-02-17 06:12:22 +03:00
|
|
|
* name, blksz, hdsz, udev, hlk, blkagn, inhead, id, st_read,
|
1994-06-13 20:13:35 +04:00
|
|
|
* read, end_read, st_write, write, end_write, trail,
|
2004-09-22 18:52:00 +04:00
|
|
|
* subtrail, rd_data, wr_data, options
|
1994-06-13 20:13:35 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
FSUB fsub[] = {
|
2005-06-29 06:21:27 +04:00
|
|
|
#ifndef NO_CPIO
|
1994-06-13 20:13:35 +04:00
|
|
|
/* 0: OLD BINARY CPIO */
|
1997-07-21 00:32:15 +04:00
|
|
|
{ "bcpio", 5120, sizeof(HD_BCPIO), 1, 0, 0, 1, bcpio_id, cpio_strd,
|
|
|
|
bcpio_rd, bcpio_endrd, cpio_stwr, bcpio_wr, cpio_endwr, NULL,
|
|
|
|
cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt },
|
1994-06-13 20:13:35 +04:00
|
|
|
|
|
|
|
/* 1: OLD OCTAL CHARACTER CPIO */
|
1997-07-21 00:32:15 +04:00
|
|
|
{ "cpio", 5120, sizeof(HD_CPIO), 1, 0, 0, 1, cpio_id, cpio_strd,
|
|
|
|
cpio_rd, cpio_endrd, cpio_stwr, cpio_wr, cpio_endwr, NULL,
|
|
|
|
cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt },
|
1994-06-13 20:13:35 +04:00
|
|
|
|
|
|
|
/* 2: SVR4 HEX CPIO */
|
1997-07-21 00:32:15 +04:00
|
|
|
{ "sv4cpio", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, vcpio_id, cpio_strd,
|
|
|
|
vcpio_rd, vcpio_endrd, cpio_stwr, vcpio_wr, cpio_endwr, NULL,
|
|
|
|
cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt },
|
1994-06-13 20:13:35 +04:00
|
|
|
|
|
|
|
/* 3: SVR4 HEX CPIO WITH CRC */
|
1997-07-21 00:32:15 +04:00
|
|
|
{ "sv4crc", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd,
|
|
|
|
vcpio_rd, vcpio_endrd, crc_stwr, vcpio_wr, cpio_endwr, NULL,
|
|
|
|
cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt },
|
2005-06-29 06:21:27 +04:00
|
|
|
#endif
|
1994-06-13 20:13:35 +04:00
|
|
|
/* 4: OLD TAR */
|
1997-07-21 00:32:15 +04:00
|
|
|
{ "tar", 10240, BLKMULT, 0, 1, BLKMULT, 0, tar_id, no_op,
|
1994-06-13 20:13:35 +04:00
|
|
|
tar_rd, tar_endrd, no_op, tar_wr, tar_endwr, tar_trail,
|
1997-07-21 00:32:15 +04:00
|
|
|
NULL, rd_wrfile, wr_rdfile, tar_opt },
|
1994-06-13 20:13:35 +04:00
|
|
|
|
|
|
|
/* 5: POSIX USTAR */
|
1997-07-21 00:32:15 +04:00
|
|
|
{ "ustar", 10240, BLKMULT, 0, 1, BLKMULT, 0, ustar_id, ustar_strd,
|
1994-06-13 20:13:35 +04:00
|
|
|
ustar_rd, tar_endrd, ustar_stwr, ustar_wr, tar_endwr, tar_trail,
|
1997-07-21 00:32:15 +04:00
|
|
|
NULL, rd_wrfile, wr_rdfile, bad_opt }
|
1994-06-13 20:13:35 +04:00
|
|
|
};
|
2005-06-29 06:21:27 +04:00
|
|
|
#ifndef NO_CPIO
|
1998-03-06 12:13:01 +03:00
|
|
|
#define F_BCPIO 0 /* old binary cpio format */
|
|
|
|
#define F_CPIO 1 /* old octal character cpio format */
|
|
|
|
#define F_SV4CPIO 2 /* SVR4 hex cpio format */
|
|
|
|
#define F_SV4CRC 3 /* SVR4 hex with crc cpio format */
|
1999-02-07 03:56:55 +03:00
|
|
|
#define F_TAR 4 /* old V7 UNIX tar format */
|
1998-03-06 12:13:01 +03:00
|
|
|
#define F_USTAR 5 /* ustar format */
|
2005-06-29 06:21:27 +04:00
|
|
|
#else
|
|
|
|
#define F_TAR 0 /* old V7 UNIX tar format */
|
|
|
|
#define F_USTAR 1 /* ustar format */
|
|
|
|
#endif
|
1998-03-06 12:13:01 +03:00
|
|
|
#define DEFLT F_USTAR /* default write format from list above */
|
1994-06-13 20:13:35 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* ford is the archive search order used by get_arc() to determine what kind
|
2003-02-02 13:21:13 +03:00
|
|
|
* of archive we are dealing with. This helps to properly id archive formats
|
1994-06-13 20:13:35 +04:00
|
|
|
* some formats may be subsets of others....
|
|
|
|
*/
|
2005-06-29 06:21:27 +04:00
|
|
|
int ford[] = {F_USTAR, F_TAR,
|
|
|
|
#ifndef NO_CPIO
|
|
|
|
F_SV4CRC, F_SV4CPIO, F_CPIO, F_BCPIO,
|
|
|
|
#endif
|
|
|
|
-1};
|
1994-06-13 20:13:35 +04:00
|
|
|
|
2004-06-19 06:27:00 +04:00
|
|
|
/*
|
|
|
|
* filename record separator
|
|
|
|
*/
|
|
|
|
int sep = '\n';
|
|
|
|
|
2006-04-16 20:20:21 +04:00
|
|
|
/*
|
|
|
|
* Do we have -C anywhere?
|
|
|
|
*/
|
|
|
|
int havechd = 0;
|
|
|
|
|
1994-06-13 20:13:35 +04:00
|
|
|
/*
|
|
|
|
* options()
|
|
|
|
* figure out if we are pax, tar or cpio. Call the appropriate options
|
|
|
|
* parser
|
|
|
|
*/
|
|
|
|
|
|
|
|
void
|
1997-01-11 05:04:27 +03:00
|
|
|
options(int argc, char **argv)
|
1994-06-13 20:13:35 +04:00
|
|
|
{
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Are we acting like pax, tar or cpio (based on argv[0])
|
|
|
|
*/
|
|
|
|
if ((argv0 = strrchr(argv[0], '/')) != NULL)
|
|
|
|
argv0++;
|
|
|
|
else
|
|
|
|
argv0 = argv[0];
|
|
|
|
|
2005-05-15 06:04:30 +04:00
|
|
|
if (strstr(argv0, NM_TAR)) {
|
|
|
|
argv0 = NM_TAR;
|
2002-11-27 21:40:34 +03:00
|
|
|
tar_options(argc, argv);
|
2005-06-29 06:21:27 +04:00
|
|
|
#ifndef NO_CPIO
|
2005-05-15 06:04:30 +04:00
|
|
|
} else if (strstr(argv0, NM_CPIO)) {
|
|
|
|
argv0 = NM_CPIO;
|
2002-11-27 21:40:34 +03:00
|
|
|
cpio_options(argc, argv);
|
2005-06-29 06:21:27 +04:00
|
|
|
#endif
|
2005-05-15 06:04:30 +04:00
|
|
|
} else {
|
1998-07-28 15:41:40 +04:00
|
|
|
argv0 = NM_PAX;
|
2002-11-27 21:40:34 +03:00
|
|
|
pax_options(argc, argv);
|
1998-07-28 15:41:40 +04:00
|
|
|
}
|
1994-06-13 20:13:35 +04:00
|
|
|
}
|
|
|
|
|
2002-10-15 20:16:29 +04:00
|
|
|
struct option pax_longopts[] = {
|
|
|
|
{ "insecure", no_argument, 0,
|
|
|
|
OPT_INSECURE },
|
2002-10-17 01:45:31 +04:00
|
|
|
{ "force-local", no_argument, 0,
|
|
|
|
OPT_FORCE_LOCAL },
|
2010-06-19 04:43:57 +04:00
|
|
|
{ "use-compress-program", required_argument, 0,
|
|
|
|
OPT_USE_COMPRESS_PROGRAM },
|
2011-06-19 03:07:04 +04:00
|
|
|
{ "xz", no_argument, 0,
|
|
|
|
OPT_XZ },
|
2006-10-16 04:11:22 +04:00
|
|
|
{ 0, 0, 0,
|
|
|
|
0 },
|
2002-10-15 20:16:29 +04:00
|
|
|
};
|
|
|
|
|
1994-06-13 20:13:35 +04:00
|
|
|
/*
|
|
|
|
* pax_options()
|
|
|
|
* look at the user specified flags. set globals as required and check if
|
|
|
|
* the user specified a legal set of flags. If not, complain and exit
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
1997-01-11 05:04:27 +03:00
|
|
|
pax_options(int argc, char **argv)
|
1994-06-13 20:13:35 +04:00
|
|
|
{
|
1997-01-11 05:04:27 +03:00
|
|
|
int c;
|
2009-02-14 11:02:04 +03:00
|
|
|
size_t i;
|
2007-04-23 22:40:22 +04:00
|
|
|
u_int64_t flg = 0;
|
|
|
|
u_int64_t bflg = 0;
|
1997-01-11 05:04:27 +03:00
|
|
|
char *pt;
|
2000-02-17 06:12:22 +03:00
|
|
|
FSUB tmp;
|
1994-06-13 20:13:35 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* process option flags
|
|
|
|
*/
|
2002-10-15 20:16:29 +04:00
|
|
|
while ((c = getopt_long(argc, argv,
|
2007-04-23 22:40:22 +04:00
|
|
|
"0ab:cdf:ijklno:p:rs:tuvwx:zAB:DE:G:HLMN:OPT:U:VXYZ",
|
2002-10-15 20:16:29 +04:00
|
|
|
pax_longopts, NULL)) != -1) {
|
1994-06-13 20:13:35 +04:00
|
|
|
switch (c) {
|
2004-06-19 06:27:00 +04:00
|
|
|
case '0':
|
|
|
|
sep = '\0';
|
|
|
|
break;
|
1994-06-13 20:13:35 +04:00
|
|
|
case 'a':
|
|
|
|
/*
|
|
|
|
* append
|
|
|
|
*/
|
|
|
|
flg |= AF;
|
|
|
|
break;
|
|
|
|
case 'b':
|
|
|
|
/*
|
|
|
|
* specify blocksize
|
|
|
|
*/
|
|
|
|
flg |= BF;
|
|
|
|
if ((wrblksz = (int)str_offt(optarg)) <= 0) {
|
1997-07-21 00:32:15 +04:00
|
|
|
tty_warn(1, "Invalid block size %s", optarg);
|
1994-06-13 20:13:35 +04:00
|
|
|
pax_usage();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
/*
|
|
|
|
* inverse match on patterns
|
|
|
|
*/
|
|
|
|
cflag = 1;
|
|
|
|
flg |= CF;
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
/*
|
|
|
|
* match only dir on extract, not the subtree at dir
|
|
|
|
*/
|
|
|
|
dflag = 1;
|
|
|
|
flg |= DF;
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
/*
|
|
|
|
* filename where the archive is stored
|
|
|
|
*/
|
|
|
|
arcname = optarg;
|
|
|
|
flg |= FF;
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
/*
|
|
|
|
* interactive file rename
|
|
|
|
*/
|
|
|
|
iflag = 1;
|
|
|
|
flg |= IF;
|
|
|
|
break;
|
2003-04-01 00:10:08 +04:00
|
|
|
case 'j':
|
|
|
|
/*
|
|
|
|
* pass through bzip2
|
|
|
|
*/
|
|
|
|
gzip_program = BZIP2_CMD;
|
|
|
|
break;
|
1994-06-13 20:13:35 +04:00
|
|
|
case 'k':
|
|
|
|
/*
|
|
|
|
* do not clobber files that exist
|
|
|
|
*/
|
|
|
|
kflag = 1;
|
|
|
|
flg |= KF;
|
|
|
|
break;
|
|
|
|
case 'l':
|
|
|
|
/*
|
|
|
|
* try to link src to dest with copy (-rw)
|
|
|
|
*/
|
|
|
|
lflag = 1;
|
|
|
|
flg |= LF;
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
/*
|
|
|
|
* select first match for a pattern only
|
|
|
|
*/
|
|
|
|
nflag = 1;
|
|
|
|
flg |= NF;
|
|
|
|
break;
|
|
|
|
case 'o':
|
|
|
|
/*
|
|
|
|
* pass format specific options
|
|
|
|
*/
|
|
|
|
flg |= OF;
|
|
|
|
if (opt_add(optarg) < 0)
|
|
|
|
pax_usage();
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
/*
|
|
|
|
* specify file characteristic options
|
|
|
|
*/
|
|
|
|
for (pt = optarg; *pt != '\0'; ++pt) {
|
|
|
|
switch(*pt) {
|
|
|
|
case 'a':
|
|
|
|
/*
|
|
|
|
* do not preserve access time
|
|
|
|
*/
|
|
|
|
patime = 0;
|
|
|
|
break;
|
|
|
|
case 'e':
|
|
|
|
/*
|
|
|
|
* preserve user id, group id, file
|
|
|
|
* mode, access/modification times
|
1999-11-01 04:35:58 +03:00
|
|
|
* and file flags.
|
1994-06-13 20:13:35 +04:00
|
|
|
*/
|
|
|
|
pids = 1;
|
|
|
|
pmode = 1;
|
|
|
|
patime = 1;
|
|
|
|
pmtime = 1;
|
1999-11-01 04:35:58 +03:00
|
|
|
pfflags = 1;
|
|
|
|
break;
|
1999-11-07 18:57:31 +03:00
|
|
|
#if 0
|
1999-11-01 04:35:58 +03:00
|
|
|
case 'f':
|
|
|
|
/*
|
|
|
|
* do not preserve file flags
|
|
|
|
*/
|
|
|
|
pfflags = 0;
|
1994-06-13 20:13:35 +04:00
|
|
|
break;
|
1999-11-07 18:57:31 +03:00
|
|
|
#endif
|
1994-06-13 20:13:35 +04:00
|
|
|
case 'm':
|
|
|
|
/*
|
|
|
|
* do not preserve modification time
|
|
|
|
*/
|
|
|
|
pmtime = 0;
|
|
|
|
break;
|
|
|
|
case 'o':
|
|
|
|
/*
|
|
|
|
* preserve uid/gid
|
|
|
|
*/
|
|
|
|
pids = 1;
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
/*
|
2002-01-24 10:45:33 +03:00
|
|
|
* preserve file mode bits
|
1994-06-13 20:13:35 +04:00
|
|
|
*/
|
|
|
|
pmode = 1;
|
|
|
|
break;
|
|
|
|
default:
|
2002-10-12 19:39:29 +04:00
|
|
|
tty_warn(1, "Invalid -p string: %c",
|
|
|
|
*pt);
|
1994-06-13 20:13:35 +04:00
|
|
|
pax_usage();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
flg |= PF;
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
/*
|
|
|
|
* read the archive
|
|
|
|
*/
|
|
|
|
flg |= RF;
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
/*
|
|
|
|
* file name substitution name pattern
|
|
|
|
*/
|
|
|
|
if (rep_add(optarg) < 0) {
|
|
|
|
pax_usage();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
flg |= SF;
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
/*
|
|
|
|
* preserve access time on filesystem nodes we read
|
|
|
|
*/
|
|
|
|
tflag = 1;
|
|
|
|
flg |= TF;
|
|
|
|
break;
|
|
|
|
case 'u':
|
|
|
|
/*
|
|
|
|
* ignore those older files
|
|
|
|
*/
|
|
|
|
uflag = 1;
|
|
|
|
flg |= UF;
|
|
|
|
break;
|
|
|
|
case 'v':
|
|
|
|
/*
|
|
|
|
* verbose operation mode
|
|
|
|
*/
|
|
|
|
vflag = 1;
|
|
|
|
flg |= VF;
|
|
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
/*
|
|
|
|
* write an archive
|
|
|
|
*/
|
|
|
|
flg |= WF;
|
|
|
|
break;
|
|
|
|
case 'x':
|
|
|
|
/*
|
|
|
|
* specify an archive format on write
|
|
|
|
*/
|
|
|
|
tmp.name = optarg;
|
1997-07-21 00:32:15 +04:00
|
|
|
frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
|
|
|
|
sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt);
|
|
|
|
if (frmt != NULL) {
|
1994-06-13 20:13:35 +04:00
|
|
|
flg |= XF;
|
|
|
|
break;
|
|
|
|
}
|
1997-07-21 00:32:15 +04:00
|
|
|
tty_warn(1, "Unknown -x format: %s", optarg);
|
1994-06-13 20:13:35 +04:00
|
|
|
(void)fputs("pax: Known -x formats are:", stderr);
|
|
|
|
for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
|
|
|
|
(void)fprintf(stderr, " %s", fsub[i].name);
|
|
|
|
(void)fputs("\n\n", stderr);
|
|
|
|
pax_usage();
|
|
|
|
break;
|
1996-03-27 02:54:13 +03:00
|
|
|
case 'z':
|
|
|
|
/*
|
|
|
|
* use gzip. Non standard option.
|
|
|
|
*/
|
|
|
|
gzip_program = GZIP_CMD;
|
|
|
|
break;
|
1999-08-24 11:57:06 +04:00
|
|
|
case 'A':
|
|
|
|
Aflag = 1;
|
|
|
|
flg |= CAF;
|
|
|
|
break;
|
1994-06-13 20:13:35 +04:00
|
|
|
case 'B':
|
|
|
|
/*
|
|
|
|
* non-standard option on number of bytes written on a
|
|
|
|
* single archive volume.
|
|
|
|
*/
|
|
|
|
if ((wrlimit = str_offt(optarg)) <= 0) {
|
1997-07-21 00:32:15 +04:00
|
|
|
tty_warn(1, "Invalid write limit %s", optarg);
|
1994-06-13 20:13:35 +04:00
|
|
|
pax_usage();
|
|
|
|
}
|
|
|
|
if (wrlimit % BLKMULT) {
|
1997-07-21 00:32:15 +04:00
|
|
|
tty_warn(1,
|
|
|
|
"Write limit is not a %d byte multiple",
|
1994-06-13 20:13:35 +04:00
|
|
|
BLKMULT);
|
|
|
|
pax_usage();
|
|
|
|
}
|
|
|
|
flg |= CBF;
|
|
|
|
break;
|
|
|
|
case 'D':
|
|
|
|
/*
|
|
|
|
* On extraction check file inode change time before the
|
|
|
|
* modification of the file name. Non standard option.
|
|
|
|
*/
|
|
|
|
Dflag = 1;
|
|
|
|
flg |= CDF;
|
|
|
|
break;
|
|
|
|
case 'E':
|
|
|
|
/*
|
|
|
|
* non-standard limit on read faults
|
|
|
|
* 0 indicates stop after first error, values
|
2004-05-11 21:12:26 +04:00
|
|
|
* indicate a limit, "none" try forever
|
1994-06-13 20:13:35 +04:00
|
|
|
*/
|
|
|
|
flg |= CEF;
|
2004-05-11 21:12:26 +04:00
|
|
|
if (strcmp(none, optarg) == 0)
|
1994-06-13 20:13:35 +04:00
|
|
|
maxflt = -1;
|
|
|
|
else if ((maxflt = atoi(optarg)) < 0) {
|
1997-07-21 00:32:15 +04:00
|
|
|
tty_warn(1,
|
|
|
|
"Error count value must be positive");
|
1994-06-13 20:13:35 +04:00
|
|
|
pax_usage();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'G':
|
|
|
|
/*
|
|
|
|
* non-standard option for selecting files within an
|
|
|
|
* archive by group (gid or name)
|
|
|
|
*/
|
|
|
|
if (grp_add(optarg) < 0) {
|
|
|
|
pax_usage();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
flg |= CGF;
|
|
|
|
break;
|
|
|
|
case 'H':
|
|
|
|
/*
|
|
|
|
* follow command line symlinks only
|
|
|
|
*/
|
|
|
|
Hflag = 1;
|
|
|
|
flg |= CHF;
|
|
|
|
break;
|
|
|
|
case 'L':
|
|
|
|
/*
|
|
|
|
* follow symlinks
|
|
|
|
*/
|
|
|
|
Lflag = 1;
|
|
|
|
flg |= CLF;
|
|
|
|
break;
|
2002-02-02 15:34:39 +03:00
|
|
|
#ifdef SMALL
|
|
|
|
case 'M':
|
|
|
|
case 'N':
|
|
|
|
tty_warn(1, "Support for -%c is not compiled in", c);
|
|
|
|
exit(1);
|
|
|
|
#else /* !SMALL */
|
Implement -M flag: During a write or copy operation, treat the list of
files on standard input as an mtree(8) `specfile' specification, and
write or copy only those items in the specfile.
If the file exists in the underlying file system, its permissions and
modification time will be used unless specifically overridden by the
specfile. An error will be raised if the type of entry in the specfile
conflicts with that of an existing file.
Otherwise, it is necessary to specify at least the following parameters
in the specfile: type, mode, gname or gid, and uname or uid, device
(in the case of block or character devices), and link (in the case of
symbolic links). If time isn't provided, the current time will be used.
2001-10-25 12:51:50 +04:00
|
|
|
case 'M':
|
|
|
|
/*
|
|
|
|
* Treat list of filenames on stdin as an
|
|
|
|
* mtree(8) specfile. Non standard option.
|
|
|
|
*/
|
|
|
|
Mflag = 1;
|
|
|
|
flg |= CMF;
|
|
|
|
break;
|
2002-01-24 10:45:33 +03:00
|
|
|
case 'N':
|
|
|
|
/*
|
|
|
|
* Use alternative directory for user db lookups.
|
|
|
|
*/
|
2002-01-26 05:22:54 +03:00
|
|
|
if (!setup_getid(optarg)) {
|
|
|
|
tty_warn(1,
|
|
|
|
"Unable to use user and group databases in `%s'",
|
|
|
|
optarg);
|
2002-01-24 10:45:33 +03:00
|
|
|
pax_usage();
|
2002-01-26 05:22:54 +03:00
|
|
|
}
|
2002-01-24 10:45:33 +03:00
|
|
|
break;
|
2002-02-02 15:34:39 +03:00
|
|
|
#endif /* !SMALL */
|
2000-03-30 21:53:04 +04:00
|
|
|
case 'O':
|
|
|
|
/*
|
|
|
|
* Force one volume. Non standard option.
|
|
|
|
*/
|
|
|
|
force_one_volume = 1;
|
|
|
|
break;
|
1994-06-13 20:13:35 +04:00
|
|
|
case 'P':
|
|
|
|
/*
|
|
|
|
* do NOT follow symlinks (default)
|
|
|
|
*/
|
|
|
|
Lflag = 0;
|
|
|
|
flg |= CPF;
|
|
|
|
break;
|
|
|
|
case 'T':
|
|
|
|
/*
|
|
|
|
* non-standard option for selecting files within an
|
|
|
|
* archive by modification time range (lower,upper)
|
|
|
|
*/
|
|
|
|
if (trng_add(optarg) < 0) {
|
|
|
|
pax_usage();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
flg |= CTF;
|
|
|
|
break;
|
|
|
|
case 'U':
|
|
|
|
/*
|
|
|
|
* non-standard option for selecting files within an
|
|
|
|
* archive by user (uid or name)
|
|
|
|
*/
|
|
|
|
if (usr_add(optarg) < 0) {
|
|
|
|
pax_usage();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
flg |= CUF;
|
|
|
|
break;
|
2007-04-23 22:40:22 +04:00
|
|
|
case 'V':
|
|
|
|
/*
|
|
|
|
* somewhat verbose operation mode (no listing)
|
|
|
|
*/
|
|
|
|
Vflag = 1;
|
|
|
|
flg |= VSF;
|
|
|
|
break;
|
1994-06-13 20:13:35 +04:00
|
|
|
case 'X':
|
|
|
|
/*
|
|
|
|
* do not pass over mount points in the file system
|
|
|
|
*/
|
|
|
|
Xflag = 1;
|
|
|
|
flg |= CXF;
|
|
|
|
break;
|
|
|
|
case 'Y':
|
|
|
|
/*
|
|
|
|
* On extraction check file inode change time after the
|
|
|
|
* modification of the file name. Non standard option.
|
|
|
|
*/
|
|
|
|
Yflag = 1;
|
|
|
|
flg |= CYF;
|
|
|
|
break;
|
|
|
|
case 'Z':
|
|
|
|
/*
|
|
|
|
* On extraction check modification time after the
|
|
|
|
* modification of the file name. Non standard option.
|
|
|
|
*/
|
|
|
|
Zflag = 1;
|
|
|
|
flg |= CZF;
|
|
|
|
break;
|
2002-10-15 20:16:29 +04:00
|
|
|
case OPT_INSECURE:
|
|
|
|
secure = 0;
|
|
|
|
break;
|
2002-10-17 01:45:31 +04:00
|
|
|
case OPT_FORCE_LOCAL:
|
2010-08-31 07:16:06 +04:00
|
|
|
forcelocal = 1;
|
2002-10-17 01:45:31 +04:00
|
|
|
break;
|
2010-06-19 04:43:57 +04:00
|
|
|
case OPT_USE_COMPRESS_PROGRAM:
|
|
|
|
gzip_program = optarg;
|
|
|
|
break;
|
2011-06-19 03:07:04 +04:00
|
|
|
case OPT_XZ:
|
|
|
|
gzip_program = XZ_CMD;
|
|
|
|
break;
|
1994-06-13 20:13:35 +04:00
|
|
|
case '?':
|
|
|
|
default:
|
|
|
|
pax_usage();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* figure out the operation mode of pax read,write,extract,copy,append
|
|
|
|
* or list. check that we have not been given a bogus set of flags
|
|
|
|
* for the operation mode.
|
|
|
|
*/
|
|
|
|
if (ISLIST(flg)) {
|
|
|
|
act = LIST;
|
2002-10-12 19:39:29 +04:00
|
|
|
listf = stdout;
|
1994-06-13 20:13:35 +04:00
|
|
|
bflg = flg & BDLIST;
|
|
|
|
} else if (ISEXTRACT(flg)) {
|
|
|
|
act = EXTRACT;
|
|
|
|
bflg = flg & BDEXTR;
|
|
|
|
} else if (ISARCHIVE(flg)) {
|
|
|
|
act = ARCHIVE;
|
|
|
|
bflg = flg & BDARCH;
|
|
|
|
} else if (ISAPPND(flg)) {
|
|
|
|
act = APPND;
|
|
|
|
bflg = flg & BDARCH;
|
|
|
|
} else if (ISCOPY(flg)) {
|
|
|
|
act = COPY;
|
|
|
|
bflg = flg & BDCOPY;
|
|
|
|
} else
|
|
|
|
pax_usage();
|
|
|
|
if (bflg) {
|
|
|
|
printflg(flg);
|
|
|
|
pax_usage();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* if we are writing (ARCHIVE) we use the default format if the user
|
|
|
|
* did not specify a format. when we write during an APPEND, we will
|
|
|
|
* adopt the format of the existing archive if none was supplied.
|
|
|
|
*/
|
|
|
|
if (!(flg & XF) && (act == ARCHIVE))
|
|
|
|
frmt = &(fsub[DEFLT]);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* process the args as they are interpreted by the operation mode
|
|
|
|
*/
|
|
|
|
switch (act) {
|
|
|
|
case LIST:
|
|
|
|
case EXTRACT:
|
|
|
|
for (; optind < argc; optind++)
|
2009-12-14 08:04:48 +03:00
|
|
|
if (pat_add(argv[optind], NULL, 0) < 0)
|
1994-06-13 20:13:35 +04:00
|
|
|
pax_usage();
|
|
|
|
break;
|
|
|
|
case COPY:
|
|
|
|
if (optind >= argc) {
|
1997-07-21 00:32:15 +04:00
|
|
|
tty_warn(0, "Destination directory was not supplied");
|
1994-06-13 20:13:35 +04:00
|
|
|
pax_usage();
|
|
|
|
}
|
2002-10-13 15:31:02 +04:00
|
|
|
--argc;
|
|
|
|
dirptr = argv[argc];
|
2002-10-12 19:39:29 +04:00
|
|
|
if (mkpath(dirptr) < 0)
|
2005-09-13 19:50:17 +04:00
|
|
|
exit(1);
|
1998-07-28 21:44:23 +04:00
|
|
|
/* FALLTHROUGH */
|
1994-06-13 20:13:35 +04:00
|
|
|
case ARCHIVE:
|
|
|
|
case APPND:
|
|
|
|
for (; optind < argc; optind++)
|
1999-10-23 00:59:08 +04:00
|
|
|
if (ftree_add(argv[optind], 0) < 0)
|
1994-06-13 20:13:35 +04:00
|
|
|
pax_usage();
|
|
|
|
/*
|
|
|
|
* no read errors allowed on updates/append operation!
|
|
|
|
*/
|
|
|
|
maxflt = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* tar_options()
|
|
|
|
* look at the user specified flags. set globals as required and check if
|
|
|
|
* the user specified a legal set of flags. If not, complain and exit
|
|
|
|
*/
|
|
|
|
|
2000-07-04 21:17:49 +04:00
|
|
|
struct option tar_longopts[] = {
|
|
|
|
{ "block-size", required_argument, 0, 'b' },
|
2003-02-25 16:36:59 +03:00
|
|
|
{ "bunzip2", no_argument, 0, 'j' },
|
|
|
|
{ "bzip2", no_argument, 0, 'j' },
|
2000-07-04 21:17:49 +04:00
|
|
|
{ "create", no_argument, 0, 'c' }, /* F */
|
|
|
|
/* -e -- no corresponding long option */
|
|
|
|
{ "file", required_argument, 0, 'f' },
|
|
|
|
{ "dereference", no_argument, 0, 'h' },
|
2003-04-08 19:13:10 +04:00
|
|
|
{ "keep-old-files", no_argument, 0, 'k' },
|
2000-07-04 21:17:49 +04:00
|
|
|
{ "one-file-system", no_argument, 0, 'l' },
|
|
|
|
{ "modification-time", no_argument, 0, 'm' },
|
|
|
|
{ "old-archive", no_argument, 0, 'o' },
|
|
|
|
{ "portability", no_argument, 0, 'o' },
|
|
|
|
{ "same-permissions", no_argument, 0, 'p' },
|
|
|
|
{ "preserve-permissions", no_argument, 0, 'p' },
|
|
|
|
{ "preserve", no_argument, 0, 'p' },
|
2002-10-15 18:58:53 +04:00
|
|
|
{ "fast-read", no_argument, 0, 'q' },
|
2000-07-04 21:17:49 +04:00
|
|
|
{ "append", no_argument, 0, 'r' }, /* F */
|
|
|
|
{ "update", no_argument, 0, 'u' }, /* F */
|
|
|
|
{ "list", no_argument, 0, 't' }, /* F */
|
|
|
|
{ "verbose", no_argument, 0, 'v' },
|
|
|
|
{ "interactive", no_argument, 0, 'w' },
|
|
|
|
{ "confirmation", no_argument, 0, 'w' },
|
|
|
|
{ "extract", no_argument, 0, 'x' }, /* F */
|
|
|
|
{ "get", no_argument, 0, 'x' }, /* F */
|
|
|
|
{ "gzip", no_argument, 0, 'z' },
|
|
|
|
{ "gunzip", no_argument, 0, 'z' },
|
|
|
|
{ "read-full-blocks", no_argument, 0, 'B' },
|
|
|
|
{ "directory", required_argument, 0, 'C' },
|
2003-07-08 10:00:48 +04:00
|
|
|
{ "to-stdout", no_argument, 0, 'O' },
|
2000-07-04 21:17:49 +04:00
|
|
|
{ "absolute-paths", no_argument, 0, 'P' },
|
2004-10-17 22:49:55 +04:00
|
|
|
{ "sparse", no_argument, 0, 'S' },
|
2002-10-12 19:39:29 +04:00
|
|
|
{ "files-from", required_argument, 0, 'T' },
|
2007-04-23 22:40:22 +04:00
|
|
|
{ "summary", no_argument, 0, 'V' },
|
|
|
|
{ "stats", no_argument, 0, 'V' },
|
2000-07-04 21:17:49 +04:00
|
|
|
{ "exclude-from", required_argument, 0, 'X' },
|
|
|
|
{ "compress", no_argument, 0, 'Z' },
|
|
|
|
{ "uncompress", no_argument, 0, 'Z' },
|
2002-10-16 07:46:07 +04:00
|
|
|
{ "strict", no_argument, 0,
|
|
|
|
OPT_STRICT },
|
2000-07-04 21:28:47 +04:00
|
|
|
{ "atime-preserve", no_argument, 0,
|
|
|
|
OPT_ATIME_PRESERVE },
|
2000-07-04 21:17:49 +04:00
|
|
|
{ "unlink", no_argument, 0,
|
|
|
|
OPT_UNLINK },
|
2000-07-04 21:24:47 +04:00
|
|
|
{ "use-compress-program", required_argument, 0,
|
|
|
|
OPT_USE_COMPRESS_PROGRAM },
|
2002-10-12 19:39:29 +04:00
|
|
|
{ "force-local", no_argument, 0,
|
|
|
|
OPT_FORCE_LOCAL },
|
2002-10-15 20:16:29 +04:00
|
|
|
{ "insecure", no_argument, 0,
|
|
|
|
OPT_INSECURE },
|
2002-12-08 04:35:12 +03:00
|
|
|
{ "exclude", required_argument, 0,
|
|
|
|
OPT_EXCLUDE },
|
2005-05-08 02:27:33 +04:00
|
|
|
{ "no-recursion", no_argument, 0,
|
|
|
|
OPT_NORECURSE },
|
2011-06-19 03:07:04 +04:00
|
|
|
{ "xz", no_argument, 0,
|
|
|
|
OPT_XZ },
|
2004-10-23 01:00:18 +04:00
|
|
|
#if !HAVE_NBTOOL_CONFIG_H
|
2004-10-17 22:49:55 +04:00
|
|
|
{ "chroot", no_argument, 0,
|
|
|
|
OPT_CHROOT },
|
2004-10-23 01:00:18 +04:00
|
|
|
#endif
|
2000-07-04 21:17:49 +04:00
|
|
|
#if 0 /* Not implemented */
|
|
|
|
{ "catenate", no_argument, 0, 'A' }, /* F */
|
|
|
|
{ "concatenate", no_argument, 0, 'A' }, /* F */
|
|
|
|
{ "diff", no_argument, 0, 'd' }, /* F */
|
|
|
|
{ "compare", no_argument, 0, 'd' }, /* F */
|
|
|
|
{ "checkpoint", no_argument, 0,
|
|
|
|
OPT_CHECKPOINT },
|
2000-07-04 21:28:47 +04:00
|
|
|
{ "help", no_argument, 0,
|
2000-07-04 21:17:49 +04:00
|
|
|
OPT_HELP },
|
|
|
|
{ "info-script", required_argument, 0, 'F' },
|
|
|
|
{ "new-volume-script", required_argument, 0, 'F' },
|
|
|
|
{ "incremental", no_argument, 0, 'G' },
|
|
|
|
{ "listed-incremental", required_argument, 0, 'g' },
|
|
|
|
{ "ignore-zeros", no_argument, 0, 'i' },
|
|
|
|
{ "ignore-failed-read", no_argument, 0,
|
|
|
|
OPT_IGNORE_FAILED_READ },
|
|
|
|
{ "starting-file", no_argument, 0, 'K' },
|
2002-10-17 01:45:31 +04:00
|
|
|
{ "tape-length", required_argument, 0, 'L' },
|
2000-07-04 21:17:49 +04:00
|
|
|
{ "multi-volume", no_argument, 0, 'M' },
|
|
|
|
{ "after-date", required_argument, 0, 'N' },
|
|
|
|
{ "newer", required_argument, 0, 'N' },
|
|
|
|
{ "record-number", no_argument, 0, 'R' },
|
|
|
|
{ "remove-files", no_argument, 0,
|
|
|
|
OPT_REMOVE_FILES },
|
|
|
|
{ "same-order", no_argument, 0, 's' },
|
|
|
|
{ "preserve-order", no_argument, 0, 's' },
|
|
|
|
{ "null", no_argument, 0,
|
|
|
|
OPT_NULL },
|
|
|
|
{ "totals", no_argument, 0,
|
|
|
|
OPT_TOTALS },
|
2007-04-23 22:40:22 +04:00
|
|
|
{ "volume-name", required_argument, 0, 'V' }, /* XXX */
|
|
|
|
{ "label", required_argument, 0, 'V' }, /* XXX */
|
2000-07-04 21:17:49 +04:00
|
|
|
{ "version", no_argument, 0,
|
|
|
|
OPT_VERSION },
|
|
|
|
{ "verify", no_argument, 0, 'W' },
|
|
|
|
{ "block-compress", no_argument, 0,
|
|
|
|
OPT_BLOCK_COMPRESS },
|
|
|
|
#endif
|
|
|
|
{ 0, 0, 0, 0 },
|
|
|
|
};
|
|
|
|
|
2007-01-16 22:06:41 +03:00
|
|
|
static void
|
|
|
|
tar_set_action(int op)
|
|
|
|
{
|
|
|
|
if (act != ERROR && act != op)
|
|
|
|
tar_usage();
|
|
|
|
act = op;
|
|
|
|
}
|
|
|
|
|
1994-06-13 20:13:35 +04:00
|
|
|
static void
|
1997-01-11 05:04:27 +03:00
|
|
|
tar_options(int argc, char **argv)
|
1994-06-13 20:13:35 +04:00
|
|
|
{
|
1997-01-11 05:04:27 +03:00
|
|
|
int c;
|
1994-06-13 20:13:35 +04:00
|
|
|
int fstdin = 0;
|
2002-10-12 19:39:29 +04:00
|
|
|
int Oflag = 0;
|
|
|
|
int nincfiles = 0;
|
|
|
|
int incfiles_max = 0;
|
|
|
|
struct incfile {
|
|
|
|
char *file;
|
|
|
|
char *dir;
|
|
|
|
};
|
|
|
|
struct incfile *incfiles = NULL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set default values.
|
|
|
|
*/
|
|
|
|
rmleadslash = 1;
|
2002-10-16 22:53:40 +04:00
|
|
|
is_gnutar = 1;
|
1994-06-13 20:13:35 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* process option flags
|
|
|
|
*/
|
2002-10-12 19:39:29 +04:00
|
|
|
while ((c = getoldopt(argc, argv,
|
2004-09-27 03:46:00 +04:00
|
|
|
"+b:cef:hjklmopqrs:tuvwxzBC:HI:OPST:X:Z014578",
|
2000-07-04 21:17:49 +04:00
|
|
|
tar_longopts, NULL))
|
1997-09-14 18:54:32 +04:00
|
|
|
!= -1) {
|
1994-06-14 05:16:02 +04:00
|
|
|
switch(c) {
|
1994-06-13 20:13:35 +04:00
|
|
|
case 'b':
|
|
|
|
/*
|
2002-10-12 19:39:29 +04:00
|
|
|
* specify blocksize in 512-byte blocks
|
1994-06-13 20:13:35 +04:00
|
|
|
*/
|
1994-06-14 05:16:02 +04:00
|
|
|
if ((wrblksz = (int)str_offt(optarg)) <= 0) {
|
1997-07-21 00:32:15 +04:00
|
|
|
tty_warn(1, "Invalid block size %s", optarg);
|
1994-06-13 20:13:35 +04:00
|
|
|
tar_usage();
|
|
|
|
}
|
2002-10-12 19:39:29 +04:00
|
|
|
wrblksz *= 512; /* XXX - check for int oflow */
|
1994-06-13 20:13:35 +04:00
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
/*
|
|
|
|
* create an archive
|
|
|
|
*/
|
2007-01-16 22:06:41 +03:00
|
|
|
tar_set_action(ARCHIVE);
|
1994-06-13 20:13:35 +04:00
|
|
|
break;
|
|
|
|
case 'e':
|
|
|
|
/*
|
|
|
|
* stop after first error
|
|
|
|
*/
|
|
|
|
maxflt = 0;
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
/*
|
|
|
|
* filename where the archive is stored
|
|
|
|
*/
|
1994-06-14 05:16:02 +04:00
|
|
|
if ((optarg[0] == '-') && (optarg[1]== '\0')) {
|
1994-06-13 20:13:35 +04:00
|
|
|
/*
|
|
|
|
* treat a - as stdin
|
|
|
|
*/
|
1994-06-14 05:16:02 +04:00
|
|
|
fstdin = 1;
|
2002-10-12 19:39:29 +04:00
|
|
|
arcname = NULL;
|
1994-06-13 20:13:35 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
fstdin = 0;
|
1994-06-14 05:16:02 +04:00
|
|
|
arcname = optarg;
|
1994-06-13 20:13:35 +04:00
|
|
|
break;
|
1999-08-24 12:00:03 +04:00
|
|
|
case 'h':
|
|
|
|
/*
|
2003-01-09 20:26:21 +03:00
|
|
|
* follow symlinks
|
1999-08-24 12:00:03 +04:00
|
|
|
*/
|
2003-01-09 20:26:21 +03:00
|
|
|
Lflag = 1;
|
1999-08-24 12:00:03 +04:00
|
|
|
break;
|
2003-02-25 16:36:59 +03:00
|
|
|
case 'j':
|
|
|
|
/*
|
|
|
|
* pass through bzip2. not a standard option
|
|
|
|
*/
|
|
|
|
gzip_program = BZIP2_CMD;
|
|
|
|
break;
|
2003-04-08 19:13:10 +04:00
|
|
|
case 'k':
|
|
|
|
/*
|
|
|
|
* do not clobber files that exist
|
|
|
|
*/
|
|
|
|
kflag = 1;
|
|
|
|
break;
|
1998-03-06 12:13:01 +03:00
|
|
|
case 'l':
|
|
|
|
/*
|
|
|
|
* do not pass over mount points in the file system
|
|
|
|
*/
|
|
|
|
Xflag = 1;
|
|
|
|
break;
|
1994-06-13 20:13:35 +04:00
|
|
|
case 'm':
|
|
|
|
/*
|
|
|
|
* do not preserve modification time
|
|
|
|
*/
|
|
|
|
pmtime = 0;
|
|
|
|
break;
|
|
|
|
case 'o':
|
1999-02-07 03:56:55 +03:00
|
|
|
/*
|
|
|
|
* This option does several things based on whether
|
|
|
|
* this is a create or extract operation.
|
|
|
|
*/
|
|
|
|
if (act == ARCHIVE) {
|
2002-10-16 07:46:07 +04:00
|
|
|
/* GNU tar: write V7 format archives. */
|
|
|
|
Oflag = 1;
|
1999-02-07 03:56:55 +03:00
|
|
|
/* 4.2BSD: don't add directory entries. */
|
|
|
|
if (opt_add("write_opt=nodir") < 0)
|
|
|
|
tar_usage();
|
|
|
|
|
|
|
|
} else {
|
|
|
|
/* SUS: don't preserve owner/group. */
|
|
|
|
pids = 0;
|
|
|
|
nopids = 1;
|
|
|
|
}
|
1994-06-13 20:13:35 +04:00
|
|
|
break;
|
2002-10-12 19:39:29 +04:00
|
|
|
case 'O':
|
|
|
|
Oflag = 1;
|
|
|
|
break;
|
1994-06-13 20:13:35 +04:00
|
|
|
case 'p':
|
|
|
|
/*
|
|
|
|
* preserve user id, group id, file
|
|
|
|
* mode, access/modification times
|
|
|
|
*/
|
1999-02-07 03:56:55 +03:00
|
|
|
if (!nopids)
|
|
|
|
pids = 1;
|
1994-06-13 20:13:35 +04:00
|
|
|
pmode = 1;
|
|
|
|
patime = 1;
|
|
|
|
pmtime = 1;
|
|
|
|
break;
|
2002-10-12 19:39:29 +04:00
|
|
|
case 'q':
|
|
|
|
/*
|
|
|
|
* select first match for a pattern only
|
|
|
|
*/
|
|
|
|
nflag = 1;
|
|
|
|
break;
|
1994-06-13 20:13:35 +04:00
|
|
|
case 'r':
|
|
|
|
case 'u':
|
|
|
|
/*
|
|
|
|
* append to the archive
|
|
|
|
*/
|
2007-01-16 22:06:41 +03:00
|
|
|
tar_set_action(APPND);
|
1994-06-13 20:13:35 +04:00
|
|
|
break;
|
2002-10-12 19:39:29 +04:00
|
|
|
case 's':
|
|
|
|
/*
|
|
|
|
* file name substitution name pattern
|
|
|
|
*/
|
|
|
|
if (rep_add(optarg) < 0) {
|
|
|
|
tar_usage();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
1994-06-13 20:13:35 +04:00
|
|
|
case 't':
|
|
|
|
/*
|
|
|
|
* list contents of the tape
|
|
|
|
*/
|
2007-01-16 22:06:41 +03:00
|
|
|
tar_set_action(LIST);
|
1994-06-13 20:13:35 +04:00
|
|
|
break;
|
|
|
|
case 'v':
|
|
|
|
/*
|
|
|
|
* verbose operation mode
|
|
|
|
*/
|
|
|
|
vflag = 1;
|
|
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
/*
|
|
|
|
* interactive file rename
|
|
|
|
*/
|
|
|
|
iflag = 1;
|
|
|
|
break;
|
|
|
|
case 'x':
|
|
|
|
/*
|
2002-10-12 19:39:29 +04:00
|
|
|
* extract an archive, preserving mode,
|
|
|
|
* and mtime if possible.
|
1994-06-13 20:13:35 +04:00
|
|
|
*/
|
2007-01-16 22:06:41 +03:00
|
|
|
tar_set_action(EXTRACT);
|
2002-10-12 19:39:29 +04:00
|
|
|
pmtime = 1;
|
1994-06-13 20:13:35 +04:00
|
|
|
break;
|
1996-03-27 02:54:13 +03:00
|
|
|
case 'z':
|
|
|
|
/*
|
|
|
|
* use gzip. Non standard option.
|
|
|
|
*/
|
|
|
|
gzip_program = GZIP_CMD;
|
|
|
|
break;
|
1994-06-13 20:13:35 +04:00
|
|
|
case 'B':
|
|
|
|
/*
|
|
|
|
* Nothing to do here, this is pax default
|
|
|
|
*/
|
|
|
|
break;
|
2002-10-12 19:39:29 +04:00
|
|
|
case 'C':
|
2006-04-16 20:20:21 +04:00
|
|
|
havechd++;
|
2002-10-12 19:39:29 +04:00
|
|
|
chdname = optarg;
|
|
|
|
break;
|
|
|
|
case 'H':
|
|
|
|
/*
|
|
|
|
* follow command line symlinks only
|
|
|
|
*/
|
|
|
|
Hflag = 1;
|
|
|
|
break;
|
|
|
|
case 'I':
|
|
|
|
case 'T':
|
|
|
|
if (++nincfiles > incfiles_max) {
|
|
|
|
incfiles_max = nincfiles + 3;
|
|
|
|
incfiles = realloc(incfiles,
|
|
|
|
sizeof(*incfiles) * incfiles_max);
|
|
|
|
if (incfiles == NULL) {
|
|
|
|
tty_warn(0, "Unable to allocate space "
|
|
|
|
"for option list");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
incfiles[nincfiles - 1].file = optarg;
|
|
|
|
incfiles[nincfiles - 1].dir = chdname;
|
|
|
|
break;
|
1994-06-13 20:13:35 +04:00
|
|
|
case 'P':
|
2002-10-12 19:39:29 +04:00
|
|
|
/*
|
|
|
|
* do not remove leading '/' from pathnames
|
|
|
|
*/
|
|
|
|
rmleadslash = 0;
|
1999-08-24 12:00:03 +04:00
|
|
|
Aflag = 1;
|
1994-06-13 20:13:35 +04:00
|
|
|
break;
|
2004-09-27 03:46:00 +04:00
|
|
|
case 'S':
|
|
|
|
/* do nothing; we already generate sparse files */
|
|
|
|
break;
|
2007-04-23 22:40:22 +04:00
|
|
|
case 'V':
|
|
|
|
/*
|
|
|
|
* semi-verbose operation mode (no listing)
|
|
|
|
*/
|
|
|
|
Vflag = 1;
|
|
|
|
break;
|
1994-06-13 20:13:35 +04:00
|
|
|
case 'X':
|
|
|
|
/*
|
1999-01-20 17:45:09 +03:00
|
|
|
* GNU tar compat: exclude the files listed in optarg
|
1994-06-13 20:13:35 +04:00
|
|
|
*/
|
1999-01-20 17:45:09 +03:00
|
|
|
if (tar_gnutar_X_compat(optarg) != 0)
|
|
|
|
tar_usage();
|
1994-06-13 20:13:35 +04:00
|
|
|
break;
|
1996-03-27 02:54:13 +03:00
|
|
|
case 'Z':
|
|
|
|
/*
|
|
|
|
* use compress.
|
|
|
|
*/
|
|
|
|
gzip_program = COMPRESS_CMD;
|
|
|
|
break;
|
1994-06-13 20:13:35 +04:00
|
|
|
case '0':
|
|
|
|
arcname = DEV_0;
|
|
|
|
break;
|
|
|
|
case '1':
|
|
|
|
arcname = DEV_1;
|
|
|
|
break;
|
|
|
|
case '4':
|
|
|
|
arcname = DEV_4;
|
|
|
|
break;
|
|
|
|
case '5':
|
|
|
|
arcname = DEV_5;
|
|
|
|
break;
|
|
|
|
case '7':
|
|
|
|
arcname = DEV_7;
|
|
|
|
break;
|
|
|
|
case '8':
|
|
|
|
arcname = DEV_8;
|
|
|
|
break;
|
2000-07-04 21:28:47 +04:00
|
|
|
case OPT_ATIME_PRESERVE:
|
|
|
|
patime = 1;
|
|
|
|
break;
|
2000-07-04 21:17:49 +04:00
|
|
|
case OPT_UNLINK:
|
|
|
|
/* Just ignore -- we always unlink first. */
|
|
|
|
break;
|
2000-07-04 21:24:47 +04:00
|
|
|
case OPT_USE_COMPRESS_PROGRAM:
|
|
|
|
gzip_program = optarg;
|
|
|
|
break;
|
2002-10-12 19:39:29 +04:00
|
|
|
case OPT_FORCE_LOCAL:
|
|
|
|
forcelocal = 1;
|
|
|
|
break;
|
2002-10-15 20:16:29 +04:00
|
|
|
case OPT_INSECURE:
|
|
|
|
secure = 0;
|
|
|
|
break;
|
2002-10-16 07:46:07 +04:00
|
|
|
case OPT_STRICT:
|
|
|
|
/* disable gnu extensions */
|
|
|
|
is_gnutar = 0;
|
|
|
|
break;
|
2002-12-08 04:35:12 +03:00
|
|
|
case OPT_EXCLUDE:
|
|
|
|
if (tar_gnutar_minus_minus_exclude(optarg) != 0)
|
|
|
|
tar_usage();
|
|
|
|
break;
|
2005-05-08 02:27:33 +04:00
|
|
|
case OPT_NORECURSE:
|
|
|
|
dflag = 1;
|
|
|
|
break;
|
2004-10-23 01:00:18 +04:00
|
|
|
#if !HAVE_NBTOOL_CONFIG_H
|
2004-10-17 22:49:55 +04:00
|
|
|
case OPT_CHROOT:
|
|
|
|
do_chroot = 1;
|
|
|
|
break;
|
2004-10-23 01:00:18 +04:00
|
|
|
#endif
|
2011-06-19 03:07:04 +04:00
|
|
|
case OPT_XZ:
|
|
|
|
gzip_program = XZ_CMD;
|
|
|
|
break;
|
1994-06-13 20:13:35 +04:00
|
|
|
default:
|
|
|
|
tar_usage();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1994-06-14 05:16:02 +04:00
|
|
|
argc -= optind;
|
|
|
|
argv += optind;
|
1994-06-13 20:13:35 +04:00
|
|
|
|
2002-10-17 03:22:59 +04:00
|
|
|
/* Tar requires an action. */
|
2002-10-17 04:42:02 +04:00
|
|
|
if (act == ERROR)
|
2002-10-17 03:22:59 +04:00
|
|
|
tar_usage();
|
|
|
|
|
2002-10-12 19:39:29 +04:00
|
|
|
/* Traditional tar behaviour (pax uses stderr unless in list mode) */
|
|
|
|
if (fstdin == 1 && act == ARCHIVE)
|
|
|
|
listf = stderr;
|
|
|
|
else
|
|
|
|
listf = stdout;
|
1999-10-23 00:59:08 +04:00
|
|
|
|
2002-10-12 19:39:29 +04:00
|
|
|
/* Traditional tar behaviour (pax wants to read file list from stdin) */
|
|
|
|
if ((act == ARCHIVE || act == APPND) && argc == 0 && nincfiles == 0)
|
|
|
|
exit(0);
|
1999-02-03 02:42:41 +03:00
|
|
|
/*
|
|
|
|
* if we are writing (ARCHIVE) specify tar, otherwise run like pax
|
2002-10-12 19:39:29 +04:00
|
|
|
* (unless -o specified)
|
1999-02-03 02:42:41 +03:00
|
|
|
*/
|
2002-10-12 19:39:29 +04:00
|
|
|
if (act == ARCHIVE || act == APPND)
|
|
|
|
frmt = &(fsub[Oflag ? F_TAR : F_USTAR]);
|
|
|
|
else if (Oflag) {
|
2003-07-08 10:00:48 +04:00
|
|
|
if (act == EXTRACT)
|
|
|
|
to_stdout = 1;
|
|
|
|
else {
|
|
|
|
tty_warn(1, "The -O/-o options are only valid when "
|
|
|
|
"writing or extracting an archive");
|
|
|
|
tar_usage();
|
|
|
|
}
|
2002-10-12 19:39:29 +04:00
|
|
|
}
|
1999-02-03 02:42:41 +03:00
|
|
|
|
1994-06-13 20:13:35 +04:00
|
|
|
/*
|
|
|
|
* process the args as they are interpreted by the operation mode
|
|
|
|
*/
|
|
|
|
switch (act) {
|
|
|
|
case LIST:
|
1999-10-23 00:59:08 +04:00
|
|
|
case EXTRACT:
|
2002-10-12 19:39:29 +04:00
|
|
|
default:
|
|
|
|
{
|
|
|
|
int sawpat = 0;
|
2002-10-18 17:45:05 +04:00
|
|
|
int dirisnext = 0;
|
2006-03-19 22:06:39 +03:00
|
|
|
char *file, *dir = NULL;
|
2008-11-23 13:08:50 +03:00
|
|
|
int mustfreedir = 0;
|
2002-10-12 19:39:29 +04:00
|
|
|
|
|
|
|
while (nincfiles || *argv != NULL) {
|
|
|
|
/*
|
|
|
|
* If we queued up any include files,
|
|
|
|
* pull them in now. Otherwise, check
|
|
|
|
* for -I and -C positional flags.
|
|
|
|
* Anything else must be a file to
|
|
|
|
* extract.
|
|
|
|
*/
|
|
|
|
if (nincfiles) {
|
|
|
|
file = incfiles->file;
|
|
|
|
dir = incfiles->dir;
|
2008-11-23 13:08:50 +03:00
|
|
|
mustfreedir = 0;
|
2002-10-12 19:39:29 +04:00
|
|
|
incfiles++;
|
|
|
|
nincfiles--;
|
|
|
|
} else if (strcmp(*argv, "-I") == 0) {
|
|
|
|
if (*++argv == NULL)
|
|
|
|
break;
|
|
|
|
file = *argv++;
|
|
|
|
dir = chdname;
|
2008-11-23 13:08:50 +03:00
|
|
|
mustfreedir = 0;
|
2005-06-01 19:25:51 +04:00
|
|
|
} else {
|
2002-10-12 19:39:29 +04:00
|
|
|
file = NULL;
|
2005-06-01 19:25:51 +04:00
|
|
|
dir = NULL;
|
2008-11-23 13:08:50 +03:00
|
|
|
mustfreedir = 0;
|
2005-06-01 19:25:51 +04:00
|
|
|
}
|
2002-10-12 19:39:29 +04:00
|
|
|
if (file != NULL) {
|
|
|
|
FILE *fp;
|
|
|
|
char *str;
|
|
|
|
|
|
|
|
if (strcmp(file, "-") == 0)
|
|
|
|
fp = stdin;
|
|
|
|
else if ((fp = fopen(file, "r")) == NULL) {
|
|
|
|
tty_warn(1, "Unable to open file '%s' for read", file);
|
|
|
|
tar_usage();
|
|
|
|
}
|
2009-07-13 23:05:39 +04:00
|
|
|
while ((str = get_line(fp)) != NULL) {
|
2002-10-18 17:45:05 +04:00
|
|
|
if (dirisnext) {
|
2008-11-23 13:08:50 +03:00
|
|
|
if (dir && mustfreedir)
|
2006-03-19 22:06:39 +03:00
|
|
|
free(dir);
|
2002-10-18 17:45:05 +04:00
|
|
|
dir = str;
|
2008-11-23 13:08:50 +03:00
|
|
|
mustfreedir = 1;
|
2002-10-18 17:45:05 +04:00
|
|
|
dirisnext = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (strcmp(str, "-C") == 0) {
|
2006-04-16 20:20:21 +04:00
|
|
|
havechd++;
|
2002-10-18 17:45:05 +04:00
|
|
|
dirisnext = 1;
|
2006-03-18 08:40:28 +03:00
|
|
|
free(str);
|
2002-10-18 17:45:05 +04:00
|
|
|
continue;
|
|
|
|
}
|
2004-10-11 02:05:26 +04:00
|
|
|
if (strncmp(str, "-C ", 3) == 0) {
|
2006-04-16 20:20:21 +04:00
|
|
|
havechd++;
|
2008-11-23 13:08:50 +03:00
|
|
|
if (dir && mustfreedir)
|
2006-03-19 22:06:39 +03:00
|
|
|
free(dir);
|
2006-03-18 08:40:28 +03:00
|
|
|
dir = strdup(str + 3);
|
2008-11-23 13:08:50 +03:00
|
|
|
mustfreedir = 1;
|
2006-03-18 08:40:28 +03:00
|
|
|
free(str);
|
2004-10-11 02:05:26 +04:00
|
|
|
continue;
|
|
|
|
}
|
2009-04-07 23:52:35 +04:00
|
|
|
if (pat_add(str, dir, NOGLOB_MTCH) < 0)
|
2002-10-12 19:39:29 +04:00
|
|
|
tar_usage();
|
|
|
|
sawpat = 1;
|
|
|
|
}
|
2002-10-18 17:45:05 +04:00
|
|
|
/* Bomb if given -C w/out a dir. */
|
|
|
|
if (dirisnext)
|
|
|
|
tar_usage();
|
2008-11-23 13:08:50 +03:00
|
|
|
if (dir && mustfreedir)
|
2006-03-19 22:06:39 +03:00
|
|
|
free(dir);
|
2002-10-12 19:39:29 +04:00
|
|
|
if (strcmp(file, "-") != 0)
|
|
|
|
fclose(fp);
|
2009-07-13 23:05:39 +04:00
|
|
|
if (get_line_error) {
|
2002-10-12 19:39:29 +04:00
|
|
|
tty_warn(1, "Problem with file '%s'", file);
|
|
|
|
tar_usage();
|
|
|
|
}
|
|
|
|
} else if (strcmp(*argv, "-C") == 0) {
|
|
|
|
if (*++argv == NULL)
|
|
|
|
break;
|
|
|
|
chdname = *argv++;
|
2006-04-16 20:20:21 +04:00
|
|
|
havechd++;
|
2009-04-07 23:52:35 +04:00
|
|
|
} else if (pat_add(*argv++, chdname, 0) < 0)
|
2002-10-12 19:39:29 +04:00
|
|
|
tar_usage();
|
|
|
|
else
|
|
|
|
sawpat = 1;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* if patterns were added, we are doing chdir()
|
|
|
|
* on a file-by-file basis, else, just one
|
|
|
|
* global chdir (if any) after opening input.
|
|
|
|
*/
|
|
|
|
if (sawpat > 0)
|
|
|
|
chdname = NULL;
|
|
|
|
}
|
1999-10-23 00:59:08 +04:00
|
|
|
break;
|
1994-06-13 20:13:35 +04:00
|
|
|
case ARCHIVE:
|
|
|
|
case APPND:
|
2002-10-12 19:39:29 +04:00
|
|
|
if (chdname != NULL) { /* initial chdir() */
|
|
|
|
if (ftree_add(chdname, 1) < 0)
|
|
|
|
tar_usage();
|
|
|
|
}
|
|
|
|
|
|
|
|
while (nincfiles || *argv != NULL) {
|
|
|
|
char *file, *dir;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we queued up any include files, pull them in
|
|
|
|
* now. Otherwise, check for -I and -C positional
|
|
|
|
* flags. Anything else must be a file to include
|
|
|
|
* in the archive.
|
|
|
|
*/
|
|
|
|
if (nincfiles) {
|
|
|
|
file = incfiles->file;
|
|
|
|
dir = incfiles->dir;
|
|
|
|
incfiles++;
|
|
|
|
nincfiles--;
|
|
|
|
} else if (strcmp(*argv, "-I") == 0) {
|
|
|
|
if (*++argv == NULL)
|
|
|
|
break;
|
|
|
|
file = *argv++;
|
|
|
|
dir = NULL;
|
2005-06-01 19:25:51 +04:00
|
|
|
} else {
|
2002-10-12 19:39:29 +04:00
|
|
|
file = NULL;
|
2005-06-01 19:25:51 +04:00
|
|
|
dir = NULL;
|
|
|
|
}
|
2002-10-12 19:39:29 +04:00
|
|
|
if (file != NULL) {
|
|
|
|
FILE *fp;
|
|
|
|
char *str;
|
2002-10-18 17:45:05 +04:00
|
|
|
int dirisnext = 0;
|
2002-10-12 19:39:29 +04:00
|
|
|
|
|
|
|
/* Set directory if needed */
|
|
|
|
if (dir) {
|
|
|
|
if (ftree_add(dir, 1) < 0)
|
|
|
|
tar_usage();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp(file, "-") == 0)
|
|
|
|
fp = stdin;
|
|
|
|
else if ((fp = fopen(file, "r")) == NULL) {
|
|
|
|
tty_warn(1, "Unable to open file '%s' for read", file);
|
|
|
|
tar_usage();
|
|
|
|
}
|
2009-07-13 23:05:39 +04:00
|
|
|
while ((str = get_line(fp)) != NULL) {
|
2002-10-18 17:45:05 +04:00
|
|
|
if (dirisnext) {
|
|
|
|
if (ftree_add(str, 1) < 0)
|
|
|
|
tar_usage();
|
|
|
|
dirisnext = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (strcmp(str, "-C") == 0) {
|
|
|
|
dirisnext = 1;
|
|
|
|
continue;
|
|
|
|
}
|
2004-10-11 02:05:26 +04:00
|
|
|
if (strncmp(str, "-C ", 3) == 0) {
|
|
|
|
if (ftree_add(str + 3, 1) < 0)
|
|
|
|
tar_usage();
|
|
|
|
continue;
|
|
|
|
}
|
2002-10-12 19:39:29 +04:00
|
|
|
if (ftree_add(str, 0) < 0)
|
|
|
|
tar_usage();
|
|
|
|
}
|
2002-10-18 17:45:05 +04:00
|
|
|
/* Bomb if given -C w/out a dir. */
|
|
|
|
if (dirisnext)
|
|
|
|
tar_usage();
|
2002-10-12 19:39:29 +04:00
|
|
|
if (strcmp(file, "-") != 0)
|
|
|
|
fclose(fp);
|
2009-07-13 23:05:39 +04:00
|
|
|
if (get_line_error) {
|
2002-10-12 19:39:29 +04:00
|
|
|
tty_warn(1, "Problem with file '%s'",
|
|
|
|
file);
|
|
|
|
tar_usage();
|
|
|
|
}
|
|
|
|
} else if (strcmp(*argv, "-C") == 0) {
|
|
|
|
if (*++argv == NULL)
|
|
|
|
break;
|
|
|
|
if (ftree_add(*argv++, 1) < 0)
|
|
|
|
tar_usage();
|
|
|
|
} else if (ftree_add(*argv++, 0) < 0)
|
|
|
|
tar_usage();
|
|
|
|
}
|
1994-06-13 20:13:35 +04:00
|
|
|
/*
|
|
|
|
* no read errors allowed on updates/append operation!
|
|
|
|
*/
|
|
|
|
maxflt = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!fstdin && ((arcname == (char *)NULL) || (*arcname == '\0'))) {
|
|
|
|
arcname = getenv("TAPE");
|
2002-10-12 19:39:29 +04:00
|
|
|
if ((arcname == NULL) || (*arcname == '\0'))
|
|
|
|
arcname = _PATH_DEFTAPE;
|
1994-06-13 20:13:35 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-10-12 19:39:29 +04:00
|
|
|
int
|
|
|
|
mkpath(path)
|
|
|
|
char *path;
|
|
|
|
{
|
|
|
|
char *slash;
|
2005-09-16 20:48:18 +04:00
|
|
|
int done = 0;
|
2002-10-12 19:39:29 +04:00
|
|
|
|
|
|
|
slash = path;
|
|
|
|
|
|
|
|
while (!done) {
|
|
|
|
slash += strspn(slash, "/");
|
|
|
|
slash += strcspn(slash, "/");
|
|
|
|
|
|
|
|
done = (*slash == '\0');
|
|
|
|
*slash = '\0';
|
|
|
|
|
2005-09-16 20:48:18 +04:00
|
|
|
if (domkdir(path, 0777) == -1)
|
2005-09-14 00:09:55 +04:00
|
|
|
goto out;
|
2002-10-12 19:39:29 +04:00
|
|
|
|
|
|
|
if (!done)
|
|
|
|
*slash = '/';
|
|
|
|
}
|
|
|
|
|
2005-09-13 19:50:17 +04:00
|
|
|
return 0;
|
2005-09-14 00:09:55 +04:00
|
|
|
out:
|
|
|
|
/* Can't create or or not a directory */
|
2005-09-16 20:48:18 +04:00
|
|
|
syswarn(1, errno, "Cannot create directory `%s'", path);
|
2005-09-14 00:09:55 +04:00
|
|
|
return -1;
|
2002-10-12 19:39:29 +04:00
|
|
|
}
|
|
|
|
|
2002-10-15 18:51:04 +04:00
|
|
|
|
2005-06-29 06:21:27 +04:00
|
|
|
#ifndef NO_CPIO
|
2002-10-15 18:51:04 +04:00
|
|
|
struct option cpio_longopts[] = {
|
|
|
|
{ "reset-access-time", no_argument, 0, 'a' },
|
|
|
|
{ "make-directories", no_argument, 0, 'd' },
|
|
|
|
{ "nonmatching", no_argument, 0, 'f' },
|
|
|
|
{ "extract", no_argument, 0, 'i' },
|
|
|
|
{ "link", no_argument, 0, 'l' },
|
|
|
|
{ "preserve-modification-time", no_argument, 0, 'm' },
|
|
|
|
{ "create", no_argument, 0, 'o' },
|
|
|
|
{ "pass-through", no_argument, 0, 'p' },
|
|
|
|
{ "rename", no_argument, 0, 'r' },
|
|
|
|
{ "list", no_argument, 0, 't' },
|
|
|
|
{ "unconditional", no_argument, 0, 'u' },
|
|
|
|
{ "verbose", no_argument, 0, 'v' },
|
|
|
|
{ "append", no_argument, 0, 'A' },
|
|
|
|
{ "pattern-file", required_argument, 0, 'E' },
|
|
|
|
{ "file", required_argument, 0, 'F' },
|
|
|
|
{ "force-local", no_argument, 0,
|
2002-10-15 20:16:29 +04:00
|
|
|
OPT_FORCE_LOCAL },
|
2002-10-15 18:51:04 +04:00
|
|
|
{ "format", required_argument, 0, 'H' },
|
|
|
|
{ "dereference", no_argument, 0, 'L' },
|
|
|
|
{ "swap-halfwords", no_argument, 0, 'S' },
|
2007-04-23 22:40:22 +04:00
|
|
|
{ "summary", no_argument, 0, 'V' },
|
|
|
|
{ "stats", no_argument, 0, 'V' },
|
2002-10-15 20:16:29 +04:00
|
|
|
{ "insecure", no_argument, 0,
|
|
|
|
OPT_INSECURE },
|
2004-09-27 03:46:00 +04:00
|
|
|
{ "sparse", no_argument, 0,
|
|
|
|
OPT_SPARSE },
|
2011-06-19 03:07:04 +04:00
|
|
|
{ "xz", no_argument, 0,
|
|
|
|
OPT_XZ },
|
2002-10-15 18:51:04 +04:00
|
|
|
|
|
|
|
#ifdef notyet
|
|
|
|
/* Not implemented */
|
|
|
|
{ "null", no_argument, 0, '0' },
|
|
|
|
{ "swap", no_argument, 0, 'b' },
|
|
|
|
{ "numeric-uid-gid", no_argument, 0, 'n' },
|
|
|
|
{ "swap-bytes", no_argument, 0, 's' },
|
|
|
|
{ "message", required_argument, 0, 'M' },
|
|
|
|
{ "owner", required_argument, 0 'R' },
|
2007-04-23 22:40:22 +04:00
|
|
|
{ "dot", no_argument, 0, 'V' }, /* xxx */
|
2002-10-15 18:51:04 +04:00
|
|
|
{ "block-size", required_argument, 0,
|
2002-10-15 20:16:29 +04:00
|
|
|
OPT_BLOCK_SIZE },
|
2002-10-15 18:51:04 +04:00
|
|
|
{ "no-absolute-pathnames", no_argument, 0,
|
2002-10-15 20:16:29 +04:00
|
|
|
OPT_NO_ABSOLUTE_PATHNAMES },
|
2002-10-15 18:51:04 +04:00
|
|
|
{ "no-preserve-owner", no_argument, 0,
|
2002-10-15 20:16:29 +04:00
|
|
|
OPT_NO_PRESERVE_OWNER },
|
2002-10-15 18:51:04 +04:00
|
|
|
{ "only-verify-crc", no_argument, 0,
|
2002-10-15 20:16:29 +04:00
|
|
|
OPT_ONLY_VERIFY_CRC },
|
2002-10-15 18:51:04 +04:00
|
|
|
{ "rsh-command", required_argument, 0,
|
2002-10-15 20:16:29 +04:00
|
|
|
OPT_RSH_COMMAND },
|
2002-10-15 18:51:04 +04:00
|
|
|
{ "version", no_argument, 0,
|
2002-10-15 20:16:29 +04:00
|
|
|
OPT_VERSION },
|
2002-10-15 18:51:04 +04:00
|
|
|
#endif
|
2005-02-10 20:48:33 +03:00
|
|
|
{ 0, 0, 0, 0 },
|
2002-10-15 18:51:04 +04:00
|
|
|
};
|
|
|
|
|
2007-01-16 22:06:41 +03:00
|
|
|
static void
|
|
|
|
cpio_set_action(int op)
|
|
|
|
{
|
|
|
|
if ((act == APPND && op == ARCHIVE) || (act == ARCHIVE && op == APPND))
|
|
|
|
act = APPND;
|
2010-08-26 01:36:02 +04:00
|
|
|
else if (act == EXTRACT && op == LIST)
|
|
|
|
act = op;
|
2007-01-16 22:06:41 +03:00
|
|
|
else if (act != ERROR && act != op)
|
|
|
|
cpio_usage();
|
|
|
|
else
|
|
|
|
act = op;
|
|
|
|
}
|
|
|
|
|
1994-06-13 20:13:35 +04:00
|
|
|
/*
|
|
|
|
* cpio_options()
|
|
|
|
* look at the user specified flags. set globals as required and check if
|
|
|
|
* the user specified a legal set of flags. If not, complain and exit
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
1997-01-11 05:04:27 +03:00
|
|
|
cpio_options(int argc, char **argv)
|
1994-06-13 20:13:35 +04:00
|
|
|
{
|
2000-02-17 06:12:22 +03:00
|
|
|
FSUB tmp;
|
2007-04-23 22:40:22 +04:00
|
|
|
u_int64_t flg = 0;
|
|
|
|
u_int64_t bflg = 0;
|
2009-02-14 11:02:04 +03:00
|
|
|
int c;
|
|
|
|
size_t i;
|
2002-10-12 19:39:29 +04:00
|
|
|
FILE *fp;
|
|
|
|
char *str;
|
|
|
|
|
|
|
|
uflag = 1;
|
|
|
|
kflag = 1;
|
|
|
|
pids = 1;
|
|
|
|
pmode = 1;
|
|
|
|
pmtime = 0;
|
|
|
|
arcname = NULL;
|
|
|
|
dflag = 1;
|
|
|
|
nodirs = 1;
|
1998-03-06 12:13:01 +03:00
|
|
|
/*
|
|
|
|
* process option flags
|
|
|
|
*/
|
2000-07-04 21:17:49 +04:00
|
|
|
while ((c = getoldopt(argc, argv,
|
2002-10-15 20:16:29 +04:00
|
|
|
"+abcdfiklmoprstuvzABC:E:F:H:I:LM:O:R:SVZ6",
|
2002-10-15 18:51:04 +04:00
|
|
|
cpio_longopts, NULL)) != -1) {
|
1998-03-06 12:13:01 +03:00
|
|
|
switch(c) {
|
|
|
|
case 'a':
|
|
|
|
/*
|
|
|
|
* preserve access time on filesystem nodes we read
|
|
|
|
*/
|
|
|
|
tflag = 1;
|
|
|
|
flg |= TF;
|
|
|
|
break;
|
|
|
|
#ifdef notyet
|
|
|
|
case 'b':
|
2002-10-12 19:39:29 +04:00
|
|
|
/*
|
|
|
|
* swap bytes and half-words when reading data
|
|
|
|
*/
|
1998-03-06 12:13:01 +03:00
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case 'c':
|
2002-10-12 19:39:29 +04:00
|
|
|
/*
|
|
|
|
* ASCII cpio header
|
|
|
|
*/
|
1998-03-06 12:13:01 +03:00
|
|
|
frmt = &fsub[F_SV4CPIO];
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
/*
|
2002-10-12 19:39:29 +04:00
|
|
|
* create directories as needed
|
1998-03-06 12:13:01 +03:00
|
|
|
* pax does this by default ..
|
|
|
|
*/
|
2002-10-12 19:39:29 +04:00
|
|
|
nodirs = 0;
|
1998-03-06 12:13:01 +03:00
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
/*
|
|
|
|
* inverse match on patterns
|
|
|
|
*/
|
|
|
|
cflag = 1;
|
|
|
|
flg |= CF;
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
/*
|
|
|
|
* read the archive
|
|
|
|
*/
|
2007-01-16 22:06:41 +03:00
|
|
|
cpio_set_action(EXTRACT);
|
1998-03-06 12:13:01 +03:00
|
|
|
flg |= RF;
|
|
|
|
break;
|
|
|
|
#ifdef notyet
|
|
|
|
case 'k':
|
|
|
|
break;
|
1994-06-13 20:13:35 +04:00
|
|
|
#endif
|
1998-03-06 12:13:01 +03:00
|
|
|
case 'l':
|
|
|
|
/*
|
|
|
|
* try to link src to dest with copy (-rw)
|
|
|
|
*/
|
|
|
|
lflag = 1;
|
|
|
|
flg |= LF;
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
/*
|
|
|
|
* preserve mtime
|
|
|
|
*/
|
|
|
|
flg |= PF;
|
|
|
|
pmtime = 1;
|
|
|
|
break;
|
|
|
|
case 'o':
|
|
|
|
/*
|
|
|
|
* write an archive
|
|
|
|
*/
|
2007-01-16 22:06:41 +03:00
|
|
|
cpio_set_action(ARCHIVE);
|
2002-10-12 19:39:29 +04:00
|
|
|
frmt = &(fsub[F_SV4CRC]);
|
1998-03-06 12:13:01 +03:00
|
|
|
flg |= WF;
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
/*
|
|
|
|
* cpio -p is like pax -rw
|
|
|
|
*/
|
2007-01-16 22:06:41 +03:00
|
|
|
cpio_set_action(COPY);
|
1998-03-06 12:13:01 +03:00
|
|
|
flg |= RF | WF;
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
/*
|
|
|
|
* interactive file rename
|
|
|
|
*/
|
|
|
|
iflag = 1;
|
|
|
|
flg |= IF;
|
|
|
|
break;
|
|
|
|
#ifdef notyet
|
|
|
|
case 's':
|
2002-10-12 19:39:29 +04:00
|
|
|
/*
|
|
|
|
* swap bytes after reading data
|
|
|
|
*/
|
1998-03-06 12:13:01 +03:00
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case 't':
|
2002-10-12 19:39:29 +04:00
|
|
|
/*
|
|
|
|
* list contents of archive
|
|
|
|
*/
|
2007-01-16 22:06:41 +03:00
|
|
|
cpio_set_action(LIST);
|
2002-10-12 19:39:29 +04:00
|
|
|
listf = stdout;
|
2004-10-26 20:11:49 +04:00
|
|
|
flg &= ~RF;
|
1998-03-06 12:13:01 +03:00
|
|
|
break;
|
|
|
|
case 'u':
|
|
|
|
/*
|
|
|
|
* don't ignore those older files
|
|
|
|
*/
|
|
|
|
uflag = 0;
|
2002-10-12 19:39:29 +04:00
|
|
|
kflag = 0;
|
1998-03-06 12:13:01 +03:00
|
|
|
flg |= UF;
|
|
|
|
break;
|
|
|
|
case 'v':
|
|
|
|
/*
|
|
|
|
* verbose operation mode
|
|
|
|
*/
|
|
|
|
vflag = 1;
|
|
|
|
flg |= VF;
|
|
|
|
break;
|
2002-10-12 19:39:29 +04:00
|
|
|
case 'z':
|
|
|
|
/*
|
|
|
|
* use gzip. Non standard option.
|
|
|
|
*/
|
|
|
|
gzip_program = GZIP_CMD;
|
|
|
|
break;
|
|
|
|
case 'A':
|
|
|
|
/*
|
|
|
|
* append to an archive
|
|
|
|
*/
|
2007-01-16 22:06:41 +03:00
|
|
|
cpio_set_action(APPND);
|
2002-10-12 19:39:29 +04:00
|
|
|
flg |= AF;
|
|
|
|
break;
|
|
|
|
case 'B':
|
|
|
|
/*
|
|
|
|
* set blocksize to 5120
|
|
|
|
*/
|
|
|
|
blksz = 5120;
|
|
|
|
break;
|
|
|
|
case 'C':
|
|
|
|
/*
|
|
|
|
* specify blocksize
|
|
|
|
*/
|
|
|
|
if ((blksz = (int)str_offt(optarg)) <= 0) {
|
|
|
|
tty_warn(1, "Invalid block size %s", optarg);
|
2003-01-16 00:56:46 +03:00
|
|
|
cpio_usage();
|
2002-10-12 19:39:29 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'E':
|
|
|
|
/*
|
|
|
|
* file with patterns to extract or list
|
|
|
|
*/
|
|
|
|
if ((fp = fopen(optarg, "r")) == NULL) {
|
|
|
|
tty_warn(1, "Unable to open file '%s' for read",
|
|
|
|
optarg);
|
|
|
|
cpio_usage();
|
|
|
|
}
|
2009-07-13 23:05:39 +04:00
|
|
|
while ((str = get_line(fp)) != NULL) {
|
2009-04-07 23:52:35 +04:00
|
|
|
pat_add(str, NULL, 0);
|
2002-10-12 19:39:29 +04:00
|
|
|
}
|
|
|
|
fclose(fp);
|
2009-07-13 23:05:39 +04:00
|
|
|
if (get_line_error) {
|
2002-10-12 19:39:29 +04:00
|
|
|
tty_warn(1, "Problem with file '%s'", optarg);
|
|
|
|
cpio_usage();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'H':
|
|
|
|
/*
|
|
|
|
* specify an archive format on write
|
|
|
|
*/
|
|
|
|
tmp.name = optarg;
|
|
|
|
frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
|
|
|
|
sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt);
|
|
|
|
if (frmt != NULL) {
|
|
|
|
flg |= XF;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
tty_warn(1, "Unknown -H format: %s", optarg);
|
|
|
|
(void)fputs("cpio: Known -H formats are:", stderr);
|
|
|
|
for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
|
|
|
|
(void)fprintf(stderr, " %s", fsub[i].name);
|
|
|
|
(void)fputs("\n\n", stderr);
|
2003-01-16 00:56:46 +03:00
|
|
|
cpio_usage();
|
2002-10-12 19:39:29 +04:00
|
|
|
break;
|
2010-08-31 07:16:06 +04:00
|
|
|
case 'F':
|
2002-10-12 19:39:29 +04:00
|
|
|
case 'I':
|
|
|
|
case 'O':
|
|
|
|
/*
|
|
|
|
* filename where the archive is stored
|
|
|
|
*/
|
|
|
|
if ((optarg[0] == '-') && (optarg[1]== '\0')) {
|
|
|
|
/*
|
|
|
|
* treat a - as stdin
|
|
|
|
*/
|
|
|
|
arcname = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
arcname = optarg;
|
|
|
|
break;
|
|
|
|
case 'L':
|
|
|
|
/*
|
|
|
|
* follow symlinks
|
|
|
|
*/
|
|
|
|
Lflag = 1;
|
|
|
|
flg |= CLF;
|
|
|
|
break;
|
|
|
|
#ifdef notyet
|
|
|
|
case 'M':
|
|
|
|
arg = optarg;
|
|
|
|
break;
|
|
|
|
case 'R':
|
|
|
|
arg = optarg;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case 'S':
|
|
|
|
/*
|
|
|
|
* swap halfwords after reading data
|
|
|
|
*/
|
|
|
|
cpio_swp_head = 1;
|
|
|
|
break;
|
|
|
|
#ifdef notyet
|
2007-04-23 22:40:22 +04:00
|
|
|
case 'V': /* print a '.' for each file processed */
|
2002-10-12 19:39:29 +04:00
|
|
|
break;
|
|
|
|
#endif
|
2007-04-23 22:40:22 +04:00
|
|
|
case 'V':
|
|
|
|
/*
|
|
|
|
* semi-verbose operation mode (no listing)
|
|
|
|
*/
|
|
|
|
Vflag = 1;
|
|
|
|
flg |= VF;
|
|
|
|
break;
|
2002-10-12 19:39:29 +04:00
|
|
|
case 'Z':
|
|
|
|
/*
|
|
|
|
* use compress. Non standard option.
|
|
|
|
*/
|
|
|
|
gzip_program = COMPRESS_CMD;
|
|
|
|
break;
|
|
|
|
case '6':
|
|
|
|
/*
|
|
|
|
* process Version 6 cpio format
|
|
|
|
*/
|
|
|
|
frmt = &(fsub[F_BCPIO]);
|
2010-08-31 07:16:06 +04:00
|
|
|
break;
|
2002-10-15 18:51:04 +04:00
|
|
|
case OPT_FORCE_LOCAL:
|
|
|
|
forcelocal = 1;
|
|
|
|
break;
|
2002-10-15 20:16:29 +04:00
|
|
|
case OPT_INSECURE:
|
|
|
|
secure = 0;
|
|
|
|
break;
|
2004-09-27 03:46:00 +04:00
|
|
|
case OPT_SPARSE:
|
|
|
|
/* do nothing; we already generate sparse files */
|
|
|
|
break;
|
2011-06-19 03:07:04 +04:00
|
|
|
case OPT_XZ:
|
|
|
|
gzip_program = XZ_CMD;
|
|
|
|
break;
|
1998-03-06 12:13:01 +03:00
|
|
|
default:
|
|
|
|
cpio_usage();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* figure out the operation mode of cpio. check that we have not been
|
|
|
|
* given a bogus set of flags for the operation mode.
|
|
|
|
*/
|
|
|
|
if (ISLIST(flg)) {
|
|
|
|
act = LIST;
|
|
|
|
bflg = flg & BDLIST;
|
|
|
|
} else if (ISEXTRACT(flg)) {
|
|
|
|
act = EXTRACT;
|
|
|
|
bflg = flg & BDEXTR;
|
|
|
|
} else if (ISARCHIVE(flg)) {
|
|
|
|
act = ARCHIVE;
|
|
|
|
bflg = flg & BDARCH;
|
|
|
|
} else if (ISAPPND(flg)) {
|
|
|
|
act = APPND;
|
|
|
|
bflg = flg & BDARCH;
|
|
|
|
} else if (ISCOPY(flg)) {
|
|
|
|
act = COPY;
|
|
|
|
bflg = flg & BDCOPY;
|
|
|
|
} else
|
|
|
|
cpio_usage();
|
|
|
|
if (bflg) {
|
|
|
|
cpio_usage();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* if we are writing (ARCHIVE) we use the default format if the user
|
|
|
|
* did not specify a format. when we write during an APPEND, we will
|
|
|
|
* adopt the format of the existing archive if none was supplied.
|
|
|
|
*/
|
|
|
|
if (!(flg & XF) && (act == ARCHIVE))
|
|
|
|
frmt = &(fsub[F_BCPIO]);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* process the args as they are interpreted by the operation mode
|
|
|
|
*/
|
|
|
|
switch (act) {
|
|
|
|
case LIST:
|
|
|
|
case EXTRACT:
|
|
|
|
for (; optind < argc; optind++)
|
2009-04-07 23:52:35 +04:00
|
|
|
if (pat_add(argv[optind], NULL, 0) < 0)
|
1998-03-06 12:13:01 +03:00
|
|
|
cpio_usage();
|
|
|
|
break;
|
|
|
|
case COPY:
|
|
|
|
if (optind >= argc) {
|
|
|
|
tty_warn(0, "Destination directory was not supplied");
|
|
|
|
cpio_usage();
|
|
|
|
}
|
|
|
|
--argc;
|
|
|
|
dirptr = argv[argc];
|
1998-07-28 21:44:23 +04:00
|
|
|
/* FALLTHROUGH */
|
1998-03-06 12:13:01 +03:00
|
|
|
case ARCHIVE:
|
|
|
|
case APPND:
|
2002-10-12 19:39:29 +04:00
|
|
|
if (argc != optind) {
|
|
|
|
for (; optind < argc; optind++)
|
|
|
|
if (ftree_add(argv[optind], 0) < 0)
|
|
|
|
cpio_usage();
|
|
|
|
break;
|
|
|
|
}
|
1998-03-06 12:13:01 +03:00
|
|
|
/*
|
|
|
|
* no read errors allowed on updates/append operation!
|
|
|
|
*/
|
|
|
|
maxflt = 0;
|
2009-07-13 23:05:39 +04:00
|
|
|
while ((str = get_line(stdin)) != NULL) {
|
2003-10-21 06:08:14 +04:00
|
|
|
ftree_add(str, 0);
|
2002-10-12 19:39:29 +04:00
|
|
|
}
|
2009-07-13 23:05:39 +04:00
|
|
|
if (get_line_error) {
|
2002-10-12 19:39:29 +04:00
|
|
|
tty_warn(1, "Problem while reading stdin");
|
|
|
|
cpio_usage();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
cpio_usage();
|
1998-03-06 12:13:01 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2005-06-29 06:21:27 +04:00
|
|
|
#endif
|
1994-06-13 20:13:35 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* printflg()
|
|
|
|
* print out those invalid flag sets found to the user
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
|
|
|
printflg(unsigned int flg)
|
|
|
|
{
|
|
|
|
int nxt;
|
|
|
|
|
|
|
|
(void)fprintf(stderr,"%s: Invalid combination of options:", argv0);
|
1997-07-21 00:32:15 +04:00
|
|
|
while ((nxt = ffs(flg)) != 0) {
|
2004-01-05 20:27:46 +03:00
|
|
|
flg &= ~(1 << (nxt - 1));
|
|
|
|
(void)fprintf(stderr, " -%c", flgch[nxt - 1]);
|
1994-06-13 20:13:35 +04:00
|
|
|
}
|
|
|
|
(void)putc('\n', stderr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* c_frmt()
|
|
|
|
* comparison routine used by bsearch to find the format specified
|
|
|
|
* by the user
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int
|
|
|
|
c_frmt(const void *a, const void *b)
|
|
|
|
{
|
2006-02-11 13:43:17 +03:00
|
|
|
return strcmp(((const FSUB *)a)->name, ((const FSUB *)b)->name);
|
1994-06-13 20:13:35 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* opt_next()
|
|
|
|
* called by format specific options routines to get each format specific
|
|
|
|
* flag and value specified with -o
|
|
|
|
* Return:
|
|
|
|
* pointer to next OPLIST entry or NULL (end of list).
|
|
|
|
*/
|
|
|
|
|
|
|
|
OPLIST *
|
|
|
|
opt_next(void)
|
|
|
|
{
|
|
|
|
OPLIST *opt;
|
|
|
|
|
|
|
|
if ((opt = ophead) != NULL)
|
|
|
|
ophead = ophead->fow;
|
2006-02-11 13:43:17 +03:00
|
|
|
return opt;
|
1994-06-13 20:13:35 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* bad_opt()
|
|
|
|
* generic routine used to complain about a format specific options
|
|
|
|
* when the format does not support options.
|
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
|
|
|
bad_opt(void)
|
|
|
|
{
|
1997-01-11 05:04:27 +03:00
|
|
|
OPLIST *opt;
|
1994-06-13 20:13:35 +04:00
|
|
|
|
|
|
|
if (ophead == NULL)
|
2006-02-11 13:43:17 +03:00
|
|
|
return 0;
|
1994-06-13 20:13:35 +04:00
|
|
|
/*
|
|
|
|
* print all we were given
|
|
|
|
*/
|
2002-10-16 07:46:07 +04:00
|
|
|
tty_warn(1," These format options are not supported for %s",
|
|
|
|
frmt->name);
|
1994-06-13 20:13:35 +04:00
|
|
|
while ((opt = opt_next()) != NULL)
|
|
|
|
(void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value);
|
2002-10-16 07:46:07 +04:00
|
|
|
if (strcmp(NM_TAR, argv0) == 0)
|
|
|
|
tar_usage();
|
2005-06-29 06:21:27 +04:00
|
|
|
#ifndef NO_CPIO
|
2002-10-16 07:46:07 +04:00
|
|
|
else if (strcmp(NM_CPIO, argv0) == 0)
|
|
|
|
cpio_usage();
|
2005-06-29 06:21:27 +04:00
|
|
|
#endif
|
2002-10-16 07:46:07 +04:00
|
|
|
else
|
|
|
|
pax_usage();
|
2006-02-11 13:43:17 +03:00
|
|
|
return 0;
|
1994-06-13 20:13:35 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* opt_add()
|
|
|
|
* breaks the value supplied to -o into a option name and value. options
|
|
|
|
* are given to -o in the form -o name-value,name=value
|
2000-02-17 06:12:22 +03:00
|
|
|
* multiple -o may be specified.
|
1994-06-13 20:13:35 +04:00
|
|
|
* Return:
|
|
|
|
* 0 if format in name=value format, -1 if -o is passed junk
|
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
1999-02-07 03:56:55 +03:00
|
|
|
opt_add(const char *str)
|
1994-06-13 20:13:35 +04:00
|
|
|
{
|
1997-01-11 05:04:27 +03:00
|
|
|
OPLIST *opt;
|
|
|
|
char *frpt;
|
|
|
|
char *pt;
|
|
|
|
char *endpt;
|
2002-10-12 19:39:29 +04:00
|
|
|
char *dstr;
|
1994-06-13 20:13:35 +04:00
|
|
|
|
|
|
|
if ((str == NULL) || (*str == '\0')) {
|
1997-07-21 00:32:15 +04:00
|
|
|
tty_warn(0, "Invalid option name");
|
2006-02-11 13:43:17 +03:00
|
|
|
return -1;
|
1994-06-13 20:13:35 +04:00
|
|
|
}
|
2002-10-12 19:39:29 +04:00
|
|
|
if ((dstr = strdup(str)) == NULL) {
|
|
|
|
tty_warn(0, "Unable to allocate space for option list");
|
2006-02-11 13:43:17 +03:00
|
|
|
return -1;
|
2002-10-12 19:39:29 +04:00
|
|
|
}
|
|
|
|
frpt = endpt = dstr;
|
1994-06-13 20:13:35 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* break into name and values pieces and stuff each one into a
|
|
|
|
* OPLIST structure. When we know the format, the format specific
|
|
|
|
* option function will go through this list
|
|
|
|
*/
|
|
|
|
while ((frpt != NULL) && (*frpt != '\0')) {
|
|
|
|
if ((endpt = strchr(frpt, ',')) != NULL)
|
|
|
|
*endpt = '\0';
|
|
|
|
if ((pt = strchr(frpt, '=')) == NULL) {
|
1997-07-21 00:32:15 +04:00
|
|
|
tty_warn(0, "Invalid options format");
|
2002-10-12 19:39:29 +04:00
|
|
|
free(dstr);
|
2006-02-11 13:43:17 +03:00
|
|
|
return -1;
|
1994-06-13 20:13:35 +04:00
|
|
|
}
|
|
|
|
if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
|
1997-07-21 00:32:15 +04:00
|
|
|
tty_warn(0, "Unable to allocate space for option list");
|
2002-10-12 19:39:29 +04:00
|
|
|
free(dstr);
|
2006-02-11 13:43:17 +03:00
|
|
|
return -1;
|
1994-06-13 20:13:35 +04:00
|
|
|
}
|
|
|
|
*pt++ = '\0';
|
|
|
|
opt->name = frpt;
|
|
|
|
opt->value = pt;
|
|
|
|
opt->fow = NULL;
|
|
|
|
if (endpt != NULL)
|
|
|
|
frpt = endpt + 1;
|
|
|
|
else
|
|
|
|
frpt = NULL;
|
|
|
|
if (ophead == NULL) {
|
|
|
|
optail = ophead = opt;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
optail->fow = opt;
|
|
|
|
optail = opt;
|
|
|
|
}
|
2006-02-11 13:43:17 +03:00
|
|
|
return 0;
|
1994-06-13 20:13:35 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* str_offt()
|
|
|
|
* Convert an expression of the following forms to an off_t > 0.
|
2000-02-17 06:12:22 +03:00
|
|
|
* 1) A positive decimal number.
|
1994-06-13 20:13:35 +04:00
|
|
|
* 2) A positive decimal number followed by a b (mult by 512).
|
|
|
|
* 3) A positive decimal number followed by a k (mult by 1024).
|
|
|
|
* 4) A positive decimal number followed by a m (mult by 512).
|
|
|
|
* 5) A positive decimal number followed by a w (mult by sizeof int)
|
|
|
|
* 6) Two or more positive decimal numbers (with/without k,b or w).
|
2001-07-22 17:33:58 +04:00
|
|
|
* separated by x (also * for backwards compatibility), specifying
|
1994-06-13 20:13:35 +04:00
|
|
|
* the product of the indicated values.
|
|
|
|
* Return:
|
|
|
|
* 0 for an error, a positive value o.w.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static off_t
|
|
|
|
str_offt(char *val)
|
|
|
|
{
|
|
|
|
char *expr;
|
|
|
|
off_t num, t;
|
|
|
|
|
2001-10-25 09:33:32 +04:00
|
|
|
num = STRTOOFFT(val, &expr, 0);
|
|
|
|
if ((num == OFFT_MAX) || (num <= 0) || (expr == val))
|
2006-02-11 13:43:17 +03:00
|
|
|
return 0;
|
1994-06-13 20:13:35 +04:00
|
|
|
|
|
|
|
switch(*expr) {
|
|
|
|
case 'b':
|
|
|
|
t = num;
|
|
|
|
num *= 512;
|
|
|
|
if (t > num)
|
2006-02-11 13:43:17 +03:00
|
|
|
return 0;
|
1994-06-13 20:13:35 +04:00
|
|
|
++expr;
|
|
|
|
break;
|
|
|
|
case 'k':
|
|
|
|
t = num;
|
|
|
|
num *= 1024;
|
|
|
|
if (t > num)
|
2006-02-11 13:43:17 +03:00
|
|
|
return 0;
|
1994-06-13 20:13:35 +04:00
|
|
|
++expr;
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
t = num;
|
|
|
|
num *= 1048576;
|
|
|
|
if (t > num)
|
2006-02-11 13:43:17 +03:00
|
|
|
return 0;
|
1994-06-13 20:13:35 +04:00
|
|
|
++expr;
|
|
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
t = num;
|
|
|
|
num *= sizeof(int);
|
|
|
|
if (t > num)
|
2006-02-11 13:43:17 +03:00
|
|
|
return 0;
|
1994-06-13 20:13:35 +04:00
|
|
|
++expr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(*expr) {
|
|
|
|
case '\0':
|
|
|
|
break;
|
|
|
|
case '*':
|
|
|
|
case 'x':
|
|
|
|
t = num;
|
|
|
|
num *= str_offt(expr + 1);
|
|
|
|
if (t > num)
|
2006-02-11 13:43:17 +03:00
|
|
|
return 0;
|
1994-06-13 20:13:35 +04:00
|
|
|
break;
|
|
|
|
default:
|
2006-02-11 13:43:17 +03:00
|
|
|
return 0;
|
1994-06-13 20:13:35 +04:00
|
|
|
}
|
2006-02-11 13:43:17 +03:00
|
|
|
return num;
|
1994-06-13 20:13:35 +04:00
|
|
|
}
|
|
|
|
|
2011-08-29 18:47:47 +04:00
|
|
|
static char *
|
2009-07-13 23:05:39 +04:00
|
|
|
get_line(FILE *f)
|
2002-10-12 19:39:29 +04:00
|
|
|
{
|
|
|
|
char *name, *temp;
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
name = fgetln(f, &len);
|
|
|
|
if (!name) {
|
2009-07-13 23:05:39 +04:00
|
|
|
get_line_error = ferror(f) ? GETLINE_FILE_CORRUPT : 0;
|
2006-02-11 13:43:17 +03:00
|
|
|
return 0;
|
2002-10-12 19:39:29 +04:00
|
|
|
}
|
|
|
|
if (name[len-1] != '\n')
|
|
|
|
len++;
|
|
|
|
temp = malloc(len);
|
|
|
|
if (!temp) {
|
2009-07-13 23:05:39 +04:00
|
|
|
get_line_error = GETLINE_OUT_OF_MEM;
|
2006-02-11 13:43:17 +03:00
|
|
|
return 0;
|
2002-10-12 19:39:29 +04:00
|
|
|
}
|
|
|
|
memcpy(temp, name, len-1);
|
|
|
|
temp[len-1] = 0;
|
2006-02-11 13:43:17 +03:00
|
|
|
return temp;
|
2002-10-12 19:39:29 +04:00
|
|
|
}
|
|
|
|
|
1994-06-13 20:13:35 +04:00
|
|
|
/*
|
|
|
|
* no_op()
|
|
|
|
* for those option functions where the archive format has nothing to do.
|
|
|
|
* Return:
|
|
|
|
* 0
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int
|
|
|
|
no_op(void)
|
|
|
|
{
|
2006-02-11 13:43:17 +03:00
|
|
|
return 0;
|
1994-06-13 20:13:35 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* pax_usage()
|
|
|
|
* print the usage summary to the user
|
|
|
|
*/
|
|
|
|
|
2011-08-29 18:47:47 +04:00
|
|
|
static void
|
1994-06-13 20:13:35 +04:00
|
|
|
pax_usage(void)
|
|
|
|
{
|
2002-01-24 10:45:33 +03:00
|
|
|
fprintf(stderr,
|
2007-10-26 20:38:12 +04:00
|
|
|
"usage: pax [-0cdjnvzVO] [-E limit] [-f archive] [-N dbdir] [-s replstr] ...\n"
|
2002-01-24 10:45:33 +03:00
|
|
|
" [-U user] ... [-G group] ... [-T [from_date][,to_date]] ...\n"
|
|
|
|
" [pattern ...]\n");
|
|
|
|
fprintf(stderr,
|
2007-10-26 20:38:12 +04:00
|
|
|
" pax -r [-cdijknuvzADOVYZ] [-E limit] [-f archive] [-N dbdir]\n"
|
2002-01-24 10:45:33 +03:00
|
|
|
" [-o options] ... [-p string] ... [-s replstr] ... [-U user] ...\n"
|
|
|
|
" [-G group] ... [-T [from_date][,to_date]] ... [pattern ...]\n");
|
|
|
|
fprintf(stderr,
|
2007-10-26 20:38:12 +04:00
|
|
|
" pax -w [-dijtuvzAHLMOPVX] [-b blocksize] [[-a] [-f archive]] [-x format]\n"
|
2002-01-24 10:45:33 +03:00
|
|
|
" [-B bytes] [-N dbdir] [-o options] ... [-s replstr] ...\n"
|
|
|
|
" [-U user] ... [-G group] ...\n"
|
|
|
|
" [-T [from_date][,to_date][/[c][m]]] ... [file ...]\n");
|
|
|
|
fprintf(stderr,
|
2007-10-26 20:38:12 +04:00
|
|
|
" pax -r -w [-dijklntuvzADHLMOPVXYZ] [-N dbdir] [-p string] ...\n"
|
2002-01-24 10:45:33 +03:00
|
|
|
" [-s replstr] ... [-U user] ... [-G group] ...\n"
|
|
|
|
" [-T [from_date][,to_date][/[c][m]]] ... [file ...] directory\n");
|
1994-06-13 20:13:35 +04:00
|
|
|
exit(1);
|
1998-07-28 09:31:22 +04:00
|
|
|
/* NOTREACHED */
|
1994-06-13 20:13:35 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* tar_usage()
|
|
|
|
* print the usage summary to the user
|
|
|
|
*/
|
|
|
|
|
2011-08-29 18:47:47 +04:00
|
|
|
static void
|
1994-06-13 20:13:35 +04:00
|
|
|
tar_usage(void)
|
|
|
|
{
|
2007-10-26 20:38:12 +04:00
|
|
|
(void)fputs("usage: tar [-]{crtux}[-befhjklmopqvwzHOPSXZ014578] [archive] "
|
2002-10-14 19:04:41 +04:00
|
|
|
"[blocksize]\n"
|
|
|
|
" [-C directory] [-T file] [-s replstr] "
|
|
|
|
"[file ...]\n", stderr);
|
1994-06-13 20:13:35 +04:00
|
|
|
exit(1);
|
1998-07-28 09:31:22 +04:00
|
|
|
/* NOTREACHED */
|
1994-06-13 20:13:35 +04:00
|
|
|
}
|
|
|
|
|
2005-06-29 06:21:27 +04:00
|
|
|
#ifndef NO_CPIO
|
1994-06-13 20:13:35 +04:00
|
|
|
/*
|
|
|
|
* cpio_usage()
|
|
|
|
* print the usage summary to the user
|
|
|
|
*/
|
|
|
|
|
2011-08-29 18:47:47 +04:00
|
|
|
static void
|
1994-06-13 20:13:35 +04:00
|
|
|
cpio_usage(void)
|
|
|
|
{
|
1998-03-06 12:13:01 +03:00
|
|
|
|
2004-01-06 02:23:32 +03:00
|
|
|
(void)fputs("usage: cpio -o [-aABcLvzZ] [-C bytes] [-F archive] "
|
2002-10-17 02:38:36 +04:00
|
|
|
"[-H format] [-O archive]\n"
|
|
|
|
" < name-list [> archive]\n"
|
|
|
|
" cpio -i [-bBcdfmrsStuvzZ6] [-C bytes] [-E file] "
|
|
|
|
"[-F archive] [-H format] \n"
|
|
|
|
" [-I archive] "
|
|
|
|
"[pattern ...] [< archive]\n"
|
|
|
|
" cpio -p [-adlLmuv] destination-directory "
|
|
|
|
"< name-list\n", stderr);
|
1994-06-13 20:13:35 +04:00
|
|
|
exit(1);
|
1998-07-28 09:31:22 +04:00
|
|
|
/* NOTREACHED */
|
1994-06-13 20:13:35 +04:00
|
|
|
}
|
2005-06-29 06:21:27 +04:00
|
|
|
#endif
|