Implement positional -C argument to tar.

This commit is contained in:
is 1999-10-22 20:59:08 +00:00
parent 864ff761d7
commit e413a4ff50
6 changed files with 187 additions and 54 deletions

View File

@ -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);
}

View File

@ -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 *));

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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

View File

@ -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;