+ # $OpenBSD: Makefile,v 1.10 2001/05/26 00:32:20 millert Exp $
+
+ # To install on versions prior to BSD 4.4 the following may have to be
+ # defined with CFLAGS +=
+ #
+ # -DLONG_OFF_T Define this if the base type of an off_t is a long (and is
+ # NOT a quad). (This is often defined in the file
+ # /usr/include/sys/types.h).
+ # This define is important, as if you do have a quad_t
+ # off_t and define LONG_OFF_T, pax will compile but will
+ # NOT RUN PROPERLY.
+ #
+
PROG= pax
SRCS= ar_io.c ar_subs.c buf_subs.c cache.c cpio.c file_subs.c ftree.c\
gen_subs.c getoldopt.c options.c pat_rep.c pax.c sel_subs.c tables.c\
- tar.c tty_subs.c
-MAN= pax.1 tar.1 cpio.1
-LINKS= ${BINDIR}/pax ${BINDIR}/tar ${BINDIR}/pax ${BINDIR}/cpio
+ tar.c tty_subs.c fgetln.c strmode.c
+OBJS= $(SRCS:.c=.o)
+MAN= pax.1
-.include <bsd.prog.mk>
+CFLAGS= -Wall -O2 -g\
+ -DNET2_STAT -D_PATH_DEFTAPE=\"/dev/rmt0\" -DDEBIAN -D_GNU_SOURCE
+
+prefix=/usr/local
+
+pax: $(OBJS)
+ $(CC) $(CFLAGS) $(OBJS) -o $@ $(LIBS)
+
+clean:
+ $(RM) *.o
+
+realclean: clean
+ $(RM) $(PROG)
+
+install:
+ install -d -m 755 $(prefix)/bin $(prefix)/share/man/man1
+ install -s -m 755 $(PROG) $(prefix)/bin
+ install -m 644 $(MAN) $(prefix)/share/man/man1
- /* $OpenBSD: ar_io.c,v 1.18 1998/09/20 02:22:21 millert Exp $ */
+ /* $OpenBSD: ar_io.c,v 1.38 2008/06/11 00:49:08 pvalchev Exp $ */
/* $NetBSD: ar_io.c,v 1.5 1996/03/26 23:54:13 mrg Exp $ */
/*-
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
#ifndef lint
#if 0
- static char sccsid[] = "@(#)ar_io.c 8.2 (Berkeley) 4/18/94";
+ static const char sccsid[] = "@(#)ar_io.c 8.2 (Berkeley) 4/18/94";
#else
- static char rcsid[] = "$OpenBSD: ar_io.c,v 1.18 1998/09/20 02:22:21 millert Exp $";
+ static const char rcsid[] = "$OpenBSD: ar_io.c,v 1.38 2008/06/11 00:49:08 pvalchev Exp $";
#endif
#endif /* not lint */
#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>
#define EXT_MODE O_RDONLY /* open mode for list/extract */
#define AR_MODE (O_WRONLY | O_CREAT | O_TRUNC) /* mode for archive */
#define APP_MODE O_RDWR /* mode for append */
- #define STDO "<STDOUT>" /* psuedo name for stdout */
- #define STDN "<STDIN>" /* psuedo name for stdin */
+ #define STDO "<STDOUT>" /* pseudo name for stdout */
+ #define STDN "<STDIN>" /* pseudo name for stdin */
static int arfd = -1; /* archive file descriptor */
static int artyp = ISREG; /* archive type: file/FIFO/tape */
static int arvol = 1; /* archive volume number */
static int invld_rec; /* tape has out of spec record size */
static int wr_trail = 1; /* trailer was rewritten in append */
static int can_unlnk = 0; /* do we unlink null archives? */
- char *arcname; /* printable name of archive */
- char *gzip_program; /* name of gzip program */
+ const char *arcname; /* printable name of archive */
+ const char *gzip_program; /* name of gzip program */
+ static pid_t zpid = -1; /* pid of child process */
+ int force_one_volume; /* 1 if we ignore volume changes */
- static int get_phys __P((void));
+ static int get_phys(void);
extern sigset_t s_mask;
- static void ar_start_gzip __P((int));
+ static void ar_start_gzip(int, const char *, int);
/*
* ar_open()
* -1 on failure, 0 otherwise
*/
- #ifdef __STDC__
int
- ar_open(char *name)
- #else
- int
- ar_open(name)
- char *name;
- #endif
+ ar_open(const char *name)
{
struct mtget mb;
arfd = STDIN_FILENO;
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);
+ syswarn(1, errno, "Failed open to read on %s", name);
+ if (arfd != -1 && gzip_program != NULL)
+ ar_start_gzip(arfd, gzip_program, 0);
break;
case ARCHIVE:
if (name == NULL) {
arfd = STDOUT_FILENO;
arcname = STDO;
} else if ((arfd = open(name, AR_MODE, DMOD)) < 0)
- syswarn(0, errno, "Failed open to write on %s", name);
+ syswarn(1, 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 filter through compressor while appending");
if (name == NULL) {
arfd = STDOUT_FILENO;
arcname = STDO;
} else if ((arfd = open(name, APP_MODE, DMOD)) < 0)
- syswarn(0, errno, "Failed open to read/write on %s",
+ syswarn(1, errno, "Failed open to read/write on %s",
name);
break;
case COPY:
return(-1);
if (chdname != NULL)
- if (chdir(chdname) != 0)
+ if (chdir(chdname) != 0) {
syswarn(1, errno, "Failed chdir to %s", chdname);
+ return(-1);
+ }
/*
* set up is based on device type
*/
if (fstat(arfd, &arsb) < 0) {
- syswarn(0, errno, "Failed stat on %s", arcname);
+ syswarn(1, errno, "Failed stat on %s", arcname);
(void)close(arfd);
arfd = -1;
can_unlnk = 0;
/*
* set default blksz on read. APPNDs writes rdblksz on the last volume
* On all new archive volumes, we shift to wrblksz (if the user
- * specified one, otherwize we will continue to use rdblksz). We
- * must to set blocksize based on what kind of device the archive is
+ * specified one, otherwise we will continue to use rdblksz). We
+ * must set blocksize based on what kind of device the archive is
* stored.
*/
- switch(artyp) {
+ switch (artyp) {
case ISTAPE:
/*
* Tape drives come in at least two flavors. Those that support
if ((arsb.st_size % rdblksz) == 0)
break;
/*
- * When we cannont find a match, we may have a flawed archive.
+ * When we cannot find a match, we may have a flawed archive.
*/
if (rdblksz <= 0)
rdblksz = FILEBLK;
break;
default:
/*
- * should never happen, worse case, slow...
+ * should never happen, worst case, slow...
*/
blksz = rdblksz = BLKMULT;
break;
* ar_close()
* closes archive device, increments volume number, and prints i/o summary
*/
- #ifdef __STDC__
void
ar_close(void)
- #else
- void
- ar_close()
- #endif
{
+ int status;
if (arfd < 0) {
did_io = io_ok = flcnt = 0;
can_unlnk = 0;
}
+ /*
+ * for a quick extract/list, pax frequently exits before the child
+ * process is done
+ */
+ if ((act == LIST || act == EXTRACT) && nflag && zpid > 0)
+ kill(zpid, SIGINT);
+
(void)close(arfd);
+ /* Do not exit before child to ensure data integrity */
+ if (zpid > 0)
+ waitpid(zpid, &status, 0);
+
if (vflag && (artyp == ISTAPE)) {
(void)fputs("done.\n", listf);
vfpart = 0;
* could have written anything yet.
*/
if (frmt == NULL) {
- # ifdef NET2_STAT
+ # ifdef LONG_OFF_T
(void)fprintf(listf, "%s: unknown format, %lu bytes skipped.\n",
# else
(void)fprintf(listf, "%s: unknown format, %qu bytes skipped.\n",
(void)fprintf(listf, "%qu blocks\n", (rdcnt ? rdcnt : wrcnt) / 5120);
else if (strcmp(NM_TAR, argv0) != 0)
(void)fprintf(listf,
- # ifdef NET2_STAT
+ # ifdef LONG_OFF_T
"%s: %s vol %d, %lu files, %lu bytes read, %lu bytes written.\n",
# else
"%s: %s vol %d, %lu files, %qu bytes read, %qu bytes written.\n",
* other side of the pipe from getting a SIGPIPE (pax will stop
* reading an archive once a format dependent trailer is detected).
*/
- #ifdef __STDC__
void
ar_drain(void)
- #else
- void
- ar_drain()
- #endif
{
- register int res;
+ int res;
char drbuf[MAXBLK];
/*
* 0 if all ready to write, -1 otherwise
*/
- #ifdef __STDC__
int
ar_set_wr(void)
- #else
- int
- ar_set_wr()
- #endif
{
off_t cpos;
*/
wr_trail = 0;
- /*
+ /*
* Add any device dependent code as required here
*/
if (artyp != ISREG)
/*
* ar_app_ok()
* check if the last volume in the archive allows appends. We cannot check
- * this until we are ready to write since there is no spec that says all
+ * this until we are ready to write since there is no spec that says all
* volumes in a single archive have to be of the same type...
* Return:
* 0 if we can append, -1 otherwise.
*/
- #ifdef __STDC__
int
ar_app_ok(void)
- #else
- int
- ar_app_ok()
- #endif
{
if (artyp == ISPIPE) {
paxwarn(1, "Cannot append to an archive obtained from a pipe.");
* Number of bytes in buffer. 0 for end of file, -1 for a read error.
*/
- #ifdef __STDC__
int
- ar_read(register char *buf, register int cnt)
- #else
- int
- ar_read(buf, cnt)
- register char *buf;
- register int cnt;
- #endif
+ ar_read(char *buf, int cnt)
{
- register int res = 0;
+ int res = 0;
/*
* if last i/o was in error, no more reads until reset or new volume
io_ok = 1;
if (res != rdblksz) {
/*
- * Record size changed. If this is happens on
+ * Record size changed. If this happens on
* any record after the first, we probably have
* a tape drive which has a fixed record size
- * we are getting multiple records in a single
+ * (we are getting multiple records in a single
* read). Watch out for record blocking that
* violates pax spec (must be a multiple of
* BLKMULT).
* Return:
* Number of bytes written. 0 indicates end of volume reached and with no
* flaws (as best that can be detected). A -1 indicates an unrecoverable
- * error in the archive occured.
+ * error in the archive occurred.
*/
- #ifdef __STDC__
int
- ar_write(register char *buf, register int bsz)
- #else
- int
- ar_write(buf, bsz)
- register char *buf;
- register int bsz;
- #endif
+ ar_write(char *buf, int bsz)
{
- register int res;
+ int res;
off_t cpos;
/*
case ISREG:
if ((res > 0) && (res % BLKMULT)) {
/*
- * try to fix up partial writes which are not BLKMULT
+ * try to fix up partial writes which are not BLKMULT
* in size by forcing the runt record to next archive
* volume
- */
+ */
if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0)
break;
cpos -= (off_t)res;
/*
* Better tell the user the bad news...
* if this is a block aligned archive format, we may have a bad archive
- * if the format wants the header to start at a BLKMULT boundry. While
+ * if the format wants the header to start at a BLKMULT boundary.. While
* we can deal with the mis-aligned data, it violates spec and other
* archive readers will likely fail. if the format is not block
* aligned, the user may be lucky (and the archive is ok).
* 0 when ok to try i/o again, -1 otherwise.
*/
- #ifdef __STDC__
int
ar_rdsync(void)
- #else
- int
- ar_rdsync()
- #endif
{
long fsbz;
off_t cpos;
struct mtop mb;
/*
- * Fail resync attempts at user request (done) or this is going to be
+ * Fail resync attempts at user request (done) or if this is going to be
* an update/append to a existing archive. if last i/o hit media end,
* we need to go to the next volume not try a resync
*/
if (io_ok)
did_io = 1;
- switch(artyp) {
+ switch (artyp) {
case ISTAPE:
/*
* if the last i/o was a successful data transfer, we assume
* the fault is just a bad record on the tape that we are now
* past. If we did not get any data since the last resync try
- * to move the tape foward one PHYSICAL record past any
+ * to move the tape forward one PHYSICAL record past any
* damaged tape section. Some tape drives are stubborn and need
* to be pushed.
*/
/*
* ar_fow()
- * Move the I/O position within the archive foward the specified number of
+ * Move the I/O position within the archive forward the specified number of
* bytes as supported by the device. If we cannot move the requested
* number of bytes, return the actual number of bytes moved in skipped.
* Return:
* partial move (the amount moved is in skipped)
*/
- #ifdef __STDC__
int
ar_fow(off_t sksz, off_t *skipped)
- #else
- int
- ar_fow(sksz, skipped)
- off_t sksz;
- off_t *skipped;
- #endif
{
off_t cpos;
off_t mpos;
return(0);
/*
- * we cannot move foward at EOF or error
+ * we cannot move forward at EOF or error
*/
if (lstrval <= 0)
return(lstrval);
* Safer to read forward on devices where it is hard to find the end of
* the media without reading to it. With tapes we cannot be sure of the
* number of physical blocks to skip (we do not know physical block
- * size at this point), so we must only read foward on tapes!
+ * size at this point), so we must only read forward on tapes!
*/
if (artyp != ISREG)
return(0);
* figure out where we are in the archive
*/
if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) >= 0) {
- /*
- * we can be asked to move farther than there are bytes in this
+ /*
+ * we can be asked to move farther than there are bytes in this
* volume, if so, just go to file end and let normal buf_fill()
* deal with the end of file (it will go to next volume by
* itself)
- */
+ */
if ((mpos = cpos + sksz) > arsb.st_size) {
*skipped = arsb.st_size - cpos;
mpos = arsb.st_size;
if (lseek(arfd, mpos, SEEK_SET) >= 0)
return(0);
}
- syswarn(1, errno, "Foward positioning operation on archive failed");
+ syswarn(1, errno, "Forward positioning operation on archive failed");
lstrval = -1;
return(-1);
}
* 0 if moved the requested distance, -1 on complete failure
*/
- #ifdef __STDC__
int
ar_rev(off_t sksz)
- #else
- int
- ar_rev(sksz)
- off_t sksz;
- #endif
{
off_t cpos;
struct mtop mb;
- register int phyblk;
+ int phyblk;
/*
* make sure we do not have try to reverse on a flawed archive
if (lstrval < 0)
return(lstrval);
- switch(artyp) {
+ switch (artyp) {
case ISPIPE:
if (sksz <= 0)
break;
/*
* we may try to go backwards past the start when the archive
- * is only a single record. If this hapens and we are on a
- * multi volume archive, we need to go to the end of the
+ * is only a single record. If this happens and we are on a
+ * multi-volume archive, we need to go to the end of the
* previous volume and continue our movement backwards from
* there.
*/
break;
case ISTAPE:
/*
- * Calculate and move the proper number of PHYSICAL tape
+ * Calculate and move the proper number of PHYSICAL tape
* blocks. If the sksz is not an even multiple of the physical
* tape size, we cannot do the move (this should never happen).
- * (We also cannot handler trailers spread over two vols).
+ * (We also cannot handle trailers spread over two vols.)
* get_phys() also makes sure we are in front of the filemark.
- */
+ */
if ((phyblk = get_phys()) <= 0) {
lstrval = -1;
return(-1);
/*
* get_phys()
* Determine the physical block size on a tape drive. We need the physical
- * block size so we know how many bytes we skip over when we move with
+ * block size so we know how many bytes we skip over when we move with
* mtio commands. We also make sure we are BEFORE THE TAPE FILEMARK when
* return.
* This is one really SLOW routine...
* physical block size if ok (ok > 0), -1 otherwise
*/
- #ifdef __STDC__
static int
get_phys(void)
- #else
- static int
- get_phys()
- #endif
{
- register int padsz = 0;
- register int res;
- register int phyblk;
+ int padsz = 0;
+ int res;
+ int phyblk;
struct mtop mb;
char scbuf[MAXBLK];
}
/*
- * read foward to the file mark, then back up in front of the filemark
+ * 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(arfd, scbuf, sizeof(scbuf))) > 0)
* 0 when ready to continue, -1 when all done
*/
- #ifdef __STDC__
int
ar_next(void)
- #else
- int
- ar_next()
- #endif
{
char buf[PAXPATHLEN+2];
static int freeit = 0;
if (sigprocmask(SIG_SETMASK, &o_mask, NULL) < 0)
syswarn(0, errno, "Unable to restore signal mask");
- if (done || !wr_trail || strcmp(NM_TAR, argv0) == 0)
+ if (done || !wr_trail || force_one_volume || strcmp(NM_TAR, argv0) == 0)
return(-1);
tty_prnt("\nATTENTION! %s archive volume change required.\n", argv0);
else
tty_prnt("\n");
- for(;;) {
+ for (;;) {
tty_prnt("Type \"y\" to continue, \".\" to quit %s,",
argv0);
tty_prnt(" or \"s\" to switch to new device.\nIf you");
*/
if (ar_open(buf) >= 0) {
if (freeit) {
- (void)free(arcname);
+ (void)free((char *)arcname);
freeit = 0;
}
if ((arcname = strdup(buf)) == NULL) {
/*
* ar_start_gzip()
- * starts the gzip compression/decompression process as a child, using magic
- * to keep the fd the same in the calling function (parent).
+ * starts the compress, gzip or bzip2 compression/decompression process
+ * as a child, using magic to keep the fd the same in the calling function
+ * (parent).
*/
void
- #ifdef __STDC__
- ar_start_gzip(int fd)
- #else
- ar_start_gzip(fd)
- int fd;
- #endif
+ ar_start_gzip(int fd, const char *gzip_program, int wr)
{
- pid_t pid;
int fds[2];
- char *gzip_flags;
+ 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)
- err(1, "could not exec");
+ if (execlp(gzip_program, gzip_program, gzip_flags, (char *)NULL) < 0)
+ err(1, "could not exec %s", gzip_program);
/* NOTREACHED */
}
}
- /* $OpenBSD: ar_subs.c,v 1.14 1998/09/20 02:22:21 millert Exp $ */
+ /* $OpenBSD: ar_subs.c,v 1.32 2008/05/06 06:54:28 henning Exp $ */
/* $NetBSD: ar_subs.c,v 1.5 1995/03/21 09:07:06 cgd Exp $ */
/*-
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
#ifndef lint
#if 0
- static char sccsid[] = "@(#)ar_subs.c 8.2 (Berkeley) 4/18/94";
+ static const char sccsid[] = "@(#)ar_subs.c 8.2 (Berkeley) 4/18/94";
#else
- static char rcsid[] = "$OpenBSD: ar_subs.c,v 1.14 1998/09/20 02:22:21 millert Exp $";
+ static const char rcsid[] = "$OpenBSD: ar_subs.c,v 1.32 2008/05/06 06:54:28 henning Exp $";
#endif
#endif /* not lint */
#include <sys/types.h>
#include <sys/time.h>
+#include <time.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <signal.h>
#include "pax.h"
#include "extern.h"
- static void wr_archive __P((register ARCHD *, int is_app));
- static int get_arc __P((void));
- static int next_head __P((register ARCHD *));
+ static void wr_archive(ARCHD *, int is_app);
+ static int get_arc(void);
+ static int next_head(ARCHD *);
extern sigset_t s_mask;
/*
* (no pattern matches all).
*/
- #ifdef __STDC__
void
list(void)
- #else
- void
- list()
- #endif
{
- register ARCHD *arcn;
- register int res;
+ ARCHD *arcn;
+ int res;
ARCHD archd;
time_t now;
* step through the archive until the format says it is done
*/
while (next_head(arcn) == 0) {
+ if (arcn->type == PAX_GLL || arcn->type == PAX_GLF) {
+ /*
+ * we need to read, to get the real filename
+ */
+ off_t cnt;
+ if (!(*frmt->rd_data)(arcn, arcn->type == PAX_GLF
+ ? -1 : -2, &cnt))
+ (void)rd_skip(cnt + arcn->pad);
+ continue;
+ }
+
/*
* check for pattern, and user specified options match.
* When all patterns are matched we are done.
* pattern(s) (no patterns extracts all members)
*/
- #ifdef __STDC__
void
extract(void)
- #else
- void
- extract()
- #endif
{
- register ARCHD *arcn;
- register int res;
+ ARCHD *arcn;
+ int res;
off_t cnt;
ARCHD archd;
struct stat sb;
* says it is done
*/
while (next_head(arcn) == 0) {
+ if (arcn->type == PAX_GLL || arcn->type == PAX_GLF) {
+ /*
+ * we need to read, to get the real filename
+ */
+ if (!(*frmt->rd_data)(arcn, arcn->type == PAX_GLF
+ ? -1 : -2, &cnt))
+ (void)rd_skip(cnt + arcn->pad);
+ continue;
+ }
/*
* check for pattern, and user specified options match. When
/*
* with -u or -D only extract when the archive member is newer
- * than the file with the same name in the file system (nos
+ * than the file with the same name in the file system (no
* test of being the same type is required).
* NOTE: this test is done BEFORE name modifications as
* specified by pax. this operation can be confusing to the
}
/*
- * Non standard -Y and -Z flag. When the exisiting file is
+ * Non standard -Y and -Z flag. When the existing file is
* same age or newer skip
*/
if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) {
if (vflag > 1)
ls_list(arcn, now, listf);
else {
- (void)fputs(arcn->name, listf);
+ (void)safe_print(arcn->name, listf);
vfpart = 1;
}
}
(void)putc('\n', listf);
vfpart = 0;
}
- continue;
+ goto popd;
}
/*
* we have a file with data here. If we can not create it, skip
if ((fd = file_creat(arcn)) < 0) {
(void)rd_skip(arcn->skip + arcn->pad);
purg_lnk(arcn);
- continue;
+ goto popd;
}
/*
* extract the file from the archive and skip over padding and
if (!res)
(void)rd_skip(cnt + arcn->pad);
+ popd:
/*
* if required, chdir around.
*/
* previously written archive.
*/
- #ifdef __STDC__
static void
- wr_archive(register ARCHD *arcn, int is_app)
- #else
- static void
- wr_archive(arcn, is_app)
- register ARCHD *arcn;
- int is_app;
- #endif
+ wr_archive(ARCHD *arcn, int is_app)
{
- register int res;
- register int hlk;
- register int wr_one;
+ int res;
+ int hlk;
+ int wr_one;
off_t cnt;
- int (*wrf)();
+ int (*wrf)(ARCHD *);
int fd = -1;
time_t now;
if (((hlk = frmt->hlk) == 1) && (lnk_start() < 0))
return;
+ /*
+ * if this is not append, and there are no files, we do not write a
+ * trailer
+ */
+ wr_one = is_app;
+
/*
* start up the file traversal code and format specific write
*/
- if ((ftree_start() < 0) || ((*frmt->st_wr)() < 0))
+ if (ftree_start() < 0) {
+ if (is_app)
+ goto trailer;
return;
+ } else if (((*frmt->st_wr)() < 0))
+ return;
+
wrf = frmt->wr;
/*
if (iflag && (name_start() < 0))
return;
- /*
- * if this not append, and there are no files, we do no write a trailer
- */
- wr_one = is_app;
-
now = time(NULL);
/*
*/
if ((res = chk_ftime(arcn)) < 0)
break;
- if (res > 0)
+ if (res > 0) {
+ ftree_skipped_newer(arcn);
continue;
+ }
}
/*
if ((res > 0) || (docrc && (set_crc(arcn, fd) < 0))) {
/*
* unable to obtain the crc we need, close the file,
- * purge link table entry
+ * purge link table entry
*/
rdfile_close(arcn, &fd);
purg_lnk(arcn);
if (vflag > 1)
ls_list(arcn, now, listf);
else {
- (void)fputs(arcn->name, listf);
+ (void)safe_print(arcn->name, listf);
vfpart = 1;
}
}
}
wr_one = 1;
if (res > 0) {
- /*
+ /*
* format write says no file data needs to be stored
* so we are done messing with this file
*/
break;
}
+ trailer:
/*
- * tell format to write trailer; pad to block boundry; reset directory
+ * tell format to write trailer; pad to block boundary; reset directory
* mode/access times, and check if all patterns supplied by the user
* were matched. block off signals to avoid chance for multiple entry
* into the cleanup code
* is called to add the new members.
* PAX IMPLEMENTATION DETAIL NOTE:
* -u is implemented by adding the new members to the end of the archive.
- * Care is taken so that these do not end up as links to the older
+ * Care is taken so that these do not end up as links to the older
* version of the same file already stored in the archive. It is expected
* when extraction occurs these newer versions will over-write the older
* ones stored "earlier" in the archive (this may be a bad assumption as
* over write existing files that it creates.
*/
- #ifdef __STDC__
void
append(void)
- #else
- void
- append()
- #endif
{
- register ARCHD *arcn;
- register int res;
+ ARCHD *arcn;
+ int res;
ARCHD archd;
FSUB *orgfrmt;
int udev;
/*
* Do not allow an append operation if the actual archive is of a
- * different format than the user specified foramt.
+ * different format than the user specified format.
*/
if (get_arc() < 0)
return;
lnk_end();
/*
- * try to postion for write, if this fails quit. if any error occurs,
+ * try to position for write, if this fails quit. if any error occurs,
* we will refuse to write
*/
if (appnd_start(tlen) < 0)
(void)fputs("done.\n", listf);
vfpart = 0;
}
-
+
/*
* go to the writing phase to add the new members
*/
* write a new archive
*/
- #ifdef __STDC__
void
archive(void)
- #else
- void
- archive()
- #endif
{
ARCHD archd;
* (except the files are forced to be under the destination directory).
*/
- #ifdef __STDC__
void
copy(void)
- #else
- void
- copy()
- #endif
{
- register ARCHD *arcn;
- register int res;
- register int fddest;
- register char *dest_pt;
- register int dlen;
- register int drem;
+ ARCHD *arcn;
+ int res;
+ int fddest;
+ char *dest_pt;
+ int dlen;
+ int drem;
int fdsrc = -1;
struct stat sb;
ARCHD archd;
* 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, sizeof(dirbuf) - 1);
+ dlen = strlcpy(dirbuf, dirptr, sizeof(dirbuf));
+ if (dlen >= sizeof(dirbuf) ||
+ (dlen == sizeof(dirbuf) - 1 && dirbuf[dlen - 1] != '/')) {
+ paxwarn(1, "directory name is too long %s", dirptr);
+ return;
+ }
dest_pt = dirbuf + dlen;
if (*(dest_pt-1) != '/') {
*dest_pt++ = '/';
+ *dest_pt = '\0';
++dlen;
}
- *dest_pt = '\0';
drem = PAXPATHLEN - dlen;
if (stat(dirptr, &sb) < 0) {
/*
* start up the hard link table; file traversal routines and the
- * modification time and access mode database
+ * modification time and access mode database
*/
if ((lnk_start() < 0) || (ftree_start() < 0) || (dir_start() < 0))
return;
/*
* 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) {
paxwarn(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
res = lstat(dirbuf, &sb);
*dest_pt = '\0';
- if (res == 0) {
+ if (res == 0) {
+ ftree_skipped_newer(arcn);
if (uflag && Dflag) {
if ((arcn->sb.st_mtime<=sb.st_mtime) &&
- (arcn->sb.st_ctime<=sb.st_ctime))
+ (arcn->sb.st_ctime<=sb.st_ctime))
continue;
} else if (Dflag) {
if (arcn->sb.st_ctime <= sb.st_ctime)
}
/*
- * Non standard -Y and -Z flag. When the exisiting file is
+ * Non standard -Y and -Z flag. When the existing file is
* same age or newer skip
*/
if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) {
}
if (vflag) {
- (void)fputs(arcn->name, listf);
+ (void)safe_print(arcn->name, listf);
vfpart = 1;
}
++flcnt;
* the specs for rd_wrbuf() for more details)
*/
- #ifdef __STDC__
- static int
- next_head(register ARCHD *arcn)
- #else
static int
- next_head(arcn)
- register ARCHD *arcn;
- #endif
+ next_head(ARCHD *arcn)
{
- register int ret;
- register char *hdend;
- register int res;
- register int shftsz;
- register int hsz;
- register int in_resync = 0; /* set when we are in resync mode */
+ int ret;
+ char *hdend;
+ int res;
+ int shftsz;
+ 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. */
res = hsz = frmt->hsz;
hdend = hdbuf;
shftsz = hsz - 1;
- for(;;) {
+ for (;;) {
/*
* keep looping until we get a contiguous FULL buffer
* (frmt->hsz is the proper size)
/*
* this format has trailers outside of valid headers
*/
- if ((ret = (*frmt->trail)(hdbuf,in_resync,&cnt)) == 0){
+ if ((ret = (*frmt->trail)(arcn,hdbuf,in_resync,&cnt)) == 0){
/*
* valid trailer found, drain input as required
*/
* the header. NOTE: the parameters are different than trailer routines
* which encode trailers outside of the header!
*/
- if (frmt->inhead && ((*frmt->trail)(arcn) == 0)) {
+ if (frmt->inhead && ((*frmt->trail)(arcn,NULL,0,NULL) == 0)) {
/*
* valid trailer found, drain input as required
*/
* 0 if archive found -1 otherwise
*/
- #ifdef __STDC__
static int
get_arc(void)
- #else
- static int
- get_arc()
- #endif
{
- register int i;
- register int hdsz = 0;
- register int res;
- register int minhd = BLKMULT;
+ int i;
+ int hdsz = 0;
+ int res;
+ int minhd = BLKMULT;
char *hdend;
int notice = 0;
res = BLKMULT;
hdsz = 0;
hdend = hdbuf;
- for(;;) {
+ for (;;) {
for (;;) {
/*
* fill the buffer with at least the smallest header
if ((*fsub[ford[i]].id)(hdbuf, hdsz) < 0)
continue;
frmt = &(fsub[ford[i]]);
- /*
+ /*
* yuck, to avoid slow special case code in the extract
* routines, just push this header back as if it was
* not seen. We have left extra space at start of the
- /* $OpenBSD: cache.c,v 1.6 1997/07/25 18:58:27 mickey Exp $ */
+ /* $OpenBSD: cache.c,v 1.17 2004/03/16 03:28:34 tedu Exp $ */
/* $NetBSD: cache.c,v 1.4 1995/03/21 09:07:10 cgd Exp $ */
/*-
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
#ifndef lint
#if 0
- static char sccsid[] = "@(#)cache.c 8.1 (Berkeley) 5/31/93";
+ static const char sccsid[] = "@(#)cache.c 8.1 (Berkeley) 5/31/93";
#else
- static char rcsid[] = "$OpenBSD: cache.c,v 1.6 1997/07/25 18:58:27 mickey Exp $";
+ static const char rcsid[] = "$OpenBSD: cache.c,v 1.17 2004/03/16 03:28:34 tedu Exp $";
#endif
#endif /* not lint */
/*
* uidtb_start
- * creates an an empty uidtb
+ * creates an empty uidtb
* Return:
* 0 if ok, -1 otherwise
*/
- #ifdef __STDC__
int
uidtb_start(void)
- #else
- int
- uidtb_start()
- #endif
{
static int fail = 0;
/*
* gidtb_start
- * creates an an empty gidtb
+ * creates an empty gidtb
* Return:
* 0 if ok, -1 otherwise
*/
- #ifdef __STDC__
int
gidtb_start(void)
- #else
- int
- gidtb_start()
- #endif
{
static int fail = 0;
/*
* usrtb_start
- * creates an an empty usrtb
+ * creates an empty usrtb
* Return:
* 0 if ok, -1 otherwise
*/
- #ifdef __STDC__
int
usrtb_start(void)
- #else
- int
- usrtb_start()
- #endif
{
static int fail = 0;
/*
* grptb_start
- * creates an an empty grptb
+ * creates an empty grptb
* Return:
* 0 if ok, -1 otherwise
*/
- #ifdef __STDC__
int
grptb_start(void)
- #else
- int
- grptb_start()
- #endif
{
static int fail = 0;
* Pointer to stored name (or a empty string)
*/
- #ifdef __STDC__
char *
name_uid(uid_t uid, int frc)
- #else
- char *
- name_uid(uid, frc)
- uid_t uid;
- int frc;
- #endif
{
- register struct passwd *pw;
- register UIDC *ptr;
+ struct passwd *pw;
+ UIDC *ptr;
if ((uidtb == NULL) && (uidtb_start() < 0))
return("");
* No entry for this uid, we will add it
*/
if (!pwopn) {
+#ifdef DEBIAN
+ setpwent();
+#else
setpassent(1);
+#endif
++pwopn;
}
if (ptr == NULL)
- ptr = (UIDC *)malloc(sizeof(UIDC));
+ ptr = uidtb[uid % UID_SZ] = malloc(sizeof(UIDC));
if ((pw = getpwuid(uid)) == NULL) {
/*
* no match for this uid in the local password file
- * a string that is the uid in numberic format
+ * a string that is the uid in numeric format
*/
if (ptr == NULL)
return("");
ptr->uid = uid;
ptr->valid = INVALID;
- # ifdef NET2_STAT
- (void)snprintf(ptr->name, sizeof(ptr->name), "%u", uid);
- # else
(void)snprintf(ptr->name, sizeof(ptr->name), "%lu",
(unsigned long)uid);
- # endif
if (frc == 0)
return("");
} else {
if (ptr == NULL)
return(pw->pw_name);
ptr->uid = uid;
- (void)strncpy(ptr->name, pw->pw_name, UNMLEN-1);
- ptr->name[UNMLEN-1] = '\0';
+ (void)strlcpy(ptr->name, pw->pw_name, sizeof(ptr->name));
ptr->valid = VALID;
}
return(ptr->name);
* Pointer to stored name (or a empty string)
*/
- #ifdef __STDC__
char *
name_gid(gid_t gid, int frc)
- #else
- char *
- name_gid(gid, frc)
- gid_t gid;
- int frc;
- #endif
{
- register struct group *gr;
- register GIDC *ptr;
+ struct group *gr;
+ GIDC *ptr;
if ((gidtb == NULL) && (gidtb_start() < 0))
return("");
* No entry for this gid, we will add it
*/
if (!gropn) {
+#ifdef DEBIAN
+ setgrent();
+#else
setgroupent(1);
+#endif
++gropn;
}
if (ptr == NULL)
- ptr = (GIDC *)malloc(sizeof(GIDC));
+ ptr = gidtb[gid % GID_SZ] = malloc(sizeof(GIDC));
if ((gr = getgrgid(gid)) == NULL) {
/*
return("");
ptr->gid = gid;
ptr->valid = INVALID;
- # ifdef NET2_STAT
- (void)snprintf(ptr->name, sizeof(ptr->name), "%u", gid);
- # else
(void)snprintf(ptr->name, sizeof(ptr->name), "%lu",
(unsigned long)gid);
- # endif
if (frc == 0)
return("");
} else {
if (ptr == NULL)
return(gr->gr_name);
ptr->gid = gid;
- (void)strncpy(ptr->name, gr->gr_name, GNMLEN-1);
- ptr->name[GNMLEN-1] = '\0';
+ (void)strlcpy(ptr->name, gr->gr_name, sizeof(ptr->name));
ptr->valid = VALID;
}
return(ptr->name);
* the uid (if any) for a user name, or a -1 if no match can be found
*/
- #ifdef __STDC__
int
uid_name(char *name, uid_t *uid)
- #else
- int
- uid_name(name, uid)
- char *name;
- uid_t *uid;
- #endif
{
- register struct passwd *pw;
- register UIDC *ptr;
- register int namelen;
+ struct passwd *pw;
+ UIDC *ptr;
+ int namelen;
/*
* return -1 for mangled names
}
if (!pwopn) {
+#ifdef DEBIAN
+ setpwent();
+#else
setpassent(1);
+#endif
++pwopn;
}
if (ptr == NULL)
- ptr = (UIDC *)malloc(sizeof(UIDC));
+ ptr = usrtb[st_hash(name, namelen, UNM_SZ)] =
+ (UIDC *)malloc(sizeof(UIDC));
/*
* no match, look it up, if no match store it as an invalid entry,
*uid = pw->pw_uid;
return(0);
}
- (void)strncpy(ptr->name, name, UNMLEN-1);
- ptr->name[UNMLEN-1] = '\0';
+ (void)strlcpy(ptr->name, name, sizeof(ptr->name));
if ((pw = getpwnam(name)) == NULL) {
ptr->valid = INVALID;
return(-1);
* the gid (if any) for a group name, or a -1 if no match can be found
*/
- #ifdef __STDC__
int
gid_name(char *name, gid_t *gid)
- #else
- int
- gid_name(name, gid)
- char *name;
- gid_t *gid;
- #endif
{
- register struct group *gr;
- register GIDC *ptr;
- register int namelen;
+ struct group *gr;
+ GIDC *ptr;
+ int namelen;
/*
* return -1 for mangled names
}
if (!gropn) {
+#ifdef DEBIAN
+ setgrent();
+#else
setgroupent(1);
+#endif
++gropn;
}
if (ptr == NULL)
- ptr = (GIDC *)malloc(sizeof(GIDC));
+ ptr = grptb[st_hash(name, namelen, GID_SZ)] =
+ (GIDC *)malloc(sizeof(GIDC));
/*
* no match, look it up, if no match store it as an invalid entry,
return(0);
}
- (void)strncpy(ptr->name, name, GNMLEN-1);
- ptr->name[GNMLEN-1] = '\0';
+ (void)strlcpy(ptr->name, name, sizeof(ptr->name));
if ((gr = getgrnam(name)) == NULL) {
ptr->valid = INVALID;
return(-1);
- /* $OpenBSD: cpio.c,v 1.5 1997/07/25 18:58:28 mickey Exp $ */
+ /* $OpenBSD: cpio.c,v 1.18 2008/01/01 16:22:44 tobias Exp $ */
/* $NetBSD: cpio.c,v 1.5 1995/03/21 09:07:13 cgd Exp $ */
/*-
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
#ifndef lint
#if 0
- static char sccsid[] = "@(#)cpio.c 8.1 (Berkeley) 5/31/93";
+ static const char sccsid[] = "@(#)cpio.c 8.1 (Berkeley) 5/31/93";
#else
- static char rcsid[] = "$OpenBSD: cpio.c,v 1.5 1997/07/25 18:58:28 mickey Exp $";
+ static const char rcsid[] = "$OpenBSD: cpio.c,v 1.18 2008/01/01 16:22:44 tobias Exp $";
#endif
#endif /* not lint */
#include <sys/types.h>
+#include <sys/sysmacros.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/param.h>
#include "cpio.h"
#include "extern.h"
- static int rd_nm __P((register ARCHD *, int));
- static int rd_ln_nm __P((register ARCHD *));
- static int com_rd __P((register ARCHD *));
+ static int rd_nm(ARCHD *, int);
+ static int rd_ln_nm(ARCHD *);
+ static int com_rd(ARCHD *);
/*
* Routines which support the different cpio versions
* 0 if ok -1 otherwise (the return values of lnk_start())
*/
- #ifdef __STDC__
int
cpio_strd(void)
- #else
- int
- cpio_strd()
- #endif
{
return(lnk_start());
}
* mode; looking for a valid header), and cnt (which starts at zero)
* which is used to count the number of empty blocks we have seen so far.
* Return:
- * 0 if a valid trailer, -1 if not a valid trailer,
+ * 0 if a valid trailer, -1 if not a valid trailer,
*/
- #ifdef __STDC__
- int
- cpio_trail(register ARCHD *arcn)
- #else
int
- cpio_trail(arcn)
- register ARCHD *arcn;
- #endif
+ cpio_trail(ARCHD *arcn, char *notused, int notused2, int *notused3)
{
/*
* look for trailer id in file we are about to process
* 0
*/
- #ifdef __STDC__
- static int
- com_rd(register ARCHD *arcn)
- #else
static int
- com_rd(arcn)
- register ARCHD *arcn;
- #endif
+ com_rd(ARCHD *arcn)
{
arcn->skip = 0;
arcn->pat = NULL;
arcn->org_name = arcn->name;
- switch(arcn->sb.st_mode & C_IFMT) {
+ switch (arcn->sb.st_mode & C_IFMT) {
case C_ISFIFO:
arcn->type = PAX_FIF;
break;
}
/*
- * cpio_end_wr()
+ * cpio_endwr()
* write the special file with the name trailer in the proper format
* Return:
* result of the write of the trailer from the cpio specific write func
*/
- #ifdef __STDC__
int
cpio_endwr(void)
- #else
- int
- cpio_endwr()
- #endif
{
ARCHD last;
last.nlen = sizeof(TRAILER) - 1;
last.type = PAX_REG;
last.sb.st_nlink = 1;
- (void)strcpy(last.name, TRAILER);
+ (void)strlcpy(last.name, TRAILER, sizeof(last.name));
return((*frmt->wr)(&last));
}
* 0 if ok, -1 otherwise
*/
- #ifdef __STDC__
static int
- rd_nm(register ARCHD *arcn, int nsz)
- #else
- static int
- rd_nm(arcn, nsz)
- register ARCHD *arcn;
- int nsz;
- #endif
+ rd_nm(ARCHD *arcn, int nsz)
{
/*
* do not even try bogus values
* 0 if ok, -1 otherwise
*/
- #ifdef __STDC__
- static int
- rd_ln_nm(register ARCHD *arcn)
- #else
static int
- rd_ln_nm(arcn)
- register ARCHD *arcn;
- #endif
+ rd_ln_nm(ARCHD *arcn)
{
/*
* check the length specified for bogus values
*/
if ((arcn->sb.st_size == 0) ||
(arcn->sb.st_size >= sizeof(arcn->ln_name))) {
- # ifdef NET2_STAT
+ # ifdef LONG_OFF_T
paxwarn(1, "Cpio link name length is invalid: %lu",
arcn->sb.st_size);
# else
* 0 if a valid header, -1 otherwise
*/
- #ifdef __STDC__
int
cpio_id(char *blk, int size)
- #else
- int
- cpio_id(blk, size)
- char *blk;
- int size;
- #endif
{
if ((size < sizeof(HD_CPIO)) ||
(strncmp(blk, AMAGIC, sizeof(AMAGIC) - 1) != 0))
* 0 if a valid header, -1 otherwise.
*/
- #ifdef __STDC__
- int
- cpio_rd(register ARCHD *arcn, register char *buf)
- #else
int
- cpio_rd(arcn, buf)
- register ARCHD *arcn;
- register char *buf;
- #endif
+ cpio_rd(ARCHD *arcn, char *buf)
{
- register int nsz;
- register HD_CPIO *hd;
+ int nsz;
+ HD_CPIO *hd;
/*
* check that this is a valid header, if not return -1
arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime, sizeof(hd->c_mtime),
OCT);
arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
- # ifdef NET2_STAT
+ # ifdef LONG_OFF_T
arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,sizeof(hd->c_filesize),
OCT);
# else
if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) {
/*
- * no link name to read for this file
- */
+ * no link name to read for this file
+ */
arcn->ln_nlen = 0;
arcn->ln_name[0] = '\0';
return(com_rd(arcn));
* size of trailer header in this format
*/
- #ifdef __STDC__
off_t
cpio_endrd(void)
- #else
- off_t
- cpio_endrd()
- #endif
{
return((off_t)(sizeof(HD_CPIO) + sizeof(TRAILER)));
}
* 0 if ok, -1 otherwise (what dev_start() returns)
*/
- #ifdef __STDC__
int
cpio_stwr(void)
- #else
- int
- cpio_stwr()
- #endif
{
return(dev_start());
}
* data to write after the header, -1 if archive write failed
*/
- #ifdef __STDC__
int
- cpio_wr(register ARCHD *arcn)
- #else
- int
- cpio_wr(arcn)
- register ARCHD *arcn;
- #endif
+ cpio_wr(ARCHD *arcn)
{
- register HD_CPIO *hd;
- register int nsz;
+ HD_CPIO *hd;
+ int nsz;
char hdblk[sizeof(HD_CPIO)];
/*
if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
arcn->sb.st_rdev = 0;
- switch(arcn->type) {
+ switch (arcn->type) {
case PAX_CTG:
case PAX_REG:
case PAX_HRG:
/*
* set data size for file data
*/
- # ifdef NET2_STAT
+ # ifdef LONG_OFF_T
if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize,
sizeof(hd->c_filesize), OCT)) {
# else
/*
* vcpio_id()
* determine if a block given to us is a valid system VR4 cpio header
- * WITHOUT crc. WATCH it the magic cookies are in OCTAL, the header
+ * WITHOUT crc. WATCH it the magic cookies are in OCTAL, the header
* uses HEX
* Return:
* 0 if a valid header, -1 otherwise
*/
- #ifdef __STDC__
int
vcpio_id(char *blk, int size)
- #else
- int
- vcpio_id(blk, size)
- char *blk;
- int size;
- #endif
{
if ((size < sizeof(HD_VCPIO)) ||
(strncmp(blk, AVMAGIC, sizeof(AVMAGIC) - 1) != 0))
* 0 if a valid header, -1 otherwise
*/
- #ifdef __STDC__
int
crc_id(char *blk, int size)
- #else
- int
- crc_id(blk, size)
- char *blk;
- int size;
- #endif
{
if ((size < sizeof(HD_VCPIO)) ||
(strncmp(blk, AVCMAGIC, sizeof(AVCMAGIC) - 1) != 0))
* 0 if ok -1 otherwise (the return values of lnk_start())
*/
- #ifdef __STDC__
int
crc_strd(void)
- #else
- int
- crc_strd()
- #endif
{
docrc = 1;
return(lnk_start());
* 0 if a valid header, -1 otherwise.
*/
- #ifdef __STDC__
- int
- vcpio_rd(register ARCHD *arcn, register char *buf)
- #else
int
- vcpio_rd(arcn, buf)
- register ARCHD *arcn;
- register char *buf;
- #endif
+ vcpio_rd(ARCHD *arcn, char *buf)
{
- register HD_VCPIO *hd;
+ HD_VCPIO *hd;
dev_t devminor;
dev_t devmajor;
- register int nsz;
+ int nsz;
/*
* during the id phase it was determined if we were using CRC, use the
arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), HEX);
arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime,sizeof(hd->c_mtime),HEX);
arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
- # ifdef NET2_STAT
+ # ifdef LONG_OFF_T
arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,
sizeof(hd->c_filesize), HEX);
# else
return(-1);
/*
- * skip padding. header + filename is aligned to 4 byte boundries
+ * skip padding. header + filename is aligned to 4 byte boundaries
*/
if (rd_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)
return(-1);
* size of trailer header in this format
*/
- #ifdef __STDC__
off_t
vcpio_endrd(void)
- #else
- off_t
- vcpio_endrd()
- #endif
{
return((off_t)(sizeof(HD_VCPIO) + sizeof(TRAILER) +
(VCPIO_PAD(sizeof(HD_VCPIO) + sizeof(TRAILER)))));
* 0 if ok, -1 otherwise (what dev_start() returns)
*/
- #ifdef __STDC__
int
crc_stwr(void)
- #else
- int
- crc_stwr()
- #endif
{
docrc = 1;
return(dev_start());
* NO data to write after the header, -1 if archive write failed
*/
- #ifdef __STDC__
- int
- vcpio_wr(register ARCHD *arcn)
- #else
int
- vcpio_wr(arcn)
- register ARCHD *arcn;
- #endif
+ vcpio_wr(ARCHD *arcn)
{
- register HD_VCPIO *hd;
+ HD_VCPIO *hd;
unsigned int nsz;
char hdblk[sizeof(HD_VCPIO)];
*/
if (docrc) {
if (ul_asc((u_long)VCMAGIC, hd->c_magic, sizeof(hd->c_magic),
- OCT) ||
+ OCT) ||
ul_asc((u_long)arcn->crc,hd->c_chksum,sizeof(hd->c_chksum),
- HEX))
+ HEX))
goto out;
} else {
if (ul_asc((u_long)VMAGIC, hd->c_magic, sizeof(hd->c_magic),
- OCT) ||
+ OCT) ||
ul_asc((u_long)0L, hd->c_chksum, sizeof(hd->c_chksum),HEX))
goto out;
}
- switch(arcn->type) {
+ switch (arcn->type) {
case PAX_CTG:
case PAX_REG:
case PAX_HRG:
* much to pad.
*/
arcn->pad = VCPIO_PAD(arcn->sb.st_size);
- # ifdef NET2_STAT
+ # ifdef LONG_OFF_T
if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize,
sizeof(hd->c_filesize), HEX)) {
# else
ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid),
HEX) ||
ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid),
- HEX) ||
+ HEX) ||
ul_asc((u_long)arcn->sb.st_mtime, hd->c_mtime, sizeof(hd->c_mtime),
- HEX) ||
+ HEX) ||
ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink),
- HEX) ||
+ HEX) ||
ul_asc((u_long)MAJOR(arcn->sb.st_dev),hd->c_maj, sizeof(hd->c_maj),
HEX) ||
ul_asc((u_long)MINOR(arcn->sb.st_dev),hd->c_min, sizeof(hd->c_min),
* 0 if a valid header, -1 otherwise
*/
- #ifdef __STDC__
int
bcpio_id(char *blk, int size)
- #else
- int
- bcpio_id(blk, size)
- char *blk;
- int size;
- #endif
{
if (size < sizeof(HD_BCPIO))
return(-1);
* 0 if a valid header, -1 otherwise.
*/
- #ifdef __STDC__
- int
- bcpio_rd(register ARCHD *arcn, register char *buf)
- #else
int
- bcpio_rd(arcn, buf)
- register ARCHD *arcn;
- register char *buf;
- #endif
+ bcpio_rd(ARCHD *arcn, char *buf)
{
- register HD_BCPIO *hd;
- register int nsz;
+ HD_BCPIO *hd;
+ int nsz;
/*
* check the header
hd = (HD_BCPIO *)buf;
if (swp_head) {
/*
- * header has swapped bytes on 16 bit boundries
+ * header has swapped bytes on 16 bit boundaries
*/
arcn->sb.st_dev = (dev_t)(RSHRT_EXT(hd->h_dev));
arcn->sb.st_ino = (ino_t)(RSHRT_EXT(hd->h_ino));
return(-1);
/*
- * header + file name are aligned to 2 byte boundries, skip if needed
+ * header + file name are aligned to 2 byte boundaries, skip if needed
*/
if (rd_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)
return(-1);
* size of trailer header in this format
*/
- #ifdef __STDC__
off_t
bcpio_endrd(void)
- #else
- off_t
- bcpio_endrd()
- #endif
{
return((off_t)(sizeof(HD_BCPIO) + sizeof(TRAILER) +
(BCPIO_PAD(sizeof(HD_BCPIO) + sizeof(TRAILER)))));
* bcpio_wr()
* copy the data in the ARCHD to buffer in old binary cpio format
* There is a real chance of field overflow with this critter. So we
- * always check the conversion is ok. nobody in his their right mind
- * should write an achive in this format...
+ * always check the conversion is ok. nobody in their right mind
+ * should write an archive in this format...
* Return
* 0 if file has data to be written after the header, 1 if file has NO
* data to write after the header, -1 if archive write failed
*/
- #ifdef __STDC__
int
- bcpio_wr(register ARCHD *arcn)
- #else
- int
- bcpio_wr(arcn)
- register ARCHD *arcn;
- #endif
+ bcpio_wr(ARCHD *arcn)
{
- register HD_BCPIO *hd;
- register int nsz;
+ HD_BCPIO *hd;
+ int nsz;
char hdblk[sizeof(HD_BCPIO)];
off_t t_offt;
int t_int;
arcn->sb.st_rdev = 0;
hd = (HD_BCPIO *)hdblk;
- switch(arcn->type) {
+ switch (arcn->type) {
case PAX_CTG:
case PAX_REG:
case PAX_HRG:
- /* $OpenBSD: gen_subs.c,v 1.8 1997/09/01 18:29:51 deraadt Exp $ */
+ /* $OpenBSD: gen_subs.c,v 1.19 2007/04/04 21:55:10 millert Exp $ */
/* $NetBSD: gen_subs.c,v 1.5 1995/03/21 09:07:26 cgd Exp $ */
/*-
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
#ifndef lint
#if 0
- static char sccsid[] = "@(#)gen_subs.c 8.1 (Berkeley) 5/31/93";
+ static const char sccsid[] = "@(#)gen_subs.c 8.1 (Berkeley) 5/31/93";
#else
- static char rcsid[] = "$OpenBSD: gen_subs.c,v 1.8 1997/09/01 18:29:51 deraadt Exp $";
+ static const char rcsid[] = "$OpenBSD: gen_subs.c,v 1.19 2007/04/04 21:55:10 millert Exp $";
#endif
#endif /* not lint */
#include <sys/types.h>
+#include <sys/sysmacros.h>
#include <sys/time.h>
+#include <time.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <stdio.h>
-#include <tzfile.h>
+#include "tzfile.h"
#include <utmp.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
+ #include <vis.h>
#include "pax.h"
#include "extern.h"
+#include "strmode.h"
+
/*
* a collection of general purpose subroutines used by pax
*/
#define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY)
#define CURFRMT "%b %e %H:%M"
#define OLDFRMT "%b %e %Y"
- #ifndef UT_NAMESIZE
- #define UT_NAMESIZE 8
- #endif
- #define UT_GRPSIZE 6
+ #define NAME_WIDTH 8
/*
* ls_list()
* list the members of an archive in ls format
*/
- #ifdef __STDC__
- void
- ls_list(register ARCHD *arcn, time_t now, FILE *fp)
- #else
void
- ls_list(arcn, now, fp)
- register ARCHD *arcn;
- time_t now;
- FILE *fp;
- #endif
+ ls_list(ARCHD *arcn, time_t now, FILE *fp)
{
- register struct stat *sbp;
+ struct stat *sbp;
char f_mode[MODELEN];
char f_date[DATELEN];
- char *timefrmt;
+ const char *timefrmt;
+ int term;
+
+ term = zeroflag ? '\0' : '\n'; /* path termination character */
/*
* if not verbose, just print the file name
*/
if (!vflag) {
- (void)fprintf(fp, "%s\n", arcn->name);
+ if (zeroflag)
+ (void)fputs(arcn->name, fp);
+ else
+ safe_print(arcn->name, fp);
+ (void)putc(term, fp);
(void)fflush(fp);
return;
}
*/
if (strftime(f_date,DATELEN,timefrmt,localtime(&(sbp->st_mtime))) == 0)
f_date[0] = '\0';
- (void)fprintf(fp, "%s%2u %-*s %-*s ", f_mode, sbp->st_nlink,
- UT_NAMESIZE, name_uid(sbp->st_uid, 1), UT_GRPSIZE,
- name_gid(sbp->st_gid, 1));
+ (void)fprintf(fp, "%s%2u %-*.*s %-*.*s ", f_mode, sbp->st_nlink,
+ NAME_WIDTH, UT_NAMESIZE, name_uid(sbp->st_uid, 1),
+ NAME_WIDTH, UT_NAMESIZE, name_gid(sbp->st_gid, 1));
/*
* print device id's for devices, or sizes for other nodes
*/
if ((arcn->type == PAX_CHR) || (arcn->type == PAX_BLK))
- # ifdef NET2_STAT
+ # ifdef LONG_OFF_T
(void)fprintf(fp, "%4u,%4u ", MAJOR(sbp->st_rdev),
# else
(void)fprintf(fp, "%4lu,%4lu ", (unsigned long)MAJOR(sbp->st_rdev),
# endif
(unsigned long)MINOR(sbp->st_rdev));
else {
- # ifdef NET2_STAT
+ # ifdef LONG_OFF_T
(void)fprintf(fp, "%9lu ", sbp->st_size);
# else
(void)fprintf(fp, "%9qu ", sbp->st_size);
/*
* print name and link info for hard and soft links
*/
- (void)fprintf(fp, "%s %s", f_date, arcn->name);
- if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG))
- (void)fprintf(fp, " == %s\n", arcn->ln_name);
- else if (arcn->type == PAX_SLK)
- (void)fprintf(fp, " => %s\n", arcn->ln_name);
- else
- (void)putc('\n', fp);
+ (void)fputs(f_date, fp);
+ (void)putc(' ', fp);
+ safe_print(arcn->name, fp);
+ if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) {
+ fputs(" == ", fp);
+ safe_print(arcn->ln_name, fp);
+ } else if (arcn->type == PAX_SLK) {
+ fputs(" -> ", fp);
+ safe_print(arcn->ln_name, fp);
+ }
+ (void)putc(term, fp);
(void)fflush(fp);
return;
}
/*
* tty_ls()
- * print a short summary of file to tty.
+ * print a short summary of file to tty.
*/
- #ifdef __STDC__
- void
- ls_tty(register ARCHD *arcn)
- #else
void
- ls_tty(arcn)
- register ARCHD *arcn;
- #endif
+ ls_tty(ARCHD *arcn)
{
char f_date[DATELEN];
char f_mode[MODELEN];
- char *timefrmt;
+ const char *timefrmt;
if (ltmfrmt == NULL) {
/*
return;
}
- /*
- * l_strncpy()
- * copy src to dest up to len chars (stopping at first '\0').
- * when src is shorter than len, pads to len with '\0'.
- * Return:
- * number of chars copied. (Note this is a real performance win over
- * doing a strncpy(), a strlen(), and then a possible memset())
- */
-
- #ifdef __STDC__
- int
- l_strncpy(register char *dest, register char *src, int len)
- #else
- int
- l_strncpy(dest, src, len)
- register char *dest;
- register char *src;
- int len;
- #endif
+ void
+ safe_print(const char *str, FILE *fp)
{
- register char *stop;
- register char *start;
-
- stop = dest + len;
- start = dest;
- while ((dest < stop) && (*src != '\0'))
- *dest++ = *src++;
- len = dest - start;
- while (dest < stop)
- *dest++ = '\0';
- return(len);
+ char visbuf[5];
+ const char *cp;
+
+ /*
+ * 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);
+ }
}
/*
* unsigned long value
*/
- #ifdef __STDC__
u_long
- asc_ul(register char *str, int len, register int base)
- #else
- u_long
- asc_ul(str, len, base)
- register char *str;
- int len;
- register int base;
- #endif
+ asc_ul(char *str, int len, int base)
{
- register char *stop;
+ char *stop;
u_long tval = 0;
stop = str + len;
break;
}
} else {
- while ((str < stop) && (*str >= '0') && (*str <= '7'))
+ while ((str < stop) && (*str >= '0') && (*str <= '7'))
tval = (tval << 3) + (*str++ - '0');
}
return(tval);
* NOTE: the string created is NOT TERMINATED.
*/
- #ifdef __STDC__
int
- ul_asc(u_long val, register char *str, register int len, register int base)
- #else
- int
- ul_asc(val, str, len, base)
- u_long val;
- register char *str;
- register int len;
- register int base;
- #endif
+ ul_asc(u_long val, char *str, int len, int base)
{
- register char *pt;
+ char *pt;
u_long digit;
/*
return(0);
}
- #ifndef NET2_STAT
+ #ifndef LONG_OFF_T
/*
* asc_uqd()
* convert hex/octal character string into a u_quad_t. We do not have to
* u_quad_t value
*/
- #ifdef __STDC__
- u_quad_t
- asc_uqd(register char *str, int len, register int base)
- #else
u_quad_t
- asc_uqd(str, len, base)
- register char *str;
- int len;
- register int base;
- #endif
+ asc_uqd(char *str, int len, int base)
{
- register char *stop;
+ char *stop;
u_quad_t tval = 0;
stop = str + len;
break;
}
} else {
- while ((str < stop) && (*str >= '0') && (*str <= '7'))
+ while ((str < stop) && (*str >= '0') && (*str <= '7'))
tval = (tval << 3) + (*str++ - '0');
}
return(tval);
* NOTE: the string created is NOT TERMINATED.
*/
- #ifdef __STDC__
- int
- uqd_asc(u_quad_t val, register char *str, register int len, register int base)
- #else
int
- uqd_asc(val, str, len, base)
- u_quad_t val;
- register char *str;
- register int len;
- register int base;
- #endif
+ uqd_asc(u_quad_t val, char *str, int len, int base)
{
- register char *pt;
+ char *pt;
u_quad_t digit;
/*
return(0);
}
#endif
+
+ /*
+ * Copy at max min(bufz, fieldsz) chars from field to buf, stopping
+ * at the first NUL char. NUL terminate buf if there is room left.
+ */
+ size_t
+ fieldcpy(char *buf, size_t bufsz, const char *field, size_t fieldsz)
+ {
+ char *p = buf;
+ const char *q = field;
+ size_t i = 0;
+
+ if (fieldsz > bufsz)
+ fieldsz = bufsz;
+ while (i < fieldsz && *q != '\0') {
+ *p++ = *q++;
+ i++;
+ }
+ if (i < bufsz)
+ *p = '\0';
+ return(i);
+ }
- /* $OpenBSD: options.c,v 1.34 1998/09/20 02:22:22 millert Exp $ */
+ /* $OpenBSD: options.c,v 1.70 2008/06/11 00:49:08 pvalchev Exp $ */
/* $NetBSD: options.c,v 1.6 1996/03/26 23:54:18 mrg Exp $ */
/*-
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
#ifndef lint
#if 0
- static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 4/18/94";
+ static const char sccsid[] = "@(#)options.c 8.2 (Berkeley) 4/18/94";
#else
- static char rcsid[] = "$OpenBSD: options.c,v 1.34 1998/09/20 02:22:22 millert Exp $";
+ static const char rcsid[] = "$OpenBSD: options.c,v 1.70 2008/06/11 00:49:08 pvalchev Exp $";
#endif
#endif /* not lint */
#include "tar.h"
#include "extern.h"
+#include "fgetln.h" /* added, David */
+
/*
* Routines which handle command line options
*/
static OPLIST *ophead = NULL; /* head for format specific options -x */
static OPLIST *optail = NULL; /* option tail */
- static int no_op __P((void));
- static void printflg __P((unsigned int));
- static int c_frmt __P((const void *, const void *));
- static off_t str_offt __P((char *));
- static void pax_options __P((register int, register char **));
- static void pax_usage __P((void));
- static void tar_options __P((register int, register char **));
- static void tar_usage __P((void));
- static void cpio_options __P((register int, register char **));
- static void cpio_usage __P((void));
+ 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 **);
+ static void tar_usage(void);
+ static void cpio_options(int, char **);
+ static void cpio_usage(void);
+
+ /* 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 */
/*
* ford is the archive search order used by get_arc() to determine what kind
- * of archive we are dealing with. This helps to properly id archive formats
+ * of archive we are dealing with. This helps to properly id archive formats
* some formats may be subsets of others....
*/
int ford[] = {5, 4, 3, 2, 1, 0, -1 };
+ /*
+ * Do we have -C anywhere?
+ */
+ int havechd = 0;
+
/*
* options()
* figure out if we are pax, tar or cpio. Call the appropriate options
* parser
*/
- #ifdef __STDC__
- void
- options(register int argc, register char **argv)
- #else
void
- options(argc, argv)
- register int argc;
- register char **argv;
- #endif
+ options(int argc, char **argv)
{
/*
else
argv0 = argv[0];
- if (strcmp(NM_TAR, argv0) == 0)
- return(tar_options(argc, argv));
- else if (strcmp(NM_CPIO, argv0) == 0)
- return(cpio_options(argc, argv));
+ if (strcmp(NM_TAR, argv0) == 0) {
+ tar_options(argc, argv);
+ return;
+ } else if (strcmp(NM_CPIO, argv0) == 0) {
+ cpio_options(argc, argv);
+ return;
+ }
/*
* assume pax as the default
*/
argv0 = NM_PAX;
- return(pax_options(argc, argv));
+ pax_options(argc, argv);
}
/*
* the user specified a legal set of flags. If not, complain and exit
*/
- #ifdef __STDC__
- static void
- pax_options(register int argc, register char **argv)
- #else
static void
- pax_options(argc, argv)
- register int argc;
- register char **argv;
- #endif
+ pax_options(int argc, char **argv)
{
- register int c;
- register int i;
+ int c;
+ int i;
unsigned int flg = 0;
unsigned int bflg = 0;
- register char *pt;
+ char *pt;
FSUB tmp;
- extern char *optarg;
- extern int optind;
/*
* process option flags
*/
- while ((c=getopt(argc,argv,"ab:cdf:ijklno:p:rs:tuvwx:zB:DE:G:HLPT:U:XYZ"))
- != EOF) {
+ while ((c=getopt(argc,argv,"ab:cdf:ijklno:p:rs:tuvwx:zB:DE:G:HLOPT:U:XYZ0"))
+ != -1) {
switch (c) {
case 'a':
/*
/*
* use bzip2. Non standard option.
*/
- zflag = 1;
gzip_program = BZIP2_CMD;
break;
case 'k':
* specify file characteristic options
*/
for (pt = optarg; *pt != '\0'; ++pt) {
- switch(*pt) {
+ switch (*pt) {
case 'a':
/*
* do not preserve access time
break;
case 'p':
/*
- * preserver file mode bits
+ * preserve file mode bits
*/
pmode = 1;
break;
/*
* use gzip. Non standard option.
*/
- zflag = 1;
gzip_program = GZIP_CMD;
break;
case 'B':
Lflag = 1;
flg |= CLF;
break;
+ case 'O':
+ /*
+ * Force one volume. Non standard option.
+ */
+ force_one_volume = 1;
+ break;
case 'P':
/*
* do NOT follow symlinks (default)
Zflag = 1;
flg |= CZF;
break;
+ case '0':
+ /*
+ * Use \0 as pathname terminator.
+ * (For use with the -print0 option of find(1).)
+ */
+ zeroflag = 1;
+ flg |= C0F;
+ break;
default:
pax_usage();
break;
* the user specified a legal set of flags. If not, complain and exit
*/
- #ifdef __STDC__
- static void
- tar_options(register int argc, register char **argv)
- #else
static void
- tar_options(argc, argv)
- register int argc;
- register char **argv;
- #endif
+ tar_options(int argc, char **argv)
{
- register int c;
+ 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.
* process option flags
*/
while ((c = getoldopt(argc, argv,
- "b:cef:hjmopruts:vwxzBC:HLOPXZ014578"))
- != EOF) {
- switch(c) {
+ "b:cef:hjmopqruts:vwxzBC:HI:LOPXZ014578")) != -1) {
+ switch (c) {
case 'b':
/*
* specify blocksize in 512-byte blocks
/*
* use bzip2. Non standard option.
*/
- zflag = 1;
gzip_program = BZIP2_CMD;
break;
case 'm':
*/
pmtime = 0;
break;
- case 'o':
- if (opt_add("write_opt=nodir") < 0)
- tar_usage();
case 'O':
Oflag = 1;
break;
+ case 'o':
+ Oflag = 2;
+ break;
case 'p':
/*
* preserve uid/gid and file mode, regardless of umask
pmode = 1;
pids = 1;
break;
+ case 'q':
+ /*
+ * select first match for a pattern only
+ */
+ nflag = 1;
+ break;
case 'r':
case 'u':
/*
/*
* use gzip. Non standard option.
*/
- zflag = 1;
gzip_program = GZIP_CMD;
break;
case 'B':
*/
break;
case 'C':
+ havechd++;
chdname = optarg;
break;
case 'H':
*/
Hflag = 1;
break;
+ case 'I':
+ if (++nincfiles > incfiles_max) {
+ incfiles_max = nincfiles + 3;
+ incfiles = realloc(incfiles,
+ sizeof(*incfiles) * incfiles_max);
+ if (incfiles == NULL) {
+ paxwarn(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
/*
* use compress.
*/
- zflag = 1;
gzip_program = COMPRESS_CMD;
break;
case '0':
else
listf = stdout;
- /* Traditional tar behaviour (pax wants to read filelist from stdin) */
- if ((act == ARCHIVE || act == APPND) && argc == 0)
+ /* 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 || act == APPND)
- frmt = &(fsub[Oflag ? F_OTAR : F_TAR]);
- else if (Oflag) {
- paxwarn(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
*/
default:
{
int sawpat = 0;
+ char *file, *dir;
- while (*argv != NULL) {
- if (strcmp(*argv, "-C") == 0) {
- if(*++argv == NULL)
+ 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) {
+ paxwarn(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) {
+ paxwarn(1, "Problem with file '%s'", file);
+ tar_usage();
+ }
+ } else if (strcmp(*argv, "-C") == 0) {
+ if (*++argv == NULL)
break;
chdname = *argv++;
-
- continue;
- }
- if (pat_add(*argv++, chdname) < 0)
+ havechd++;
+ } else if (pat_add(*argv++, chdname) < 0)
tar_usage();
- sawpat++;
+ else
+ sawpat = 1;
}
/*
* if patterns were added, we are doing chdir()
- * on a file-by-file basis, else, just one
+ * on a file-by-file basis, else, just one
* global chdir (if any) after opening input.
*/
if (sawpat > 0)
break;
case ARCHIVE:
case APPND:
+ frmt = &(fsub[Oflag ? F_OTAR : F_TAR]);
+
+ if (Oflag == 2 && opt_add("write_opt=nodir") < 0)
+ tar_usage();
+
if (chdname != NULL) { /* initial chdir() */
if (ftree_add(chdname, 1) < 0)
tar_usage();
}
- while (*argv != NULL) {
- if (!strcmp(*argv, "-C")) {
+ 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;
- if (ftree_add(*argv++, 1) < 0)
+ 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) {
+ paxwarn(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) {
+ paxwarn(1, "Problem with file '%s'",
+ file);
tar_usage();
- } else {
- if (ftree_add(*argv++, 0) < 0)
+ }
+ } else if (strcmp(*argv, "-C") == 0) {
+ if (*++argv == NULL)
+ break;
+ if (ftree_add(*argv++, 1) < 0)
tar_usage();
- }
+ havechd++;
+ } else if (ftree_add(*argv++, 0) < 0)
+ tar_usage();
}
/*
* no read errors allowed on updates/append operation!
}
}
+ int mkpath(char *);
+
int
mkpath(path)
char *path;
{
struct stat sb;
- register char *slash;
+ char *slash;
int done = 0;
slash = path;
* the user specified a legal set of flags. If not, complain and exit
*/
- #ifdef __STDC__
static void
- cpio_options(register int argc, register char **argv)
- #else
- static void
- cpio_options(argc, argv)
- register int argc;
- register char **argv;
- #endif
+ cpio_options(int argc, char **argv)
{
- register int c, i;
- size_t len;
+ int c, i;
char *str;
FSUB tmp;
FILE *fp;
dflag = 1;
act = -1;
nodirs = 1;
- while ((c=getopt(argc,argv,"abcdfijklmoprstuvzABC:E:F:H:I:LO:SZ6")) != EOF)
+ while ((c=getopt(argc,argv,"abcdfijklmoprstuvzABC:E:F:H:I:LO:SZ6")) != -1)
switch (c) {
case 'a':
/*
/*
* use bzip2. Non standard option.
*/
- zflag = 1;
gzip_program = BZIP2_CMD;
break;
case 'k':
/*
* use gzip. Non standard option.
*/
- zflag = 1;
gzip_program = GZIP_CMD;
break;
case 'A':
paxwarn(1, "Unable to open file '%s' for read", optarg);
cpio_usage();
}
- while ((str = fgetln(fp, &len)) != NULL) {
- str[len - 1] = '\0';
+ while ((str = getline(fp)) != NULL) {
pat_add(str, NULL);
}
fclose(fp);
+ if (getline_error) {
+ paxwarn(1, "Problem with file '%s'", optarg);
+ cpio_usage();
+ }
break;
case 'F':
case 'I':
/*
* use compress. Non standard option.
*/
- zflag = 1;
gzip_program = COMPRESS_CMD;
break;
case '6':
* no read errors allowed on updates/append operation!
*/
maxflt = 0;
- while ((str = fgetln(stdin, &len)) != NULL) {
- str[len - 1] = '\0';
- ftree_add(strdup(str), NULL);
+ while ((str = getline(stdin)) != NULL) {
+ ftree_add(str, 0);
+ }
+ if (getline_error) {
+ paxwarn(1, "Problem while reading stdin");
+ cpio_usage();
}
break;
default:
* print out those invalid flag sets found to the user
*/
- #ifdef __STDC__
static void
printflg(unsigned int flg)
- #else
- static void
- printflg(flg)
- unsigned int flg;
- #endif
{
int nxt;
int pos = 0;
* by the user
*/
- #ifdef __STDC__
static int
c_frmt(const void *a, const void *b)
- #else
- static int
- c_frmt(a, b)
- void *a;
- void *b;
- #endif
{
return(strcmp(((FSUB *)a)->name, ((FSUB *)b)->name));
}
* pointer to next OPLIST entry or NULL (end of list).
*/
- #ifdef __STDC__
OPLIST *
opt_next(void)
- #else
- OPLIST *
- opt_next()
- #endif
{
OPLIST *opt;
* when the format does not support options.
*/
- #ifdef __STDC__
int
bad_opt(void)
- #else
- int
- bad_opt()
- #endif
{
- register OPLIST *opt;
+ OPLIST *opt;
if (ophead == NULL)
return(0);
* opt_add()
* breaks the value supplied to -o into a option name and value. options
* are given to -o in the form -o name-value,name=value
- * mulltiple -o may be specified.
+ * multiple -o may be specified.
* Return:
* 0 if format in name=value format, -1 if -o is passed junk
*/
- #ifdef __STDC__
int
- opt_add(register char *str)
- #else
- int
- opt_add(str)
- register char *str;
- #endif
+ opt_add(const char *str)
{
- register OPLIST *opt;
- register char *frpt;
- register char *pt;
- register char *endpt;
+ OPLIST *opt;
+ char *frpt;
+ char *pt;
+ char *endpt;
+ char *dstr;
if ((str == NULL) || (*str == '\0')) {
paxwarn(0, "Invalid option name");
return(-1);
}
- if ((str = strdup(str)) == NULL) {
+ if ((dstr = strdup(str)) == NULL) {
paxwarn(0, "Unable to allocate space for option list");
return(-1);
}
- frpt = endpt = str;
+ frpt = endpt = dstr;
/*
* break into name and values pieces and stuff each one into a
*endpt = '\0';
if ((pt = strchr(frpt, '=')) == NULL) {
paxwarn(0, "Invalid options format");
- free(str);
+ free(dstr);
return(-1);
}
if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
paxwarn(0, "Unable to allocate space for option list");
- free(str);
+ free(dstr);
return(-1);
}
*pt++ = '\0';
* 4) A positive decimal number followed by a m (mult by 512).
* 5) A positive decimal number followed by a w (mult by sizeof int)
* 6) Two or more positive decimal numbers (with/without k,b or w).
- * seperated by x (also * for backwards compatibility), specifying
+ * separated by x (also * for backwards compatibility), specifying
* the product of the indicated values.
* Return:
* 0 for an error, a positive value o.w.
*/
- #ifdef __STDC__
static off_t
str_offt(char *val)
- #else
- static off_t
- str_offt(val)
- char *val;
- #endif
{
char *expr;
off_t num, t;
- # ifdef NET2_STAT
+ # ifdef LONG_OFF_T
num = strtol(val, &expr, 0);
if ((num == LONG_MAX) || (num <= 0) || (expr == val))
# else
# endif
return(0);
- switch(*expr) {
+ switch (*expr) {
case 'b':
t = num;
num *= 512;
break;
}
- switch(*expr) {
+ switch (*expr) {
case '\0':
break;
case '*':
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.
* 0
*/
- #ifdef __STDC__
static int
no_op(void)
- #else
- static int
- no_op()
- #endif
{
return(0);
}
* print the usage summary to the user
*/
- #ifdef __STDC__
void
pax_usage(void)
- #else
- void
- pax_usage()
- #endif
{
- (void)fputs("usage: pax [-cdjnvz] [-E limit] [-f archive] ", stderr);
- (void)fputs("[-s replstr] ... [-U user] ...", stderr);
- (void)fputs("\n [-G group] ... ", stderr);
- (void)fputs("[-T [from_date][,to_date]] ... ", stderr);
- (void)fputs("[pattern ...]\n", stderr);
- (void)fputs(" pax -r [-cdijknuvzDYZ] [-E limit] ", stderr);
- (void)fputs("[-f archive] [-o options] ... \n", stderr);
- (void)fputs(" [-p string] ... [-s replstr] ... ", stderr);
- (void)fputs("[-U user] ... [-G group] ...\n ", stderr);
- (void)fputs("[-T [from_date][,to_date]] ... ", stderr);
- (void)fputs(" [pattern ...]\n", stderr);
- (void)fputs(" pax -w [-dijtuvzHLPX] [-b blocksize] ", stderr);
- (void)fputs("[ [-a] [-f archive] ] [-x format] \n", stderr);
- (void)fputs(" [-B bytes] [-s replstr] ... ", stderr);
- (void)fputs("[-o options] ... [-U user] ...", stderr);
- (void)fputs("\n [-G group] ... ", stderr);
- (void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
- (void)fputs("[file ...]\n", stderr);
- (void)fputs(" pax -r -w [-diklntuvDHLPXYZ] ", stderr);
- (void)fputs("[-p string] ... [-s replstr] ...", stderr);
- (void)fputs("\n [-U user] ... [-G group] ... ", stderr);
- (void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
- (void)fputs("\n [file ...] directory\n", stderr);
+ (void)fputs(
+ "usage: pax [-0cdjnOvz] [-E limit] [-f archive] [-G group] [-s replstr]\n"
+ " [-T range] [-U user] [pattern ...]\n"
+ " pax -r [-0cDdijknOuvYZz] [-E limit] [-f archive] [-G group] [-o options]\n"
+ " [-p string] [-s replstr] [-T range] [-U user] [pattern ...]\n"
+ " pax -w [-0adHijLOPtuvXz] [-B bytes] [-b blocksize] [-f archive]\n"
+ " [-G group] [-o options] [-s replstr] [-T range] [-U user]\n"
+ " [-x format] [file ...]\n"
+ " pax -rw [-0DdHikLlnOPtuvXYZ] [-G group] [-p string] [-s replstr]\n"
+ " [-T range] [-U user] [file ...] directory\n",
+ stderr);
exit(1);
}
* print the usage summary to the user
*/
- #ifdef __STDC__
void
tar_usage(void)
- #else
- void
- tar_usage()
- #endif
{
- (void)fputs("usage: tar -{txru}[cevfbjmopswzBHLPXZ014578] [tapefile] ",
- stderr);
- (void)fputs("[blocksize] [replstr] [-C directory] file1 file2...\n",
+ (void)fputs(
+ "usage: tar {crtux}[014578befHhjLmOoPpqsvwXZz]\n"
+ " [blocking-factor | archive | replstr] [-C directory] [-I file]\n"
+ " [file ...]\n"
+ " tar {-crtux} [-014578eHhjLmOoPpqvwXZz] [-b blocking-factor]\n"
+ " [-C directory] [-f archive] [-I file] [-s replstr] [file ...]\n",
stderr);
exit(1);
}
* print the usage summary to the user
*/
- #ifdef __STDC__
void
cpio_usage(void)
- #else
- void
- cpio_usage()
- #endif
{
- (void)fputs("usage: cpio -o [-aABcjLvVzZ] [-C bytes] [-H format] [-O archive]\n", stderr);
- (void)fputs(" [-F archive] < name-list [> archive]\n", stderr);
- (void)fputs(" cpio -i [-bBcdfjmnrsStuvVzZ6] [-C bytes] [-E file] [-H format]\n", stderr);
- (void)fputs(" [-I archive] [-F archive] [pattern...] [< archive]\n", stderr);
- (void)fputs(" cpio -p [-adlLmuvV] destination-directory < name-list\n", stderr);
+ (void)fputs(
+ "usage: cpio -o [-AaBcjLvZz] [-C bytes] [-F archive] [-H format]\n"
+ " [-O archive] < name-list [> archive]\n"
+ " cpio -i [-6BbcdfjmrSstuvZz] [-C bytes] [-E file] [-F archive] [-H format]\n"
+ " [-I archive] [pattern ...] [< archive]\n"
+ " cpio -p [-adLlmuv] destination-directory < name-list\n",
+ stderr);
exit(1);
}
- /* $OpenBSD: sel_subs.c,v 1.7 1997/08/17 23:05:09 millert Exp $ */
+ /* $OpenBSD: sel_subs.c,v 1.18 2004/04/16 22:50:23 deraadt Exp $ */
/* $NetBSD: sel_subs.c,v 1.5 1995/03/21 09:07:42 cgd Exp $ */
/*-
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
#ifndef lint
#if 0
- static char sccsid[] = "@(#)sel_subs.c 8.1 (Berkeley) 5/31/93";
+ static const char sccsid[] = "@(#)sel_subs.c 8.1 (Berkeley) 5/31/93";
#else
- static char rcsid[] = "$OpenBSD: sel_subs.c,v 1.7 1997/08/17 23:05:09 millert Exp $";
+ static const char rcsid[] = "$OpenBSD: sel_subs.c,v 1.18 2004/04/16 22:50:23 deraadt Exp $";
#endif
#endif /* not lint */
#include <sys/types.h>
#include <sys/time.h>
+#include <time.h>
#include <sys/stat.h>
#include <sys/param.h>
- #include <pwd.h>
+ #include <ctype.h>
#include <grp.h>
+ #include <pwd.h>
#include <stdio.h>
+ #include <stdlib.h>
#include <string.h>
+ #include <tzfile.h>
#include <unistd.h>
- #include <stdlib.h>
#include "pax.h"
#include "sel_subs.h"
#include "extern.h"
- static int str_sec __P((register char *, time_t *));
- static int usr_match __P((register ARCHD *));
- static int grp_match __P((register ARCHD *));
- static int trng_match __P((register ARCHD *));
+ static int str_sec(const char *, time_t *);
+ static int usr_match(ARCHD *);
+ static int grp_match(ARCHD *);
+ static int trng_match(ARCHD *);
static TIME_RNG *trhead = NULL; /* time range list head */
static TIME_RNG *trtail = NULL; /* time range list tail */
/*
* sel_chk()
- * check if this file matches a specfied uid, gid or time range
+ * check if this file matches a specified uid, gid or time range
* Return:
* 0 if this archive member should be processed, 1 if it should be skipped
*/
- #ifdef __STDC__
int
- sel_chk(register ARCHD *arcn)
- #else
- int
- sel_chk(arcn)
- register ARCHD *arcn;
- #endif
+ sel_chk(ARCHD *arcn)
{
if (((usrtb != NULL) && usr_match(arcn)) ||
((grptb != NULL) && grp_match(arcn)) ||
* User/group selection routines
*
* Routines to handle user selection of files based on the file uid/gid. To
- * add an entry, the user supplies either then name or the uid/gid starting with
- * a # on the command line. A \# will eascape the #.
+ * add an entry, the user supplies either the name or the uid/gid starting with
+ * a # on the command line. A \# will escape the #.
*/
/*
* 0 if added ok, -1 otherwise;
*/
- #ifdef __STDC__
int
- usr_add(register char *str)
- #else
- int
- usr_add(str)
- register char *str;
- #endif
+ usr_add(char *str)
{
- register u_int indx;
- register USRT *pt;
- register struct passwd *pw;
- register uid_t uid;
+ u_int indx;
+ USRT *pt;
+ struct passwd *pw;
+ uid_t uid;
/*
* create the table if it doesn't exist
}
uid = (uid_t)pw->pw_uid;
} else
- # ifdef NET2_STAT
- uid = (uid_t)atoi(str+1);
- # else
uid = (uid_t)strtoul(str+1, NULL, 10);
- # endif
endpwent();
/*
* 0 if this archive member should be processed, 1 if it should be skipped
*/
- #ifdef __STDC__
static int
- usr_match(register ARCHD *arcn)
- #else
- static int
- usr_match(arcn)
- register ARCHD *arcn;
- #endif
+ usr_match(ARCHD *arcn)
{
- register USRT *pt;
+ USRT *pt;
/*
* hash and look for it in the table
* 0 if added ok, -1 otherwise;
*/
- #ifdef __STDC__
int
- grp_add(register char *str)
- #else
- int
- grp_add(str)
- register char *str;
- #endif
+ grp_add(char *str)
{
- register u_int indx;
- register GRPT *pt;
- register struct group *gr;
- register gid_t gid;
+ u_int indx;
+ GRPT *pt;
+ struct group *gr;
+ gid_t gid;
/*
* create the table if it doesn't exist
}
gid = (gid_t)gr->gr_gid;
} else
- # ifdef NET2_STAT
- gid = (gid_t)atoi(str+1);
- # else
gid = (gid_t)strtoul(str+1, NULL, 10);
- # endif
endgrent();
/*
* 0 if this archive member should be processed, 1 if it should be skipped
*/
- #ifdef __STDC__
- static int
- grp_match(register ARCHD *arcn)
- #else
static int
- grp_match(arcn)
- register ARCHD *arcn;
- #endif
+ grp_match(ARCHD *arcn)
{
- register GRPT *pt;
+ GRPT *pt;
/*
* hash and look for it in the table
* trng_add()
* add a time range match to the time range list.
* This is a non-standard pax option. Lower and upper ranges are in the
- * format: [yy[mm[dd[hh]]]]mm[.ss] and are comma separated.
+ * format: [[[[[cc]yy]mm]dd]HH]MM[.SS] and are comma separated.
* Time ranges are based on current time, so 1234 would specify a time of
* 12:34 today.
* Return:
* 0 if the time range was added to the list, -1 otherwise
*/
- #ifdef __STDC__
- int
- trng_add(register char *str)
- #else
int
- trng_add(str)
- register char *str;
- #endif
+ trng_add(char *str)
{
- register TIME_RNG *pt;
- register char *up_pt = NULL;
- register char *stpt;
- register char *flgpt;
- register int dot = 0;
+ TIME_RNG *pt;
+ char *up_pt = NULL;
+ char *stpt;
+ char *flgpt;
+ int dot = 0;
/*
* throw out the badly formed time ranges
}
/*
- * by default we only will check file mtime, but usee can specify
+ * by default we only will check file mtime, but user can specify
* mtime, ctime (inode change time) or both.
*/
if ((flgpt == NULL) || (*flgpt == '\0'))
else {
pt->flgs = 0;
while (*flgpt != '\0') {
- switch(*flgpt) {
+ switch (*flgpt) {
case 'M':
case 'm':
pt->flgs |= CMPMTME;
return(0);
out:
- paxwarn(1, "Time range format is: [yy[mm[dd[hh]]]]mm[.ss][/[c][m]]");
+ paxwarn(1, "Time range format is: [[[[[cc]yy]mm]dd]HH]MM[.SS][/[c][m]]");
return(-1);
}
* 0 if this archive member should be processed, 1 if it should be skipped
*/
- #ifdef __STDC__
- static int
- trng_match(register ARCHD *arcn)
- #else
static int
- trng_match(arcn)
- register ARCHD *arcn;
- #endif
+ trng_match(ARCHD *arcn)
{
- register TIME_RNG *pt;
+ TIME_RNG *pt;
/*
* have to search down the list one at a time looking for a match.
*/
pt = trhead;
while (pt != NULL) {
- switch(pt->flgs & CMPBOTH) {
+ switch (pt->flgs & CMPBOTH) {
case CMPBOTH:
/*
* user wants both mtime and ctime checked for this
/*
* str_sec()
- * Convert a time string in the format of [yy[mm[dd[hh]]]]mm[.ss] to gmt
- * seconds. Tval already has current time loaded into it at entry.
+ * Convert a time string in the format of [[[[[cc]yy]mm]dd]HH]MM[.SS] to
+ * seconds UTC. Tval already has current time loaded into it at entry.
* Return:
* 0 if converted ok, -1 otherwise
*/
- #ifdef __STDC__
- static int
- str_sec(register char *str, time_t *tval)
- #else
static int
- str_sec(str, tval)
- register char *str;
- time_t *tval;
- #endif
+ str_sec(const char *p, time_t *tval)
{
- register struct tm *lt;
- register char *dot = NULL;
+ struct tm *lt;
+ const char *dot, *t;
+ size_t len;
+ int bigyear;
+ int yearset;
+
+ yearset = 0;
+ len = strlen(p);
+
+ for (t = p, dot = NULL; *t; ++t) {
+ if (isdigit(*t))
+ continue;
+ if (*t == '.' && dot == NULL) {
+ dot = t;
+ continue;
+ }
+ return(-1);
+ }
lt = localtime(tval);
- if ((dot = strchr(str, '.')) != NULL) {
- /*
- * seconds (.ss)
- */
- *dot++ = '\0';
- if (strlen(dot) != 2)
+
+ if (dot != NULL) { /* .SS */
+ if (strlen(++dot) != 2)
return(-1);
- if ((lt->tm_sec = ATOI2(dot)) > 61)
+ lt->tm_sec = ATOI2(dot);
+ if (lt->tm_sec > 61)
return(-1);
+ len -= 3;
} else
lt->tm_sec = 0;
- switch (strlen(str)) {
- case 10:
- /*
- * year (yy)
- * watch out for year 2000
- */
- if ((lt->tm_year = ATOI2(str)) < 69)
- lt->tm_year += 100;
- str += 2;
+ switch (len) {
+ case 12: /* cc */
+ bigyear = ATOI2(p);
+ lt->tm_year = (bigyear * 100) - TM_YEAR_BASE;
+ yearset = 1;
/* FALLTHROUGH */
- case 8:
- /*
- * month (mm)
- * watch out months are from 0 - 11 internally
- */
- if ((lt->tm_mon = ATOI2(str)) > 12)
+ case 10: /* yy */
+ if (yearset) {
+ lt->tm_year += ATOI2(p);
+ } else {
+ lt->tm_year = ATOI2(p);
+ if (lt->tm_year < 69) /* hack for 2000 ;-} */
+ lt->tm_year += (2000 - TM_YEAR_BASE);
+ else
+ lt->tm_year += (1900 - TM_YEAR_BASE);
+ }
+ /* FALLTHROUGH */
+ case 8: /* mm */
+ lt->tm_mon = ATOI2(p);
+ if ((lt->tm_mon > 12) || !lt->tm_mon)
return(-1);
- --lt->tm_mon;
- str += 2;
+ --lt->tm_mon; /* time struct is 0 - 11 */
/* FALLTHROUGH */
- case 6:
- /*
- * day (dd)
- */
- if ((lt->tm_mday = ATOI2(str)) > 31)
+ case 6: /* dd */
+ lt->tm_mday = ATOI2(p);
+ if ((lt->tm_mday > 31) || !lt->tm_mday)
return(-1);
- str += 2;
/* FALLTHROUGH */
- case 4:
- /*
- * hour (hh)
- */
- if ((lt->tm_hour = ATOI2(str)) > 23)
+ case 4: /* HH */
+ lt->tm_hour = ATOI2(p);
+ if (lt->tm_hour > 23)
return(-1);
- str += 2;
/* FALLTHROUGH */
- case 2:
- /*
- * minute (mm)
- */
- if ((lt->tm_min = ATOI2(str)) > 59)
+ case 2: /* MM */
+ lt->tm_min = ATOI2(p);
+ if (lt->tm_min > 59)
return(-1);
break;
default:
return(-1);
}
- /*
- * convert broken-down time to GMT clock time seconds
- */
+
+ /* convert broken-down time to UTC clock time seconds */
if ((*tval = mktime(lt)) == -1)
return(-1);
return(0);
- /* $OpenBSD: tar.c,v 1.13 1998/09/26 21:29:41 millert Exp $ */
+ /* $OpenBSD: tar.c,v 1.41 2006/03/04 20:24:55 otto Exp $ */
/* $NetBSD: tar.c,v 1.5 1995/03/21 09:07:49 cgd Exp $ */
/*-
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
#ifndef lint
#if 0
- static char sccsid[] = "@(#)tar.c 8.2 (Berkeley) 4/18/94";
+ static const char sccsid[] = "@(#)tar.c 8.2 (Berkeley) 4/18/94";
#else
- static char rcsid[] = "$OpenBSD: tar.c,v 1.13 1998/09/26 21:29:41 millert Exp $";
+ static const char rcsid[] = "$OpenBSD: tar.c,v 1.41 2006/03/04 20:24:55 otto Exp $";
#endif
#endif /* not lint */
#include <sys/types.h>
+#include <sys/sysmacros.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/param.h>
* Routines for reading, writing and header identify of various versions of tar
*/
- static u_long tar_chksm __P((register char *, register int));
- static char *name_split __P((register char *, register int));
- static int ul_oct __P((u_long, register char *, register int, int));
- #ifndef NET2_STAT
- static int uqd_oct __P((u_quad_t, register char *, register int, int));
+ static size_t expandname(char *, size_t, char **, const char *, size_t);
+ static u_long tar_chksm(char *, int);
+ static char *name_split(char *, int);
+ static int ul_oct(u_long, char *, int, int);
+ #ifndef LONG_OFF_T
+ static int uqd_oct(u_quad_t, char *, int, int);
#endif
+ static uid_t uid_nobody;
+ static uid_t uid_warn;
+ static gid_t gid_nobody;
+ static gid_t gid_warn;
+
/*
* Routines common to all versions of tar
*/
static int tar_nodir; /* do not write dirs under old tar */
+ char *gnu_name_string; /* GNU ././@LongLink hackery name */
+ char *gnu_link_string; /* GNU ././@LongLink hackery link */
/*
* tar_endwr()
* 0 if ok, -1 otherwise (what wr_skip returns)
*/
- #ifdef __STDC__
int
tar_endwr(void)
- #else
- int
- tar_endwr()
- #endif
{
return(wr_skip((off_t)(NULLCNT*BLKMULT)));
}
* size of trailer (2 * BLKMULT)
*/
- #ifdef __STDC__
off_t
tar_endrd(void)
- #else
- off_t
- tar_endrd()
- #endif
{
return((off_t)(NULLCNT*BLKMULT));
}
* could never contain a header.
*/
- #ifdef __STDC__
- int
- tar_trail(register char *buf, register int in_resync, register int *cnt)
- #else
int
- tar_trail(buf, in_resync, cnt)
- register char *buf;
- register int in_resync;
- register int *cnt;
- #endif
+ tar_trail(ARCHD *ignore, char *buf, int in_resync, int *cnt)
{
- register int i;
+ int i;
/*
* look for all zero, trailer is two consecutive blocks of zero
* 0 if the number fit into the string, -1 otherwise
*/
- #ifdef __STDC__
- static int
- ul_oct(u_long val, register char *str, register int len, int term)
- #else
static int
- ul_oct(val, str, len, term)
- u_long val;
- register char *str;
- register int len;
- int term;
- #endif
+ ul_oct(u_long val, char *str, int len, int term)
{
- register char *pt;
+ char *pt;
/*
* term selects the appropriate character(s) for the end of the string
*/
pt = str + len - 1;
- switch(term) {
+ switch (term) {
case 3:
*pt-- = '\0';
break;
return(0);
}
- #ifndef NET2_STAT
+ #ifndef LONG_OFF_T
/*
* uqd_oct()
* convert an u_quad_t to an octal string. one of many oddball field
* 0 if the number fit into the string, -1 otherwise
*/
- #ifdef __STDC__
- static int
- uqd_oct(u_quad_t val, register char *str, register int len, int term)
- #else
static int
- uqd_oct(val, str, len, term)
- u_quad_t val;
- register char *str;
- register int len;
- int term;
- #endif
+ uqd_oct(u_quad_t val, char *str, int len, int term)
{
- register char *pt;
+ char *pt;
/*
* term selects the appropriate character(s) for the end of the string
*/
pt = str + len - 1;
- switch(term) {
+ switch (term) {
case 3:
*pt-- = '\0';
break;
/*
* tar_chksm()
* calculate the checksum for a tar block counting the checksum field as
- * all blanks (BLNKSUM is that value pre-calculated, the sume of 8 blanks).
+ * all blanks (BLNKSUM is that value pre-calculated, the sum of 8 blanks).
* NOTE: we use len to short circuit summing 0's on write since we ALWAYS
* pad headers with 0.
* Return:
* unsigned long checksum
*/
- #ifdef __STDC__
static u_long
- tar_chksm(register char *blk, register int len)
- #else
- static u_long
- tar_chksm(blk, len)
- register char *blk;
- register int len;
- #endif
+ tar_chksm(char *blk, int len)
{
- register char *stop;
- register char *pt;
- u_long chksm = BLNKSUM; /* inital value is checksum field sum */
+ char *stop;
+ char *pt;
+ u_long chksm = BLNKSUM; /* initial value is checksum field sum */
/*
* add the part of the block before the checksum field
* 0 if a tar header, -1 otherwise
*/
- #ifdef __STDC__
int
- tar_id(register char *blk, int size)
- #else
- int
- tar_id(blk, size)
- register char *blk;
- int size;
- #endif
+ tar_id(char *blk, int size)
{
- register HD_TAR *hd;
- register HD_USTAR *uhd;
+ HD_TAR *hd;
+ HD_USTAR *uhd;
if (size < BLKMULT)
return(-1);
return(-1);
if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT))
return(-1);
+ force_one_volume = 1;
return(0);
}
* 0 if ok -1 otherwise
*/
- #ifdef __STDC__
int
tar_opt(void)
- #else
- int
- tar_opt()
- #endif
{
OPLIST *opt;
* 0
*/
- #ifdef __STDC__
int
- tar_rd(register ARCHD *arcn, register char *buf)
- #else
- int
- tar_rd(arcn, buf)
- register ARCHD *arcn;
- register char *buf;
- #endif
+ tar_rd(ARCHD *arcn, char *buf)
{
- register HD_TAR *hd;
- register char *pt;
+ HD_TAR *hd;
+ char *pt;
/*
* we only get proper sized buffers passed to us
*/
if (tar_id(buf, BLKMULT) < 0)
return(-1);
+ memset(arcn, 0, sizeof(*arcn));
arcn->org_name = arcn->name;
arcn->sb.st_nlink = 1;
- arcn->pat = NULL;
/*
* copy out the name and values in the stat buffer
*/
hd = (HD_TAR *)buf;
- arcn->nlen = l_strncpy(arcn->name, hd->name, sizeof(arcn->name) - 1);
- arcn->name[arcn->nlen] = '\0';
+ if (hd->linkflag != LONGLINKTYPE && hd->linkflag != LONGNAMETYPE) {
+ arcn->nlen = expandname(arcn->name, sizeof(arcn->name),
+ &gnu_name_string, hd->name, sizeof(hd->name));
+ arcn->ln_nlen = expandname(arcn->ln_name, sizeof(arcn->ln_name),
+ &gnu_link_string, hd->linkname, sizeof(hd->linkname));
+ }
arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode,sizeof(hd->mode),OCT) &
0xfff);
arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT);
arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT);
- arcn->sb.st_size = (size_t)asc_ul(hd->size, sizeof(hd->size), OCT);
+ #ifdef LONG_OFF_T
+ arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT);
+ #else
+ arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT);
+ #endif
arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
pt = &(arcn->name[arcn->nlen - 1]);
arcn->pad = 0;
arcn->skip = 0;
- switch(hd->linkflag) {
+ switch (hd->linkflag) {
case SYMTYPE:
/*
* symbolic link, need to get the link name and set the type in
* the st_mode so -v printing will look correct.
*/
arcn->type = PAX_SLK;
- arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
- sizeof(arcn->ln_name) - 1);
- arcn->ln_name[arcn->ln_nlen] = '\0';
arcn->sb.st_mode |= S_IFLNK;
break;
case LNKTYPE:
*/
arcn->type = PAX_HLK;
arcn->sb.st_nlink = 2;
- arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
- sizeof(arcn->ln_name) - 1);
- arcn->ln_name[arcn->ln_nlen] = '\0';
/*
* no idea of what type this thing really points at, but
*/
arcn->sb.st_mode |= S_IFREG;
break;
+ case LONGLINKTYPE:
+ case LONGNAMETYPE:
+ /*
+ * GNU long link/file; we tag these here and let the
+ * pax internals deal with it -- too ugly otherwise.
+ */
+ arcn->type =
+ hd->linkflag == LONGLINKTYPE ? PAX_GLL : PAX_GLF;
+ arcn->pad = TAR_PAD(arcn->sb.st_size);
+ arcn->skip = arcn->sb.st_size;
+ break;
case DIRTYPE:
/*
* It is a directory, set the mode for -v printing
arcn->type = PAX_DIR;
arcn->sb.st_mode |= S_IFDIR;
arcn->sb.st_nlink = 2;
- arcn->ln_name[0] = '\0';
- arcn->ln_nlen = 0;
break;
case AREGTYPE:
case REGTYPE:
} else {
/*
* have a file that will be followed by data. Set the
- * skip value to the size field and caluculate the size
+ * skip value to the size field and calculate the size
* of the padding.
*/
arcn->type = PAX_REG;
* strip off any trailing slash.
*/
if (*pt == '/') {
- *pt = '\0';
+ *pt = '\0';
--arcn->nlen;
}
return(0);
* data to write after the header, -1 if archive write failed
*/
- #ifdef __STDC__
int
- tar_wr(register ARCHD *arcn)
- #else
- int
- tar_wr(arcn)
- register ARCHD *arcn;
- #endif
+ tar_wr(ARCHD *arcn)
{
- register HD_TAR *hd;
+ HD_TAR *hd;
int len;
char hdblk[sizeof(HD_TAR)];
/*
* check for those file system types which tar cannot store
*/
- switch(arcn->type) {
+ switch (arcn->type) {
case PAX_DIR:
/*
* user asked that dirs not be written to the archive
case PAX_HLK:
case PAX_HRG:
if (arcn->ln_nlen > sizeof(hd->linkname)) {
- paxwarn(1,"Link name too long for tar %s", arcn->ln_name);
+ paxwarn(1, "Link name too long for tar %s",
+ arcn->ln_name);
return(1);
}
break;
len = arcn->nlen;
if (arcn->type == PAX_DIR)
++len;
- if (len >= sizeof(hd->name)) {
+ if (len > sizeof(hd->name)) {
paxwarn(1, "File name too long for tar %s", arcn->name);
return(1);
}
/*
- * copy the data out of the ARCHD into the tar header based on the type
- * of the file. Remember many tar readers want the unused fields to be
- * padded with zero. We set the linkflag field (type), the linkname
- * (or zero if not used),the size, and set the padding (if any) to be
- * added after the file data (0 for all other types, as they only have
- * a header)
+ * Copy the data out of the ARCHD into the tar header based on the type
+ * of the file. Remember, many tar readers want all fields to be
+ * padded with zero so we zero the header first. We then set the
+ * linkflag field (type), the linkname, the size, and set the padding
+ * (if any) to be added after the file data (0 for all other types,
+ * as they only have a header).
*/
+ memset(hdblk, 0, sizeof(hdblk));
hd = (HD_TAR *)hdblk;
- l_strncpy(hd->name, arcn->name, sizeof(hd->name) - 1);
- hd->name[sizeof(hd->name) - 1] = '\0';
+ fieldcpy(hd->name, sizeof(hd->name), arcn->name, sizeof(arcn->name));
arcn->pad = 0;
if (arcn->type == PAX_DIR) {
/*
* directories are the same as files, except have a filename
- * that ends with a /, we add the slash here. No data follows,
+ * that ends with a /, we add the slash here. No data follows
* dirs, so no pad.
*/
hd->linkflag = AREGTYPE;
- memset(hd->linkname, 0, sizeof(hd->linkname));
hd->name[len-1] = '/';
if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
goto out;
* no data follows this file, so no pad
*/
hd->linkflag = SYMTYPE;
- l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1);
- hd->linkname[sizeof(hd->linkname) - 1] = '\0';
+ fieldcpy(hd->linkname, sizeof(hd->linkname), arcn->ln_name,
+ sizeof(arcn->ln_name));
if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
goto out;
} else if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) {
* no data follows this file, so no pad
*/
hd->linkflag = LNKTYPE;
- l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1);
- hd->linkname[sizeof(hd->linkname) - 1] = '\0';
+ fieldcpy(hd->linkname, sizeof(hd->linkname), arcn->ln_name,
+ sizeof(arcn->ln_name));
if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
goto out;
} else {
* data follows this file, so set the pad
*/
hd->linkflag = AREGTYPE;
- memset(hd->linkname, 0, sizeof(hd->linkname));
- # ifdef NET2_STAT
+ # ifdef LONG_OFF_T
if (ul_oct((u_long)arcn->sb.st_size, hd->size,
sizeof(hd->size), 1)) {
# else
if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 0) ||
ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 0) ||
ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 0) ||
- ul_oct((u_long)arcn->sb.st_mtime, hd->mtime, sizeof(hd->mtime), 1))
+ ul_oct((u_long)(u_int)arcn->sb.st_mtime, hd->mtime, sizeof(hd->mtime), 1))
goto out;
/*
* 0 if ok, -1 otherwise
*/
- #ifdef __STDC__
int
ustar_strd(void)
- #else
- int
- ustar_strd()
- #endif
{
if ((usrtb_start() < 0) || (grptb_start() < 0))
return(-1);
* 0 if ok, -1 otherwise
*/
- #ifdef __STDC__
int
ustar_stwr(void)
- #else
- int
- ustar_stwr()
- #endif
{
if ((uidtb_start() < 0) || (gidtb_start() < 0))
return(-1);
* 0 if a ustar header, -1 otherwise
*/
- #ifdef __STDC__
int
ustar_id(char *blk, int size)
- #else
- int
- ustar_id(blk, size)
- char *blk;
- int size;
- #endif
{
- register HD_USTAR *hd;
+ HD_USTAR *hd;
if (size < BLKMULT)
return(-1);
* programs are fouled up and create archives missing the \0. Last we
* check the checksum. If ok we have to assume it is a valid header.
*/
- if (hd->name[0] == '\0')
+ if (hd->prefix[0] == '\0' && hd->name[0] == '\0')
return(-1);
if (strncmp(hd->magic, TMAGIC, TMAGLEN - 1) != 0)
return(-1);
* 0
*/
- #ifdef __STDC__
int
- ustar_rd(register ARCHD *arcn, register char *buf)
- #else
- int
- ustar_rd(arcn, buf)
- register ARCHD *arcn;
- register char *buf;
- #endif
+ ustar_rd(ARCHD *arcn, char *buf)
{
- register HD_USTAR *hd;
- register char *dest;
- register int cnt = 0;
+ HD_USTAR *hd;
+ char *dest;
+ int cnt = 0;
dev_t devmajor;
dev_t devminor;
*/
if (ustar_id(buf, BLKMULT) < 0)
return(-1);
+ memset(arcn, 0, sizeof(*arcn));
arcn->org_name = arcn->name;
arcn->sb.st_nlink = 1;
- arcn->pat = NULL;
- arcn->nlen = 0;
hd = (HD_USTAR *)buf;
/*
* see if the filename is split into two parts. if, so joint the parts.
* we copy the prefix first and add a / between the prefix and name.
+ *
+ * the length passed to l_strncpy must be the length of the field
+ * being copied *from*, since these fields are NOT null terminated
+ * when full. the destination buffer is plenty big enough to hold
+ * the longest supported ustar path length, so there's no need
+ * to check against that.
*/
dest = arcn->name;
if (*(hd->prefix) != '\0') {
- cnt = l_strncpy(dest, hd->prefix, sizeof(hd->prefix));
+ cnt = fieldcpy(dest, sizeof(arcn->name) - 1, hd->prefix,
+ sizeof(hd->prefix));
dest += cnt;
*dest++ = '/';
cnt++;
+ } else {
+ cnt = 0;
+ }
+
+ if (hd->typeflag != LONGLINKTYPE && hd->typeflag != LONGNAMETYPE) {
+ arcn->nlen = cnt + expandname(dest, sizeof(arcn->name) - cnt,
+ &gnu_name_string, hd->name, sizeof(hd->name));
+ arcn->ln_nlen = expandname(arcn->ln_name, sizeof(arcn->ln_name),
+ &gnu_link_string, hd->linkname, sizeof(hd->linkname));
}
- arcn->nlen = cnt + l_strncpy(dest, hd->name, sizeof(hd->name));
- arcn->name[arcn->nlen] = '\0';
/*
* follow the spec to the letter. we should only have mode bits, strip
*/
arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode, sizeof(hd->mode), OCT) &
0xfff);
- arcn->sb.st_size = (size_t)asc_ul(hd->size, sizeof(hd->size), OCT);
+ #ifdef LONG_OFF_T
+ arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT);
+ #else
+ arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT);
+ #endif
arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
/*
* set the defaults, these may be changed depending on the file type
*/
- arcn->ln_name[0] = '\0';
- arcn->ln_nlen = 0;
arcn->pad = 0;
arcn->skip = 0;
arcn->sb.st_rdev = (dev_t)0;
/*
* set the mode and PAX type according to the typeflag in the header
*/
- switch(hd->typeflag) {
+ switch (hd->typeflag) {
case FIFOTYPE:
arcn->type = PAX_FIF;
arcn->sb.st_mode |= S_IFIFO;
arcn->sb.st_mode |= S_IFREG;
arcn->sb.st_nlink = 2;
}
+ break;
+ case LONGLINKTYPE:
+ case LONGNAMETYPE:
/*
- * copy the link name
- *
- * see comment above (for hd->name) regarding the length
- * passed to l_strncpy
+ * GNU long link/file; we tag these here and let the
+ * pax internals deal with it -- too ugly otherwise.
*/
- arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
- sizeof(hd->linkname));
- arcn->ln_name[arcn->ln_nlen] = '\0';
+ arcn->type =
+ hd->typeflag == LONGLINKTYPE ? PAX_GLL : PAX_GLF;
+ arcn->pad = TAR_PAD(arcn->sb.st_size);
+ arcn->skip = arcn->sb.st_size;
break;
case CONTTYPE:
case AREGTYPE:
* data to write after the header, -1 if archive write failed
*/
- #ifdef __STDC__
int
- ustar_wr(register ARCHD *arcn)
- #else
- int
- ustar_wr(arcn)
- register ARCHD *arcn;
- #endif
+ ustar_wr(ARCHD *arcn)
{
- register HD_USTAR *hd;
- register char *pt;
+ HD_USTAR *hd;
+ char *pt;
char hdblk[sizeof(HD_USTAR)];
/*
paxwarn(1, "File name too long for ustar %s", arcn->name);
return(1);
}
+
+ /*
+ * zero out the header so we don't have to worry about zero fill below
+ */
+ memset(hdblk, 0, sizeof(hdblk));
hd = (HD_USTAR *)hdblk;
arcn->pad = 0L;
* occur, we remove the / and copy the first part to the prefix
*/
*pt = '\0';
- l_strncpy(hd->prefix, arcn->name, sizeof(hd->prefix));
+ fieldcpy(hd->prefix, sizeof(hd->prefix), arcn->name,
+ sizeof(arcn->name));
*pt++ = '/';
- } else
- memset(hd->prefix, 0, sizeof(hd->prefix));
+ }
/*
* copy the name part. this may be the whole path or the part after
* the prefix
*/
- l_strncpy(hd->name, pt, sizeof(hd->name));
+ fieldcpy(hd->name, sizeof(hd->name), pt,
+ sizeof(arcn->name) - (pt - arcn->name));
/*
* set the fields in the header that are type dependent
*/
- switch(arcn->type) {
+ switch (arcn->type) {
case PAX_DIR:
hd->typeflag = DIRTYPE;
- memset(hd->linkname, 0, sizeof(hd->linkname));
- memset(hd->devmajor, 0, sizeof(hd->devmajor));
- hd->devmajor[0] = '0';
- memset(hd->devminor, 0, sizeof(hd->devminor));
- hd->devminor[0] = '0';
if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
goto out;
break;
hd->typeflag = CHRTYPE;
else
hd->typeflag = BLKTYPE;
- memset(hd->linkname, 0, sizeof(hd->linkname));
if (ul_oct((u_long)MAJOR(arcn->sb.st_rdev), hd->devmajor,
sizeof(hd->devmajor), 3) ||
ul_oct((u_long)MINOR(arcn->sb.st_rdev), hd->devminor,
break;
case PAX_FIF:
hd->typeflag = FIFOTYPE;
- memset(hd->linkname, 0, sizeof(hd->linkname));
- memset(hd->devmajor, 0, sizeof(hd->devmajor));
- hd->devmajor[0] = '0';
- memset(hd->devminor, 0, sizeof(hd->devminor));
- hd->devminor[0] = '0';
if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
goto out;
break;
hd->typeflag = SYMTYPE;
else
hd->typeflag = LNKTYPE;
- l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname));
- memset(hd->devmajor, 0, sizeof(hd->devmajor));
- hd->devmajor[0] = '0';
- memset(hd->devminor, 0, sizeof(hd->devminor));
- hd->devminor[0] = '0';
+ fieldcpy(hd->linkname, sizeof(hd->linkname), arcn->ln_name,
+ sizeof(arcn->ln_name));
if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
goto out;
break;
hd->typeflag = CONTTYPE;
else
hd->typeflag = REGTYPE;
- memset(hd->linkname, 0, sizeof(hd->linkname));
- memset(hd->devmajor, 0, sizeof(hd->devmajor));
- hd->devmajor[0] = '0';
- memset(hd->devminor, 0, sizeof(hd->devminor));
- hd->devminor[0] = '0';
arcn->pad = TAR_PAD(arcn->sb.st_size);
- # ifdef NET2_STAT
+ # ifdef LONG_OFF_T
if (ul_oct((u_long)arcn->sb.st_size, hd->size,
sizeof(hd->size), 3)) {
# else
break;
}
- l_strncpy(hd->magic, TMAGIC, TMAGLEN);
- l_strncpy(hd->version, TVERSION, TVERSLEN);
+ strncpy(hd->magic, TMAGIC, TMAGLEN);
+ strncpy(hd->version, TVERSION, TVERSLEN);
/*
* set the remaining fields. Some versions want all 16 bits of mode
* we better humor them (they really do not meet spec though)....
*/
+ if (ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 3)) {
+ if (uid_nobody == 0) {
+ if (uid_name("nobody", &uid_nobody) == -1)
+ goto out;
+ }
+ if (uid_warn != arcn->sb.st_uid) {
+ uid_warn = arcn->sb.st_uid;
+ paxwarn(1,
+ "Ustar header field is too small for uid %lu, "
+ "using nobody", (u_long)arcn->sb.st_uid);
+ }
+ if (ul_oct((u_long)uid_nobody, hd->uid, sizeof(hd->uid), 3))
+ goto out;
+ }
+ if (ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3)) {
+ if (gid_nobody == 0) {
+ if (gid_name("nobody", &gid_nobody) == -1)
+ goto out;
+ }
+ if (gid_warn != arcn->sb.st_gid) {
+ gid_warn = arcn->sb.st_gid;
+ paxwarn(1,
+ "Ustar header field is too small for gid %lu, "
+ "using nobody", (u_long)arcn->sb.st_gid);
+ }
+ if (ul_oct((u_long)gid_nobody, hd->gid, sizeof(hd->gid), 3))
+ goto out;
+ }
if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 3) ||
- ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 3) ||
- ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3) ||
- ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3))
+ ul_oct((u_long)(u_int)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3))
goto out;
- l_strncpy(hd->uname,name_uid(arcn->sb.st_uid, 0),sizeof(hd->uname));
- l_strncpy(hd->gname,name_gid(arcn->sb.st_gid, 0),sizeof(hd->gname));
+ strncpy(hd->uname, name_uid(arcn->sb.st_uid, 0), sizeof(hd->uname));
+ strncpy(hd->gname, name_gid(arcn->sb.st_gid, 0), sizeof(hd->gname));
/*
* calculate and store the checksum write the header to the archive
return(1);
out:
- /*
+ /*
* header field is out of range
*/
paxwarn(1, "Ustar header field is too small for %s", arcn->org_name);
* the file name is too long
*/
- #ifdef __STDC__
- static char *
- name_split(register char *name, register int len)
- #else
static char *
- name_split(name, len)
- register char *name;
- register int len;
- #endif
+ name_split(char *name, int len)
{
- register char *start;
+ char *start;
/*
* check to see if the file name is small enough to fit in the name
* field. if so just return a pointer to the name.
+ * The strings can fill the complete name and prefix fields
+ * without a NUL terminator.
*/
if (len <= TNMSZ)
return(name);
/*
* we start looking at the biggest sized piece that fits in the name
- * field. We walk foward looking for a slash to split at. The idea is
+ * field. We walk forward looking for a slash to split at. The idea is
* to find the biggest piece to fit in the name field (or the smallest
* prefix we can find) (the -1 is correct the biggest piece would
* include the slash between the two parts that gets thrown away)
*/
return(start);
}
+
+ static size_t
+ expandname(char *buf, size_t len, char **gnu_name, const char *name,
+ size_t limit)
+ {
+ size_t nlen;
+
+ if (*gnu_name) {
+ /* *gnu_name is NUL terminated */
+ if ((nlen = strlcpy(buf, *gnu_name, len)) >= len)
+ nlen = len - 1;
+ free(*gnu_name);
+ *gnu_name = NULL;
+ } else
+ nlen = fieldcpy(buf, len, name, limit);
+ return(nlen);
+ }