Implement positional -C argument to tar.
This commit is contained in:
parent
864ff761d7
commit
e413a4ff50
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ar_io.c,v 1.13 1999/03/03 18:06:52 christos Exp $ */
|
||||
/* $NetBSD: ar_io.c,v 1.14 1999/10/22 20:59:08 is Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
|
@ -42,7 +42,7 @@
|
|||
#if 0
|
||||
static char sccsid[] = "@(#)ar_io.c 8.2 (Berkeley) 4/18/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: ar_io.c,v 1.13 1999/03/03 18:06:52 christos Exp $");
|
||||
__RCSID("$NetBSD: ar_io.c,v 1.14 1999/10/22 20:59:08 is Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
|
@ -88,6 +88,8 @@ static int can_unlnk = 0; /* do we unlink null archives? */
|
|||
const char *arcname; /* printable name of archive */
|
||||
const char *gzip_program; /* name of gzip program */
|
||||
time_t starttime; /* time the run started */
|
||||
int minusCfd = -1; /* active -C directory */
|
||||
int curdirfd = -1; /* original current directory */
|
||||
|
||||
static int get_phys __P((void));
|
||||
extern sigset_t s_mask;
|
||||
|
@ -114,7 +116,6 @@ ar_open(name)
|
|||
#endif
|
||||
{
|
||||
struct mtget mb;
|
||||
static int minusCfd = -1, curdirfd = -1;
|
||||
|
||||
/*
|
||||
* change back to the current directory (for now).
|
||||
|
@ -209,6 +210,13 @@ ar_open(name)
|
|||
*/
|
||||
if (artyp != ISREG)
|
||||
can_unlnk = 0;
|
||||
|
||||
/*
|
||||
* change directory if necessary
|
||||
*/
|
||||
if (minusCfd != -1)
|
||||
fchdir(minusCfd);
|
||||
|
||||
/*
|
||||
* if we are writing, we are done
|
||||
*/
|
||||
|
@ -218,27 +226,6 @@ ar_open(name)
|
|||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* change directory if necessary
|
||||
*/
|
||||
if (chdir_dir) {
|
||||
if (curdirfd == -1)
|
||||
curdirfd = open(".", O_RDONLY);
|
||||
if (curdirfd < 1) {
|
||||
syswarn(0, errno, "failed to open directory .");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (minusCfd == -1)
|
||||
minusCfd = open(chdir_dir, O_RDONLY);
|
||||
if (minusCfd < 1) {
|
||||
syswarn(0, errno, "failed to open directory %s",
|
||||
chdir_dir);
|
||||
return (-1);
|
||||
}
|
||||
fchdir(minusCfd);
|
||||
}
|
||||
|
||||
/*
|
||||
* set default blksz on read. APPNDs writes rdblksz on the last volume
|
||||
* On all new archive volumes, we shift to wrblksz (if the user
|
||||
|
@ -1477,3 +1464,62 @@ ar_summary(n)
|
|||
else
|
||||
(void)write(STDERR_FILENO, buf, strlen(buf));
|
||||
}
|
||||
|
||||
/*
|
||||
* ar_dochdir(name)
|
||||
* change directory to name, and remember where we came from and
|
||||
* where we change to (for ar_open).
|
||||
*
|
||||
* Maybe we could try to be smart and only do the actual chdir
|
||||
* when necessary to write a file read from the archive, but this
|
||||
* is not easy to get right given the pax code structure.
|
||||
*
|
||||
* Be sure to not leak descriptors!
|
||||
*
|
||||
* We are called N * M times when extracting, and N times when
|
||||
* writing archives, where
|
||||
* N: number of -C options
|
||||
* M: number of files in archive
|
||||
*
|
||||
* Returns 0 if all went well, else -1.
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
int
|
||||
ar_dochdir(char *name)
|
||||
#else
|
||||
int
|
||||
ar_dochdir(name)
|
||||
char *name;
|
||||
#endif
|
||||
{
|
||||
if (curdirfd == -1) {
|
||||
/* first time. remember where we came from */
|
||||
curdirfd = open(".", O_RDONLY);
|
||||
if (curdirfd < 0) {
|
||||
syswarn(0, errno, "failed to open directory .");
|
||||
return (-1);
|
||||
}
|
||||
} else /* XXX if (*name != '/') XXX */ {
|
||||
/*
|
||||
* relative chdir. Make sure to get the same directory
|
||||
* each time by fchdir-ing back first.
|
||||
*/
|
||||
fchdir(curdirfd);
|
||||
}
|
||||
|
||||
if (minusCfd != -1) {
|
||||
/* don't leak descriptors */
|
||||
close(minusCfd);
|
||||
minusCfd = -1;
|
||||
}
|
||||
|
||||
minusCfd = open(name, O_RDONLY);
|
||||
if (minusCfd < 0) {
|
||||
syswarn(0, errno, "failed to open directory %s", name);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
fchdir(minusCfd);
|
||||
return (0);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: extern.h,v 1.18 1999/10/22 10:43:11 mrg Exp $ */
|
||||
/* $NetBSD: extern.h,v 1.19 1999/10/22 20:59:08 is Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
|
@ -49,6 +49,7 @@
|
|||
* ar_io.c
|
||||
*/
|
||||
extern const char *arcname;
|
||||
extern int curdirfd;
|
||||
extern const char *gzip_program;
|
||||
extern time_t starttime;
|
||||
int ar_open __P((const char *));
|
||||
|
@ -63,6 +64,7 @@ int ar_fow __P((off_t, off_t *));
|
|||
int ar_rev __P((off_t ));
|
||||
int ar_next __P((void));
|
||||
void ar_summary __P((int));
|
||||
int ar_dochdir __P((char *));
|
||||
|
||||
/*
|
||||
* ar_subs.c
|
||||
|
@ -150,7 +152,7 @@ int set_crc __P((ARCHD *, int));
|
|||
* ftree.c
|
||||
*/
|
||||
int ftree_start __P((void));
|
||||
int ftree_add __P((char *));
|
||||
int ftree_add __P((char *, int));
|
||||
void ftree_sel __P((ARCHD *));
|
||||
void ftree_chk __P((void));
|
||||
int next_file __P((ARCHD *));
|
||||
|
@ -181,17 +183,17 @@ int getoldopt __P((int, char **, char *));
|
|||
extern FSUB fsub[];
|
||||
extern int ford[];
|
||||
extern int cpio_mode;
|
||||
extern char *chdir_dir;
|
||||
void options __P((int, char **));
|
||||
OPLIST * opt_next __P((void));
|
||||
int opt_add __P((const char *));
|
||||
int opt_chdir __P((char *));
|
||||
int bad_opt __P((void));
|
||||
|
||||
/*
|
||||
* pat_rep.c
|
||||
*/
|
||||
int rep_add __P((char *));
|
||||
int pat_add __P((char *));
|
||||
int pat_add __P((char *, int));
|
||||
void pat_chk __P((void));
|
||||
int pat_sel __P((ARCHD *));
|
||||
int pat_match __P((ARCHD *));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ftree.c,v 1.8 1998/07/28 17:44:24 mycroft Exp $ */
|
||||
/* $NetBSD: ftree.c,v 1.9 1999/10/22 20:59:08 is Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
|
@ -42,7 +42,7 @@
|
|||
#if 0
|
||||
static char sccsid[] = "@(#)ftree.c 8.2 (Berkeley) 4/18/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: ftree.c,v 1.8 1998/07/28 17:44:24 mycroft Exp $");
|
||||
__RCSID("$NetBSD: ftree.c,v 1.9 1999/10/22 20:59:08 is Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
|
@ -157,11 +157,12 @@ ftree_start()
|
|||
|
||||
#if __STDC__
|
||||
int
|
||||
ftree_add(char *str)
|
||||
ftree_add(char *str, int isdir)
|
||||
#else
|
||||
int
|
||||
ftree_add(str)
|
||||
ftree_add(str, isdir)
|
||||
char *str;
|
||||
int isdir;
|
||||
#endif
|
||||
{
|
||||
FTREE *ft;
|
||||
|
@ -188,7 +189,7 @@ ftree_add(str)
|
|||
if (((len = strlen(str) - 1) > 0) && (str[len] == '/'))
|
||||
str[len] = '\0';
|
||||
ft->fname = str;
|
||||
ft->refcnt = 0;
|
||||
ft->refcnt = -isdir;
|
||||
ft->fow = NULL;
|
||||
if (fthead == NULL) {
|
||||
fttail = fthead = ft;
|
||||
|
@ -266,7 +267,7 @@ ftree_chk()
|
|||
* that never had a match
|
||||
*/
|
||||
for (ft = fthead; ft != NULL; ft = ft->fow) {
|
||||
if (ft->refcnt > 0)
|
||||
if (ft->refcnt != 0)
|
||||
continue;
|
||||
if (wban == 0) {
|
||||
tty_warn(1,
|
||||
|
@ -327,6 +328,16 @@ ftree_arg()
|
|||
ftcur = fthead;
|
||||
else if ((ftcur = ftcur->fow) == NULL)
|
||||
return(-1);
|
||||
|
||||
if (ftcur->refcnt < 0) {
|
||||
/*
|
||||
* chdir entry.
|
||||
* Change directory and retry loop.
|
||||
*/
|
||||
if (ar_dochdir(ftcur->fname))
|
||||
return (-1);
|
||||
continue;
|
||||
}
|
||||
farray[0] = ftcur->fname;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: options.c,v 1.22 1999/08/24 08:02:27 tron Exp $ */
|
||||
/* $NetBSD: options.c,v 1.23 1999/10/22 20:59:08 is Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
|
@ -42,7 +42,7 @@
|
|||
#if 0
|
||||
static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 4/18/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: options.c,v 1.22 1999/08/24 08:02:27 tron Exp $");
|
||||
__RCSID("$NetBSD: options.c,v 1.23 1999/10/22 20:59:08 is Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
|
@ -68,12 +68,12 @@ __RCSID("$NetBSD: options.c,v 1.22 1999/08/24 08:02:27 tron Exp $");
|
|||
*/
|
||||
|
||||
int cpio_mode; /* set if we are in cpio mode */
|
||||
char *chdir_dir; /* directory to chdir to before operating */
|
||||
|
||||
static int nopids; /* tar mode: suppress "pids" for -p option */
|
||||
static char *flgch = FLGCH; /* list of all possible flags (pax) */
|
||||
static OPLIST *ophead = NULL; /* head for format specific options -x */
|
||||
static OPLIST *optail = NULL; /* option tail */
|
||||
static char *firstminusC; /* first -C argument encountered. */
|
||||
|
||||
static int no_op __P((void));
|
||||
static void printflg __P((unsigned int));
|
||||
|
@ -86,6 +86,8 @@ static void tar_usage __P((void));
|
|||
static void cpio_options __P((int, char **));
|
||||
static void cpio_usage __P((void));
|
||||
|
||||
static void checkpositionalminusC __P((char ***, int (*)(char *, int)));
|
||||
|
||||
#define GZIP_CMD "gzip" /* command to run as gzip */
|
||||
#define COMPRESS_CMD "compress" /* command to run as compress */
|
||||
|
||||
|
@ -570,7 +572,7 @@ pax_options(argc, argv)
|
|||
case LIST:
|
||||
case EXTRACT:
|
||||
for (; optind < argc; optind++)
|
||||
if (pat_add(argv[optind]) < 0)
|
||||
if (pat_add(argv[optind], 0) < 0)
|
||||
pax_usage();
|
||||
break;
|
||||
case COPY:
|
||||
|
@ -584,7 +586,7 @@ pax_options(argc, argv)
|
|||
case ARCHIVE:
|
||||
case APPND:
|
||||
for (; optind < argc; optind++)
|
||||
if (ftree_add(argv[optind]) < 0)
|
||||
if (ftree_add(argv[optind], 0) < 0)
|
||||
pax_usage();
|
||||
/*
|
||||
* no read errors allowed on updates/append operation!
|
||||
|
@ -638,8 +640,9 @@ tar_options(argc, argv)
|
|||
case 'C':
|
||||
/*
|
||||
* chdir here before extracting.
|
||||
* do so lazily, in case it's a list
|
||||
*/
|
||||
chdir_dir = optarg;
|
||||
firstminusC = optarg;
|
||||
break;
|
||||
case 'e':
|
||||
/*
|
||||
|
@ -801,6 +804,9 @@ tar_options(argc, argv)
|
|||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (firstminusC && (opt_chdir(firstminusC) < 0))
|
||||
tty_warn(1, "can't remember -C directory");
|
||||
|
||||
/*
|
||||
* if we are writing (ARCHIVE) specify tar, otherwise run like pax
|
||||
*/
|
||||
|
@ -812,17 +818,17 @@ tar_options(argc, argv)
|
|||
*/
|
||||
switch (act) {
|
||||
case LIST:
|
||||
case EXTRACT:
|
||||
default:
|
||||
while (*argv != (char *)NULL)
|
||||
if (pat_add(*argv++) < 0)
|
||||
if (pat_add(*argv++, 0) < 0)
|
||||
tar_usage();
|
||||
break;
|
||||
case EXTRACT:
|
||||
checkpositionalminusC(&argv, pat_add);
|
||||
break;
|
||||
case ARCHIVE:
|
||||
case APPND:
|
||||
while (*argv != (char *)NULL)
|
||||
if (ftree_add(*argv++) < 0)
|
||||
tar_usage();
|
||||
checkpositionalminusC(&argv, ftree_add);
|
||||
/*
|
||||
* no read errors allowed on updates/append operation!
|
||||
*/
|
||||
|
@ -1082,7 +1088,7 @@ cpio_options(argc, argv)
|
|||
case LIST:
|
||||
case EXTRACT:
|
||||
for (; optind < argc; optind++)
|
||||
if (pat_add(argv[optind]) < 0)
|
||||
if (pat_add(argv[optind], 0) < 0)
|
||||
cpio_usage();
|
||||
break;
|
||||
case COPY:
|
||||
|
@ -1096,7 +1102,7 @@ cpio_options(argc, argv)
|
|||
case ARCHIVE:
|
||||
case APPND:
|
||||
for (; optind < argc; optind++)
|
||||
if (ftree_add(argv[optind]) < 0)
|
||||
if (ftree_add(argv[optind], 0) < 0)
|
||||
cpio_usage();
|
||||
/*
|
||||
* no read errors allowed on updates/append operation!
|
||||
|
@ -1463,3 +1469,61 @@ cpio_usage()
|
|||
exit(1);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/*
|
||||
* opt_chdir
|
||||
* call ftree_add or pat_add, depending on archive type.
|
||||
*
|
||||
* Returns: -1 for listing, else what ftree_add or pat_add returned.
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
int
|
||||
opt_chdir(char *name)
|
||||
#else
|
||||
int
|
||||
opt_chdir(name)
|
||||
char *name;
|
||||
#endif
|
||||
{
|
||||
switch (act) {
|
||||
default:
|
||||
return (-1);
|
||||
break;
|
||||
case ARCHIVE:
|
||||
case APPND:
|
||||
return (ftree_add(name, 1));
|
||||
break;
|
||||
case EXTRACT:
|
||||
return (pat_add(name, 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* checkpositionalminusC(argvp, addfunc)
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
void
|
||||
checkpositionalminusC(char ***argvp, int (*addfunc)(char *, int))
|
||||
#else
|
||||
void
|
||||
checkpositionalminusC(argvp, addfunc)
|
||||
char ***argvp;
|
||||
int (*addfunc)();
|
||||
#endif
|
||||
{
|
||||
while (**argvp != (char *)NULL) {
|
||||
if (!strcmp(**argvp, "-C")) {
|
||||
/* XXX should be allow for positional -C/dir, too? */
|
||||
if ((*addfunc)(*++*argvp, 1) < 0) {
|
||||
tar_usage();
|
||||
}
|
||||
++*argvp;
|
||||
continue;
|
||||
}
|
||||
if ((*addfunc)(*(*argvp)++, 0) < 0)
|
||||
tar_usage();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pat_rep.c,v 1.9 1999/03/24 17:00:23 pk Exp $ */
|
||||
/* $NetBSD: pat_rep.c,v 1.10 1999/10/22 20:59:09 is Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
|
@ -42,7 +42,7 @@
|
|||
#if 0
|
||||
static char sccsid[] = "@(#)pat_rep.c 8.2 (Berkeley) 4/18/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: pat_rep.c,v 1.9 1999/03/24 17:00:23 pk Exp $");
|
||||
__RCSID("$NetBSD: pat_rep.c,v 1.10 1999/10/22 20:59:09 is Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
|
@ -222,17 +222,20 @@ rep_add(str)
|
|||
* arguments to pax in the list and read modes). If no patterns are
|
||||
* supplied to pax, all members in the archive will be selected (and the
|
||||
* pattern match list is empty).
|
||||
*
|
||||
* if ischdir is !0, a special entry used for chdiring is created.
|
||||
* Return:
|
||||
* 0 if the pattern was added to the list, -1 otherwise
|
||||
*/
|
||||
|
||||
#if __STDC__
|
||||
int
|
||||
pat_add(char *str)
|
||||
pat_add(char *str, int ischdir)
|
||||
#else
|
||||
int
|
||||
pat_add(str)
|
||||
pat_add(str ischdir)
|
||||
char *str;
|
||||
int ischdir;
|
||||
#endif
|
||||
{
|
||||
PATTERN *pt;
|
||||
|
@ -259,7 +262,7 @@ pat_add(str)
|
|||
pt->pend = NULL;
|
||||
pt->plen = strlen(str);
|
||||
pt->fow = NULL;
|
||||
pt->flgs = 0;
|
||||
pt->flgs = ischdir ? PTCHDIR : 0;
|
||||
if (pathead == NULL) {
|
||||
pattail = pathead = pt;
|
||||
return(0);
|
||||
|
@ -291,7 +294,7 @@ pat_chk()
|
|||
* if not complain
|
||||
*/
|
||||
for (pt = pathead; pt != NULL; pt = pt->fow) {
|
||||
if (pt->flgs & MTCH)
|
||||
if (pt->flgs & (MTCH|PTCHDIR))
|
||||
continue;
|
||||
if (!wban) {
|
||||
tty_warn(1, "WARNING! These patterns were not matched:");
|
||||
|
@ -469,7 +472,13 @@ pat_match(arcn)
|
|||
* have to search down the list one at a time looking for a match.
|
||||
*/
|
||||
pt = pathead;
|
||||
fchdir(curdirfd);
|
||||
while (pt != NULL) {
|
||||
if (pt->flgs & PTCHDIR) {
|
||||
ar_dochdir(pt->pstr);
|
||||
pt = pt->fow;
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* check for a file name match unless we have DIR_MTCH set in
|
||||
* this pattern then we want a prefix match
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pax.h,v 1.7 1999/10/22 10:43:12 mrg Exp $ */
|
||||
/* $NetBSD: pax.h,v 1.8 1999/10/22 20:59:09 is Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
|
@ -85,6 +85,7 @@ typedef struct pattern {
|
|||
int flgs; /* processing/state flags */
|
||||
#define MTCH 0x1 /* pattern has been matched */
|
||||
#define DIR_MTCH 0x2 /* pattern matched a directory */
|
||||
#define PTCHDIR 0x4 /* not pattern but chdir */
|
||||
struct pattern *fow; /* next pattern */
|
||||
} PATTERN;
|
||||
|
||||
|
|
Loading…
Reference in New Issue