merge OpenBSD changes:

- correct -C processing
    - add ability to read filenames and flags from a file
    - don't print dangerous escape sequences to the terminal
    - use strlcpy/strncpy properly.
    - handle tmpfile creation better.
    - improve documentation of options.
    - handle stdout/stderr list selection correctly.
    - kill gzip when we get interrupted.
    - simplify gzip setup.
    - add more flags to programs.

additional changes:
    - librmt processing.
    - set POSIXLY_CORRECT in options parsing.
    - prevent more string overruns.
    - support -T

we don't turn the switch on to replace tar and cpio yet.
This commit is contained in:
christos 2002-10-12 15:39:29 +00:00
parent b73dcc21ce
commit 0c61202168
15 changed files with 992 additions and 479 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.19 2002/08/19 09:56:01 lukem Exp $
# $NetBSD: Makefile,v 1.20 2002/10/12 15:39:29 christos Exp $
# @(#)Makefile 8.1 (Berkeley) 5/31/93
# To install on versions prior to BSD 4.4 the following may have to be
@ -52,8 +52,8 @@ CPPFLAGS+= -I${NETBSDSRCDIR}/usr.sbin/mtree \
NOHTML=doc2html-error
.ifndef HOSTPROG
LDADD+= -lutil
DPADD+= ${LIBUTIL}
LDADD+= -lutil -lrmt
DPADD+= ${LIBUTIL} ${LIBRMT}
.include <bsd.prog.mk>
.endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: ar_io.c,v 1.22 2002/01/31 19:27:53 tv Exp $ */
/* $NetBSD: ar_io.c,v 1.23 2002/10/12 15:39:29 christos 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.22 2002/01/31 19:27:53 tv Exp $");
__RCSID("$NetBSD: ar_io.c,v 1.23 2002/10/12 15:39:29 christos Exp $");
#endif
#endif /* not lint */
@ -52,6 +52,7 @@ __RCSID("$NetBSD: ar_io.c,v 1.22 2002/01/31 19:27:53 tv Exp $");
#include <sys/ioctl.h>
#include <sys/mtio.h>
#include <sys/param.h>
#include <sys/wait.h>
#include <signal.h>
#include <string.h>
#include <fcntl.h>
@ -60,7 +61,10 @@ __RCSID("$NetBSD: ar_io.c,v 1.22 2002/01/31 19:27:53 tv Exp $");
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#define __RMTLIB_PRIVATE
#include <rmt.h>
#include "pax.h"
#include "options.h"
#include "extern.h"
/*
@ -86,16 +90,22 @@ static int wr_trail = 1; /* trailer was rewritten in append */
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 */
static pid_t zpid = -1; /* pid of child process */
time_t starttime; /* time the run started */
int minusCfd = -1; /* active -C directory */
int curdirfd = -1; /* original current directory */
int force_one_volume; /* 1 if we ignore volume changes */
static int get_phys(void);
extern sigset_t s_mask;
static void ar_start_gzip(int);
static void ar_start_gzip(int, const char *, int);
static const char *timefmt(char *, size_t, off_t, time_t);
static const char *sizefmt(char *, size_t, off_t);
#ifdef SYS_NO_RESTART
static int rmtread_with_restart(int, void *, int);
static int rmtwrite_with_restart(int, void *, int);
#else
#define rmtread_with_restart(a, b, c) rmtread((a), (b), (c))
#define rmtwrite_with_restart(a, b, c) rmtwrite((a), (b), (c))
#endif
/*
* ar_open()
@ -111,12 +121,6 @@ ar_open(const char *name)
{
struct mtget mb;
/*
* change back to the current directory (for now).
*/
if (curdirfd != -1)
fchdir(curdirfd);
if (arfd != -1)
(void)close(arfd);
arfd = -1;
@ -124,6 +128,17 @@ ar_open(const char *name)
artyp = ISREG;
flcnt = 0;
if (strchr(name, ':') != NULL && !forcelocal) {
artyp = ISRMT;
if ((arfd = rmtopen(name, O_RDWR, DMOD)) == -1) {
syswarn(0, errno, "Failed open on %s", name);
return -1;
}
blksz = rdblksz = 8192;
lstrval = 1;
return 0;
}
/*
* open based on overall operation mode
*/
@ -135,8 +150,8 @@ ar_open(const char *name)
arcname = STDN;
} else if ((arfd = open(name, EXT_MODE, DMOD)) < 0)
syswarn(0, errno, "Failed open to read on %s", name);
if (zflag)
ar_start_gzip(arfd);
if (arfd != -1 && gzip_program != NULL)
ar_start_gzip(arfd, gzip_program, 0);
break;
case ARCHIVE:
if (name == NULL) {
@ -146,12 +161,10 @@ ar_open(const char *name)
syswarn(0, errno, "Failed open to write on %s", name);
else
can_unlnk = 1;
if (zflag)
ar_start_gzip(arfd);
if (arfd != -1 && gzip_program != NULL)
ar_start_gzip(arfd, gzip_program, 1);
break;
case APPND:
if (zflag)
err(1, "can not gzip while appending");
if (name == NULL) {
arfd = STDOUT_FILENO;
arcname = STDO;
@ -170,6 +183,9 @@ ar_open(const char *name)
if (arfd < 0)
return(-1);
if (chdname != NULL)
if (chdir(chdname) != 0)
syswarn(1, errno, "Failed chdir to %s", chdname);
/*
* set up is based on device type
*/
@ -205,12 +221,6 @@ ar_open(const char *name)
if (artyp != ISREG)
can_unlnk = 0;
/*
* change directory if necessary
*/
if (minusCfd != -1)
fchdir(minusCfd);
/*
* if we are writing, we are done
*/
@ -320,17 +330,11 @@ ar_open(const char *name)
void
ar_close(void)
{
FILE *outf;
if (arfd < 0) {
did_io = io_ok = flcnt = 0;
return;
}
if (act == LIST)
outf = stdout;
else
outf = stderr;
/*
* Close archive file. This may take a LONG while on tapes (we may be
@ -340,11 +344,11 @@ ar_close(void)
*/
if (vflag && (artyp == ISTAPE)) {
if (vfpart)
(void)putc('\n', outf);
(void)fprintf(outf,
(void)putc('\n', listf);
(void)fprintf(listf,
"%s: Waiting for tape drive close to complete...",
argv0);
(void)fflush(outf);
(void)fflush(listf);
}
/*
@ -357,12 +361,25 @@ ar_close(void)
can_unlnk = 0;
}
(void)close(arfd);
/*
* for a quick extract/list, pax frequently exits before the child
* process is done
*/
if ((act == LIST || act == EXTRACT) && nflag && zpid > 0) {
int status;
kill(zpid, SIGINT);
waitpid(zpid, &status, 0);
}
if (artyp == ISRMT)
(void)rmtclose(arfd);
else
(void)close(arfd);
if (vflag && (artyp == ISTAPE)) {
(void)fputs("done.\n", outf);
(void)fputs("done.\n", listf);
vfpart = 0;
(void)fflush(outf);
(void)fflush(listf);
}
arfd = -1;
@ -388,13 +405,35 @@ ar_close(void)
* Print out a summary of I/O for this archive volume.
*/
if (vfpart) {
(void)putc('\n', outf);
(void)putc('\n', listf);
vfpart = 0;
}
/*
* If we have not determined the format yet, we just say how many bytes
* we have skipped over looking for a header to id. there is no way we
* could have written anything yet.
*/
if (frmt == NULL) {
(void)fprintf(listf, "%s: unknown format, " OFFT_F
" bytes skipped.\n", argv0, rdcnt);
(void)fflush(listf);
flcnt = 0;
return;
}
if (strcmp(NM_CPIO, argv0) == 0) {
(void)fprintf(listf, OFFT_F " blocks\n",
(rdcnt ? rdcnt : wrcnt) / 5120);
} else if (strcmp(NM_TAR, argv0) != 0) {
(void)fprintf(listf,
"%s: %s vol %d, %lu files, " OFFT_F " bytes read, "
OFFT_F " bytes written.\n",
argv0, frmt->name, arvol-1, flcnt, rdcnt, wrcnt);
}
ar_summary(0);
(void)fflush(outf);
(void)fflush(listf);
flcnt = 0;
}
@ -422,8 +461,13 @@ ar_drain(void)
/*
* keep reading until pipe is drained
*/
while ((res = read_with_restart(arfd, drbuf, sizeof(drbuf))) > 0)
;
if (artyp == ISRMT) {
while ((res = rmtread_with_restart(arfd, drbuf, sizeof(drbuf))) > 0)
continue;
} else {
while ((res = read_with_restart(arfd, drbuf, sizeof(drbuf))) > 0)
continue;
}
lstrval = res;
}
@ -507,7 +551,25 @@ read_with_restart(int fd, void *buf, int bsz)
int r;
while (((r = read(fd, buf, bsz)) < 0) && errno == EINTR)
;
continue;
return(r);
}
/*
* rmtread_with_restart()
* Equivalent to rmtread() but does retry on signals.
* This function is not needed on 4.2BSD and later.
* Return:
* Number of bytes written. -1 indicates an error.
*/
static int
rmtread_with_restart(int fd, void *buf, int bsz)
{
int r;
while (((r = rmtread(fd, buf, bsz)) < 0) && errno == EINTR)
continue;
return(r);
}
@ -529,7 +591,7 @@ xread(int fd, void *buf, int bsz)
int r;
do {
if ((r = read_with_restart(fd, b, bsz)) <= 0)
if ((r = rmtread_with_restart(fd, b, bsz)) <= 0)
break;
b += r;
bsz -= r;
@ -558,6 +620,25 @@ write_with_restart(int fd, void *buf, int bsz)
return(r);
}
/*
* rmtwrite_with_restart()
* Equivalent to write() but does retry on signals.
* This function is not needed on 4.2BSD and later.
* Return:
* Number of bytes written. -1 indicates an error.
*/
static int
rmtwrite_with_restart(int fd, void *buf, int bsz)
{
int r;
while (((r = rmtwrite(fd, buf, bsz)) < 0) && errno == EINTR)
;
return(r);
}
#endif
/*
@ -576,7 +657,7 @@ xwrite(int fd, void *buf, int bsz)
int r;
do {
if ((r = write_with_restart(fd, b, bsz)) <= 0)
if ((r = rmtwrite_with_restart(fd, b, bsz)) <= 0)
break;
b += r;
bsz -= r;
@ -610,6 +691,12 @@ ar_read(char *buf, int cnt)
* how we read must be based on device type
*/
switch (artyp) {
case ISRMT:
if ((res = rmtread_with_restart(arfd, buf, cnt)) > 0) {
io_ok = 1;
return res;
}
break;
case ISTAPE:
if ((res = read_with_restart(arfd, buf, cnt)) > 0) {
/*
@ -732,6 +819,7 @@ ar_write(char *buf, int bsz)
case ISTAPE:
case ISCHR:
case ISBLK:
case ISRMT:
if (res >= 0)
break;
if (errno == EACCES) {
@ -823,6 +911,7 @@ ar_rdsync(void)
did_io = 1;
switch(artyp) {
case ISRMT:
case ISTAPE:
/*
* if the last i/o was a successful data transfer, we assume
@ -839,8 +928,13 @@ ar_rdsync(void)
}
mb.mt_op = MTFSR;
mb.mt_count = 1;
if (ioctl(arfd, MTIOCTOP, &mb) < 0)
break;
if (artyp == ISRMT) {
if (rmtioctl(arfd, MTIOCTOP, &mb) < 0)
break;
} else {
if (ioctl(arfd, MTIOCTOP, &mb) < 0)
break;
}
lstrval = 1;
break;
case ISREG:
@ -907,7 +1001,7 @@ ar_fow(off_t sksz, off_t *skipped)
* number of physical blocks to skip (we do not know physical block
* size at this point), so we must only read forward on tapes!
*/
if (artyp == ISTAPE || artyp == ISPIPE)
if (artyp == ISTAPE || artyp == ISPIPE || artyp == ISRMT)
return(0);
/*
@ -1017,6 +1111,7 @@ ar_rev(off_t sksz)
}
break;
case ISTAPE:
case ISRMT:
/*
* Calculate and move the proper number of PHYSICAL tape
* blocks. If the sksz is not an even multiple of the physical
@ -1057,7 +1152,7 @@ ar_rev(off_t sksz)
*/
mb.mt_op = MTBSR;
mb.mt_count = sksz/phyblk;
if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
if (rmtioctl(arfd, MTIOCTOP, &mb) < 0) {
syswarn(1,errno, "Unable to backspace tape %ld blocks.",
(long) mb.mt_count);
lstrval = -1;
@ -1098,7 +1193,7 @@ get_phys(void)
* we know we are at file mark when we get back a 0 from
* read()
*/
while ((res = read_with_restart(arfd, scbuf, sizeof(scbuf))) > 0)
while ((res = rmtread_with_restart(arfd, scbuf, sizeof(scbuf))) > 0)
padsz += res;
if (res < 0) {
syswarn(1, errno, "Unable to locate tape filemark.");
@ -1112,7 +1207,7 @@ get_phys(void)
*/
mb.mt_op = MTBSF;
mb.mt_count = 1;
if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
if (rmtioctl(arfd, MTIOCTOP, &mb) < 0) {
syswarn(1, errno, "Unable to backspace over tape filemark.");
return(-1);
}
@ -1123,11 +1218,11 @@ get_phys(void)
*/
mb.mt_op = MTBSR;
mb.mt_count = 1;
if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
if (rmtioctl(arfd, MTIOCTOP, &mb) < 0) {
syswarn(1, errno, "Unable to backspace over last tape block.");
return(-1);
}
if ((phyblk = read_with_restart(arfd, scbuf, sizeof(scbuf))) <= 0) {
if ((phyblk = rmtread_with_restart(arfd, scbuf, sizeof(scbuf))) <= 0) {
syswarn(1, errno, "Cannot determine archive tape blocksize.");
return(-1);
}
@ -1136,7 +1231,7 @@ get_phys(void)
* read forward to the file mark, then back up in front of the filemark
* (this is a bit paranoid, but should be safe to do).
*/
while ((res = read_with_restart(arfd, scbuf, sizeof(scbuf))) > 0)
while ((res = rmtread_with_restart(arfd, scbuf, sizeof(scbuf))) > 0)
;
if (res < 0) {
syswarn(1, errno, "Unable to locate tape filemark.");
@ -1144,7 +1239,7 @@ get_phys(void)
}
mb.mt_op = MTBSF;
mb.mt_count = 1;
if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
if (rmtioctl(arfd, MTIOCTOP, &mb) < 0) {
syswarn(1, errno, "Unable to backspace over tape filemark.");
return(-1);
}
@ -1175,7 +1270,7 @@ get_phys(void)
*/
mb.mt_op = MTBSR;
mb.mt_count = padsz/phyblk;
if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
if (rmtioctl(arfd, MTIOCTOP, &mb) < 0) {
syswarn(1,errno,"Unable to backspace tape over %ld pad blocks",
(long)mb.mt_count);
return(-1);
@ -1222,7 +1317,7 @@ ar_next(void)
*/
if (strcmp(arcname, STDO) && strcmp(arcname, STDN) && (artyp != ISREG)
&& (artyp != ISPIPE)) {
if (artyp == ISTAPE) {
if (artyp == ISTAPE || artyp == ISRMT) {
tty_prnt("%s ready for archive tape volume: %d\n",
arcname, arvol);
tty_prnt("Load the NEXT TAPE on the tape drive");
@ -1340,52 +1435,38 @@ ar_next(void)
* to keep the fd the same in the calling function (parent).
*/
void
ar_start_gzip(int fd)
ar_start_gzip(int fd, const char *gzp, int wr)
{
pid_t pid;
int fds[2];
const char *gzip_flags;
if (pipe(fds) < 0)
err(1, "could not pipe");
pid = fork();
if (pid < 0)
zpid = fork();
if (zpid < 0)
err(1, "could not fork");
/* parent */
if (pid) {
switch (act) {
case ARCHIVE:
if (zpid) {
if (wr)
dup2(fds[1], fd);
break;
case LIST:
case EXTRACT:
else
dup2(fds[0], fd);
break;
default:
errx(1, "ar_start_gzip: impossible");
}
close(fds[0]);
close(fds[1]);
} else {
switch (act) {
case ARCHIVE:
if (wr) {
dup2(fds[0], STDIN_FILENO);
dup2(fd, STDOUT_FILENO);
gzip_flags = "-c";
break;
case LIST:
case EXTRACT:
} else {
dup2(fds[1], STDOUT_FILENO);
dup2(fd, STDIN_FILENO);
gzip_flags = "-dc";
break;
default:
errx(1, "ar_start_gzip: impossible");
}
close(fds[0]);
close(fds[1]);
if (execlp(gzip_program, gzip_program, gzip_flags, NULL) < 0)
if (execlp(gzp, gzp, gzip_flags, NULL) < 0)
err(1, "could not exec");
/* NOTREACHED */
}
@ -1496,33 +1577,14 @@ ar_summary(int n)
int
ar_dochdir(char *name)
{
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);
/* First fchdir() back... */
if (fchdir(cwdfd) < 0) {
syswarn(1, errno, "Can't fchdir to starting directory");
return(-1);
}
if (minusCfd != -1) {
/* don't leak descriptors */
close(minusCfd);
minusCfd = -1;
if (chdir(name) < 0) {
syswarn(1, errno, "Can't chdir to %s", name);
return(-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: ar_subs.c,v 1.16 2002/01/31 19:27:53 tv Exp $ */
/* $NetBSD: ar_subs.c,v 1.17 2002/10/12 15:39:29 christos Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@ -42,7 +42,7 @@
#if 0
static char sccsid[] = "@(#)ar_subs.c 8.2 (Berkeley) 4/18/94";
#else
__RCSID("$NetBSD: ar_subs.c,v 1.16 2002/01/31 19:27:53 tv Exp $");
__RCSID("$NetBSD: ar_subs.c,v 1.17 2002/10/12 15:39:29 christos Exp $");
#endif
#endif /* not lint */
@ -131,7 +131,7 @@ list(void)
if ((res = mod_name(arcn)) < 0)
break;
if (res == 0)
ls_list(arcn, now);
ls_list(arcn, now, stdout);
}
/*
@ -166,6 +166,7 @@ extract(void)
off_t cnt;
struct stat sb;
int fd;
time_t now;
arcn = &archd;
/*
@ -177,6 +178,8 @@ extract(void)
((*frmt->st_rd)() < 0) || (dir_start() < 0))
return;
now = time((time_t *)NULL);
/*
* When we are doing interactive rename, we store the mapping of names
* so we can fix up hard links files later in the archive.
@ -281,10 +284,21 @@ extract(void)
}
if (vflag) {
(void)fputs(arcn->name, stderr);
vfpart = 1;
if (vflag > 1)
ls_list(arcn, now, listf);
else {
(void)safe_print(arcn->name, listf);
vfpart = 1;
}
}
/*
* if required, chdir around.
*/
if ((arcn->pat != NULL) && (arcn->pat->chdname != NULL))
if (chdir(arcn->pat->chdname) != 0)
syswarn(1, errno, "Cannot chdir to %s",
arcn->pat->chdname);
/*
* all ok, extract this member based on type
*/
@ -305,7 +319,7 @@ extract(void)
purg_lnk(arcn);
if (vflag && vfpart) {
(void)putc('\n', stderr);
(void)putc('\n', listf);
vfpart = 0;
}
continue;
@ -329,11 +343,19 @@ extract(void)
if (!gnu_longlink_hack)
file_close(arcn, fd);
if (vflag && vfpart) {
(void)putc('\n', stderr);
(void)putc('\n', listf);
vfpart = 0;
}
if (!res)
(void)rd_skip(cnt + arcn->pad);
/*
* if required, chdir around.
*/
if ((arcn->pat != NULL) && (arcn->pat->chdname != NULL))
if (fchdir(cwdfd) != 0)
syswarn(1, errno,
"Can't fchdir to starting directory");
}
/*
@ -363,6 +385,7 @@ wr_archive(ARCHD *arcn, int is_app)
off_t cnt;
int (*wrf)(ARCHD *);
int fd = -1;
time_t now;
/*
* if this format supports hard link storage, start up the database
@ -378,6 +401,8 @@ wr_archive(ARCHD *arcn, int is_app)
return;
wrf = frmt->wr;
now = time((time_t *)NULL);
/*
* When we are doing interactive rename, we store the mapping of names
* so we can fix up hard links files later in the archive.
@ -462,8 +487,12 @@ wr_archive(ARCHD *arcn, int is_app)
}
if (vflag) {
(void)fputs(arcn->name, stderr);
vfpart = 1;
if (vflag > 1)
ls_list(arcn, now, listf);
else {
(void)safe_print(arcn->name, listf);
vfpart = 1;
}
}
++flcnt;
@ -482,7 +511,7 @@ wr_archive(ARCHD *arcn, int is_app)
* so we are done messing with this file
*/
if (vflag && vfpart) {
(void)putc('\n', stderr);
(void)putc('\n', listf);
vfpart = 0;
}
rdfile_close(arcn, &fd);
@ -500,7 +529,7 @@ wr_archive(ARCHD *arcn, int is_app)
res = (*frmt->wr_data)(arcn, fd, &cnt);
rdfile_close(arcn, &fd);
if (vflag && vfpart) {
(void)putc('\n', stderr);
(void)putc('\n', listf);
vfpart = 0;
}
if (res < 0)
@ -611,7 +640,7 @@ append(void)
* reading the archive may take a long time. If verbose tell the user
*/
if (vflag) {
(void)fprintf(stderr,
(void)fprintf(listf,
"%s: Reading archive to position at the end...", argv0);
vfpart = 1;
}
@ -673,7 +702,7 @@ append(void)
* tell the user we are done reading.
*/
if (vflag && vfpart) {
(void)fputs("done.\n", stderr);
(void)safe_print("done.\n", listf);
vfpart = 0;
}
@ -731,7 +760,12 @@ copy(void)
* set up the destination dir path and make sure it is a directory. We
* make sure we have a trailing / on the destination
*/
dlen = l_strncpy(dirbuf, dirptr, PAXPATHLEN);
dlen = strlcpy(dirbuf, dirptr, sizeof(dirbuf));
if (dlen >= sizeof(dirbuf) ||
(dlen == sizeof(dirbuf) - 1 && dirbuf[dlen - 1] != '/')) {
tty_warn(1, "directory name is too long %s", dirptr);
return;
}
dest_pt = dirbuf + dlen;
if (*(dest_pt-1) != '/') {
*dest_pt++ = '/';
@ -795,17 +829,12 @@ copy(void)
/*
* create the destination name
*/
if (*(arcn->name) == '/')
res = 1;
else
res = 0;
if ((arcn->nlen - res) > drem) {
if (strlcpy(dest_pt, arcn->name + (*arcn->name == '/'),
drem + 1) > drem) {
tty_warn(1, "Destination pathname too long %s",
arcn->name);
continue;
}
(void)strncpy(dest_pt, arcn->name + res, drem);
dirbuf[PAXPATHLEN] = '\0';
/*
* if existing file is same age or newer skip
@ -859,7 +888,7 @@ copy(void)
}
if (vflag) {
(void)fputs(arcn->name, stderr);
(void)safe_print(arcn->name, listf);
vfpart = 1;
}
++flcnt;
@ -874,7 +903,7 @@ copy(void)
res = chk_same(arcn);
if (res <= 0) {
if (vflag && vfpart) {
(void)putc('\n', stderr);
(void)putc('\n', listf);
vfpart = 0;
}
continue;
@ -894,7 +923,7 @@ copy(void)
if (res < 0)
purg_lnk(arcn);
if (vflag && vfpart) {
(void)putc('\n', stderr);
(void)putc('\n', listf);
vfpart = 0;
}
continue;
@ -924,7 +953,7 @@ copy(void)
rdfile_close(arcn, &fdsrc);
if (vflag && vfpart) {
(void)putc('\n', stderr);
(void)putc('\n', listf);
vfpart = 0;
}
}
@ -969,6 +998,7 @@ next_head(ARCHD *arcn)
int hsz;
int in_resync = 0; /* set when we are in resync mode */
int cnt = 0; /* counter for trailer function */
int first = 1; /* on 1st read, EOF isn't premature. */
/*
* set up initial conditions, we want a whole frmt->hsz block as we
@ -986,6 +1016,17 @@ next_head(ARCHD *arcn)
if ((ret = rd_wrbuf(hdend, res)) == res)
break;
/*
* If we read 0 bytes (EOF) from an archive when we
* expect to find a header, we have stepped upon
* an archive without the customary block of zeroes
* end marker. It's just stupid to error out on
* them, so exit gracefully.
*/
if (first && ret == 0)
return(-1);
first = 0;
/*
* some kind of archive read problem, try to resync the
* storage device, better give the user the bad news.

View File

@ -1,4 +1,4 @@
/* $NetBSD: extern.h,v 1.30 2002/01/31 22:43:35 tv Exp $ */
/* $NetBSD: extern.h,v 1.31 2002/10/12 15:39:29 christos Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@ -54,6 +54,9 @@ extern int curdirfd;
extern const char *gzip_program;
extern time_t starttime;
extern int force_one_volume;
extern char *chdname;
extern int forcelocal;
int ar_open(const char *);
void ar_close(void);
void ar_drain(void);
@ -172,10 +175,9 @@ int next_file(ARCHD *);
/*
* gen_subs.c
*/
void ls_list(ARCHD *, time_t);
void ls_list(ARCHD *, time_t, FILE *);
void ls_tty(ARCHD *);
void zf_strncpy(char *, const char *, int);
int l_strncpy(char *, const char *, int);
void safe_print(const char *, FILE *);
u_long asc_ul(char *, int, int);
int ul_asc(u_long, char *, int, int);
#ifndef NET2_STAT
@ -195,18 +197,18 @@ int getoldopt(int, char **, const char *, struct option *, int *);
*/
extern FSUB fsub[];
extern int ford[];
extern int cpio_mode;
void options(int, char **);
OPLIST * opt_next(void);
int opt_add(const char *);
int opt_chdir(char *);
int bad_opt(void);
int mkpath(char *);
char *chdname;
/*
* pat_rep.c
*/
int rep_add(char *);
int pat_add(char *, int);
int pat_add(char *, char *);
void pat_chk(void);
int pat_sel(ARCHD *);
int pat_match(ARCHD *);
@ -220,6 +222,7 @@ extern int act;
extern FSUB *frmt;
extern int Aflag;
extern int cflag;
extern int cwdfd;
extern int dflag;
extern int iflag;
extern int kflag;
@ -239,13 +242,20 @@ extern int Zflag;
extern int vfpart;
extern int patime;
extern int pmtime;
extern int nodirs;
extern int pfflags;
extern int pmode;
extern int pids;
extern int rmleadslash;
extern int exit_val;
extern int docrc;
extern char *dirptr;
extern char *ltmfrmt;
extern char *argv0;
extern FILE *listf;
extern char *tempfile;
extern char *tempbase;
int main(int, char **);
void sig_cleanup(int);
@ -268,7 +278,7 @@ int ftime_start(void);
int chk_ftime(ARCHD *);
int name_start(void);
int add_name(char *, int, char *);
void sub_name(char *, int *);
void sub_name(char *, int *, size_t);
int dev_start(void);
int add_dev(ARCHD *);
int map_dev(ARCHD *, u_long, u_long);

View File

@ -1,4 +1,4 @@
/* $NetBSD: file_subs.c,v 1.23 2002/02/11 11:19:26 wiz Exp $ */
/* $NetBSD: file_subs.c,v 1.24 2002/10/12 15:39:29 christos Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@ -42,7 +42,7 @@
#if 0
static char sccsid[] = "@(#)file_subs.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: file_subs.c,v 1.23 2002/02/11 11:19:26 wiz Exp $");
__RCSID("$NetBSD: file_subs.c,v 1.24 2002/10/12 15:39:29 christos Exp $");
#endif
#endif /* not lint */
@ -60,6 +60,7 @@ __RCSID("$NetBSD: file_subs.c,v 1.23 2002/02/11 11:19:26 wiz Exp $");
#include <stdlib.h>
#include "pax.h"
#include "extern.h"
#include "options.h"
static int
mk_link(char *,struct stat *,char *, int);
@ -121,7 +122,7 @@ file_creat(ARCHD *arcn)
file_mode)) >= 0)
break;
oerrno = errno;
if (chk_path(arcn->name,arcn->sb.st_uid,arcn->sb.st_gid) < 0) {
if (nodirs || chk_path(arcn->name,arcn->sb.st_uid,arcn->sb.st_gid) < 0) {
syswarn(1, oerrno, "Unable to create %s", arcn->name);
return(-1);
}
@ -357,6 +358,9 @@ node_creat(ARCHD *arcn)
int pass = 0;
mode_t file_mode;
struct stat sb;
char target[MAXPATHLEN];
char *nm = arcn->name;
int len;
/*
* create node based on type, if that fails try to unlink the node and
@ -369,20 +373,43 @@ node_creat(ARCHD *arcn)
for (;;) {
switch(arcn->type) {
case PAX_DIR:
res = mkdir(arcn->name, file_mode);
/*
* If -h (or -L) was given in tar-mode, follow the
* potential symlink chain before trying to create the
* directory.
*/
if (strcmp(NM_TAR, argv0) == 0 && Lflag) {
while (lstat(nm, &sb) == 0 &&
S_ISLNK(sb.st_mode)) {
len = readlink(nm, target,
sizeof target - 1);
if (len == -1) {
syswarn(0, errno,
"cannot follow symlink %s in chain for %s",
nm, arcn->name);
res = -1;
goto badlink;
}
target[len] = '\0';
nm = target;
}
}
res = mkdir(nm, file_mode);
badlink:
if (ign)
res = 0;
break;
case PAX_CHR:
file_mode |= S_IFCHR;
res = mknod(arcn->name, file_mode, arcn->sb.st_rdev);
res = mknod(nm, file_mode, arcn->sb.st_rdev);
break;
case PAX_BLK:
file_mode |= S_IFBLK;
res = mknod(arcn->name, file_mode, arcn->sb.st_rdev);
res = mknod(nm, file_mode, arcn->sb.st_rdev);
break;
case PAX_FIF:
res = mkfifo(arcn->name, file_mode);
res = mkfifo(nm, file_mode);
break;
case PAX_SCK:
/*
@ -390,10 +417,10 @@ node_creat(ARCHD *arcn)
*/
tty_warn(0,
"%s skipped. Sockets cannot be copied or extracted",
arcn->name);
nm);
return(-1);
case PAX_SLK:
res = symlink(arcn->ln_name, arcn->name);
res = symlink(arcn->ln_name, nm);
break;
case PAX_CTG:
case PAX_HLK:
@ -404,7 +431,7 @@ node_creat(ARCHD *arcn)
* we should never get here
*/
tty_warn(0, "%s has an unknown file type, skipping",
arcn->name);
nm);
return(-1);
}
@ -420,14 +447,14 @@ node_creat(ARCHD *arcn)
* we failed to make the node
*/
oerrno = errno;
if ((ign = unlnk_exist(arcn->name, arcn->type)) < 0)
if ((ign = unlnk_exist(nm, arcn->type)) < 0)
return(-1);
if (++pass <= 1)
continue;
if (chk_path(arcn->name,arcn->sb.st_uid,arcn->sb.st_gid) < 0) {
syswarn(1, oerrno, "Could not create: %s", arcn->name);
if (nodirs || chk_path(nm,arcn->sb.st_uid,arcn->sb.st_gid) < 0) {
syswarn(1, oerrno, "Could not create: %s", nm);
return(-1);
}
}
@ -440,7 +467,7 @@ node_creat(ARCHD *arcn)
#else
if (pids && arcn->type != PAX_SLK)
#endif
res = set_ids(arcn->name, arcn->sb.st_uid, arcn->sb.st_gid);
res = set_ids(nm, arcn->sb.st_uid, arcn->sb.st_gid);
else
res = 0;
@ -458,7 +485,7 @@ node_creat(ARCHD *arcn)
#endif
set_pmode(arcn->name, arcn->sb.st_mode);
if (arcn->type == PAX_DIR) {
if (arcn->type == PAX_DIR && strcmp(NM_CPIO, argv0) != 0) {
/*
* Dirs must be processed again at end of extract to set times
* and modes to agree with those stored in the archive. However
@ -468,11 +495,11 @@ node_creat(ARCHD *arcn)
* and modes will be fixed after the entire archive is read and
* before pax exits.
*/
if (access(arcn->name, R_OK | W_OK | X_OK) < 0) {
if (lstat(arcn->name, &sb) < 0) {
if (access(nm, R_OK | W_OK | X_OK) < 0) {
if (lstat(nm, &sb) < 0) {
syswarn(0, errno,"Could not access %s (stat)",
arcn->name);
set_pmode(arcn->name,file_mode | S_IRWXU);
set_pmode(nm,file_mode | S_IRWXU);
} else {
/*
* We have to add rights to the dir, so we make
@ -480,7 +507,7 @@ node_creat(ARCHD *arcn)
* restored AS CREATED and not as stored if
* pmode is not set.
*/
set_pmode(arcn->name,
set_pmode(nm,
((sb.st_mode & FILEBITS) | S_IRWXU));
if (!pmode)
arcn->sb.st_mode = sb.st_mode;
@ -490,9 +517,9 @@ node_creat(ARCHD *arcn)
* we have to force the mode to what was set here,
* since we changed it from the default as created.
*/
add_dir(arcn->name, arcn->nlen, &(arcn->sb), 1);
add_dir(nm, arcn->nlen, &(arcn->sb), 1);
} else if (pmode || patime || pmtime)
add_dir(arcn->name, arcn->nlen, &(arcn->sb), 0);
add_dir(nm, arcn->nlen, &(arcn->sb), 0);
}
#if HAVE_LUTIMES

View File

@ -1,4 +1,4 @@
/* $NetBSD: ftree.c,v 1.21 2002/06/28 11:29:45 lukem Exp $ */
/* $NetBSD: ftree.c,v 1.22 2002/10/12 15:39:29 christos Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@ -78,7 +78,7 @@
#if 0
static char sccsid[] = "@(#)ftree.c 8.2 (Berkeley) 4/18/94";
#else
__RCSID("$NetBSD: ftree.c,v 1.21 2002/06/28 11:29:45 lukem Exp $");
__RCSID("$NetBSD: ftree.c,v 1.22 2002/10/12 15:39:29 christos Exp $");
#endif
#endif /* not lint */
@ -96,6 +96,7 @@ __RCSID("$NetBSD: ftree.c,v 1.21 2002/06/28 11:29:45 lukem Exp $");
#include "pax.h"
#include "ftree.h"
#include "extern.h"
#include "options.h"
#ifndef SMALL
#include "mtree.h"
#endif /* SMALL */
@ -529,7 +530,7 @@ next_file(ARCHD *arcn)
if (ftnode->type == F_DIR && ftnode->child != NULL) {
/* directory with unseen child */
ftnode = ftnode->child;
curdirlen = l_strncpy(curdir, curpath, sizeof(curdir));
curdirlen = strlcpy(curdir, curpath, sizeof(curdir));
} else do {
if (ftnode->next != NULL) {
/* next node at current level */
@ -597,7 +598,7 @@ next_file(ARCHD *arcn)
* here. failure to do so results in massive amounts
* of duplicated files in the output.
*/
if (cpio_mode)
if (strcmp(NM_CPIO, argv0) == 0)
continue;
/* FALLTHROUGH */
case FTS_DEFAULT:
@ -704,7 +705,7 @@ next_file(ARCHD *arcn)
case S_IFLNK:
arcn->type = PAX_SLK;
if (curlink != NULL) {
cnt = l_strncpy(arcn->ln_name, curlink,
cnt = strlcpy(arcn->ln_name, curlink,
sizeof(arcn->ln_name));
/*
* have to read the symlink path from the file
@ -741,8 +742,7 @@ next_file(ARCHD *arcn)
/*
* copy file name, set file name length
*/
arcn->nlen = l_strncpy(arcn->name, ftent->fts_path, PAXPATHLEN+1);
arcn->name[arcn->nlen] = '\0';
arcn->nlen = strlcpy(arcn->name, ftent->fts_path, sizeof(arcn->name));
arcn->org_name = ftent->fts_path;
return(0);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: gen_subs.c,v 1.24 2002/08/01 18:41:34 wiz Exp $ */
/* $NetBSD: gen_subs.c,v 1.25 2002/10/12 15:39:29 christos Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@ -42,7 +42,7 @@
#if 0
static char sccsid[] = "@(#)gen_subs.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: gen_subs.c,v 1.24 2002/08/01 18:41:34 wiz Exp $");
__RCSID("$NetBSD: gen_subs.c,v 1.25 2002/10/12 15:39:29 christos Exp $");
#endif
#endif /* not lint */
@ -54,6 +54,7 @@ __RCSID("$NetBSD: gen_subs.c,v 1.24 2002/08/01 18:41:34 wiz Exp $");
#include <ctype.h>
#include <grp.h>
#include <pwd.h>
#include <vis.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -87,7 +88,7 @@ __RCSID("$NetBSD: gen_subs.c,v 1.24 2002/08/01 18:41:34 wiz Exp $");
*/
void
ls_list(ARCHD *arcn, time_t now)
ls_list(ARCHD *arcn, time_t now, FILE *fp)
{
struct stat *sbp;
char f_mode[MODELEN];
@ -98,8 +99,8 @@ ls_list(ARCHD *arcn, time_t now)
* if not verbose, just print the file name
*/
if (!vflag) {
(void)printf("%s\n", arcn->name);
(void)fflush(stdout);
(void)fprintf(fp, "%s\n", arcn->name);
(void)fflush(fp);
return;
}
@ -124,31 +125,31 @@ ls_list(ARCHD *arcn, time_t now)
f_date[0] = '\0';
user = user_from_uid(sbp->st_uid, 0);
group = group_from_gid(sbp->st_gid, 0);
(void)printf("%s%2lu %-*s %-*s ", f_mode, (unsigned long)sbp->st_nlink,
(void)fprintf(fp, "%s%2lu %-*s %-*s ", f_mode,
(unsigned long)sbp->st_nlink,
UT_NAMESIZE, user ? user : "", UT_GRPSIZE, group ? group : "");
/*
* print device id's for devices, or sizes for other nodes
*/
if ((arcn->type == PAX_CHR) || (arcn->type == PAX_BLK))
(void)printf("%4lu,%4lu ", (long) MAJOR(sbp->st_rdev),
(void)fprintf(fp, "%4lu,%4lu ", (long) MAJOR(sbp->st_rdev),
(long) MINOR(sbp->st_rdev));
else {
(void)printf(OFFT_FP("9") " ", (OFFT_T)sbp->st_size);
(void)fprintf(fp, OFFT_FP("9") " ", (OFFT_T)sbp->st_size);
}
/*
* print name and link info for hard and soft links
*/
(void)printf("%s %s", f_date, arcn->name);
(void)fprintf(fp, "%s %s", f_date, arcn->name);
if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG))
(void)printf(" == %s\n", arcn->ln_name);
(void)fprintf(fp, " == %s\n", arcn->ln_name);
else if (arcn->type == PAX_SLK)
(void)printf(" => %s\n", arcn->ln_name);
(void)fprintf(fp, " => %s\n", arcn->ln_name);
else
(void)putchar('\n');
(void)fflush(stdout);
return;
(void)fputc('\n', fp);
(void)fflush(fp);
}
/*
@ -179,48 +180,23 @@ ls_tty(ARCHD *arcn)
return;
}
/*
* zf_strncpy()
* copy src to dest up to len chars (stopping at first '\0'), when src is
* shorter than len, pads to len with '\0'. big performance win (and
* a lot easier to code) over strncpy(), then a strlen() then a
* memset(). (or doing the memset() first).
*/
void
zf_strncpy(char *dest, const char *src, int len)
safe_print(const char *str, FILE *fp)
{
char *stop;
char visbuf[5];
const char *cp;
stop = dest + len;
while ((dest < stop) && (*src != '\0'))
*dest++ = *src++;
while (dest < stop)
*dest++ = '\0';
return;
}
/*
* l_strncpy()
* copy src to dest up to len chars (stopping at first '\0')
* Return:
* number of chars copied. (Note this is a real performance win over
* doing a strncpy() then a strlen()
*/
int
l_strncpy(char *dest, const char *src, int len)
{
char *stop;
char *start;
stop = dest + len;
start = dest;
while ((dest < stop) && (*src != '\0'))
*dest++ = *src++;
if (dest < stop)
*dest = '\0';
return(dest - start);
/*
* if printing to a tty, use vis(3) to print special characters.
*/
if (isatty(fileno(fp))) {
for (cp = str; *cp; cp++) {
(void)vis(visbuf, cp[0], VIS_CSTYLE, cp[1]);
(void)fputs(visbuf, fp);
}
} else {
(void)fputs(str, fp);
}
}
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: getoldopt.c,v 1.14 2002/01/31 22:43:35 tv Exp $ */
/* $NetBSD: getoldopt.c,v 1.15 2002/10/12 15:39:29 christos Exp $ */
/*
* Plug-compatible replacement for getopt() for parsing tar-like
@ -11,12 +11,13 @@
#include <sys/cdefs.h>
#if defined(__RCSID) && !defined(lint)
__RCSID("$NetBSD: getoldopt.c,v 1.14 2002/01/31 22:43:35 tv Exp $");
__RCSID("$NetBSD: getoldopt.c,v 1.15 2002/10/12 15:39:29 christos Exp $");
#endif /* not lint */
#include <getopt.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include "pax.h"
@ -42,10 +43,19 @@ getoldopt(int argc, char **argv, const char *optstring,
optind = 2;
}
if (use_getopt)
return ((longopts != NULL) ?
getopt_long(argc, argv, optstring, longopts, idx) :
getopt(argc, argv, optstring));
if (use_getopt) {
if (longopts != NULL) {
/*
* Setting POSIXLY_CORRECT here, makes getopt_long
* stop argument processing at the first non-option.
*/
setenv("POSIXLY_CORRECT", "", 0);
return getopt_long(argc, argv, optstring,
longopts, idx);
} else {
return getopt(argc, argv, optstring);
}
}
c = *key++;
if (c == '\0') {

View File

@ -1,4 +1,4 @@
/* $NetBSD: options.c,v 1.39 2002/02/02 12:34:39 lukem Exp $ */
/* $NetBSD: options.c,v 1.40 2002/10/12 15:39:29 christos 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.39 2002/02/02 12:34:39 lukem Exp $");
__RCSID("$NetBSD: options.c,v 1.40 2002/10/12 15:39:29 christos Exp $");
#endif
#endif /* not lint */
@ -52,12 +52,14 @@ __RCSID("$NetBSD: options.c,v 1.39 2002/02/02 12:34:39 lukem Exp $");
#include <sys/mtio.h>
#include <sys/param.h>
#include <ctype.h>
#include <errno.h>
#include <getopt.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <paths.h>
#include "pax.h"
#include "options.h"
#include "cpio.h"
@ -71,18 +73,16 @@ __RCSID("$NetBSD: options.c,v 1.39 2002/02/02 12:34:39 lukem Exp $");
* Routines which handle command line options
*/
int cpio_mode; /* set if we are in cpio mode */
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(void);
static void printflg(unsigned int);
static int c_frmt(const void *, const void *);
static off_t str_offt(char *);
static char *getline(FILE *fp);
static void pax_options(int, char **);
static void pax_usage(void);
static void tar_options(int, char **);
@ -90,7 +90,10 @@ static void tar_usage(void);
static void cpio_options(int, char **);
static void cpio_usage(void);
static void checkpositionalminusC(char ***, int (*)(char *, int));
/* errors from getline */
#define GETLINE_FILE_CORRUPT 1
#define GETLINE_OUT_OF_MEM 2
static int getline_error;
#define GZIP_CMD "gzip" /* command to run as gzip */
#define COMPRESS_CMD "compress" /* command to run as compress */
@ -169,12 +172,12 @@ options(int argc, char **argv)
argv0 = argv[0];
if (strcmp(NM_TAR, argv0) == 0)
tar_options(argc, argv);
return(tar_options(argc, argv));
else if (strcmp(NM_CPIO, argv0) == 0)
cpio_options(argc, argv);
return(cpio_options(argc, argv));
else {
argv0 = NM_PAX;
pax_options(argc, argv);
return(pax_options(argc, argv));
}
}
@ -324,8 +327,8 @@ pax_options(int argc, char **argv)
pmode = 1;
break;
default:
tty_warn(1,
"Invalid -p string: %c", *pt);
tty_warn(1, "Invalid -p string: %c",
*pt);
pax_usage();
break;
}
@ -397,7 +400,6 @@ pax_options(int argc, char **argv)
/*
* use gzip. Non standard option.
*/
zflag = 1;
gzip_program = GZIP_CMD;
break;
case 'A':
@ -567,6 +569,7 @@ pax_options(int argc, char **argv)
*/
if (ISLIST(flg)) {
act = LIST;
listf = stdout;
bflg = flg & BDLIST;
} else if (ISEXTRACT(flg)) {
act = EXTRACT;
@ -602,7 +605,7 @@ pax_options(int argc, char **argv)
case LIST:
case EXTRACT:
for (; optind < argc; optind++)
if (pat_add(argv[optind], 0) < 0)
if (pat_add(argv[optind], NULL) < 0)
pax_usage();
break;
case COPY:
@ -610,8 +613,9 @@ pax_options(int argc, char **argv)
tty_warn(0, "Destination directory was not supplied");
pax_usage();
}
--argc;
dirptr = argv[argc];
dirptr = argv[optind++];
if (mkpath(dirptr) < 0)
cpio_usage();
/* FALLTHROUGH */
case ARCHIVE:
case APPND:
@ -647,6 +651,7 @@ pax_options(int argc, char **argv)
#define OPT_EXCLUDE 11
#define OPT_BLOCK_COMPRESS 12
#define OPT_NORECURSE 13
#define OPT_FORCE_LOCAL 14
struct option tar_longopts[] = {
{ "block-size", required_argument, 0, 'b' },
@ -675,6 +680,7 @@ struct option tar_longopts[] = {
{ "directory", required_argument, 0, 'C' },
{ "tape-length", required_argument, 0, 'L' },
{ "absolute-paths", no_argument, 0, 'P' },
{ "files-from", required_argument, 0, 'T' },
{ "exclude-from", required_argument, 0, 'X' },
{ "compress", no_argument, 0, 'Z' },
{ "uncompress", no_argument, 0, 'Z' },
@ -684,6 +690,8 @@ struct option tar_longopts[] = {
OPT_UNLINK },
{ "use-compress-program", required_argument, 0,
OPT_USE_COMPRESS_PROGRAM },
{ "force-local", no_argument, 0,
OPT_FORCE_LOCAL },
#if 0 /* Not implemented */
{ "catenate", no_argument, 0, 'A' }, /* F */
{ "concatenate", no_argument, 0, 'A' }, /* F */
@ -714,7 +722,6 @@ struct option tar_longopts[] = {
{ "same-order", no_argument, 0, 's' },
{ "preserve-order", no_argument, 0, 's' },
{ "sparse", no_argument, 0, 'S' },
{ "files-from", no_argument, 0, 'T' },
{ "null", no_argument, 0,
OPT_NULL },
{ "totals", no_argument, 0,
@ -739,22 +746,37 @@ tar_options(int argc, char **argv)
{
int c;
int fstdin = 0;
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;
/*
* process option flags
*/
while ((c = getoldopt(argc, argv, "b:cef:hlmoprutvwxzBC:LPX:Z014578",
while ((c = getoldopt(argc, argv,
"b:cef:hlmopqrstuvwxzBC:HI:LOPTX:Z014578",
tar_longopts, NULL))
!= -1) {
switch(c) {
case 'b':
/*
* specify blocksize
* specify blocksize in 512-byte blocks
*/
if ((wrblksz = (int)str_offt(optarg)) <= 0) {
tty_warn(1, "Invalid block size %s", optarg);
tar_usage();
}
wrblksz *= 512; /* XXX - check for int oflow */
break;
case 'c':
/*
@ -762,13 +784,6 @@ tar_options(int argc, char **argv)
*/
act = ARCHIVE;
break;
case 'C':
/*
* chdir here before extracting.
* do so lazily, in case it's a list
*/
firstminusC = optarg;
break;
case 'e':
/*
* stop after first error
@ -784,7 +799,7 @@ tar_options(int argc, char **argv)
* treat a - as stdin
*/
fstdin = 1;
arcname = (char *)0;
arcname = NULL;
break;
}
fstdin = 0;
@ -826,6 +841,9 @@ tar_options(int argc, char **argv)
nopids = 1;
}
break;
case 'O':
Oflag = 1;
break;
case 'p':
/*
* preserve user id, group id, file
@ -837,6 +855,12 @@ tar_options(int argc, char **argv)
patime = 1;
pmtime = 1;
break;
case 'q':
/*
* select first match for a pattern only
*/
nflag = 1;
break;
case 'r':
case 'u':
/*
@ -844,6 +868,15 @@ tar_options(int argc, char **argv)
*/
act = APPND;
break;
case 's':
/*
* file name substitution name pattern
*/
if (rep_add(optarg) < 0) {
tar_usage();
break;
}
break;
case 't':
/*
* list contents of the tape
@ -864,9 +897,11 @@ tar_options(int argc, char **argv)
break;
case 'x':
/*
* write an archive
* extract an archive, preserving mode,
* and mtime if possible.
*/
act = EXTRACT;
pmtime = 1;
break;
case 'z':
/*
@ -880,6 +915,30 @@ tar_options(int argc, char **argv)
* Nothing to do here, this is pax default
*/
break;
case 'C':
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;
case 'L':
/*
* follow symlinks
@ -887,6 +946,10 @@ tar_options(int argc, char **argv)
Lflag = 1;
break;
case 'P':
/*
* do not remove leading '/' from pathnames
*/
rmleadslash = 0;
Aflag = 1;
break;
case 'X':
@ -931,6 +994,9 @@ tar_options(int argc, char **argv)
zflag = 1;
gzip_program = optarg;
break;
case OPT_FORCE_LOCAL:
forcelocal = 1;
break;
default:
tar_usage();
break;
@ -939,31 +1005,159 @@ tar_options(int argc, char **argv)
argc -= optind;
argv += optind;
if (firstminusC && (opt_chdir(firstminusC) < 0))
tty_warn(1, "can't remember -C directory");
/* Traditional tar behaviour (pax uses stderr unless in list mode) */
if (fstdin == 1 && act == ARCHIVE)
listf = stderr;
else
listf = stdout;
/* Traditional tar behaviour (pax wants to read file list from stdin) */
if ((act == ARCHIVE || act == APPND) && argc == 0 && nincfiles == 0)
exit(0);
/*
* if we are writing (ARCHIVE) specify tar, otherwise run like pax
* (unless -o specified)
*/
if (act == ARCHIVE && frmt == NULL)
frmt = &(fsub[F_USTAR]);
if (act == ARCHIVE || act == APPND)
frmt = &(fsub[Oflag ? F_TAR : F_USTAR]);
else if (Oflag) {
tty_warn(1, "The -O/-o options are only valid when writing an archive");
tar_usage(); /* only valid when writing */
}
/*
* process the args as they are interpreted by the operation mode
*/
switch (act) {
case LIST:
default:
while (*argv != (char *)NULL)
if (pat_add(*argv++, 0) < 0)
tar_usage();
break;
case EXTRACT:
checkpositionalminusC(&argv, pat_add);
default:
{
int sawpat = 0;
char *file, *dir;
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;
incfiles++;
nincfiles--;
} else if (strcmp(*argv, "-I") == 0) {
if (*++argv == NULL)
break;
file = *argv++;
dir = chdname;
} else
file = NULL;
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();
}
while ((str = getline(fp)) != NULL) {
if (pat_add(str, dir) < 0)
tar_usage();
sawpat = 1;
}
if (strcmp(file, "-") != 0)
fclose(fp);
if (getline_error) {
tty_warn(1, "Problem with file '%s'", file);
tar_usage();
}
} else if (strcmp(*argv, "-C") == 0) {
if (*++argv == NULL)
break;
chdname = *argv++;
} else if (pat_add(*argv++, chdname) < 0)
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;
}
break;
case ARCHIVE:
case APPND:
checkpositionalminusC(&argv, ftree_add);
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;
} else
file = NULL;
if (file != NULL) {
FILE *fp;
char *str;
/* 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();
}
while ((str = getline(fp)) != NULL) {
if (ftree_add(str, 0) < 0)
tar_usage();
}
if (strcmp(file, "-") != 0)
fclose(fp);
if (getline_error) {
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();
}
/*
* no read errors allowed on updates/append operation!
*/
@ -972,11 +1166,45 @@ tar_options(int argc, char **argv)
}
if (!fstdin && ((arcname == (char *)NULL) || (*arcname == '\0'))) {
arcname = getenv("TAPE");
if ((arcname == (char *)NULL) || (*arcname == '\0'))
arcname = DEV_8;
if ((arcname == NULL) || (*arcname == '\0'))
arcname = _PATH_DEFTAPE;
}
}
int
mkpath(path)
char *path;
{
struct stat sb;
char *slash;
int done = 0;
slash = path;
while (!done) {
slash += strspn(slash, "/");
slash += strcspn(slash, "/");
done = (*slash == '\0');
*slash = '\0';
if (stat(path, &sb)) {
if (errno != ENOENT || mkdir(path, 0777)) {
tty_warn(1, "%s", path);
return (-1);
}
} else if (!S_ISDIR(sb.st_mode)) {
syswarn(1, ENOTDIR, "%s", path);
return (-1);
}
if (!done)
*slash = '/';
}
return (0);
}
/*
* cpio_options()
* look at the user specified flags. set globals as required and check if
@ -990,14 +1218,141 @@ cpio_options(int argc, char **argv)
unsigned int flg = 0;
unsigned int bflg = 0;
int c, i;
FILE *fp;
char *str;
cpio_mode = uflag = 1;
uflag = 1;
kflag = 1;
pids = 1;
pmode = 1;
pmtime = 0;
arcname = NULL;
dflag = 1;
act = -1;
nodirs = 1;
/*
* process option flags
*/
while ((c = getoldopt(argc, argv,
"ABC:E:H:I:LM:O:R:SVabcdfiklmoprstuv", NULL, NULL)) != -1) {
"abcdfiklmoprstuvzABC:E:F:H:I:LM:O:R:SVZ6", NULL, NULL)) != -1) {
switch(c) {
case 'a':
/*
* preserve access time on filesystem nodes we read
*/
tflag = 1;
flg |= TF;
break;
#ifdef notyet
case 'b':
/*
* swap bytes and half-words when reading data
*/
break;
#endif
case 'c':
/*
* ASCII cpio header
*/
frmt = &fsub[F_SV4CPIO];
break;
case 'd':
/*
* create directories as needed
* pax does this by default ..
*/
nodirs = 0;
flg |= RF;
break;
case 'f':
/*
* inverse match on patterns
*/
cflag = 1;
flg |= CF;
break;
case 'i':
/*
* read the archive
*/
act = EXTRACT;
flg |= RF;
break;
#ifdef notyet
case 'k':
break;
#endif
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
*/
act = ARCHIVE;
frmt = &(fsub[F_SV4CRC]);
flg |= WF;
break;
case 'p':
/*
* cpio -p is like pax -rw
*/
act = COPY;
flg |= RF | WF;
break;
case 'r':
/*
* interactive file rename
*/
iflag = 1;
flg |= IF;
break;
#ifdef notyet
case 's':
/*
* swap bytes after reading data
*/
break;
#endif
case 't':
/*
* list contents of archive
*/
act = LIST;
listf = stdout;
break;
case 'u':
/*
* don't ignore those older files
*/
uflag = 0;
kflag = 0;
flg |= UF;
break;
case 'v':
/*
* verbose operation mode
*/
vflag = 1;
flg |= VF;
break;
case 'z':
/*
* use gzip. Non standard option.
*/
gzip_program = GZIP_CMD;
break;
case 'A':
/*
* append to an archive
@ -1020,11 +1375,24 @@ cpio_options(int argc, char **argv)
tar_usage();
}
break;
#ifdef notyet
case 'E':
arg = optarg;
/*
* 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();
}
while ((str = getline(fp)) != NULL) {
pat_add(str, NULL);
}
fclose(fp);
if (getline_error) {
tty_warn(1, "Problem with file '%s'", optarg);
cpio_usage();
}
break;
#endif
case 'H':
/*
* specify an archive format on write
@ -1052,7 +1420,7 @@ cpio_options(int argc, char **argv)
/*
* treat a - as stdin
*/
arcname = (char *)0;
arcname = NULL;
break;
}
arcname = optarg;
@ -1073,103 +1441,26 @@ cpio_options(int argc, char **argv)
break;
#endif
case 'S':
/*
* swap halfwords after reading data
*/
cpio_swp_head = 1;
break;
#ifdef notyet
case 'V':
break;
#endif
case 'a':
case 'Z':
/*
* preserve access time on filesystem nodes we read
* use compress. Non standard option.
*/
tflag = 1;
flg |= TF;
gzip_program = COMPRESS_CMD;
break;
#ifdef notyet
case 'b':
break;
#endif
case 'c':
frmt = &fsub[F_SV4CPIO];
break;
case 'd':
case '6':
/*
* pax does this by default ..
* process Version 6 cpio format
*/
flg |= RF;
break;
case 'f':
/*
* inverse match on patterns
*/
cflag = 1;
flg |= CF;
break;
case 'i':
/*
* read the archive
*/
flg |= RF;
break;
#ifdef notyet
case 'k':
break;
#endif
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
*/
flg |= WF;
break;
case 'p':
/*
* cpio -p is like pax -rw
*/
flg |= RF | WF;
break;
case 'r':
/*
* interactive file rename
*/
iflag = 1;
flg |= IF;
break;
#ifdef notyet
case 's':
break;
#endif
case 't':
act = LIST;
break;
case 'u':
/*
* don't ignore those older files
*/
uflag = 0;
flg |= UF;
break;
case 'v':
/*
* verbose operation mode
*/
vflag = 1;
flg |= VF;
break;
frmt = &(fsub[F_BCPIO]);
default:
cpio_usage();
break;
@ -1229,13 +1520,26 @@ cpio_options(int argc, char **argv)
/* FALLTHROUGH */
case ARCHIVE:
case APPND:
for (; optind < argc; optind++)
if (ftree_add(argv[optind], 0) < 0)
cpio_usage();
if (argc != optind) {
for (; optind < argc; optind++)
if (ftree_add(argv[optind], 0) < 0)
cpio_usage();
break;
}
/*
* no read errors allowed on updates/append operation!
*/
maxflt = 0;
while ((str = getline(stdin)) != NULL) {
ftree_add(str, NULL);
}
if (getline_error) {
tty_warn(1, "Problem while reading stdin");
cpio_usage();
}
break;
default:
cpio_usage();
break;
}
}
@ -1329,12 +1633,17 @@ opt_add(const char *str)
char *frpt;
char *pt;
char *endpt;
char *dstr;
if ((str == NULL) || (*str == '\0')) {
tty_warn(0, "Invalid option name");
return(-1);
}
frpt = endpt = strdup(str);
if ((dstr = strdup(str)) == NULL) {
tty_warn(0, "Unable to allocate space for option list");
return(-1);
}
frpt = endpt = dstr;
/*
* break into name and values pieces and stuff each one into a
@ -1346,10 +1655,12 @@ opt_add(const char *str)
*endpt = '\0';
if ((pt = strchr(frpt, '=')) == NULL) {
tty_warn(0, "Invalid options format");
free(dstr);
return(-1);
}
if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
tty_warn(0, "Unable to allocate space for option list");
free(dstr);
return(-1);
}
*pt++ = '\0';
@ -1442,6 +1753,29 @@ str_offt(char *val)
return(num);
}
char *
getline(FILE *f)
{
char *name, *temp;
size_t len;
name = fgetln(f, &len);
if (!name) {
getline_error = ferror(f) ? GETLINE_FILE_CORRUPT : 0;
return(0);
}
if (name[len-1] != '\n')
len++;
temp = malloc(len);
if (!temp) {
getline_error = GETLINE_OUT_OF_MEM;
return(0);
}
memcpy(temp, name, len-1);
temp[len-1] = 0;
return(temp);
}
/*
* no_op()
* for those option functions where the archive format has nothing to do.
@ -1531,48 +1865,3 @@ cpio_usage(void)
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.
*/
int
opt_chdir(char *name)
{
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)
*/
void
checkpositionalminusC(char ***argvp, int (*addfunc)(char *, int))
{
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.13 2002/01/31 19:27:54 tv Exp $ */
/* $NetBSD: pat_rep.c,v 1.14 2002/10/12 15:39:30 christos 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.13 2002/01/31 19:27:54 tv Exp $");
__RCSID("$NetBSD: pat_rep.c,v 1.14 2002/10/12 15:39:30 christos Exp $");
#endif
#endif /* not lint */
@ -77,7 +77,7 @@ static PATTERN *pattail = NULL; /* file pattern match list tail */
static REPLACE *rephead = NULL; /* replacement string list head */
static REPLACE *reptail = NULL; /* replacement string list tail */
static int rep_name(char *, int *, int);
static int rep_name(char *, size_t, int *, int);
static int tty_rename(ARCHD *);
static int fix_path(char *, int *, char *, int);
static int fn_match(char *, char *, char **);
@ -125,13 +125,17 @@ rep_add(char *str)
/*
* first character in the string specifies what the delimiter is for
* this expression. find the end and middle, from the end. this
* allows the string to be something like /foo\/bar//, but will still
* fail on /foo\/bar/foo\/baz/. XXX need to parse the RE to properly
* do this!
* this expression.
*/
if ((pt2 = strrchr(str+1, *str)) == NULL || pt2 == str+1 ||
(*pt2 = '\0') || (pt1 = strrchr(str+1, *str)) == NULL) {
for (pt1 = str+1; *pt1; pt1++) {
if (*pt1 == '\\') {
pt1++;
continue;
}
if (*pt1 == *str)
break;
}
if (pt1 == NULL) {
tty_warn(1, "Invalid replacement string %s", str);
return(-1);
}
@ -164,6 +168,26 @@ rep_add(char *str)
* we then point the node at the new substitution string
*/
*pt1++ = *str;
for (pt2 = pt1; *pt2; pt2++) {
if (*pt2 == '\\') {
pt2++;
continue;
}
if (*pt2 == *str)
break;
}
if (pt2 == NULL) {
#ifdef NET2_REGEX
(void)free((char *)rep->rcmp);
#else
regfree(&(rep->rcmp));
#endif
(void)free((char *)rep);
tty_warn(1, "Invalid replacement string %s", str);
return(-1);
}
*pt2 = '\0';
rep->nstr = pt1;
pt1 = pt2++;
rep->flgs = 0;
@ -217,13 +241,12 @@ rep_add(char *str)
* 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
*/
int
pat_add(char *str, int ischdir)
pat_add(char *str, char *chdn)
{
PATTERN *pt;
@ -249,7 +272,8 @@ pat_add(char *str, int ischdir)
pt->pend = NULL;
pt->plen = strlen(str);
pt->fow = NULL;
pt->flgs = ischdir ? PTCHDIR : 0;
pt->flgs = 0;
pt->chdname = chdn;
if (pathead == NULL) {
pattail = pathead = pt;
return(0);
@ -276,7 +300,7 @@ pat_chk(void)
* if not complain
*/
for (pt = pathead; pt != NULL; pt = pt->fow) {
if (pt->flgs & (MTCH|PTCHDIR))
if (pt->flgs & MTCH)
continue;
if (!wban) {
tty_warn(1, "WARNING! These patterns were not matched:");
@ -442,13 +466,7 @@ pat_match(ARCHD *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
@ -620,6 +638,38 @@ mod_name(ARCHD *arcn)
{
int res = 0;
/*
* Strip off leading '/' if appropriate.
* Currently, this option is only set for the tar format.
*/
if (rmleadslash && arcn->name[0] == '/') {
if (arcn->name[1] == '\0') {
arcn->name[0] = '.';
} else {
(void)memmove(arcn->name, &arcn->name[1],
strlen(arcn->name));
arcn->nlen--;
}
if (rmleadslash < 2) {
rmleadslash = 2;
tty_warn(0, "Removing leading / from absolute path names in the archive");
}
}
if (rmleadslash && arcn->ln_name[0] == '/' &&
(arcn->type == PAX_HLK || arcn->type == PAX_HRG)) {
if (arcn->ln_name[1] == '\0') {
arcn->ln_name[0] = '.';
} else {
(void)memmove(arcn->ln_name, &arcn->ln_name[1],
strlen(arcn->ln_name));
arcn->ln_nlen--;
}
if (rmleadslash < 2) {
rmleadslash = 2;
tty_warn(0, "Removing leading / from absolute path names in the archive");
}
}
/*
* IMPORTANT: We have a problem. what do we do with symlinks?
* Modifying a hard link name makes sense, as we know the file it
@ -644,12 +694,14 @@ mod_name(ARCHD *arcn)
* we have replacement strings, modify the name and the link
* name if any.
*/
if ((res = rep_name(arcn->name, &(arcn->nlen), 1)) != 0)
if ((res = rep_name(arcn->name, sizeof(arcn->name),
&(arcn->nlen), 1)) != 0)
return(res);
if (((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) ||
(arcn->type == PAX_HRG)) &&
((res = rep_name(arcn->ln_name, &(arcn->ln_nlen), 0)) != 0))
((res = rep_name(arcn->ln_name, sizeof(arcn->ln_name),
&(arcn->ln_nlen), 0)) != 0))
return(res);
}
@ -661,7 +713,7 @@ mod_name(ARCHD *arcn)
return(res);
if ((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) ||
(arcn->type == PAX_HRG))
sub_name(arcn->ln_name, &(arcn->ln_nlen));
sub_name(arcn->ln_name, &(arcn->ln_nlen), sizeof(arcn->ln_name));
}
return(res);
}
@ -727,7 +779,7 @@ tty_rename(ARCHD *arcn)
*/
tty_prnt("Processing continues, name changed to: %s\n", tmpname);
res = add_name(arcn->name, arcn->nlen, tmpname);
arcn->nlen = l_strncpy(arcn->name, tmpname, PAXPATHLEN+1);
arcn->nlen = strlcpy(arcn->name, tmpname, sizeof(arcn->name));
if (res < 0)
return(-1);
return(0);
@ -823,6 +875,7 @@ fix_path( char *or_name, int *or_len, char *dir_name, int dir_len)
* --Parameters--
* name is the file name we are going to apply the regular expressions to
* (and may be modified)
* namelen the size of the name buffer.
* nlen is the length of this name (and is modified to hold the length of
* the final string).
* prnt is a flag that says whether to print the final result.
@ -832,7 +885,7 @@ fix_path( char *or_name, int *or_len, char *dir_name, int dir_len)
*/
static int
rep_name(char *name, int *nlen, int prnt)
rep_name(char *name, size_t namelen, int *nlen, int prnt)
{
REPLACE *pt;
char *inpt;
@ -983,7 +1036,7 @@ rep_name(char *name, int *nlen, int prnt)
*/
if (*nname == '\0')
return(1);
*nlen = l_strncpy(name, nname, PAXPATHLEN + 1);
*nlen = strlcpy(name, nname, namelen);
}
return(0);
}
@ -1028,9 +1081,8 @@ resub(regexp *prog, char *src, char *dest, char *destend)
* fail if we run out of space or the match string is damaged
*/
if (len > (destend - dpt))
len = destend - dpt;
if (l_strncpy(dpt, prog->startp[no], len) != len)
return(-1);
return (-1);
strncpy(dpt, prog->startp[no], len);
dpt += len;
}
return(dpt - dest);
@ -1096,9 +1148,8 @@ resub(regex_t *rp, regmatch_t *pm, char *src, char *txt, char *dest,
* fail if we run out of space or the match string is damaged
*/
if (len > (destend - dpt))
len = destend - dpt;
if (l_strncpy(dpt, txt + pmpt->rm_so, len) != len)
return(-1);
return -1;
strncpy(dpt, txt + pmpt->rm_so, len);
dpt += len;
}
return(dpt - dest);

View File

@ -1,4 +1,4 @@
/* $NetBSD: pax.c,v 1.17 2002/01/31 19:27:54 tv Exp $ */
/* $NetBSD: pax.c,v 1.18 2002/10/12 15:39:30 christos Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@ -47,20 +47,22 @@ __COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\
#if 0
static char sccsid[] = "@(#)pax.c 8.2 (Berkeley) 4/18/94";
#else
__RCSID("$NetBSD: pax.c,v 1.17 2002/01/31 19:27:54 tv Exp $");
__RCSID("$NetBSD: pax.c,v 1.18 2002/10/12 15:39:30 christos Exp $");
#endif
#endif /* not lint */
#include <stdio.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <paths.h>
#include "pax.h"
#include "extern.h"
static int gen_init(void);
@ -75,6 +77,7 @@ static int gen_init(void);
int act = DEFOP; /* read/write/append/copy */
FSUB *frmt = NULL; /* archive format type */
int cflag; /* match all EXCEPT pattern/file */
int cwdfd; /* starting cwd */
int dflag; /* directory member match only */
int iflag; /* interactive file/archive rename */
int kflag; /* do not overwrite existing files */
@ -95,14 +98,23 @@ int Zflag; /* same as uflg except after name mode */
int vfpart; /* is partial verbose output in progress */
int patime = 1; /* preserve file access time */
int pmtime = 1; /* preserve file modification times */
int nodirs; /* do not create directories as needed */
int pfflags = 1; /* preserve file flags */
int pmode; /* preserve file mode bits */
int pids; /* preserve file uid/gid */
int rmleadslash = 0; /* remove leading '/' from pathnames */
int exit_val; /* exit value */
int docrc; /* check/create file crc */
char *dirptr; /* destination dir in a copy */
char *ltmfrmt; /* -v locale time format (if any) */
char *argv0; /* root of argv[0] */
sigset_t s_mask; /* signal mask for cleanup critical sect */
FILE *listf = stderr; /* file pointer to print file list to */
char *tempfile; /* tempfile to use for mkstemp(3) */
char *tempbase; /* basename of tempfile to use for mkstemp(3) */
int forcelocal; /* force local operation even if the name
* contains a :
*/
/*
* PAX - Portable Archive Interchange
@ -227,6 +239,36 @@ sigset_t s_mask; /* signal mask for cleanup critical sect */
int
main(int argc, char **argv)
{
char *tmpdir;
size_t tdlen;
/*
* Keep a reference to cwd, so we can always come back home.
*/
cwdfd = open(".", O_RDONLY);
if (cwdfd < 0) {
syswarn(0, errno, "Can't open current working directory.");
return(exit_val);
}
/*
* Where should we put temporary files?
*/
if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0')
tmpdir = _PATH_TMP;
tdlen = strlen(tmpdir);
while(tdlen > 0 && tmpdir[tdlen - 1] == '/')
tdlen--;
tempfile = malloc(tdlen + 1 + sizeof(_TFILE_BASE));
if (tempfile == NULL) {
tty_warn(1, "Cannot allocate memory for temp file name.");
return(exit_val);
}
if (tdlen)
memcpy(tempfile, tmpdir, tdlen);
tempbase = tempfile + tdlen;
*tempbase++ = '/';
/*
* parse options, determine operational mode, general init
*/
@ -249,6 +291,8 @@ main(int argc, char **argv)
archive();
break;
case APPND:
if (gzip_program != NULL)
err(1, "can not gzip while appending");
append();
break;
case COPY:
@ -290,7 +334,6 @@ sig_cleanup(int which_sig)
if (tflag)
atdir_end();
exit(1);
/* NOTREACHED */
}
/*
@ -342,6 +385,13 @@ gen_init(void)
}
#endif
/*
* Handle posix locale
*
* set user defines time printing format for -v option
*/
ltmfrmt = getenv("LC_TIME");
/*
* signal handling to reset stored directory times and modes. Since
* we deal with broken pipes via failed writes we ignore it. We also
@ -355,6 +405,7 @@ gen_init(void)
tty_warn(1, "Unable to set up signal mask");
return(-1);
}
memset(&n_hand, 0, sizeof n_hand);
n_hand.sa_mask = s_mask;
n_hand.sa_flags = 0;
n_hand.sa_handler = sig_cleanup;

View File

@ -1,4 +1,4 @@
/* $NetBSD: pax.h,v 1.13 2002/01/31 22:43:36 tv Exp $ */
/* $NetBSD: pax.h,v 1.14 2002/10/12 15:39:30 christos Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@ -80,6 +80,7 @@
#define ISBLK 2 /* block device */
#define ISTAPE 3 /* tape drive */
#define ISPIPE 4 /* pipe/socket */
#define ISRMT 5 /* rmt */
/*
@ -90,11 +91,11 @@
typedef struct pattern {
char *pstr; /* pattern to match, user supplied */
char *pend; /* end of a prefix match */
char *chdname; /* the dir to change to if not NULL. */
int plen; /* length of pstr */
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;
@ -259,7 +260,7 @@ typedef struct oplist {
* Pathname base component of the temporary file template, to be created in
* ${TMPDIR} or, as a fall-back, _PATH_TMP.
*/
#define TMPFILE "paxXXXXXX"
#define _TFILE_BASE "paxXXXXXXXXXX"
/*
* Macros to manipulate off_t as a unsigned long or unsigned long long

View File

@ -1,4 +1,4 @@
/* $NetBSD: tables.c,v 1.17 2002/01/31 19:27:54 tv Exp $ */
/* $NetBSD: tables.c,v 1.18 2002/10/12 15:39:30 christos Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@ -42,7 +42,7 @@
#if 0
static char sccsid[] = "@(#)tables.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: tables.c,v 1.17 2002/01/31 19:27:54 tv Exp $");
__RCSID("$NetBSD: tables.c,v 1.18 2002/10/12 15:39:30 christos Exp $");
#endif
#endif /* not lint */
@ -176,8 +176,8 @@ chk_lnk(ARCHD *arcn)
* handle hardlinks to regular files differently than
* other links.
*/
arcn->ln_nlen = l_strncpy(arcn->ln_name, pt->name,
PAXPATHLEN+1);
arcn->ln_nlen = strlcpy(arcn->ln_name, pt->name,
sizeof(arcn->ln_name));
if (arcn->type == PAX_REG)
arcn->type = PAX_HRG;
else
@ -340,9 +340,6 @@ lnk_end(void)
int
ftime_start(void)
{
const char *tmpdir;
char template[MAXPATHLEN];
if (ftab != NULL)
return(0);
if ((ftab = (FTM **)calloc(F_TAB_SZ, sizeof(FTM *))) == NULL) {
@ -354,16 +351,14 @@ ftime_start(void)
* get random name and create temporary scratch file, unlink name
* so it will get removed on exit
*/
if ((tmpdir = getenv("TMPDIR")) == NULL)
tmpdir = _PATH_TMP;
(void)snprintf(template, sizeof(template), "%s/%s", tmpdir, TMPFILE);
if ((ffd = mkstemp(template)) == -1) {
memcpy(tempbase, _TFILE_BASE, sizeof(_TFILE_BASE));
if ((ffd = mkstemp(tempfile)) == -1) {
syswarn(1, errno, "Unable to create temporary file: %s",
template);
tempfile);
return(-1);
}
(void)unlink(template);
(void)unlink(tempfile);
return(0);
}
@ -589,7 +584,7 @@ add_name(char *oname, int onamelen, char *nname)
*/
void
sub_name(char *oname, int *onamelen)
sub_name(char *oname, int *onamelen, size_t onamesize)
{
NAMT *pt;
u_int indx;
@ -612,7 +607,7 @@ sub_name(char *oname, int *onamelen)
* found it, replace it with the new name
* and return (we know that oname has enough space)
*/
*onamelen = l_strncpy(oname, pt->nname, PAXPATHLEN+1);
*onamelen = strlcpy(oname, pt->nname, onamesize);
return;
}
pt = pt->fow;
@ -1112,24 +1107,19 @@ int
dir_start(void)
{
#ifdef DIRS_USE_FILE
const char *tmpdir;
char template[MAXPATHLEN];
if (dirfd != -1)
return(0);
/*
* unlink the file so it goes away at termination by itself
*/
if ((tmpdir = getenv("TMPDIR")) == NULL)
tmpdir = _PATH_TMP;
(void)snprintf(template, sizeof(template), "%s/%s", tmpdir, TMPFILE);
if ((dirfd = mkstemp(template)) >= 0) {
(void)unlink(template);
memcpy(tempbase, _TFILE_BASE, sizeof(_TFILE_BASE));
if ((dirfd = mkstemp(tempfile)) >= 0) {
(void)unlink(tempfile);
return(0);
}
tty_warn(1, "Unable to create temporary file for directory times: %s",
template);
tempfile);
return(-1);
#else
return (0);

View File

@ -1,4 +1,4 @@
/* $NetBSD: tar.c,v 1.22 2002/10/11 13:07:36 christos Exp $ */
/* $NetBSD: tar.c,v 1.23 2002/10/12 15:39:30 christos Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@ -42,7 +42,7 @@
#if 0
static char sccsid[] = "@(#)tar.c 8.2 (Berkeley) 4/18/94";
#else
__RCSID("$NetBSD: tar.c,v 1.22 2002/10/11 13:07:36 christos Exp $");
__RCSID("$NetBSD: tar.c,v 1.23 2002/10/12 15:39:30 christos Exp $");
#endif
#endif /* not lint */
@ -650,7 +650,12 @@ tar_wr(ARCHD *arcn)
*/
if (ul_oct(tar_chksm(hdblk, sizeof(HD_TAR)), hd->chksum,
sizeof(hd->chksum), 3))
goto out;
goto out; /* XXX Something's wrong here
* because a zero-byte file can
* cause this to be done and
* yet the resulting warning
* seems incorrect */
if (wr_rdbuf(hdblk, sizeof(HD_TAR)) < 0)
return(-1);
if (wr_skip((off_t)(BLKMULT - sizeof(HD_TAR))) < 0)

View File

@ -1,4 +1,4 @@
/* $NetBSD: tar.h,v 1.5 2000/02/17 03:12:27 itohy Exp $ */
/* $NetBSD: tar.h,v 1.6 2002/10/12 15:39:30 christos Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@ -119,12 +119,12 @@ typedef struct {
/*
* default device names
*/
#define DEV_0 "/dev/rmt0"
#define DEV_1 "/dev/rmt1"
#define DEV_4 "/dev/rmt4"
#define DEV_5 "/dev/rmt5"
#define DEV_7 "/dev/rmt7"
#define DEV_8 "/dev/rmt8"
#define DEV_0 "/dev/rst0"
#define DEV_1 "/dev/rst1"
#define DEV_4 "/dev/rst4"
#define DEV_5 "/dev/rst5"
#define DEV_7 "/dev/rst7"
#define DEV_8 "/dev/rst8"
#endif /* _PAX_ */
/*