Upgrading pax.
This also means importing librmt. Change-Id: Ie5b314aeaad28dca46acb64f20f2d70746ea52d0
This commit is contained in:
parent
6ab1df59f6
commit
85fee539f4
46 changed files with 7804 additions and 4741 deletions
|
@ -2,6 +2,6 @@
|
|||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
SUBDIR= cat date ed mkdir rm rmdir
|
||||
SUBDIR= cat date ed mkdir pax rm rmdir
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
|
|
61
bin/pax/Makefile
Normal file
61
bin/pax/Makefile
Normal file
|
@ -0,0 +1,61 @@
|
|||
# $NetBSD: Makefile,v 1.39 2010/04/23 19:41:02 joerg Exp $
|
||||
# @(#)Makefile 8.1 (Berkeley) 5/31/93
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
PROG= pax
|
||||
SRCS= ar_io.c ar_subs.c buf_subs.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
|
||||
|
||||
.if defined(SMALLPROG)
|
||||
CPPFLAGS+= -DSMALL -DNO_CPIO
|
||||
.else
|
||||
SRCS+= getid.c spec.c misc.c pack_dev.c cpio.c
|
||||
CPPFLAGS+= -I${NETBSDSRCDIR}/usr.sbin/mtree \
|
||||
-I${NETBSDSRCDIR}/sbin/mknod
|
||||
.PATH: ${NETBSDSRCDIR}/usr.sbin/mtree \
|
||||
${NETBSDSRCDIR}/sbin/mknod
|
||||
|
||||
.if (${HOSTPROG:U} == "")
|
||||
DPADD+= ${LIBUTIL}
|
||||
LDADD+= -lutil
|
||||
.endif
|
||||
.endif
|
||||
|
||||
MAN= pax.1 tar.1 cpio.1
|
||||
|
||||
.if defined(HOSTPROG)
|
||||
CPPFLAGS+= -DHOSTPROG
|
||||
.else # { ! HOSTPROG
|
||||
|
||||
# XXX: Interix does not have it; we need a conditional for it.
|
||||
CPPFLAGS+= -DHAVE_SYS_MTIO_H
|
||||
|
||||
.if ${MKBSDTAR} == "no"
|
||||
LINKS+= ${BINDIR}/pax ${BINDIR}/tar
|
||||
SYMLINKS+=${BINDIR}/tar /usr/bin/tar
|
||||
.if defined(__MINIX)
|
||||
SYMLINKS+=${BINDIR}/tar /usr/bin/bsdtar
|
||||
.endif
|
||||
|
||||
LINKS+= ${BINDIR}/pax ${BINDIR}/cpio
|
||||
SYMLINKS+=${BINDIR}/cpio /usr/bin/cpio
|
||||
.endif
|
||||
.endif # } ! HOSTPROG
|
||||
|
||||
.if !defined(HOSTPROG) && !defined(SMALLPROG)
|
||||
CPPFLAGS+= -DSUPPORT_RMT
|
||||
|
||||
LDADD+= -lrmt
|
||||
DPADD+= ${LIBRMT}
|
||||
.endif
|
||||
|
||||
.if defined(__MINIX)
|
||||
CPPFLAGS+= -DHOSTPROG
|
||||
CPPFLAGS+= -Dlchown=chown -Dlchmod=chmod
|
||||
DPADD+= ${LIBUTIL}
|
||||
LDADD+= -lutil
|
||||
.endif
|
||||
|
||||
.include <bsd.prog.mk>
|
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,5 @@
|
|||
/* $NetBSD: ar_subs.c,v 1.56 2011/08/31 16:24:54 plunky Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -14,7 +16,7 @@
|
|||
* 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.
|
||||
* 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.
|
||||
*
|
||||
|
@ -31,29 +33,43 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)ar_subs.c 8.2 (Berkeley) 4/18/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: ar_subs.c,v 1.56 2011/08/31 16:24:54 plunky Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include "pax.h"
|
||||
#include "pat_rep.h"
|
||||
#include "extern.h"
|
||||
|
||||
static void wr_archive(ARCHD *, int is_app);
|
||||
static int path_check(ARCHD *, int);
|
||||
static int wr_archive(ARCHD *, int is_app);
|
||||
static int get_arc(void);
|
||||
static int next_head(ARCHD *);
|
||||
#if !HAVE_NBTOOL_CONFIG_H && !defined(__minix)
|
||||
static int fdochroot(int);
|
||||
#endif
|
||||
extern sigset_t s_mask;
|
||||
|
||||
/*
|
||||
|
@ -63,19 +79,124 @@ extern sigset_t s_mask;
|
|||
|
||||
static char hdbuf[BLKMULT]; /* space for archive header on read */
|
||||
u_long flcnt; /* number of files processed */
|
||||
ARCHD archd;
|
||||
|
||||
static char cwdpath[MAXPATHLEN]; /* current working directory path */
|
||||
static size_t cwdpathlen; /* current working directory path len */
|
||||
|
||||
int
|
||||
updatepath(void)
|
||||
{
|
||||
if (getcwd(cwdpath, sizeof(cwdpath)) == NULL) {
|
||||
syswarn(1, errno, "Cannot get working directory");
|
||||
return -1;
|
||||
}
|
||||
cwdpathlen = strlen(cwdpath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
fdochdir(int fcwd)
|
||||
{
|
||||
if (fchdir(fcwd) == -1) {
|
||||
syswarn(1, errno, "Cannot chdir to `.'");
|
||||
return -1;
|
||||
}
|
||||
return updatepath();
|
||||
}
|
||||
|
||||
int
|
||||
dochdir(const char *name)
|
||||
{
|
||||
if (chdir(name) == -1)
|
||||
syswarn(1, errno, "Cannot chdir to `%s'", name);
|
||||
return updatepath();
|
||||
}
|
||||
|
||||
#if !HAVE_NBTOOL_CONFIG_H && !defined(__minix)
|
||||
static int
|
||||
fdochroot(int fcwd)
|
||||
{
|
||||
if (fchroot(fcwd) != 0) {
|
||||
syswarn(1, errno, "Can't fchroot to \".\"");
|
||||
return -1;
|
||||
}
|
||||
return updatepath();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* mkdir(), but if we failed, check if someone else made it for us
|
||||
* already and don't error out.
|
||||
*/
|
||||
int
|
||||
domkdir(const char *fname, mode_t mode)
|
||||
{
|
||||
int error;
|
||||
struct stat sb;
|
||||
|
||||
if ((error = mkdir(fname, mode)) != -1)
|
||||
return error;
|
||||
|
||||
switch (errno) {
|
||||
case EISDIR:
|
||||
return 0;
|
||||
case EEXIST:
|
||||
case EACCES:
|
||||
case ENOSYS: /* Grr Solaris */
|
||||
case EROFS:
|
||||
error = errno;
|
||||
if (stat(fname, &sb) != -1 && S_ISDIR(sb.st_mode))
|
||||
return 0;
|
||||
errno = error;
|
||||
/*FALLTHROUGH*/
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
path_check(ARCHD *arcn, int level)
|
||||
{
|
||||
char buf[MAXPATHLEN];
|
||||
char *p;
|
||||
|
||||
if ((p = strrchr(arcn->name, '/')) == NULL)
|
||||
return 0;
|
||||
*p = '\0';
|
||||
|
||||
if (realpath(arcn->name, buf) == NULL) {
|
||||
int error;
|
||||
error = path_check(arcn, level + 1);
|
||||
*p = '/';
|
||||
if (error == 0)
|
||||
return 0;
|
||||
if (level == 0)
|
||||
syswarn(1, 0, "Cannot resolve `%s'", arcn->name);
|
||||
return -1;
|
||||
}
|
||||
if (strncmp(buf, cwdpath, cwdpathlen) != 0) {
|
||||
*p = '/';
|
||||
syswarn(1, 0, "Attempt to write file `%s' that resolves into "
|
||||
"`%s/%s' outside current working directory `%s' ignored",
|
||||
arcn->name, buf, p + 1, cwdpath);
|
||||
return -1;
|
||||
}
|
||||
*p = '/';
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* list()
|
||||
* list the contents of an archive which match user supplied pattern(s)
|
||||
* (no pattern matches all).
|
||||
* (if no pattern is supplied, list entire contents).
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
list(void)
|
||||
{
|
||||
ARCHD *arcn;
|
||||
int res;
|
||||
ARCHD archd;
|
||||
time_t now;
|
||||
|
||||
arcn = &archd;
|
||||
|
@ -88,10 +209,7 @@ list(void)
|
|||
*/
|
||||
if ((get_arc() < 0) || ((*frmt->options)() < 0) ||
|
||||
((*frmt->st_rd)() < 0))
|
||||
return;
|
||||
|
||||
if (vflag && ((uidtb_start() < 0) || (gidtb_start() < 0)))
|
||||
return;
|
||||
return 1;
|
||||
|
||||
now = time(NULL);
|
||||
|
||||
|
@ -99,6 +217,16 @@ list(void)
|
|||
* 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, &cnt))
|
||||
(void)rd_skip(cnt + arcn->pad);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* check for pattern, and user specified options match.
|
||||
* When all patterns are matched we are done.
|
||||
|
@ -117,12 +245,25 @@ list(void)
|
|||
* modify the name as requested by the user if name
|
||||
* survives modification, do a listing of the file
|
||||
*/
|
||||
if ((res = mod_name(arcn)) < 0)
|
||||
if ((res = mod_name(arcn, RENM)) < 0)
|
||||
break;
|
||||
if (res == 0)
|
||||
if (res == 0) {
|
||||
if (arcn->name[0] == '/' && !check_Aflag()) {
|
||||
memmove(arcn->name, arcn->name + 1,
|
||||
strlen(arcn->name));
|
||||
}
|
||||
ls_list(arcn, now, stdout);
|
||||
}
|
||||
/*
|
||||
* if there's an error writing to stdout then we must
|
||||
* stop now -- we're probably writing to a pipe that
|
||||
* has been closed by the reader.
|
||||
*/
|
||||
if (ferror(stdout)) {
|
||||
syswarn(1, errno, "Listing incomplete.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* skip to next archive format header using values calculated
|
||||
* by the format header read routine
|
||||
|
@ -139,6 +280,8 @@ list(void)
|
|||
(void)sigprocmask(SIG_BLOCK, &s_mask, NULL);
|
||||
ar_close();
|
||||
pat_chk();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -147,13 +290,12 @@ list(void)
|
|||
* pattern(s) (no patterns extracts all members)
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
extract(void)
|
||||
{
|
||||
ARCHD *arcn;
|
||||
int res;
|
||||
off_t cnt;
|
||||
ARCHD archd;
|
||||
struct stat sb;
|
||||
int fd;
|
||||
time_t now;
|
||||
|
@ -166,22 +308,36 @@ extract(void)
|
|||
*/
|
||||
if ((get_arc() < 0) || ((*frmt->options)() < 0) ||
|
||||
((*frmt->st_rd)() < 0) || (dir_start() < 0))
|
||||
return;
|
||||
return 1;
|
||||
|
||||
now = time(NULL);
|
||||
#if !HAVE_NBTOOL_CONFIG_H && !defined(__minix)
|
||||
if (do_chroot)
|
||||
(void)fdochroot(cwdfd);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* When we are doing interactive rename, we store the mapping of names
|
||||
* so we can fix up hard links files later in the archive.
|
||||
*/
|
||||
if (iflag && (name_start() < 0))
|
||||
return;
|
||||
|
||||
now = time(NULL);
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* step through each entry on the archive until the format read routine
|
||||
* says it is done
|
||||
*/
|
||||
while (next_head(arcn) == 0) {
|
||||
int write_to_hard_link = 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, &cnt))
|
||||
(void)rd_skip(cnt + arcn->pad);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* check for pattern, and user specified options match. When
|
||||
|
@ -192,22 +348,28 @@ extract(void)
|
|||
|
||||
if ((res > 0) || (sel_chk(arcn) != 0)) {
|
||||
/*
|
||||
* file is not selected. skip past any file data and
|
||||
* padding and go back for the next archive member
|
||||
* file is not selected. skip past any file
|
||||
* data and padding and go back for the next
|
||||
* archive member
|
||||
*/
|
||||
(void)rd_skip(arcn->skip + arcn->pad);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (kflag && (lstat(arcn->name, &sb) == 0)) {
|
||||
(void)rd_skip(arcn->skip + arcn->pad);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
* user who might expect the test to be done on an existing
|
||||
* file AFTER the name mod. In honesty the pax spec is probably
|
||||
* flawed in this respect.
|
||||
* flawed in this respect. ignore this for GNU long links.
|
||||
*/
|
||||
if ((uflag || Dflag) && ((lstat(arcn->name, &sb) == 0))) {
|
||||
if (uflag && Dflag) {
|
||||
|
@ -230,7 +392,7 @@ extract(void)
|
|||
/*
|
||||
* this archive member is now been selected. modify the name.
|
||||
*/
|
||||
if ((pat_sel(arcn) < 0) || ((res = mod_name(arcn)) < 0))
|
||||
if ((pat_sel(arcn) < 0) || ((res = mod_name(arcn, RENM)) < 0))
|
||||
break;
|
||||
if (res > 0) {
|
||||
/*
|
||||
|
@ -241,9 +403,12 @@ extract(void)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (arcn->name[0] == '/' && !check_Aflag()) {
|
||||
memmove(arcn->name, arcn->name + 1, strlen(arcn->name));
|
||||
}
|
||||
/*
|
||||
* Non standard -Y and -Z flag. When the existing file is
|
||||
* same age or newer skip
|
||||
* same age or newer skip; ignore this for GNU long links.
|
||||
*/
|
||||
if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) {
|
||||
if (Yflag && Zflag) {
|
||||
|
@ -267,7 +432,7 @@ extract(void)
|
|||
if (vflag > 1)
|
||||
ls_list(arcn, now, listf);
|
||||
else {
|
||||
(void)fputs(arcn->name, listf);
|
||||
(void)safe_print(arcn->name, listf);
|
||||
vfpart = 1;
|
||||
}
|
||||
}
|
||||
|
@ -275,11 +440,16 @@ extract(void)
|
|||
/*
|
||||
* if required, chdir around.
|
||||
*/
|
||||
if ((arcn->pat != NULL) && (arcn->pat->chdname != NULL))
|
||||
if (chdir(arcn->pat->chdname) != 0)
|
||||
syswarn(1, errno, "Cannot chdir to %s",
|
||||
arcn->pat->chdname);
|
||||
if ((arcn->pat != NULL) && (arcn->pat->chdname != NULL) &&
|
||||
!to_stdout)
|
||||
dochdir(arcn->pat->chdname);
|
||||
|
||||
if (secure && path_check(arcn, 0) != 0) {
|
||||
(void)rd_skip(arcn->skip + arcn->pad);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* all ok, extract this member based on type
|
||||
*/
|
||||
|
@ -289,36 +459,46 @@ extract(void)
|
|||
* throw out padding and any data that might follow the
|
||||
* header (as determined by the format).
|
||||
*/
|
||||
if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG))
|
||||
res = lnk_creat(arcn);
|
||||
if ((arcn->type == PAX_HLK) ||
|
||||
(arcn->type == PAX_HRG))
|
||||
res = lnk_creat(arcn, &write_to_hard_link);
|
||||
else
|
||||
res = node_creat(arcn);
|
||||
|
||||
(void)rd_skip(arcn->skip + arcn->pad);
|
||||
if (res < 0)
|
||||
purg_lnk(arcn);
|
||||
if (!write_to_hard_link) {
|
||||
(void)rd_skip(arcn->skip + arcn->pad);
|
||||
if (res < 0)
|
||||
purg_lnk(arcn);
|
||||
|
||||
if (vflag && vfpart) {
|
||||
(void)putc('\n', listf);
|
||||
vfpart = 0;
|
||||
if (vflag && vfpart) {
|
||||
(void)putc('\n', listf);
|
||||
vfpart = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* we have a file with data here. If we can not create it, skip
|
||||
* over the data and purge the name from hard link table
|
||||
*/
|
||||
if ((fd = file_creat(arcn)) < 0) {
|
||||
(void)rd_skip(arcn->skip + arcn->pad);
|
||||
purg_lnk(arcn);
|
||||
continue;
|
||||
if (to_stdout)
|
||||
fd = STDOUT_FILENO;
|
||||
else {
|
||||
/*
|
||||
* We have a file with data here. If we cannot create
|
||||
* it, skip over the data and purge the name from hard
|
||||
* link table.
|
||||
*/
|
||||
if ((fd = file_creat(arcn, write_to_hard_link)) < 0) {
|
||||
(void)fflush(listf);
|
||||
(void)rd_skip(arcn->skip + arcn->pad);
|
||||
purg_lnk(arcn);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* extract the file from the archive and skip over padding and
|
||||
* any unprocessed data
|
||||
*/
|
||||
res = (*frmt->rd_data)(arcn, fd, &cnt);
|
||||
file_close(arcn, fd);
|
||||
if (!to_stdout)
|
||||
file_close(arcn, fd);
|
||||
if (vflag && vfpart) {
|
||||
(void)putc('\n', listf);
|
||||
vfpart = 0;
|
||||
|
@ -330,9 +510,7 @@ extract(void)
|
|||
* if required, chdir around.
|
||||
*/
|
||||
if ((arcn->pat != NULL) && (arcn->pat->chdname != NULL))
|
||||
if (fchdir(cwdfd) != 0)
|
||||
syswarn(1, errno,
|
||||
"Can't fchdir to starting directory");
|
||||
fdochdir(cwdfd);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -345,6 +523,8 @@ extract(void)
|
|||
ar_close();
|
||||
proc_dir();
|
||||
pat_chk();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -353,7 +533,7 @@ extract(void)
|
|||
* previously written archive.
|
||||
*/
|
||||
|
||||
static void
|
||||
static int
|
||||
wr_archive(ARCHD *arcn, int is_app)
|
||||
{
|
||||
int res;
|
||||
|
@ -369,29 +549,29 @@ wr_archive(ARCHD *arcn, int is_app)
|
|||
* that detects them.
|
||||
*/
|
||||
if (((hlk = frmt->hlk) == 1) && (lnk_start() < 0))
|
||||
return;
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* start up the file traversal code and format specific write
|
||||
*/
|
||||
if ((ftree_start() < 0) || ((*frmt->st_wr)() < 0))
|
||||
return;
|
||||
return 1;
|
||||
wrf = frmt->wr;
|
||||
|
||||
now = time(NULL);
|
||||
|
||||
/*
|
||||
* When we are doing interactive rename, we store the mapping of names
|
||||
* so we can fix up hard links files later in the archive.
|
||||
*/
|
||||
if (iflag && (name_start() < 0))
|
||||
return;
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* if this not append, and there are no files, we do no write a trailer
|
||||
* if this is not append, and there are no files, we do no write a trailer
|
||||
*/
|
||||
wr_one = is_app;
|
||||
|
||||
now = time(NULL);
|
||||
|
||||
/*
|
||||
* while there are files to archive, process them one at at time
|
||||
*/
|
||||
|
@ -399,10 +579,18 @@ wr_archive(ARCHD *arcn, int is_app)
|
|||
/*
|
||||
* check if this file meets user specified options match.
|
||||
*/
|
||||
if (sel_chk(arcn) != 0) {
|
||||
ftree_notsel();
|
||||
if (sel_chk(arcn) != 0)
|
||||
continue;
|
||||
/*
|
||||
* Here we handle the exclusion -X gnu style patterns which
|
||||
* are implemented like a pattern list. We don't modify the
|
||||
* name as this will be done below again, and we don't want
|
||||
* to double modify it.
|
||||
*/
|
||||
if ((res = mod_name(arcn, 0)) < 0)
|
||||
break;
|
||||
if (res == 1)
|
||||
continue;
|
||||
}
|
||||
fd = -1;
|
||||
if (uflag) {
|
||||
/*
|
||||
|
@ -432,7 +620,7 @@ wr_archive(ARCHD *arcn, int is_app)
|
|||
* the link table).
|
||||
*/
|
||||
if ((fd = open(arcn->org_name, O_RDONLY, 0)) < 0) {
|
||||
syswarn(1,errno, "Unable to open %s to read",
|
||||
syswarn(1, errno, "Unable to open %s to read",
|
||||
arcn->org_name);
|
||||
purg_lnk(arcn);
|
||||
continue;
|
||||
|
@ -442,7 +630,7 @@ wr_archive(ARCHD *arcn, int is_app)
|
|||
/*
|
||||
* Now modify the name as requested by the user
|
||||
*/
|
||||
if ((res = mod_name(arcn)) < 0) {
|
||||
if ((res = mod_name(arcn, RENM)) < 0) {
|
||||
/*
|
||||
* name modification says to skip this file, close the
|
||||
* file and purge link table entry
|
||||
|
@ -452,6 +640,10 @@ wr_archive(ARCHD *arcn, int is_app)
|
|||
break;
|
||||
}
|
||||
|
||||
if (arcn->name[0] == '/' && !check_Aflag()) {
|
||||
memmove(arcn->name, arcn->name + 1, strlen(arcn->name));
|
||||
}
|
||||
|
||||
if ((res > 0) || (docrc && (set_crc(arcn, fd) < 0))) {
|
||||
/*
|
||||
* unable to obtain the crc we need, close the file,
|
||||
|
@ -466,7 +658,7 @@ wr_archive(ARCHD *arcn, int is_app)
|
|||
if (vflag > 1)
|
||||
ls_list(arcn, now, listf);
|
||||
else {
|
||||
(void)fputs(arcn->name, listf);
|
||||
(void)safe_print(arcn->name, listf);
|
||||
vfpart = 1;
|
||||
}
|
||||
}
|
||||
|
@ -534,6 +726,8 @@ wr_archive(ARCHD *arcn, int is_app)
|
|||
if (tflag)
|
||||
proc_dir();
|
||||
ftree_chk();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -553,17 +747,16 @@ wr_archive(ARCHD *arcn, int is_app)
|
|||
* It is really difficult to splice in members without either re-writing
|
||||
* the entire archive (from the point were the old version was), or having
|
||||
* assistance of the format specification in terms of a special update
|
||||
* header that invalidates a previous archive record. The POSIX spec left
|
||||
* header that invalidates a previous archive record. The posix spec left
|
||||
* the method used to implement -u unspecified. This pax is able to
|
||||
* over write existing files that it creates.
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
append(void)
|
||||
{
|
||||
ARCHD *arcn;
|
||||
int res;
|
||||
ARCHD archd;
|
||||
FSUB *orgfrmt;
|
||||
int udev;
|
||||
off_t tlen;
|
||||
|
@ -576,25 +769,25 @@ append(void)
|
|||
* different format than the user specified format.
|
||||
*/
|
||||
if (get_arc() < 0)
|
||||
return;
|
||||
return 1;
|
||||
if ((orgfrmt != NULL) && (orgfrmt != frmt)) {
|
||||
paxwarn(1, "Cannot mix current archive format %s with %s",
|
||||
tty_warn(1, "Cannot mix current archive format %s with %s",
|
||||
frmt->name, orgfrmt->name);
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* pass the format any options and start up format
|
||||
*/
|
||||
if (((*frmt->options)() < 0) || ((*frmt->st_rd)() < 0))
|
||||
return;
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* if we only are adding members that are newer, we need to save the
|
||||
* mod times for all files we see.
|
||||
*/
|
||||
if (uflag && (ftime_start() < 0))
|
||||
return;
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* some archive formats encode hard links by recording the device and
|
||||
|
@ -611,12 +804,12 @@ append(void)
|
|||
* header. See the remap routines for more details.
|
||||
*/
|
||||
if ((udev = frmt->udev) && (dev_start() < 0))
|
||||
return;
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* reading the archive may take a long time. If verbose tell the user
|
||||
*/
|
||||
if (vflag) {
|
||||
if (vflag || Vflag) {
|
||||
(void)fprintf(listf,
|
||||
"%s: Reading archive to position at the end...", argv0);
|
||||
vfpart = 1;
|
||||
|
@ -673,20 +866,31 @@ append(void)
|
|||
* we will refuse to write
|
||||
*/
|
||||
if (appnd_start(tlen) < 0)
|
||||
return;
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* tell the user we are done reading.
|
||||
*/
|
||||
if (vflag && vfpart) {
|
||||
(void)fputs("done.\n", listf);
|
||||
if ((vflag || Vflag) && vfpart) {
|
||||
(void)safe_print("done.\n", listf);
|
||||
vfpart = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* go to the writing phase to add the new members
|
||||
*/
|
||||
wr_archive(arcn, 1);
|
||||
res = wr_archive(arcn, 1);
|
||||
if (res == 1) {
|
||||
/*
|
||||
* wr_archive failed in some way, but before any files were
|
||||
* added. These are the only steps needed to cleanup (and
|
||||
* not truncate the archive).
|
||||
*/
|
||||
wr_fin();
|
||||
(void)sigprocmask(SIG_BLOCK, &s_mask, NULL);
|
||||
ar_close();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -694,10 +898,9 @@ append(void)
|
|||
* write a new archive
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
archive(void)
|
||||
{
|
||||
ARCHD archd;
|
||||
|
||||
/*
|
||||
* if we only are adding members that are newer, we need to save the
|
||||
|
@ -705,11 +908,11 @@ archive(void)
|
|||
* options write the archive
|
||||
*/
|
||||
if ((uflag && (ftime_start() < 0)) || (wr_start() < 0))
|
||||
return;
|
||||
return 1;
|
||||
if ((*frmt->options)() < 0)
|
||||
return;
|
||||
return 1;
|
||||
|
||||
wr_archive(&archd, 0);
|
||||
return wr_archive(&archd, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -720,18 +923,17 @@ archive(void)
|
|||
* (except the files are forced to be under the destination directory).
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
copy(void)
|
||||
{
|
||||
ARCHD *arcn;
|
||||
int res;
|
||||
int fddest;
|
||||
char *dest_pt;
|
||||
int dlen;
|
||||
int drem;
|
||||
size_t dlen;
|
||||
size_t drem;
|
||||
int fdsrc = -1;
|
||||
struct stat sb;
|
||||
ARCHD archd;
|
||||
char dirbuf[PAXPATHLEN+1];
|
||||
|
||||
arcn = &archd;
|
||||
|
@ -739,7 +941,12 @@ copy(void)
|
|||
* set up the destination dir path and make sure it is a directory. We
|
||||
* make sure we have a trailing / on the destination
|
||||
*/
|
||||
dlen = l_strncpy(dirbuf, dirptr, sizeof(dirbuf) - 1);
|
||||
dlen = strlcpy(dirbuf, dirptr, sizeof(dirbuf));
|
||||
if (dlen >= sizeof(dirbuf) ||
|
||||
(dlen == sizeof(dirbuf) - 1 && dirbuf[dlen - 1] != '/')) {
|
||||
tty_warn(1, "directory name is too long %s", dirptr);
|
||||
return 1;
|
||||
}
|
||||
dest_pt = dirbuf + dlen;
|
||||
if (*(dest_pt-1) != '/') {
|
||||
*dest_pt++ = '/';
|
||||
|
@ -751,11 +958,11 @@ copy(void)
|
|||
if (stat(dirptr, &sb) < 0) {
|
||||
syswarn(1, errno, "Cannot access destination directory %s",
|
||||
dirptr);
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
if (!S_ISDIR(sb.st_mode)) {
|
||||
paxwarn(1, "Destination is not a directory %s", dirptr);
|
||||
return;
|
||||
tty_warn(1, "Destination is not a directory %s", dirptr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -763,14 +970,14 @@ copy(void)
|
|||
* modification time and access mode database
|
||||
*/
|
||||
if ((lnk_start() < 0) || (ftree_start() < 0) || (dir_start() < 0))
|
||||
return;
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* When we are doing interactive rename, we store the mapping of names
|
||||
* so we can fix up hard links files later in the archive.
|
||||
*/
|
||||
if (iflag && (name_start() < 0))
|
||||
return;
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* set up to cp file trees
|
||||
|
@ -786,10 +993,8 @@ copy(void)
|
|||
/*
|
||||
* check if this file meets user specified options
|
||||
*/
|
||||
if (sel_chk(arcn) != 0) {
|
||||
ftree_notsel();
|
||||
if (sel_chk(arcn) != 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* if there is already a file in the destination directory with
|
||||
|
@ -805,17 +1010,12 @@ copy(void)
|
|||
/*
|
||||
* create the destination name
|
||||
*/
|
||||
if (*(arcn->name) == '/')
|
||||
res = 1;
|
||||
else
|
||||
res = 0;
|
||||
if ((arcn->nlen - res) > drem) {
|
||||
paxwarn(1, "Destination pathname too long %s",
|
||||
if (strlcpy(dest_pt, arcn->name + (*arcn->name == '/'),
|
||||
drem + 1) > drem) {
|
||||
tty_warn(1, "Destination pathname too long %s",
|
||||
arcn->name);
|
||||
continue;
|
||||
}
|
||||
(void)strncpy(dest_pt, arcn->name + res, drem);
|
||||
dirbuf[PAXPATHLEN] = '\0';
|
||||
|
||||
/*
|
||||
* if existing file is same age or newer skip
|
||||
|
@ -823,10 +1023,10 @@ copy(void)
|
|||
res = lstat(dirbuf, &sb);
|
||||
*dest_pt = '\0';
|
||||
|
||||
if (res == 0) {
|
||||
if (res == 0) {
|
||||
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)
|
||||
|
@ -842,7 +1042,7 @@ copy(void)
|
|||
* user; set the final destination.
|
||||
*/
|
||||
ftree_sel(arcn);
|
||||
if ((chk_lnk(arcn) < 0) || ((res = mod_name(arcn)) < 0))
|
||||
if ((chk_lnk(arcn) < 0) || ((res = mod_name(arcn, RENM)) < 0))
|
||||
break;
|
||||
if ((res > 0) || (set_dest(arcn, dirbuf, dlen) < 0)) {
|
||||
/*
|
||||
|
@ -869,7 +1069,7 @@ copy(void)
|
|||
}
|
||||
|
||||
if (vflag) {
|
||||
(void)fputs(arcn->name, listf);
|
||||
(void)safe_print(arcn->name, listf);
|
||||
vfpart = 1;
|
||||
}
|
||||
++flcnt;
|
||||
|
@ -897,10 +1097,14 @@ copy(void)
|
|||
/*
|
||||
* create a link or special file
|
||||
*/
|
||||
if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG))
|
||||
res = lnk_creat(arcn);
|
||||
else
|
||||
if ((arcn->type == PAX_HLK) ||
|
||||
(arcn->type == PAX_HRG)) {
|
||||
int payload;
|
||||
|
||||
res = lnk_creat(arcn, &payload);
|
||||
} else {
|
||||
res = node_creat(arcn);
|
||||
}
|
||||
if (res < 0)
|
||||
purg_lnk(arcn);
|
||||
if (vflag && vfpart) {
|
||||
|
@ -920,7 +1124,7 @@ copy(void)
|
|||
purg_lnk(arcn);
|
||||
continue;
|
||||
}
|
||||
if ((fddest = file_creat(arcn)) < 0) {
|
||||
if ((fddest = file_creat(arcn, 0)) < 0) {
|
||||
rdfile_close(arcn, &fdsrc);
|
||||
purg_lnk(arcn);
|
||||
continue;
|
||||
|
@ -948,6 +1152,8 @@ copy(void)
|
|||
ar_close();
|
||||
proc_dir();
|
||||
ftree_chk();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -977,7 +1183,7 @@ next_head(ARCHD *arcn)
|
|||
int res;
|
||||
int shftsz;
|
||||
int hsz;
|
||||
int in_resync = 0; /* set when we are in resync mode */
|
||||
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. */
|
||||
|
||||
|
@ -1005,7 +1211,7 @@ next_head(ARCHD *arcn)
|
|||
* them, so exit gracefully.
|
||||
*/
|
||||
if (first && ret == 0)
|
||||
return(-1);
|
||||
return -1;
|
||||
first = 0;
|
||||
|
||||
/*
|
||||
|
@ -1013,16 +1219,18 @@ next_head(ARCHD *arcn)
|
|||
* storage device, better give the user the bad news.
|
||||
*/
|
||||
if ((ret == 0) || (rd_sync() < 0)) {
|
||||
paxwarn(1,"Premature end of file on archive read");
|
||||
return(-1);
|
||||
tty_warn(1,
|
||||
"Premature end of file on archive read");
|
||||
return -1;
|
||||
}
|
||||
if (!in_resync) {
|
||||
if (act == APPND) {
|
||||
paxwarn(1,
|
||||
tty_warn(1,
|
||||
"Archive I/O error, cannot continue");
|
||||
return(-1);
|
||||
return -1;
|
||||
}
|
||||
paxwarn(1,"Archive I/O error. Trying to recover.");
|
||||
tty_warn(1,
|
||||
"Archive I/O error. Trying to recover.");
|
||||
++in_resync;
|
||||
}
|
||||
|
||||
|
@ -1052,12 +1260,12 @@ next_head(ARCHD *arcn)
|
|||
/*
|
||||
* this format has trailers outside of valid headers
|
||||
*/
|
||||
if ((ret = (*frmt->trail_tar)(hdbuf,in_resync,&cnt)) == 0){
|
||||
if ((ret = (*frmt->trail)(hdbuf,in_resync,&cnt)) == 0){
|
||||
/*
|
||||
* valid trailer found, drain input as required
|
||||
*/
|
||||
ar_drain();
|
||||
return(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ret == 1) {
|
||||
|
@ -1083,10 +1291,12 @@ next_head(ARCHD *arcn)
|
|||
*/
|
||||
if (!in_resync) {
|
||||
if (act == APPND) {
|
||||
paxwarn(1,"Unable to append, archive header flaw");
|
||||
return(-1);
|
||||
tty_warn(1,
|
||||
"Unable to append, archive header flaw");
|
||||
return -1;
|
||||
}
|
||||
paxwarn(1,"Invalid header, starting valid header search.");
|
||||
tty_warn(1,
|
||||
"Invalid header, starting valid header search.");
|
||||
++in_resync;
|
||||
}
|
||||
memmove(hdbuf, hdbuf+1, shftsz);
|
||||
|
@ -1096,18 +1306,19 @@ next_head(ARCHD *arcn)
|
|||
|
||||
/*
|
||||
* ok got a valid header, check for trailer if format encodes it in the
|
||||
* the header.
|
||||
* the header. NOTE: the parameters are different than trailer routines
|
||||
* which encode trailers outside of the header!
|
||||
*/
|
||||
if (frmt->inhead && ((*frmt->trail_cpio)(arcn) == 0)) {
|
||||
if (frmt->inhead && ((*frmt->subtrail)(arcn) == 0)) {
|
||||
/*
|
||||
* valid trailer found, drain input as required
|
||||
*/
|
||||
ar_drain();
|
||||
return(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
++flcnt;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1139,7 +1350,7 @@ get_arc(void)
|
|||
minhd = fsub[ford[i]].hsz;
|
||||
}
|
||||
if (rd_start() < 0)
|
||||
return(-1);
|
||||
return -1;
|
||||
res = BLKMULT;
|
||||
hdsz = 0;
|
||||
hdend = hdbuf;
|
||||
|
@ -1171,8 +1382,9 @@ get_arc(void)
|
|||
hdend = hdbuf;
|
||||
if (!notice) {
|
||||
if (act == APPND)
|
||||
return(-1);
|
||||
paxwarn(1,"Cannot identify format. Searching...");
|
||||
return -1;
|
||||
tty_warn(1,
|
||||
"Cannot identify format. Searching...");
|
||||
++notice;
|
||||
}
|
||||
}
|
||||
|
@ -1197,7 +1409,7 @@ get_arc(void)
|
|||
* adding all the special case code is far worse.
|
||||
*/
|
||||
pback(hdbuf, hdsz);
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1206,8 +1418,8 @@ get_arc(void)
|
|||
*/
|
||||
if (!notice) {
|
||||
if (act == APPND)
|
||||
return(-1);
|
||||
paxwarn(1, "Cannot identify format. Searching...");
|
||||
return -1;
|
||||
tty_warn(1, "Cannot identify format. Searching...");
|
||||
++notice;
|
||||
}
|
||||
|
||||
|
@ -1232,6 +1444,6 @@ get_arc(void)
|
|||
/*
|
||||
* we cannot find a header, bow, apologize and quit
|
||||
*/
|
||||
paxwarn(1, "Sorry, unable to determine archive format.");
|
||||
return(-1);
|
||||
tty_warn(1, "Sorry, unable to determine archive format.");
|
||||
return -1;
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
/* $NetBSD: buf_subs.c,v 1.28 2007/04/29 20:23:34 msaitoh Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -14,7 +16,7 @@
|
|||
* 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.
|
||||
* 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.
|
||||
*
|
||||
|
@ -31,17 +33,27 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)buf_subs.c 8.2 (Berkeley) 4/18/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: buf_subs.c,v 1.28 2007/04/29 20:23:34 msaitoh Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "pax.h"
|
||||
|
@ -92,19 +104,14 @@ wr_start(void)
|
|||
if (!wrblksz)
|
||||
wrblksz = frmt->bsz;
|
||||
if (wrblksz > MAXBLK) {
|
||||
paxwarn(1, "Write block size of %d too large, maximum is: %d",
|
||||
tty_warn(1, "Write block size of %d too large, maximum is: %d",
|
||||
wrblksz, MAXBLK);
|
||||
return(-1);
|
||||
return -1;
|
||||
}
|
||||
if (wrblksz % BLKMULT) {
|
||||
paxwarn(1, "Write block size of %d is not a %d byte multiple",
|
||||
tty_warn(1, "Write block size of %d is not a %d byte multiple",
|
||||
wrblksz, BLKMULT);
|
||||
return(-1);
|
||||
}
|
||||
if (wrblksz > MAXBLK_POSIX) {
|
||||
paxwarn(0, "Write block size of %d larger than POSIX max %d, archive may not be portable",
|
||||
wrblksz, MAXBLK_POSIX);
|
||||
return(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -112,11 +119,11 @@ wr_start(void)
|
|||
*/
|
||||
blksz = rdblksz = wrblksz;
|
||||
if ((ar_open(arcname) < 0) && (ar_next() < 0))
|
||||
return(-1);
|
||||
return -1;
|
||||
wrcnt = 0;
|
||||
bufend = buf + wrblksz;
|
||||
bufpt = buf;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -137,14 +144,16 @@ rd_start(void)
|
|||
buf = &(bufmem[BLKMULT]);
|
||||
if ((act == APPND) && wrblksz) {
|
||||
if (wrblksz > MAXBLK) {
|
||||
paxwarn(1,"Write block size %d too large, maximum is: %d",
|
||||
wrblksz, MAXBLK);
|
||||
return(-1);
|
||||
tty_warn(1,
|
||||
"Write block size %d too large, maximum is: %d",
|
||||
wrblksz, MAXBLK);
|
||||
return -1;
|
||||
}
|
||||
if (wrblksz % BLKMULT) {
|
||||
paxwarn(1, "Write block size %d is not a %d byte multiple",
|
||||
wrblksz, BLKMULT);
|
||||
return(-1);
|
||||
tty_warn(1,
|
||||
"Write block size %d is not a %d byte multiple",
|
||||
wrblksz, BLKMULT);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,11 +161,11 @@ rd_start(void)
|
|||
* open the archive
|
||||
*/
|
||||
if ((ar_open(arcname) < 0) && (ar_next() < 0))
|
||||
return(-1);
|
||||
return -1;
|
||||
bufend = buf + rdblksz;
|
||||
bufpt = bufend;
|
||||
rdcnt = 0;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -180,13 +189,13 @@ cp_start(void)
|
|||
* the start of the header of the first file added to the archive. The
|
||||
* format specific end read function tells us how many bytes to move
|
||||
* backwards in the archive to be positioned BEFORE the trailer. Two
|
||||
* different postions have to be adjusted, the O.S. file offset (e.g. the
|
||||
* different positions have to be adjusted, the O.S. file offset (e.g. the
|
||||
* position of the tape head) and the write point within the data we have
|
||||
* stored in the read (soon to become write) buffer. We may have to move
|
||||
* back several records (the number depends on the size of the archive
|
||||
* record and the size of the format trailer) to read up the record where
|
||||
* the first byte of the trailer is recorded. Trailers may span (and
|
||||
* overlap) record boundries.
|
||||
* overlap) record boundaries.
|
||||
* We first calculate which record has the first byte of the trailer. We
|
||||
* move the OS file offset back to the start of this record and read it
|
||||
* up. We set the buffer write pointer to be at this byte (the byte where
|
||||
|
@ -194,9 +203,9 @@ cp_start(void)
|
|||
* start of this record so a flush of this buffer will replace the record
|
||||
* in the archive.
|
||||
* A major problem is rewriting this last record. For archives stored
|
||||
* on disk files, this is trival. However, many devices are really picky
|
||||
* on disk files, this is trivial. However, many devices are really picky
|
||||
* about the conditions under which they will allow a write to occur.
|
||||
* Often devices restrict the conditions where writes can be made writes,
|
||||
* Often devices restrict the conditions where writes can be made,
|
||||
* so it may not be feasable to append archives stored on all types of
|
||||
* devices.
|
||||
* Return:
|
||||
|
@ -210,8 +219,8 @@ appnd_start(off_t skcnt)
|
|||
off_t cnt;
|
||||
|
||||
if (exit_val != 0) {
|
||||
paxwarn(0, "Cannot append to an archive that may have flaws.");
|
||||
return(-1);
|
||||
tty_warn(0, "Cannot append to an archive that may have flaws.");
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* if the user did not specify a write blocksize, inherit the size used
|
||||
|
@ -227,7 +236,7 @@ appnd_start(off_t skcnt)
|
|||
* make sure that this volume allows appends
|
||||
*/
|
||||
if (ar_app_ok() < 0)
|
||||
return(-1);
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Calculate bytes to move back and move in front of record where we
|
||||
|
@ -282,15 +291,15 @@ appnd_start(off_t skcnt)
|
|||
* ARCHIVE mode (write) conditions
|
||||
*/
|
||||
if (ar_set_wr() < 0)
|
||||
return(-1);
|
||||
return -1;
|
||||
act = ARCHIVE;
|
||||
return(0);
|
||||
return 0;
|
||||
|
||||
out:
|
||||
paxwarn(1, "Unable to rewrite archive trailer, cannot append.");
|
||||
return(-1);
|
||||
tty_warn(1, "Unable to rewrite archive trailer, cannot append.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* rd_sync()
|
||||
* A read error occurred on this archive volume. Resync the buffer and
|
||||
|
@ -312,10 +321,11 @@ rd_sync(void)
|
|||
* if the user says bail out on first fault, we are out of here...
|
||||
*/
|
||||
if (maxflt == 0)
|
||||
return(-1);
|
||||
return -1;
|
||||
if (act == APPND) {
|
||||
paxwarn(1, "Unable to append when there are archive read errors.");
|
||||
return(-1);
|
||||
tty_warn(1,
|
||||
"Unable to append when there are archive read errors.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -323,7 +333,7 @@ rd_sync(void)
|
|||
*/
|
||||
if (ar_rdsync() < 0) {
|
||||
if (ar_next() < 0)
|
||||
return(-1);
|
||||
return -1;
|
||||
else
|
||||
rdcnt = 0;
|
||||
}
|
||||
|
@ -336,19 +346,20 @@ rd_sync(void)
|
|||
bufpt = buf;
|
||||
bufend = buf + res;
|
||||
rdcnt += res;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Oh well, yet another failed read...
|
||||
* if error limit reached, ditch. o.w. poke device to move past
|
||||
* if error limit reached, ditch. otherwise poke device to move past
|
||||
* bad media and try again. if media is badly damaged, we ask
|
||||
* the poor (and upset user at this point) for the next archive
|
||||
* volume. remember the goal on reads is to get the most we
|
||||
* can extract out of the archive.
|
||||
*/
|
||||
if ((maxflt > 0) && (++errcnt > maxflt))
|
||||
paxwarn(0,"Archive read error limit (%d) reached",maxflt);
|
||||
tty_warn(0,
|
||||
"Archive read error limit (%d) reached",maxflt);
|
||||
else if (ar_rdsync() == 0)
|
||||
continue;
|
||||
if (ar_next() < 0)
|
||||
|
@ -356,14 +367,14 @@ rd_sync(void)
|
|||
rdcnt = 0;
|
||||
errcnt = 0;
|
||||
}
|
||||
return(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* pback()
|
||||
* push the data used during the archive id phase back into the I/O
|
||||
* buffer. This is required as we cannot be sure that the header does NOT
|
||||
* overlap a block boundry (as in the case we are trying to recover a
|
||||
* overlap a block boundary (as in the case we are trying to recover a
|
||||
* flawed archived). This was not designed to be used for any other
|
||||
* purpose. (What software engineering, HA!)
|
||||
* WARNING: do not even THINK of pback greater than BLKMULT, unless the
|
||||
|
@ -380,7 +391,7 @@ pback(char *pt, int cnt)
|
|||
|
||||
/*
|
||||
* rd_skip()
|
||||
* skip foward in the archive during an archive read. Used to get quickly
|
||||
* skip forward in the archive during an archive read. Used to get quickly
|
||||
* past file data and padding for files the user did NOT select.
|
||||
* Return:
|
||||
* 0 if ok, -1 failure, and 1 when EOF on the archive volume was detected.
|
||||
|
@ -394,13 +405,13 @@ rd_skip(off_t skcnt)
|
|||
off_t skipped = 0;
|
||||
|
||||
/*
|
||||
* consume what data we have in the buffer. If we have to move foward
|
||||
* consume what data we have in the buffer. If we have to move forward
|
||||
* whole records, we call the low level skip function to see if we can
|
||||
* move within the archive without doing the expensive reads on data we
|
||||
* do not want.
|
||||
*/
|
||||
if (skcnt == 0)
|
||||
return(0);
|
||||
return 0;
|
||||
res = MIN((bufend - bufpt), skcnt);
|
||||
bufpt += res;
|
||||
skcnt -= res;
|
||||
|
@ -409,7 +420,7 @@ rd_skip(off_t skcnt)
|
|||
* if skcnt is now 0, then no additional i/o is needed
|
||||
*/
|
||||
if (skcnt == 0)
|
||||
return(0);
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* We have to read more, calculate complete and partial record reads
|
||||
|
@ -423,7 +434,7 @@ rd_skip(off_t skcnt)
|
|||
* how much it can skip over. We will have to read the rest.
|
||||
*/
|
||||
if (ar_fow(cnt, &skipped) < 0)
|
||||
return(-1);
|
||||
return -1;
|
||||
res += cnt - skipped;
|
||||
rdcnt += skipped;
|
||||
|
||||
|
@ -437,14 +448,14 @@ rd_skip(off_t skcnt)
|
|||
* if the read fails, we will have to resync
|
||||
*/
|
||||
if ((cnt <= 0) && ((cnt = buf_fill()) < 0))
|
||||
return(-1);
|
||||
return -1;
|
||||
if (cnt == 0)
|
||||
return(1);
|
||||
return 1;
|
||||
cnt = MIN(cnt, res);
|
||||
bufpt += cnt;
|
||||
res -= cnt;
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -488,7 +499,7 @@ wr_rdbuf(char *out, int outcnt)
|
|||
while (outcnt > 0) {
|
||||
cnt = bufend - bufpt;
|
||||
if ((cnt <= 0) && ((cnt = buf_flush(blksz)) < 0))
|
||||
return(-1);
|
||||
return -1;
|
||||
/*
|
||||
* only move what we have space for
|
||||
*/
|
||||
|
@ -498,7 +509,7 @@ wr_rdbuf(char *out, int outcnt)
|
|||
out += cnt;
|
||||
outcnt -= cnt;
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -528,12 +539,12 @@ rd_wrbuf(char *in, int cpcnt)
|
|||
/*
|
||||
* read error, return what we got (or the error if
|
||||
* no data was copied). The caller must know that an
|
||||
* error occured and has the best knowledge what to
|
||||
* error occurred and has the best knowledge what to
|
||||
* do with it
|
||||
*/
|
||||
if ((res = cpcnt - incnt) > 0)
|
||||
return(res);
|
||||
return(cnt);
|
||||
return res;
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -546,7 +557,7 @@ rd_wrbuf(char *in, int cpcnt)
|
|||
incnt -= cnt;
|
||||
in += cnt;
|
||||
}
|
||||
return(cpcnt);
|
||||
return cpcnt;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -571,19 +582,19 @@ wr_skip(off_t skcnt)
|
|||
while (skcnt > 0L) {
|
||||
cnt = bufend - bufpt;
|
||||
if ((cnt <= 0) && ((cnt = buf_flush(blksz)) < 0))
|
||||
return(-1);
|
||||
return -1;
|
||||
cnt = MIN(cnt, skcnt);
|
||||
memset(bufpt, 0, cnt);
|
||||
bufpt += cnt;
|
||||
skcnt -= cnt;
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* wr_rdfile()
|
||||
* fill write buffer with the contents of a file. We are passed an open
|
||||
* file descriptor to the file and the archive structure that describes the
|
||||
* file descriptor to the file an the archive structure that describes the
|
||||
* file we are storing. The variable "left" is modified to contain the
|
||||
* number of bytes of the file we were NOT able to write to the archive.
|
||||
* it is important that we always write EXACTLY the number of bytes that
|
||||
|
@ -604,7 +615,16 @@ wr_rdfile(ARCHD *arcn, int ifd, off_t *left)
|
|||
int cnt;
|
||||
int res = 0;
|
||||
off_t size = arcn->sb.st_size;
|
||||
struct stat sb;
|
||||
struct stat origsb, sb;
|
||||
|
||||
/*
|
||||
* by default, remember the previously obtained stat information
|
||||
* (in arcn->sb) for comparing the mtime after reading.
|
||||
* if Mflag is set, use the actual mtime instead.
|
||||
*/
|
||||
origsb = arcn->sb;
|
||||
if (Mflag && (fstat(ifd, &origsb) < 0))
|
||||
syswarn(1, errno, "Failed stat on %s", arcn->org_name);
|
||||
|
||||
/*
|
||||
* while there are more bytes to write
|
||||
|
@ -613,10 +633,10 @@ wr_rdfile(ARCHD *arcn, int ifd, off_t *left)
|
|||
cnt = bufend - bufpt;
|
||||
if ((cnt <= 0) && ((cnt = buf_flush(blksz)) < 0)) {
|
||||
*left = size;
|
||||
return(-1);
|
||||
return -1;
|
||||
}
|
||||
cnt = MIN(cnt, size);
|
||||
if ((res = read(ifd, bufpt, cnt)) <= 0)
|
||||
if ((res = read_with_restart(ifd, bufpt, cnt)) <= 0)
|
||||
break;
|
||||
size -= res;
|
||||
bufpt += res;
|
||||
|
@ -629,14 +649,14 @@ wr_rdfile(ARCHD *arcn, int ifd, off_t *left)
|
|||
if (res < 0)
|
||||
syswarn(1, errno, "Read fault on %s", arcn->org_name);
|
||||
else if (size != 0L)
|
||||
paxwarn(1, "File changed size during read %s", arcn->org_name);
|
||||
tty_warn(1, "File changed size during read %s", arcn->org_name);
|
||||
else if (fstat(ifd, &sb) < 0)
|
||||
syswarn(1, errno, "Failed stat on %s", arcn->org_name);
|
||||
else if (arcn->sb.st_mtime != sb.st_mtime)
|
||||
paxwarn(1, "File %s was modified during copy to archive",
|
||||
else if (origsb.st_mtime != sb.st_mtime)
|
||||
tty_warn(1, "File %s was modified during copy to archive",
|
||||
arcn->org_name);
|
||||
*left = size;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -669,21 +689,21 @@ rd_wrfile(ARCHD *arcn, int ofd, off_t *left)
|
|||
int isem = 1;
|
||||
int rem;
|
||||
int sz = MINFBSZ;
|
||||
struct stat sb;
|
||||
struct stat sb;
|
||||
u_long crc = 0L;
|
||||
|
||||
/*
|
||||
* pass the blocksize of the file being written to the write routine,
|
||||
* if the size is zero, use the default MINFBSZ
|
||||
*/
|
||||
if (fstat(ofd, &sb) == 0) {
|
||||
#if 0
|
||||
/* not under minix */
|
||||
if (ofd < 0)
|
||||
sz = PAXPATHLEN+1;
|
||||
else if (fstat(ofd, &sb) == 0) {
|
||||
if (sb.st_blksize > 0)
|
||||
sz = (int)sb.st_blksize;
|
||||
#endif
|
||||
} else
|
||||
syswarn(0,errno,"Unable to obtain block size for file %s",fnm);
|
||||
syswarn(0, errno,
|
||||
"Unable to obtain block size for file %s", fnm);
|
||||
rem = sz;
|
||||
*left = 0L;
|
||||
|
||||
|
@ -725,22 +745,23 @@ rd_wrfile(ARCHD *arcn, int ofd, off_t *left)
|
|||
* written. just closing with the file offset moved forward may not put
|
||||
* a hole at the end of the file.
|
||||
*/
|
||||
if (isem && (arcn->sb.st_size > 0L))
|
||||
if (ofd >= 0 && isem && (arcn->sb.st_size > 0L))
|
||||
file_flush(ofd, fnm, isem);
|
||||
|
||||
/*
|
||||
* if we failed from archive read, we do not want to skip
|
||||
*/
|
||||
if ((size > 0L) && (*left == 0L))
|
||||
return(-1);
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* some formats record a crc on file data. If so, then we compare the
|
||||
* calculated crc to the crc stored in the archive
|
||||
*/
|
||||
if (docrc && (size == 0L) && (arcn->crc != crc))
|
||||
paxwarn(1,"Actual crc does not match expected crc %s",arcn->name);
|
||||
return(0);
|
||||
tty_warn(1,"Actual crc does not match expected crc %s",
|
||||
arcn->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -761,40 +782,44 @@ cp_file(ARCHD *arcn, int fd1, int fd2)
|
|||
int isem = 1;
|
||||
int rem;
|
||||
int sz = MINFBSZ;
|
||||
struct stat sb;
|
||||
struct stat sb, origsb;
|
||||
|
||||
/*
|
||||
* check for holes in the source file. If none, we will use regular
|
||||
* write instead of file write.
|
||||
*/
|
||||
#if 0
|
||||
/* not under minix */
|
||||
if (((off_t)(arcn->sb.st_blocks * BLKMULT)) >= arcn->sb.st_size)
|
||||
#endif
|
||||
++no_hole;
|
||||
|
||||
/*
|
||||
* by default, remember the previously obtained stat information
|
||||
* (in arcn->sb) for comparing the mtime after reading.
|
||||
* if Mflag is set, use the actual mtime instead.
|
||||
*/
|
||||
origsb = arcn->sb;
|
||||
if (Mflag && (fstat(fd1, &origsb) < 0))
|
||||
syswarn(1, errno, "Failed stat on %s", arcn->org_name);
|
||||
|
||||
/*
|
||||
* pass the blocksize of the file being written to the write routine,
|
||||
* if the size is zero, use the default MINFBSZ
|
||||
*/
|
||||
if (fstat(fd2, &sb) == 0) {
|
||||
#if 0
|
||||
/* not under minix */
|
||||
if (sb.st_blksize > 0)
|
||||
sz = sb.st_blksize;
|
||||
#endif
|
||||
} else
|
||||
syswarn(0,errno,"Unable to obtain block size for file %s",fnm);
|
||||
syswarn(0, errno,
|
||||
"Unable to obtain block size for file %s", fnm);
|
||||
rem = sz;
|
||||
|
||||
/*
|
||||
* read the source file and copy to destination file until EOF
|
||||
*/
|
||||
for(;;) {
|
||||
if ((cnt = read(fd1, buf, blksz)) <= 0)
|
||||
if ((cnt = read_with_restart(fd1, buf, blksz)) <= 0)
|
||||
break;
|
||||
if (no_hole)
|
||||
res = write(fd2, buf, cnt);
|
||||
res = xwrite(fd2, buf, cnt);
|
||||
else
|
||||
res = file_write(fd2, buf, cnt, &rem, &isem, sz, fnm);
|
||||
if (res != cnt)
|
||||
|
@ -809,12 +834,12 @@ cp_file(ARCHD *arcn, int fd1, int fd2)
|
|||
syswarn(1, errno, "Failed write during copy of %s to %s",
|
||||
arcn->org_name, arcn->name);
|
||||
else if (cpcnt != arcn->sb.st_size)
|
||||
paxwarn(1, "File %s changed size during copy to %s",
|
||||
tty_warn(1, "File %s changed size during copy to %s",
|
||||
arcn->org_name, arcn->name);
|
||||
else if (fstat(fd1, &sb) < 0)
|
||||
syswarn(1, errno, "Failed stat of %s", arcn->org_name);
|
||||
else if (arcn->sb.st_mtime != sb.st_mtime)
|
||||
paxwarn(1, "File %s was modified during copy to %s",
|
||||
else if (origsb.st_mtime != sb.st_mtime)
|
||||
tty_warn(1, "File %s was modified during copy to %s",
|
||||
arcn->org_name, arcn->name);
|
||||
|
||||
/*
|
||||
|
@ -844,7 +869,7 @@ buf_fill(void)
|
|||
static int fini = 0;
|
||||
|
||||
if (fini)
|
||||
return(0);
|
||||
return 0;
|
||||
|
||||
for(;;) {
|
||||
/*
|
||||
|
@ -855,22 +880,25 @@ buf_fill(void)
|
|||
bufpt = buf;
|
||||
bufend = buf + cnt;
|
||||
rdcnt += cnt;
|
||||
return(cnt);
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/*
|
||||
* errors require resync, EOF goes to next archive
|
||||
* but in case we have not determined yet the format,
|
||||
* this means that we have a very short file, so we
|
||||
* are done again.
|
||||
*/
|
||||
if (cnt < 0)
|
||||
break;
|
||||
if (ar_next() < 0) {
|
||||
if (frmt == NULL || ar_next() < 0) {
|
||||
fini = 1;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
rdcnt = 0;
|
||||
}
|
||||
exit_val = 1;
|
||||
return(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -891,16 +919,17 @@ buf_flush(int bufcnt)
|
|||
|
||||
/*
|
||||
* if we have reached the user specified byte count for each archive
|
||||
* volume, prompt for the next volume. (The non-standrad -R flag).
|
||||
* volume, prompt for the next volume. (The non-standard -R flag).
|
||||
* NOTE: If the wrlimit is smaller than wrcnt, we will always write
|
||||
* at least one record. We always round limit UP to next blocksize.
|
||||
*/
|
||||
if ((wrlimit > 0) && (wrcnt > wrlimit)) {
|
||||
paxwarn(0, "User specified archive volume byte limit reached.");
|
||||
tty_warn(0,
|
||||
"User specified archive volume byte limit reached.");
|
||||
if (ar_next() < 0) {
|
||||
wrcnt = 0;
|
||||
exit_val = 1;
|
||||
return(-1);
|
||||
return -1;
|
||||
}
|
||||
wrcnt = 0;
|
||||
|
||||
|
@ -915,7 +944,7 @@ buf_flush(int bufcnt)
|
|||
*/
|
||||
bufend = buf + blksz;
|
||||
if (blksz > bufcnt)
|
||||
return(0);
|
||||
return 0;
|
||||
if (blksz < bufcnt)
|
||||
push = bufcnt - blksz;
|
||||
}
|
||||
|
@ -947,7 +976,7 @@ buf_flush(int bufcnt)
|
|||
}
|
||||
} else
|
||||
bufpt = buf;
|
||||
return(totcnt);
|
||||
return totcnt;
|
||||
} else if (cnt > 0) {
|
||||
/*
|
||||
* Oh drat we got a partial write!
|
||||
|
@ -962,7 +991,7 @@ buf_flush(int bufcnt)
|
|||
memcpy(buf, bufpt, cnt);
|
||||
bufpt = buf + cnt;
|
||||
if (!frmt->blkalgn || ((cnt % frmt->blkalgn) == 0))
|
||||
return(totcnt);
|
||||
return totcnt;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -980,7 +1009,7 @@ buf_flush(int bufcnt)
|
|||
*/
|
||||
bufend = buf + blksz;
|
||||
if (blksz > bufcnt)
|
||||
return(0);
|
||||
return 0;
|
||||
if (blksz < bufcnt)
|
||||
push = bufcnt - blksz;
|
||||
}
|
||||
|
@ -989,5 +1018,5 @@ buf_flush(int bufcnt)
|
|||
* write failed, stop pax. we must not create a bad archive!
|
||||
*/
|
||||
exit_val = 1;
|
||||
return(-1);
|
||||
return -1;
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
.\"-
|
||||
.\" $NetBSD: cpio.1,v 1.13 2011/06/19 07:34:24 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1997 SigmaSoft, Th. Lockert
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
|
@ -10,11 +11,6 @@
|
|||
.\" 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 SigmaSoft, Th. Lockert.
|
||||
.\" 4. The name of the author may not be used to endorse or promote products
|
||||
.\" derived from this software without specific prior written permission
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
|
@ -27,66 +23,67 @@
|
|||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $OpenBSD: cpio.1,v 1.16 2001/05/01 17:58:01 aaron Exp $
|
||||
.\" $FreeBSD$
|
||||
.\" OpenBSD: cpio.1,v 1.14 2000/11/10 17:52:02 aaron Exp
|
||||
.\"
|
||||
.Dd February 16, 1997
|
||||
.Dd June 18, 2011
|
||||
.Dt CPIO 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm cpio
|
||||
.Nd copy file archives in and out
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Nm cpio
|
||||
.Fl o
|
||||
.Op Fl aABcLvzZ
|
||||
.Op Fl AaBcLvZz
|
||||
.Op Fl C Ar bytes
|
||||
.Op Fl F Ar archive
|
||||
.Op Fl H Ar format
|
||||
.Op Fl O Ar archive
|
||||
.No < Ar name-list
|
||||
.Op No > Ar archive
|
||||
.Nm
|
||||
.Ar "\*[Lt] name-list"
|
||||
.Op Ar "\*[Gt] archive"
|
||||
.Nm cpio
|
||||
.Fl i
|
||||
.Op Fl bBcdfmrsStuvzZ6
|
||||
.Op Fl 6BbcdfmrSstuvZz
|
||||
.Op Fl C Ar bytes
|
||||
.Op Fl E Ar file
|
||||
.Op Fl F Ar archive
|
||||
.Op Fl H Ar format
|
||||
.Op Fl I Ar archive
|
||||
.Op Ar pattern ...
|
||||
.Op No < Ar archive
|
||||
.Nm
|
||||
.Op Ar "pattern ..."
|
||||
.Op Ar "\*[Lt] archive"
|
||||
.Nm cpio
|
||||
.Fl p
|
||||
.Op Fl adlLmuv
|
||||
.Op Fl adLlmuv
|
||||
.Ar destination-directory
|
||||
.No < Ar name-list
|
||||
.Ar "\*[Lt] name-list"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
command copies files to and from a
|
||||
.Nm
|
||||
archive.
|
||||
If the archive is of the form:
|
||||
.Ar [[user@]host:]file
|
||||
then the archive will be processed using
|
||||
.Xr rmt 8 .
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width indent
|
||||
.It Fl o
|
||||
.Bl -tag -width Ds
|
||||
.It Fl o , Fl Fl create
|
||||
Create an archive.
|
||||
Reads the list of files to store in the
|
||||
archive from standard input, and writes the archive on standard
|
||||
output.
|
||||
.Bl -tag -width indent
|
||||
.It Fl a
|
||||
.Bl -tag -width Ds
|
||||
.It Fl a , Fl Fl reset-access-time
|
||||
Reset the access times on files that have been copied to the
|
||||
archive.
|
||||
.It Fl A
|
||||
.It Fl A , Fl Fl append
|
||||
Append to the specified archive.
|
||||
.It Fl B
|
||||
Set block size of output to 5120 bytes.
|
||||
.It Fl c
|
||||
Use
|
||||
.Tn ASCII
|
||||
format for
|
||||
Use ASCII format for
|
||||
.Nm
|
||||
header for portability.
|
||||
.It Fl C Ar bytes
|
||||
|
@ -100,46 +97,48 @@ Write the archive in the specified format.
|
|||
Recognized formats are:
|
||||
.Pp
|
||||
.Bl -tag -width sv4cpio -compact
|
||||
.It Cm bcpio
|
||||
.It Ar bcpio
|
||||
Old binary
|
||||
.Nm
|
||||
format.
|
||||
.It Cm cpio
|
||||
.It Ar cpio
|
||||
Old octal character
|
||||
.Nm
|
||||
format.
|
||||
.It Cm sv4cpio
|
||||
.Tn SVR4
|
||||
hex
|
||||
.It Ar sv4cpio
|
||||
SVR4 hex
|
||||
.Nm
|
||||
format.
|
||||
.It Cm tar
|
||||
.It Ar tar
|
||||
Old tar format.
|
||||
.It Cm ustar
|
||||
.Tn POSIX
|
||||
ustar format.
|
||||
.It Ar ustar
|
||||
POSIX ustar format.
|
||||
.El
|
||||
.It Fl L
|
||||
Follow symbolic links.
|
||||
.It Fl v
|
||||
Be verbose about operations.
|
||||
List filenames as they are written to the archive.
|
||||
.It Fl z
|
||||
Compress archive using
|
||||
.Xr gzip 1
|
||||
.It Fl Fl xz
|
||||
Compress/decompress archive using
|
||||
.Xr xz 1
|
||||
format.
|
||||
.It Fl Z
|
||||
Compress archive using
|
||||
.Xr compress 1
|
||||
format.
|
||||
.It Fl z
|
||||
Compress/decompress archive using
|
||||
.Xr gzip 1
|
||||
format.
|
||||
.El
|
||||
.It Fl i
|
||||
.It Fl i , Fl Fl extract
|
||||
Restore files from an archive.
|
||||
Reads the archive file from
|
||||
standard input and extracts files matching the
|
||||
.Ar patterns
|
||||
that were specified on the command line.
|
||||
.Bl -tag -width indent
|
||||
.Bl -tag -width Ds
|
||||
.It Fl b
|
||||
Do byte and word swapping after reading in data from the
|
||||
archive, for restoring archives created on systems with
|
||||
|
@ -147,63 +146,60 @@ a different byte order.
|
|||
.It Fl B
|
||||
Set the block size of the archive being read to 5120 bytes.
|
||||
.It Fl c
|
||||
Expect the archive headers to be in
|
||||
.Tn ASCII
|
||||
format.
|
||||
Expect the archive headers to be in ASCII format.
|
||||
.It Fl C Ar bytes
|
||||
Read archive written with a block size of
|
||||
.Ar bytes .
|
||||
.It Fl d
|
||||
.It Fl d , Fl Fl make-directories
|
||||
Create any intermediate directories as needed during
|
||||
restore.
|
||||
.It Fl E Ar file
|
||||
.It Fl E Ar file , Fl Fl pattern-file Ar file
|
||||
Read list of file name patterns to extract or list from
|
||||
.Ar file .
|
||||
.It Fl f
|
||||
.It Fl f , Fl Fl nonmatching
|
||||
Restore all files except those matching the
|
||||
.Ar patterns
|
||||
given on the command line.
|
||||
.It Fl F Ar archive , Fl I Ar archive
|
||||
.It Fl F Ar archive , Fl Fl file Ar archive
|
||||
.It Fl I Ar archive
|
||||
Use the specified file as the input for the archive.
|
||||
.It Fl H Ar format
|
||||
.It Fl H Ar format , Fl Fl format Ar format
|
||||
Read an archive of the specified format.
|
||||
Recognized formats are:
|
||||
.Pp
|
||||
.Bl -tag -width sv4cpio -compact
|
||||
.It Cm bcpio
|
||||
.It Ar bcpio
|
||||
Old binary
|
||||
.Nm
|
||||
format.
|
||||
.It Cm cpio
|
||||
.It Ar cpio
|
||||
Old octal character
|
||||
.Nm
|
||||
format.
|
||||
.It Cm sv4cpio
|
||||
.Tn SVR4
|
||||
hex
|
||||
.It Ar sv4cpio
|
||||
SVR4 hex
|
||||
.Nm
|
||||
format.
|
||||
.It Cm tar
|
||||
.It Ar tar
|
||||
Old tar format.
|
||||
.It Cm ustar
|
||||
.Tn POSIX
|
||||
ustar format.
|
||||
.It Ar ustar
|
||||
POSIX ustar format.
|
||||
.El
|
||||
.It Fl m
|
||||
Restore modification times on files.
|
||||
.It Fl r
|
||||
.It Fl r , Fl Fl rename
|
||||
Rename restored files interactively.
|
||||
.It Fl s
|
||||
Swap bytes after reading data from the archive.
|
||||
.It Fl S
|
||||
.It Fl S , Fl Fl swap-halfwords
|
||||
Swap words after reading data from the archive.
|
||||
.It Fl t
|
||||
.It Fl t , Fl Fl list
|
||||
Only list the contents of the archive, no files or
|
||||
directories will be created.
|
||||
.It Fl u
|
||||
.It Fl u , Fl Fl unconditional
|
||||
Overwrite files even when the file in the archive is
|
||||
older than the one that will be overwritten.
|
||||
.It Fl v
|
||||
.It Fl v , Fl Fl verbose
|
||||
Be verbose about operations.
|
||||
List filenames as they are copied in from the archive.
|
||||
.It Fl z
|
||||
|
@ -219,42 +215,49 @@ Process old-style
|
|||
.Nm
|
||||
format archives.
|
||||
.El
|
||||
.It Fl p
|
||||
.It Fl p , Fl Fl pass-through
|
||||
Copy files from one location to another in a single pass.
|
||||
The list of files to copy are read from standard input and
|
||||
written out to a directory relative to the specified
|
||||
.Ar directory
|
||||
argument.
|
||||
.Bl -tag -width indent
|
||||
.Bl -tag -width Ds
|
||||
.It Fl a
|
||||
Reset the access times on files that have been copied.
|
||||
.It Fl d
|
||||
Create any intermediate directories as needed to write
|
||||
the files at the new location.
|
||||
.It Fl l
|
||||
.It Fl l , Fl Fl link
|
||||
When possible, link files rather than creating an
|
||||
extra copy.
|
||||
.It Fl L
|
||||
.It Fl L , Fl Fl dereference
|
||||
Follow symbolic links.
|
||||
.It Fl m
|
||||
.It Fl m , Fl Fl preserve-modification-time
|
||||
Restore modification times on files.
|
||||
.It Fl u
|
||||
.It Fl u , Fl Fl unconditional
|
||||
Overwrite files even when the original file being copied is
|
||||
older than the one that will be overwritten.
|
||||
.It Fl v
|
||||
.It Fl v , Fl Fl verbose
|
||||
Be verbose about operations.
|
||||
List filenames as they are copied.
|
||||
.It Fl Fl force-local
|
||||
Do not interpret filenames that contain a
|
||||
.Sq \&:
|
||||
as remote files.
|
||||
.It Fl Fl insecure
|
||||
Normally
|
||||
.Nm
|
||||
ignores filenames that contain
|
||||
.Dq ..
|
||||
as a path component.
|
||||
With this option, files that contain
|
||||
.Dq ..
|
||||
can be processed.
|
||||
.El
|
||||
.El
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width TMPDIR
|
||||
.It Ev TMPDIR
|
||||
Path in which to store temporary files.
|
||||
.El
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
utility will exit with one of the following values:
|
||||
will exit with one of the following values:
|
||||
.Bl -tag -width 2n
|
||||
.It 0
|
||||
All files were processed successfully.
|
||||
|
@ -294,8 +297,7 @@ specific archive format specification.
|
|||
.Xr pax 1 ,
|
||||
.Xr tar 1
|
||||
.Sh AUTHORS
|
||||
.An Keith Muller
|
||||
at the University of California, San Diego.
|
||||
Keith Muller at the University of California, San Diego.
|
||||
.Sh BUGS
|
||||
The
|
||||
.Fl s
|
|
@ -1,3 +1,5 @@
|
|||
/* $NetBSD: cpio.c,v 1.22 2012/08/09 08:09:21 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -14,7 +16,7 @@
|
|||
* 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.
|
||||
* 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.
|
||||
*
|
||||
|
@ -31,17 +33,25 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)cpio.c 8.1 (Berkeley) 5/31/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: cpio.c,v 1.22 2012/08/09 08:09:21 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -57,7 +67,7 @@ static int com_rd(ARCHD *);
|
|||
* Routines which support the different cpio versions
|
||||
*/
|
||||
|
||||
static int swp_head; /* binary cpio header byte swap */
|
||||
int cpio_swp_head; /* binary cpio header byte swap */
|
||||
|
||||
/*
|
||||
* Routines common to all versions of cpio
|
||||
|
@ -67,17 +77,17 @@ static int swp_head; /* binary cpio header byte swap */
|
|||
* cpio_strd()
|
||||
* Fire up the hard link detection code
|
||||
* Return:
|
||||
* 0 if ok -1 otherwise (the return values of lnk_start())
|
||||
* 0 if ok -1 otherwise (the return values of lnk_start())
|
||||
*/
|
||||
|
||||
int
|
||||
cpio_strd(void)
|
||||
{
|
||||
return(lnk_start());
|
||||
return lnk_start();
|
||||
}
|
||||
|
||||
/*
|
||||
* cpio_trail()
|
||||
* cpio_subtrail()
|
||||
* Called to determine if a header block is a valid trailer. We are
|
||||
* passed the block, the in_sync flag (which tells us we are in resync
|
||||
* mode; looking for a valid header), and cnt (which starts at zero)
|
||||
|
@ -87,14 +97,14 @@ cpio_strd(void)
|
|||
*/
|
||||
|
||||
int
|
||||
cpio_trail(ARCHD *arcn)
|
||||
cpio_subtrail(ARCHD *arcn)
|
||||
{
|
||||
/*
|
||||
* look for trailer id in file we are about to process
|
||||
*/
|
||||
if ((strcmp(arcn->name, TRAILER) == 0) && (arcn->sb.st_size == 0))
|
||||
return(0);
|
||||
return(-1);
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -142,8 +152,8 @@ com_rd(ARCHD *arcn)
|
|||
break;
|
||||
}
|
||||
if (chk_lnk(arcn) < 0)
|
||||
return(-1);
|
||||
return(0);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -166,7 +176,7 @@ cpio_endwr(void)
|
|||
last.type = PAX_REG;
|
||||
last.sb.st_nlink = 1;
|
||||
(void)strcpy(last.name, TRAILER);
|
||||
return((*frmt->wr)(&last));
|
||||
return (*frmt->wr)(&last);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -182,9 +192,9 @@ rd_nm(ARCHD *arcn, int nsz)
|
|||
/*
|
||||
* do not even try bogus values
|
||||
*/
|
||||
if ((nsz == 0) || (nsz > (int)sizeof(arcn->name))) {
|
||||
paxwarn(1, "Cpio file name length %d is out of range", nsz);
|
||||
return(-1);
|
||||
if ((nsz <= 0) || (nsz > (int)sizeof(arcn->name))) {
|
||||
tty_warn(1, "Cpio file name length %d is out of range", nsz);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -192,10 +202,10 @@ rd_nm(ARCHD *arcn, int nsz)
|
|||
*/
|
||||
if ((rd_wrbuf(arcn->name,nsz) != nsz) || (arcn->name[nsz-1] != '\0') ||
|
||||
(arcn->name[0] == '\0')) {
|
||||
paxwarn(1, "Cpio file name in header is corrupted");
|
||||
return(-1);
|
||||
tty_warn(1, "Cpio file name in header is corrupted");
|
||||
return -1;
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -213,15 +223,10 @@ rd_ln_nm(ARCHD *arcn)
|
|||
* check the length specified for bogus values
|
||||
*/
|
||||
if ((arcn->sb.st_size == 0) ||
|
||||
((size_t)arcn->sb.st_size >= sizeof(arcn->ln_name))) {
|
||||
# ifdef NET2_STAT
|
||||
paxwarn(1, "Cpio link name length is invalid: %lu",
|
||||
arcn->sb.st_size);
|
||||
# else
|
||||
paxwarn(1, "Cpio link name length is invalid: %ju",
|
||||
(uintmax_t)arcn->sb.st_size);
|
||||
# endif
|
||||
return(-1);
|
||||
(arcn->sb.st_size >= (off_t)sizeof(arcn->ln_name))) {
|
||||
tty_warn(1, "Cpio link name length is invalid: " OFFT_F,
|
||||
(OFFT_T) arcn->sb.st_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -229,8 +234,8 @@ rd_ln_nm(ARCHD *arcn)
|
|||
*/
|
||||
if (rd_wrbuf(arcn->ln_name, (int)arcn->sb.st_size) !=
|
||||
(int)arcn->sb.st_size) {
|
||||
paxwarn(1, "Cpio link name read error");
|
||||
return(-1);
|
||||
tty_warn(1, "Cpio link name read error");
|
||||
return -1;
|
||||
}
|
||||
arcn->ln_nlen = arcn->sb.st_size;
|
||||
arcn->ln_name[arcn->ln_nlen] = '\0';
|
||||
|
@ -239,10 +244,10 @@ rd_ln_nm(ARCHD *arcn)
|
|||
* watch out for those empty link names
|
||||
*/
|
||||
if (arcn->ln_name[0] == '\0') {
|
||||
paxwarn(1, "Cpio link name is corrupt");
|
||||
return(-1);
|
||||
tty_warn(1, "Cpio link name is corrupt");
|
||||
return -1;
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -251,10 +256,10 @@ rd_ln_nm(ARCHD *arcn)
|
|||
|
||||
/*
|
||||
* cpio_id()
|
||||
* determine if a block given to us is a valid extended byte oriented
|
||||
* determine if a block given to us is a valid extended byte oriented
|
||||
* cpio header
|
||||
* Return:
|
||||
* 0 if a valid header, -1 otherwise
|
||||
* 0 if a valid header, -1 otherwise
|
||||
*/
|
||||
|
||||
int
|
||||
|
@ -262,8 +267,8 @@ cpio_id(char *blk, int size)
|
|||
{
|
||||
if ((size < (int)sizeof(HD_CPIO)) ||
|
||||
(strncmp(blk, AMAGIC, sizeof(AMAGIC) - 1) != 0))
|
||||
return(-1);
|
||||
return(0);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -284,7 +289,7 @@ cpio_rd(ARCHD *arcn, char *buf)
|
|||
* check that this is a valid header, if not return -1
|
||||
*/
|
||||
if (cpio_id(buf, sizeof(HD_CPIO)) < 0)
|
||||
return(-1);
|
||||
return -1;
|
||||
hd = (HD_CPIO *)buf;
|
||||
|
||||
/*
|
||||
|
@ -292,47 +297,37 @@ cpio_rd(ARCHD *arcn, char *buf)
|
|||
* ascii fields from the header
|
||||
*/
|
||||
arcn->pad = 0L;
|
||||
arcn->sb.st_dev = (dev_t)asc_ul(hd->c_dev, sizeof(hd->c_dev), OCT);
|
||||
arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), OCT);
|
||||
arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), OCT);
|
||||
arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), OCT);
|
||||
arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), OCT);
|
||||
arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink),
|
||||
arcn->sb.st_dev = (dev_t)asc_u32(hd->c_dev, sizeof(hd->c_dev), OCT);
|
||||
arcn->sb.st_ino = (ino_t)asc_u32(hd->c_ino, sizeof(hd->c_ino), OCT);
|
||||
arcn->sb.st_mode = (mode_t)asc_u32(hd->c_mode, sizeof(hd->c_mode), OCT);
|
||||
arcn->sb.st_uid = (uid_t)asc_u32(hd->c_uid, sizeof(hd->c_uid), OCT);
|
||||
arcn->sb.st_gid = (gid_t)asc_u32(hd->c_gid, sizeof(hd->c_gid), OCT);
|
||||
arcn->sb.st_nlink = (nlink_t)asc_u32(hd->c_nlink, sizeof(hd->c_nlink),
|
||||
OCT);
|
||||
arcn->sb.st_rdev = (dev_t)asc_ul(hd->c_rdev, sizeof(hd->c_rdev), OCT);
|
||||
#ifdef NET2_STAT
|
||||
arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime, sizeof(hd->c_mtime),
|
||||
arcn->sb.st_rdev = (dev_t)asc_u32(hd->c_rdev, sizeof(hd->c_rdev), OCT);
|
||||
arcn->sb.st_mtime = (time_t)(int32_t)asc_u32(hd->c_mtime, sizeof(hd->c_mtime),
|
||||
OCT);
|
||||
#else
|
||||
arcn->sb.st_mtime = (time_t)asc_uqd(hd->c_mtime, sizeof(hd->c_mtime),
|
||||
OCT);
|
||||
#endif
|
||||
arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
|
||||
#ifdef NET2_STAT
|
||||
arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,sizeof(hd->c_filesize),
|
||||
OCT);
|
||||
#else
|
||||
arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize,sizeof(hd->c_filesize),
|
||||
OCT);
|
||||
#endif
|
||||
arcn->sb.st_size = (off_t)ASC_OFFT(hd->c_filesize,
|
||||
sizeof(hd->c_filesize), OCT);
|
||||
|
||||
/*
|
||||
* check name size and if valid, read in the name of this entry (name
|
||||
* follows header in the archive)
|
||||
*/
|
||||
if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),OCT)) < 2)
|
||||
return(-1);
|
||||
if ((nsz = (int)asc_u32(hd->c_namesize,sizeof(hd->c_namesize),OCT)) < 2)
|
||||
return -1;
|
||||
arcn->nlen = nsz - 1;
|
||||
if (rd_nm(arcn, nsz) < 0)
|
||||
return(-1);
|
||||
return -1;
|
||||
|
||||
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));
|
||||
return com_rd(arcn);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -340,25 +335,25 @@ cpio_rd(ARCHD *arcn, char *buf)
|
|||
* stored like file data.
|
||||
*/
|
||||
if (rd_ln_nm(arcn) < 0)
|
||||
return(-1);
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* we have a valid header (with a link)
|
||||
*/
|
||||
return(com_rd(arcn));
|
||||
return com_rd(arcn);
|
||||
}
|
||||
|
||||
/*
|
||||
* cpio_endrd()
|
||||
* no cleanup needed here, just return size of the trailer (for append)
|
||||
* no cleanup needed here, just return size of the trailer (for append)
|
||||
* Return:
|
||||
* size of trailer header in this format
|
||||
* size of trailer header in this format
|
||||
*/
|
||||
|
||||
off_t
|
||||
cpio_endrd(void)
|
||||
{
|
||||
return((off_t)(sizeof(HD_CPIO) + sizeof(TRAILER)));
|
||||
return (off_t)(sizeof(HD_CPIO) + sizeof(TRAILER));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -371,7 +366,7 @@ cpio_endrd(void)
|
|||
int
|
||||
cpio_stwr(void)
|
||||
{
|
||||
return(dev_start());
|
||||
return dev_start();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -379,7 +374,7 @@ cpio_stwr(void)
|
|||
* copy the data in the ARCHD to buffer in extended byte oriented cpio
|
||||
* format.
|
||||
* Return
|
||||
* 0 if file has data to be written after the header, 1 if file has NO
|
||||
* 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
|
||||
*/
|
||||
|
||||
|
@ -394,7 +389,7 @@ cpio_wr(ARCHD *arcn)
|
|||
* check and repair truncated device and inode fields in the header
|
||||
*/
|
||||
if (map_dev(arcn, (u_long)CPIO_MASK, (u_long)CPIO_MASK) < 0)
|
||||
return(-1);
|
||||
return -1;
|
||||
|
||||
arcn->pad = 0L;
|
||||
nsz = arcn->nlen + 1;
|
||||
|
@ -409,23 +404,18 @@ cpio_wr(ARCHD *arcn)
|
|||
/*
|
||||
* set data size for file data
|
||||
*/
|
||||
# ifdef NET2_STAT
|
||||
if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize,
|
||||
if (OFFT_ASC(arcn->sb.st_size, hd->c_filesize,
|
||||
sizeof(hd->c_filesize), OCT)) {
|
||||
# else
|
||||
if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize,
|
||||
sizeof(hd->c_filesize), OCT)) {
|
||||
# endif
|
||||
paxwarn(1,"File is too large for cpio format %s",
|
||||
tty_warn(1,"File is too large for cpio format %s",
|
||||
arcn->org_name);
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case PAX_SLK:
|
||||
/*
|
||||
* set data size to hold link name
|
||||
*/
|
||||
if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize,
|
||||
if (u32_asc((uintmax_t)arcn->ln_nlen, hd->c_filesize,
|
||||
sizeof(hd->c_filesize), OCT))
|
||||
goto out;
|
||||
break;
|
||||
|
@ -433,7 +423,7 @@ cpio_wr(ARCHD *arcn)
|
|||
/*
|
||||
* all other file types have no file data
|
||||
*/
|
||||
if (ul_asc((u_long)0, hd->c_filesize, sizeof(hd->c_filesize),
|
||||
if (u32_asc((uintmax_t)0, hd->c_filesize, sizeof(hd->c_filesize),
|
||||
OCT))
|
||||
goto out;
|
||||
break;
|
||||
|
@ -442,24 +432,24 @@ cpio_wr(ARCHD *arcn)
|
|||
/*
|
||||
* copy the values to the header using octal ascii
|
||||
*/
|
||||
if (ul_asc((u_long)MAGIC, hd->c_magic, sizeof(hd->c_magic), OCT) ||
|
||||
ul_asc((u_long)arcn->sb.st_dev, hd->c_dev, sizeof(hd->c_dev),
|
||||
if (u32_asc((uintmax_t)MAGIC, hd->c_magic, sizeof(hd->c_magic), OCT) ||
|
||||
u32_asc((uintmax_t)arcn->sb.st_dev, hd->c_dev, sizeof(hd->c_dev),
|
||||
OCT) ||
|
||||
ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino),
|
||||
u32_asc((uintmax_t)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino),
|
||||
OCT) ||
|
||||
ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode),
|
||||
u32_asc((uintmax_t)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode),
|
||||
OCT) ||
|
||||
ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid),
|
||||
u32_asc((uintmax_t)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid),
|
||||
OCT) ||
|
||||
ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid),
|
||||
u32_asc((uintmax_t)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid),
|
||||
OCT) ||
|
||||
ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink),
|
||||
u32_asc((uintmax_t)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink),
|
||||
OCT) ||
|
||||
ul_asc((u_long)arcn->sb.st_rdev, hd->c_rdev, sizeof(hd->c_rdev),
|
||||
u32_asc((uintmax_t)arcn->sb.st_rdev, hd->c_rdev, sizeof(hd->c_rdev),
|
||||
OCT) ||
|
||||
ul_asc((u_long)arcn->sb.st_mtime,hd->c_mtime,sizeof(hd->c_mtime),
|
||||
u32_asc((uintmax_t)arcn->sb.st_mtime,hd->c_mtime,sizeof(hd->c_mtime),
|
||||
OCT) ||
|
||||
ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), OCT))
|
||||
u32_asc((uintmax_t)nsz, hd->c_namesize, sizeof(hd->c_namesize), OCT))
|
||||
goto out;
|
||||
|
||||
/*
|
||||
|
@ -467,37 +457,38 @@ cpio_wr(ARCHD *arcn)
|
|||
*/
|
||||
if ((wr_rdbuf(hdblk, (int)sizeof(HD_CPIO)) < 0) ||
|
||||
(wr_rdbuf(arcn->name, nsz) < 0)) {
|
||||
paxwarn(1, "Unable to write cpio header for %s", arcn->org_name);
|
||||
return(-1);
|
||||
tty_warn(1, "Unable to write cpio header for %s",
|
||||
arcn->org_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* if this file has data, we are done. The caller will write the file
|
||||
* data, if we are link tell caller we are done, go to next file
|
||||
*/
|
||||
if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
|
||||
(arcn->type == PAX_HRG))
|
||||
return(0);
|
||||
if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG))
|
||||
return 0;
|
||||
if (arcn->type != PAX_SLK)
|
||||
return(1);
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* write the link name to the archive, tell the caller to go to the
|
||||
* next file as we are done.
|
||||
*/
|
||||
if (wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) {
|
||||
paxwarn(1,"Unable to write cpio link name for %s",arcn->org_name);
|
||||
return(-1);
|
||||
tty_warn(1,"Unable to write cpio link name for %s",
|
||||
arcn->org_name);
|
||||
return -1;
|
||||
}
|
||||
return(1);
|
||||
return 1;
|
||||
|
||||
out:
|
||||
/*
|
||||
* header field is out of range
|
||||
*/
|
||||
paxwarn(1, "Cpio header field is too small to store file %s",
|
||||
tty_warn(1, "Cpio header field is too small to store file %s",
|
||||
arcn->org_name);
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -506,11 +497,11 @@ cpio_wr(ARCHD *arcn)
|
|||
|
||||
/*
|
||||
* vcpio_id()
|
||||
* determine if a block given to us is a valid system VR4 cpio header
|
||||
* 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
|
||||
* uses HEX
|
||||
* Return:
|
||||
* 0 if a valid header, -1 otherwise
|
||||
* 0 if a valid header, -1 otherwise
|
||||
*/
|
||||
|
||||
int
|
||||
|
@ -518,39 +509,39 @@ vcpio_id(char *blk, int size)
|
|||
{
|
||||
if ((size < (int)sizeof(HD_VCPIO)) ||
|
||||
(strncmp(blk, AVMAGIC, sizeof(AVMAGIC) - 1) != 0))
|
||||
return(-1);
|
||||
return(0);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* crc_id()
|
||||
* determine if a block given to us is a valid system VR4 cpio header
|
||||
* determine if a block given to us is a valid system VR4 cpio header
|
||||
* WITH crc. WATCH it the magic cookies are in OCTAL the header uses HEX
|
||||
* Return:
|
||||
* 0 if a valid header, -1 otherwise
|
||||
* 0 if a valid header, -1 otherwise
|
||||
*/
|
||||
|
||||
int
|
||||
crc_id(char *blk, int size)
|
||||
{
|
||||
if ((size < (int)sizeof(HD_VCPIO)) ||
|
||||
(strncmp(blk, AVCMAGIC, (int)sizeof(AVCMAGIC) - 1) != 0))
|
||||
return(-1);
|
||||
return(0);
|
||||
(strncmp(blk, AVCMAGIC, sizeof(AVCMAGIC) - 1) != 0))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* crc_strd()
|
||||
w set file data CRC calculations. Fire up the hard link detection code
|
||||
* set file data CRC calculations. Fire up the hard link detection code
|
||||
* Return:
|
||||
* 0 if ok -1 otherwise (the return values of lnk_start())
|
||||
* 0 if ok -1 otherwise (the return values of lnk_start())
|
||||
*/
|
||||
|
||||
int
|
||||
crc_strd(void)
|
||||
{
|
||||
docrc = 1;
|
||||
return(lnk_start());
|
||||
return lnk_start();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -575,10 +566,10 @@ vcpio_rd(ARCHD *arcn, char *buf)
|
|||
*/
|
||||
if (docrc) {
|
||||
if (crc_id(buf, sizeof(HD_VCPIO)) < 0)
|
||||
return(-1);
|
||||
return -1;
|
||||
} else {
|
||||
if (vcpio_id(buf, sizeof(HD_VCPIO)) < 0)
|
||||
return(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
hd = (HD_VCPIO *)buf;
|
||||
|
@ -587,48 +578,39 @@ vcpio_rd(ARCHD *arcn, char *buf)
|
|||
/*
|
||||
* extract the hex ascii fields from the header
|
||||
*/
|
||||
arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), HEX);
|
||||
arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), HEX);
|
||||
arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), HEX);
|
||||
arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), HEX);
|
||||
#ifdef NET2_STAT
|
||||
arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime,sizeof(hd->c_mtime),HEX);
|
||||
#else
|
||||
arcn->sb.st_mtime = (time_t)asc_uqd(hd->c_mtime,sizeof(hd->c_mtime),HEX);
|
||||
#endif
|
||||
arcn->sb.st_ino = (ino_t)asc_u32(hd->c_ino, sizeof(hd->c_ino), HEX);
|
||||
arcn->sb.st_mode = (mode_t)asc_u32(hd->c_mode, sizeof(hd->c_mode), HEX);
|
||||
arcn->sb.st_uid = (uid_t)asc_u32(hd->c_uid, sizeof(hd->c_uid), HEX);
|
||||
arcn->sb.st_gid = (gid_t)asc_u32(hd->c_gid, sizeof(hd->c_gid), HEX);
|
||||
arcn->sb.st_mtime = (time_t)(int32_t)asc_u32(hd->c_mtime,sizeof(hd->c_mtime),HEX);
|
||||
arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
|
||||
#ifdef NET2_STAT
|
||||
arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,
|
||||
arcn->sb.st_size = (off_t)ASC_OFFT(hd->c_filesize,
|
||||
sizeof(hd->c_filesize), HEX);
|
||||
#else
|
||||
arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize,
|
||||
sizeof(hd->c_filesize), HEX);
|
||||
#endif
|
||||
arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink),
|
||||
arcn->sb.st_nlink = (nlink_t)asc_u32(hd->c_nlink, sizeof(hd->c_nlink),
|
||||
HEX);
|
||||
devmajor = (dev_t)asc_ul(hd->c_maj, sizeof(hd->c_maj), HEX);
|
||||
devminor = (dev_t)asc_ul(hd->c_min, sizeof(hd->c_min), HEX);
|
||||
devmajor = (dev_t)asc_u32(hd->c_maj, sizeof(hd->c_maj), HEX);
|
||||
devminor = (dev_t)asc_u32(hd->c_min, sizeof(hd->c_min), HEX);
|
||||
arcn->sb.st_dev = TODEV(devmajor, devminor);
|
||||
devmajor = (dev_t)asc_ul(hd->c_rmaj, sizeof(hd->c_maj), HEX);
|
||||
devminor = (dev_t)asc_ul(hd->c_rmin, sizeof(hd->c_min), HEX);
|
||||
devmajor = (dev_t)asc_u32(hd->c_rmaj, sizeof(hd->c_maj), HEX);
|
||||
devminor = (dev_t)asc_u32(hd->c_rmin, sizeof(hd->c_min), HEX);
|
||||
arcn->sb.st_rdev = TODEV(devmajor, devminor);
|
||||
arcn->crc = asc_ul(hd->c_chksum, sizeof(hd->c_chksum), HEX);
|
||||
arcn->crc = asc_u32(hd->c_chksum, sizeof(hd->c_chksum), HEX);
|
||||
|
||||
/*
|
||||
* check the length of the file name, if ok read it in, return -1 if
|
||||
* bogus
|
||||
*/
|
||||
if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),HEX)) < 2)
|
||||
return(-1);
|
||||
if ((nsz = (int)asc_u32(hd->c_namesize,sizeof(hd->c_namesize),HEX)) < 2)
|
||||
return -1;
|
||||
arcn->nlen = nsz - 1;
|
||||
if (rd_nm(arcn, nsz) < 0)
|
||||
return(-1);
|
||||
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);
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* if not a link (or a file with no data), calculate pad size (for
|
||||
|
@ -641,7 +623,7 @@ vcpio_rd(ARCHD *arcn, char *buf)
|
|||
arcn->ln_nlen = 0;
|
||||
arcn->ln_name[0] = '\0';
|
||||
arcn->pad = VCPIO_PAD(arcn->sb.st_size);
|
||||
return(com_rd(arcn));
|
||||
return com_rd(arcn);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -649,26 +631,26 @@ vcpio_rd(ARCHD *arcn, char *buf)
|
|||
*/
|
||||
if ((rd_ln_nm(arcn) < 0) ||
|
||||
(rd_skip((off_t)(VCPIO_PAD(arcn->sb.st_size))) < 0))
|
||||
return(-1);
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* we have a valid header (with a link)
|
||||
*/
|
||||
return(com_rd(arcn));
|
||||
return com_rd(arcn);
|
||||
}
|
||||
|
||||
/*
|
||||
* vcpio_endrd()
|
||||
* no cleanup needed here, just return size of the trailer (for append)
|
||||
* no cleanup needed here, just return size of the trailer (for append)
|
||||
* Return:
|
||||
* size of trailer header in this format
|
||||
* size of trailer header in this format
|
||||
*/
|
||||
|
||||
off_t
|
||||
vcpio_endrd(void)
|
||||
{
|
||||
return((off_t)(sizeof(HD_VCPIO) + sizeof(TRAILER) +
|
||||
(VCPIO_PAD(sizeof(HD_VCPIO) + sizeof(TRAILER)))));
|
||||
return (off_t)(sizeof(HD_VCPIO) + sizeof(TRAILER) +
|
||||
(VCPIO_PAD(sizeof(HD_VCPIO) + sizeof(TRAILER))));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -682,7 +664,7 @@ int
|
|||
crc_stwr(void)
|
||||
{
|
||||
docrc = 1;
|
||||
return(dev_start());
|
||||
return dev_start();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -706,7 +688,7 @@ vcpio_wr(ARCHD *arcn)
|
|||
* header
|
||||
*/
|
||||
if (map_dev(arcn, (u_long)VCPIO_MASK, (u_long)VCPIO_MASK) < 0)
|
||||
return(-1);
|
||||
return -1;
|
||||
nsz = arcn->nlen + 1;
|
||||
hd = (HD_VCPIO *)hdblk;
|
||||
if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
|
||||
|
@ -717,15 +699,15 @@ vcpio_wr(ARCHD *arcn)
|
|||
* file data crc's, and the crc if needed.
|
||||
*/
|
||||
if (docrc) {
|
||||
if (ul_asc((u_long)VCMAGIC, hd->c_magic, sizeof(hd->c_magic),
|
||||
OCT) ||
|
||||
ul_asc((u_long)arcn->crc,hd->c_chksum,sizeof(hd->c_chksum),
|
||||
HEX))
|
||||
if (u32_asc((uintmax_t)VCMAGIC, hd->c_magic, sizeof(hd->c_magic),
|
||||
OCT) ||
|
||||
u32_asc((uintmax_t)arcn->crc,hd->c_chksum,sizeof(hd->c_chksum),
|
||||
HEX))
|
||||
goto out;
|
||||
} else {
|
||||
if (ul_asc((u_long)VMAGIC, hd->c_magic, sizeof(hd->c_magic),
|
||||
OCT) ||
|
||||
ul_asc((u_long)0L, hd->c_chksum, sizeof(hd->c_chksum),HEX))
|
||||
if (u32_asc((uintmax_t)VMAGIC, hd->c_magic, sizeof(hd->c_magic),
|
||||
OCT) ||
|
||||
u32_asc((uintmax_t)0, hd->c_chksum, sizeof(hd->c_chksum),HEX))
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -738,16 +720,11 @@ vcpio_wr(ARCHD *arcn)
|
|||
* much to pad.
|
||||
*/
|
||||
arcn->pad = VCPIO_PAD(arcn->sb.st_size);
|
||||
# ifdef NET2_STAT
|
||||
if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize,
|
||||
if (OFFT_ASC(arcn->sb.st_size, hd->c_filesize,
|
||||
sizeof(hd->c_filesize), HEX)) {
|
||||
# else
|
||||
if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize,
|
||||
sizeof(hd->c_filesize), HEX)) {
|
||||
# endif
|
||||
paxwarn(1,"File is too large for sv4cpio format %s",
|
||||
tty_warn(1,"File is too large for sv4cpio format %s",
|
||||
arcn->org_name);
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case PAX_SLK:
|
||||
|
@ -756,7 +733,7 @@ vcpio_wr(ARCHD *arcn)
|
|||
* the size of the link
|
||||
*/
|
||||
arcn->pad = 0L;
|
||||
if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize,
|
||||
if (u32_asc((uintmax_t)arcn->ln_nlen, hd->c_filesize,
|
||||
sizeof(hd->c_filesize), HEX))
|
||||
goto out;
|
||||
break;
|
||||
|
@ -765,7 +742,7 @@ vcpio_wr(ARCHD *arcn)
|
|||
* no file data for the caller to process
|
||||
*/
|
||||
arcn->pad = 0L;
|
||||
if (ul_asc((u_long)0L, hd->c_filesize, sizeof(hd->c_filesize),
|
||||
if (u32_asc((uintmax_t)0, hd->c_filesize, sizeof(hd->c_filesize),
|
||||
HEX))
|
||||
goto out;
|
||||
break;
|
||||
|
@ -774,27 +751,27 @@ vcpio_wr(ARCHD *arcn)
|
|||
/*
|
||||
* set the other fields in the header
|
||||
*/
|
||||
if (ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino),
|
||||
if (u32_asc((uintmax_t)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino),
|
||||
HEX) ||
|
||||
ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode),
|
||||
u32_asc((uintmax_t)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode),
|
||||
HEX) ||
|
||||
ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid),
|
||||
u32_asc((uintmax_t)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) ||
|
||||
ul_asc((u_long)arcn->sb.st_mtime, hd->c_mtime, sizeof(hd->c_mtime),
|
||||
HEX) ||
|
||||
ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink),
|
||||
HEX) ||
|
||||
ul_asc((u_long)major(arcn->sb.st_dev),hd->c_maj, sizeof(hd->c_maj),
|
||||
u32_asc((uintmax_t)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid),
|
||||
HEX) ||
|
||||
ul_asc((u_long)minor(arcn->sb.st_dev),hd->c_min, sizeof(hd->c_min),
|
||||
u32_asc((uintmax_t)arcn->sb.st_mtime, hd->c_mtime, sizeof(hd->c_mtime),
|
||||
HEX) ||
|
||||
ul_asc((u_long)major(arcn->sb.st_rdev),hd->c_rmaj,sizeof(hd->c_maj),
|
||||
u32_asc((uintmax_t)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink),
|
||||
HEX) ||
|
||||
ul_asc((u_long)minor(arcn->sb.st_rdev),hd->c_rmin,sizeof(hd->c_min),
|
||||
u32_asc((uintmax_t)MAJOR(arcn->sb.st_dev),hd->c_maj, sizeof(hd->c_maj),
|
||||
HEX) ||
|
||||
ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), HEX))
|
||||
u32_asc((uintmax_t)MINOR(arcn->sb.st_dev),hd->c_min, sizeof(hd->c_min),
|
||||
HEX) ||
|
||||
u32_asc((uintmax_t)MAJOR(arcn->sb.st_rdev),hd->c_rmaj,sizeof(hd->c_maj),
|
||||
HEX) ||
|
||||
u32_asc((uintmax_t)MINOR(arcn->sb.st_rdev),hd->c_rmin,sizeof(hd->c_min),
|
||||
HEX) ||
|
||||
u32_asc((uintmax_t)nsz, hd->c_namesize, sizeof(hd->c_namesize), HEX))
|
||||
goto out;
|
||||
|
||||
/*
|
||||
|
@ -803,8 +780,9 @@ vcpio_wr(ARCHD *arcn)
|
|||
if ((wr_rdbuf(hdblk, (int)sizeof(HD_VCPIO)) < 0) ||
|
||||
(wr_rdbuf(arcn->name, (int)nsz) < 0) ||
|
||||
(wr_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)) {
|
||||
paxwarn(1,"Could not write sv4cpio header for %s",arcn->org_name);
|
||||
return(-1);
|
||||
tty_warn(1,"Could not write sv4cpio header for %s",
|
||||
arcn->org_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -812,31 +790,32 @@ vcpio_wr(ARCHD *arcn)
|
|||
*/
|
||||
if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
|
||||
(arcn->type == PAX_HRG))
|
||||
return(0);
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* if we are not a link, tell the caller we are done, go to next file
|
||||
*/
|
||||
if (arcn->type != PAX_SLK)
|
||||
return(1);
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* write the link name, tell the caller we are done.
|
||||
*/
|
||||
if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) ||
|
||||
(wr_skip((off_t)(VCPIO_PAD(arcn->ln_nlen))) < 0)) {
|
||||
paxwarn(1,"Could not write sv4cpio link name for %s",
|
||||
tty_warn(1,"Could not write sv4cpio link name for %s",
|
||||
arcn->org_name);
|
||||
return(-1);
|
||||
return -1;
|
||||
}
|
||||
return(1);
|
||||
return 1;
|
||||
|
||||
out:
|
||||
/*
|
||||
* header field is out of range
|
||||
*/
|
||||
paxwarn(1,"Sv4cpio header field is too small for file %s",arcn->org_name);
|
||||
return(1);
|
||||
tty_warn(1,"Sv4cpio header field is too small for file %s",
|
||||
arcn->org_name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -845,34 +824,34 @@ vcpio_wr(ARCHD *arcn)
|
|||
|
||||
/*
|
||||
* bcpio_id()
|
||||
* determine if a block given to us is an old binary cpio header
|
||||
* determine if a block given to us is a old binary cpio header
|
||||
* (with/without header byte swapping)
|
||||
* Return:
|
||||
* 0 if a valid header, -1 otherwise
|
||||
* 0 if a valid header, -1 otherwise
|
||||
*/
|
||||
|
||||
int
|
||||
bcpio_id(char *blk, int size)
|
||||
{
|
||||
if (size < (int)sizeof(HD_BCPIO))
|
||||
return(-1);
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* check both normal and byte swapped magic cookies
|
||||
*/
|
||||
if (((u_short)SHRT_EXT(blk)) == MAGIC)
|
||||
return(0);
|
||||
return 0;
|
||||
if (((u_short)RSHRT_EXT(blk)) == MAGIC) {
|
||||
if (!swp_head)
|
||||
++swp_head;
|
||||
return(0);
|
||||
if (!cpio_swp_head)
|
||||
++cpio_swp_head;
|
||||
return 0;
|
||||
}
|
||||
return(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* bcpio_rd()
|
||||
* determine if a buffer is an old binary archive entry. (It may have byte
|
||||
* determine if a buffer is a old binary archive entry. (it may have byte
|
||||
* swapped header) convert and store the values in the ARCHD parameter.
|
||||
* This is a very old header format and should not really be used.
|
||||
* Return:
|
||||
|
@ -889,11 +868,11 @@ bcpio_rd(ARCHD *arcn, char *buf)
|
|||
* check the header
|
||||
*/
|
||||
if (bcpio_id(buf, sizeof(HD_BCPIO)) < 0)
|
||||
return(-1);
|
||||
return -1;
|
||||
|
||||
arcn->pad = 0L;
|
||||
hd = (HD_BCPIO *)buf;
|
||||
if (swp_head) {
|
||||
if (cpio_swp_head) {
|
||||
/*
|
||||
* header has swapped bytes on 16 bit boundaries
|
||||
*/
|
||||
|
@ -934,16 +913,16 @@ bcpio_rd(ARCHD *arcn, char *buf)
|
|||
* name
|
||||
*/
|
||||
if (nsz < 2)
|
||||
return(-1);
|
||||
return -1;
|
||||
arcn->nlen = nsz - 1;
|
||||
if (rd_nm(arcn, nsz) < 0)
|
||||
return(-1);
|
||||
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);
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* if not a link (or a file with no data), calculate pad size (for
|
||||
|
@ -956,41 +935,41 @@ bcpio_rd(ARCHD *arcn, char *buf)
|
|||
arcn->ln_nlen = 0;
|
||||
arcn->ln_name[0] = '\0';
|
||||
arcn->pad = BCPIO_PAD(arcn->sb.st_size);
|
||||
return(com_rd(arcn));
|
||||
return com_rd(arcn);
|
||||
}
|
||||
|
||||
if ((rd_ln_nm(arcn) < 0) ||
|
||||
(rd_skip((off_t)(BCPIO_PAD(arcn->sb.st_size))) < 0))
|
||||
return(-1);
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* we have a valid header (with a link)
|
||||
*/
|
||||
return(com_rd(arcn));
|
||||
return com_rd(arcn);
|
||||
}
|
||||
|
||||
/*
|
||||
* bcpio_endrd()
|
||||
* no cleanup needed here, just return size of the trailer (for append)
|
||||
* no cleanup needed here, just return size of the trailer (for append)
|
||||
* Return:
|
||||
* size of trailer header in this format
|
||||
* size of trailer header in this format
|
||||
*/
|
||||
|
||||
off_t
|
||||
bcpio_endrd(void)
|
||||
{
|
||||
return((off_t)(sizeof(HD_BCPIO) + sizeof(TRAILER) +
|
||||
(BCPIO_PAD(sizeof(HD_BCPIO) + sizeof(TRAILER)))));
|
||||
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
|
||||
* 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
|
||||
*/
|
||||
|
||||
|
@ -1009,7 +988,7 @@ bcpio_wr(ARCHD *arcn)
|
|||
* header
|
||||
*/
|
||||
if (map_dev(arcn, (u_long)BCPIO_MASK, (u_long)BCPIO_MASK) < 0)
|
||||
return(-1);
|
||||
return -1;
|
||||
|
||||
if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
|
||||
arcn->sb.st_rdev = 0;
|
||||
|
@ -1031,9 +1010,9 @@ bcpio_wr(ARCHD *arcn)
|
|||
t_offt = (off_t)(SHRT_EXT(hd->h_filesize_1));
|
||||
t_offt = (t_offt<<16) | ((off_t)(SHRT_EXT(hd->h_filesize_2)));
|
||||
if (arcn->sb.st_size != t_offt) {
|
||||
paxwarn(1,"File is too large for bcpio format %s",
|
||||
tty_warn(1,"File is too large for bcpio format %s",
|
||||
arcn->org_name);
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case PAX_SLK:
|
||||
|
@ -1116,8 +1095,9 @@ bcpio_wr(ARCHD *arcn)
|
|||
if ((wr_rdbuf(hdblk, (int)sizeof(HD_BCPIO)) < 0) ||
|
||||
(wr_rdbuf(arcn->name, nsz) < 0) ||
|
||||
(wr_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)) {
|
||||
paxwarn(1, "Could not write bcpio header for %s", arcn->org_name);
|
||||
return(-1);
|
||||
tty_warn(1, "Could not write bcpio header for %s",
|
||||
arcn->org_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1125,28 +1105,30 @@ bcpio_wr(ARCHD *arcn)
|
|||
*/
|
||||
if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
|
||||
(arcn->type == PAX_HRG))
|
||||
return(0);
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* if we are not a link, tell the caller we are done, go to next file
|
||||
*/
|
||||
if (arcn->type != PAX_SLK)
|
||||
return(1);
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* write the link name, tell the caller we are done.
|
||||
*/
|
||||
if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) ||
|
||||
(wr_skip((off_t)(BCPIO_PAD(arcn->ln_nlen))) < 0)) {
|
||||
paxwarn(1,"Could not write bcpio link name for %s",arcn->org_name);
|
||||
return(-1);
|
||||
tty_warn(1,"Could not write bcpio link name for %s",
|
||||
arcn->org_name);
|
||||
return -1;
|
||||
}
|
||||
return(1);
|
||||
return 1;
|
||||
|
||||
out:
|
||||
/*
|
||||
* header field is out of range
|
||||
*/
|
||||
paxwarn(1,"Bcpio header field is too small for file %s", arcn->org_name);
|
||||
return(1);
|
||||
tty_warn(1,"Bcpio header field is too small for file %s",
|
||||
arcn->org_name);
|
||||
return 1;
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
/* $NetBSD: cpio.h,v 1.6 2003/10/13 07:41:22 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -14,7 +16,7 @@
|
|||
* 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.
|
||||
* 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.
|
||||
*
|
||||
|
@ -31,7 +33,6 @@
|
|||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)cpio.h 8.1 (Berkeley) 5/31/93
|
||||
* $FreeBSD: src/bin/pax/cpio.h,v 1.7 2004/04/06 20:06:48 markm Exp $
|
||||
*/
|
||||
|
||||
/*
|
122
bin/pax/dumptar.c
Normal file
122
bin/pax/dumptar.c
Normal file
|
@ -0,0 +1,122 @@
|
|||
/* $NetBSD: dumptar.c,v 1.2 2008/04/28 20:22:51 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2004 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Christos Zoulas.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "tar.h"
|
||||
|
||||
#define ussum(a) 1
|
||||
|
||||
static char *
|
||||
buf(const char *p, size_t s)
|
||||
{
|
||||
static char buf[1024];
|
||||
(void)snprintf(buf, sizeof(buf), "%s", p);
|
||||
buf[s] = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
int
|
||||
intarg(const char *p, size_t s)
|
||||
{
|
||||
char *ep, *b = buf(p, s);
|
||||
int r = (int)strtol(p, &ep, 8);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
usdump(void *p)
|
||||
{
|
||||
HD_USTAR *t = p;
|
||||
int size = intarg(t->size, sizeof(t->size));
|
||||
size = ((size + 511) / 512) * 512 + 512;
|
||||
|
||||
(void)fprintf(stdout, "*****\n");
|
||||
#define PR(a) \
|
||||
(void)fprintf(stdout, #a "=%s\n", buf(t->a, sizeof(t->a)));
|
||||
#define IPR(a) \
|
||||
(void)fprintf(stdout, #a "=%d\n", intarg(t->a, sizeof(t->a)));
|
||||
#define OPR(a) \
|
||||
(void)fprintf(stdout, #a "=%o\n", intarg(t->a, sizeof(t->a)));
|
||||
PR(name);
|
||||
OPR(mode);
|
||||
IPR(uid);
|
||||
IPR(gid);
|
||||
IPR(size);
|
||||
OPR(mtime);
|
||||
OPR(chksum);
|
||||
(void)fprintf(stdout, "typeflag=%c\n", t->typeflag);
|
||||
PR(linkname);
|
||||
PR(magic);
|
||||
PR(version);
|
||||
PR(uname);
|
||||
PR(gname);
|
||||
OPR(devmajor);
|
||||
OPR(devminor);
|
||||
PR(prefix);
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int fd;
|
||||
struct stat st;
|
||||
char *p, *ep;
|
||||
|
||||
if (argc != 2) {
|
||||
(void)fprintf(stderr, "Usage: %s <filename>\n", getprogname());
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((fd = open(argv[1], O_RDONLY)) == -1)
|
||||
err(1, "Cannot open `%s'", argv[1]);
|
||||
|
||||
if (fstat(fd, &st) == -1)
|
||||
err(1, "Cannot fstat `%s'", argv[1]);
|
||||
|
||||
if ((p = mmap(NULL, (size_t)st.st_size, PROT_READ,
|
||||
MAP_FILE|MAP_PRIVATE, fd, (off_t)0)) == MAP_FAILED)
|
||||
err(1, "Cannot mmap `%s'", argv[1]);
|
||||
(void)close(fd);
|
||||
|
||||
ep = (char *)p + (size_t)st.st_size;
|
||||
|
||||
for (; p < ep + sizeof(HD_USTAR);) {
|
||||
if (ussum(p))
|
||||
p += usdump(p);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
/* $NetBSD: extern.h,v 1.59 2012/08/09 08:09:21 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -14,7 +16,7 @@
|
|||
* 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.
|
||||
* 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.
|
||||
*
|
||||
|
@ -31,39 +33,64 @@
|
|||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)extern.h 8.2 (Berkeley) 4/18/94
|
||||
* $FreeBSD: src/bin/pax/extern.h,v 1.16 2005/01/12 03:25:55 brian Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* External references from each source file
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <err.h>
|
||||
|
||||
/*
|
||||
* ar_io.c
|
||||
*/
|
||||
extern const char *arcname;
|
||||
extern int curdirfd;
|
||||
extern const char *gzip_program;
|
||||
extern time_t starttime;
|
||||
extern int force_one_volume;
|
||||
extern char *chdname;
|
||||
extern int forcelocal;
|
||||
extern int secure;
|
||||
|
||||
int ar_open(const char *);
|
||||
void ar_close(void);
|
||||
void ar_drain(void);
|
||||
int ar_set_wr(void);
|
||||
int ar_app_ok(void);
|
||||
#ifdef SYS_NO_RESTART
|
||||
int read_with_restart(int, void *, int);
|
||||
int write_with_restart(int, void *, int);
|
||||
#else
|
||||
#define read_with_restart read
|
||||
#define write_with_restart write
|
||||
#endif
|
||||
int xread(int, void *, int);
|
||||
int xwrite(int, void *, int);
|
||||
int ar_read(char *, int);
|
||||
int ar_write(char *, int);
|
||||
int ar_rdsync(void);
|
||||
int ar_fow(off_t, off_t *);
|
||||
int ar_rev(off_t );
|
||||
int ar_next(void);
|
||||
void ar_summary(int);
|
||||
int ar_dochdir(const char *);
|
||||
|
||||
/*
|
||||
* ar_subs.c
|
||||
*/
|
||||
extern u_long flcnt;
|
||||
void list(void);
|
||||
void extract(void);
|
||||
void append(void);
|
||||
void archive(void);
|
||||
void copy(void);
|
||||
extern ARCHD archd;
|
||||
int updatepath(void);
|
||||
int dochdir(const char *);
|
||||
int fdochdir(int);
|
||||
int domkdir(const char *, mode_t);
|
||||
int list(void);
|
||||
int extract(void);
|
||||
int append(void);
|
||||
int archive(void);
|
||||
int copy(void);
|
||||
|
||||
/*
|
||||
* buf_subs.c
|
||||
|
@ -92,23 +119,12 @@ void cp_file(ARCHD *, int, int);
|
|||
int buf_fill(void);
|
||||
int buf_flush(int);
|
||||
|
||||
/*
|
||||
* cache.c
|
||||
*/
|
||||
int uidtb_start(void);
|
||||
int gidtb_start(void);
|
||||
int usrtb_start(void);
|
||||
int grptb_start(void);
|
||||
const char * name_uid(uid_t, int);
|
||||
const char * name_gid(gid_t, int);
|
||||
int uid_name(char *, uid_t *);
|
||||
int gid_name(char *, gid_t *);
|
||||
|
||||
/*
|
||||
* cpio.c
|
||||
*/
|
||||
extern int cpio_swp_head;
|
||||
int cpio_strd(void);
|
||||
int cpio_trail(ARCHD *);
|
||||
int cpio_subtrail(ARCHD *);
|
||||
int cpio_endwr(void);
|
||||
int cpio_id(char *, int);
|
||||
int cpio_rd(ARCHD *, char *);
|
||||
|
@ -130,18 +146,21 @@ int bcpio_wr(ARCHD *);
|
|||
/*
|
||||
* file_subs.c
|
||||
*/
|
||||
int file_creat(ARCHD *);
|
||||
extern char *gnu_name_string, *gnu_link_string;
|
||||
extern size_t gnu_name_length, gnu_link_length;
|
||||
extern char *xtmp_name;
|
||||
int file_creat(ARCHD *, int);
|
||||
void file_close(ARCHD *, int);
|
||||
int lnk_creat(ARCHD *);
|
||||
int lnk_creat(ARCHD *, int *);
|
||||
int cross_lnk(ARCHD *);
|
||||
int chk_same(ARCHD *);
|
||||
int node_creat(ARCHD *);
|
||||
int unlnk_exist(char *, int);
|
||||
int chk_path(char *, uid_t, gid_t);
|
||||
void set_ftime(char *fnm, time_t mtime, time_t atime, int frc);
|
||||
void set_ftime(char *fnm, time_t mtime, time_t atime, int frc, int slk);
|
||||
int set_ids(char *, uid_t, gid_t);
|
||||
int set_lids(char *, uid_t, gid_t);
|
||||
void set_pmode(char *, mode_t);
|
||||
void set_chflags(char *fnm, u_int32_t flags);
|
||||
int file_write(int, char *, int, int *, int *, int, char *);
|
||||
void file_flush(int, char *, int);
|
||||
void rdfile_close(ARCHD *, int *);
|
||||
|
@ -153,7 +172,6 @@ int set_crc(ARCHD *, int);
|
|||
int ftree_start(void);
|
||||
int ftree_add(char *, int);
|
||||
void ftree_sel(ARCHD *);
|
||||
void ftree_notsel(void);
|
||||
void ftree_chk(void);
|
||||
int next_file(ARCHD *);
|
||||
|
||||
|
@ -162,39 +180,44 @@ int next_file(ARCHD *);
|
|||
*/
|
||||
void ls_list(ARCHD *, time_t, FILE *);
|
||||
void ls_tty(ARCHD *);
|
||||
int l_strncpy(char *, const char *, int);
|
||||
u_long asc_ul(char *, int, int);
|
||||
int ul_asc(u_long, char *, int, int);
|
||||
#ifndef NET2_STAT
|
||||
u_quad_t asc_uqd(char *, int, int);
|
||||
int uqd_asc(u_quad_t, char *, int, int);
|
||||
#endif
|
||||
void safe_print(const char *, FILE *);
|
||||
uint32_t asc_u32(char *, int, int);
|
||||
int u32_asc(uintmax_t, char *, int, int);
|
||||
uintmax_t asc_umax(char *, int, int);
|
||||
int umax_asc(uintmax_t, char *, int, int);
|
||||
int check_Aflag(void);
|
||||
|
||||
/*
|
||||
* getoldopt.c
|
||||
*/
|
||||
int getoldopt(int, char **, const char *);
|
||||
struct option;
|
||||
int getoldopt(int, char **, const char *, struct option *, int *);
|
||||
|
||||
/*
|
||||
* options.c
|
||||
*/
|
||||
extern FSUB fsub[];
|
||||
extern int ford[];
|
||||
extern int sep;
|
||||
extern int havechd;
|
||||
void options(int, char **);
|
||||
OPLIST * opt_next(void);
|
||||
int opt_add(const char *);
|
||||
int bad_opt(void);
|
||||
int mkpath(char *);
|
||||
char *chdname;
|
||||
#if !HAVE_NBTOOL_CONFIG_H
|
||||
int do_chroot;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* pat_rep.c
|
||||
*/
|
||||
int rep_add(char *);
|
||||
int pat_add(char *, char *);
|
||||
int pat_add(char *, char *, int);
|
||||
void pat_chk(void);
|
||||
int pat_sel(ARCHD *);
|
||||
int pat_match(ARCHD *);
|
||||
int mod_name(ARCHD *);
|
||||
int mod_name(ARCHD *, int);
|
||||
int set_dest(ARCHD *, char *, int);
|
||||
|
||||
/*
|
||||
|
@ -202,6 +225,7 @@ int set_dest(ARCHD *, char *, int);
|
|||
*/
|
||||
extern int act;
|
||||
extern FSUB *frmt;
|
||||
extern int Aflag;
|
||||
extern int cflag;
|
||||
extern int cwdfd;
|
||||
extern int dflag;
|
||||
|
@ -215,6 +239,8 @@ extern int vflag;
|
|||
extern int Dflag;
|
||||
extern int Hflag;
|
||||
extern int Lflag;
|
||||
extern int Mflag;
|
||||
extern int Vflag;
|
||||
extern int Xflag;
|
||||
extern int Yflag;
|
||||
extern int Zflag;
|
||||
|
@ -222,19 +248,20 @@ extern int vfpart;
|
|||
extern int patime;
|
||||
extern int pmtime;
|
||||
extern int nodirs;
|
||||
extern int pfflags;
|
||||
extern int pmode;
|
||||
extern int pids;
|
||||
extern int rmleadslash;
|
||||
extern int exit_val;
|
||||
extern int docrc;
|
||||
extern int to_stdout;
|
||||
extern char *dirptr;
|
||||
extern char *ltmfrmt;
|
||||
extern const char *argv0;
|
||||
extern FILE *listf;
|
||||
extern char *tempfile;
|
||||
extern char *tempbase;
|
||||
|
||||
void sig_cleanup(int);
|
||||
|
||||
/*
|
||||
* sel_subs.c
|
||||
*/
|
||||
|
@ -270,6 +297,7 @@ u_int st_hash(char *, int, int);
|
|||
/*
|
||||
* tar.c
|
||||
*/
|
||||
extern int is_gnutar;
|
||||
int tar_endwr(void);
|
||||
off_t tar_endrd(void);
|
||||
int tar_trail(char *, int, int *);
|
||||
|
@ -282,12 +310,17 @@ int ustar_stwr(void);
|
|||
int ustar_id(char *, int);
|
||||
int ustar_rd(ARCHD *, char *);
|
||||
int ustar_wr(ARCHD *);
|
||||
int tar_gnutar_X_compat(const char *);
|
||||
int tar_gnutar_minus_minus_exclude(const char *);
|
||||
|
||||
/*
|
||||
* tty_subs.c
|
||||
*/
|
||||
int tty_init(void);
|
||||
void tty_prnt(const char *, ...);
|
||||
void tty_prnt(const char *, ...)
|
||||
__attribute__((format (printf, 1, 2)));
|
||||
int tty_read(char *, int);
|
||||
void paxwarn(int, const char *, ...);
|
||||
void syswarn(int, int, const char *, ...);
|
||||
void tty_warn(int, const char *, ...)
|
||||
__attribute__((format (printf, 2, 3)));
|
||||
void syswarn(int, int, const char *, ...)
|
||||
__attribute__((format (printf, 3, 4)));
|
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,5 @@
|
|||
/* $NetBSD: ftree.c,v 1.42 2012/09/27 00:44:59 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -14,7 +16,7 @@
|
|||
* 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.
|
||||
* 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.
|
||||
*
|
||||
|
@ -31,24 +33,66 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Luke Mewburn of Wasabi Systems.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)ftree.c 8.2 (Berkeley) 4/18/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: ftree.c,v 1.42 2012/09/27 00:44:59 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/param.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <fts.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "pax.h"
|
||||
#include "ftree.h"
|
||||
#include "extern.h"
|
||||
#include "options.h"
|
||||
#ifndef SMALL
|
||||
#include "mtree.h"
|
||||
#endif /* SMALL */
|
||||
|
||||
/*
|
||||
* routines to interface with the fts library function.
|
||||
|
@ -72,9 +116,14 @@ static FTREE *fttail = NULL; /* tail of linked list of file args */
|
|||
static FTREE *ftcur = NULL; /* current file arg being processed */
|
||||
static FTSENT *ftent = NULL; /* current file tree entry */
|
||||
static int ftree_skip; /* when set skip to next file arg */
|
||||
#ifndef SMALL
|
||||
static NODE *ftnode = NULL; /* mtree(8) specfile; used by -M */
|
||||
#endif /* SMALL */
|
||||
|
||||
static int ftree_arg(void);
|
||||
|
||||
#define FTS_ERRNO(x) (x)->fts_errno
|
||||
|
||||
/*
|
||||
* ftree_start()
|
||||
* initialize the options passed to fts_open() during this run of pax
|
||||
|
@ -88,11 +137,35 @@ static int ftree_arg(void);
|
|||
int
|
||||
ftree_start(void)
|
||||
{
|
||||
|
||||
#ifndef SMALL
|
||||
/*
|
||||
* Set up the operation mode of fts, open the first file arg. We must
|
||||
* if -M is given, the list of filenames on stdin is actually
|
||||
* an mtree(8) specfile, so parse the specfile into a NODE *
|
||||
* tree at ftnode, for use by next_file()
|
||||
*/
|
||||
if (Mflag) {
|
||||
if (fthead != NULL) {
|
||||
tty_warn(1,
|
||||
"The -M flag is only supported when reading file list from stdin");
|
||||
return -1;
|
||||
}
|
||||
ftnode = spec(stdin);
|
||||
if (ftnode != NULL &&
|
||||
(ftnode->type != F_DIR || strcmp(ftnode->name, ".") != 0)) {
|
||||
tty_warn(1,
|
||||
"First node of specfile is not `.' directory");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* SMALL */
|
||||
|
||||
/*
|
||||
* set up the operation mode of fts, open the first file arg. We must
|
||||
* use FTS_NOCHDIR, as the user may have to open multiple archives and
|
||||
* if fts did a chdir off into the boondocks, we may create an archive
|
||||
* volume in a place where the user did not expect to.
|
||||
* volume in an place where the user did not expect to.
|
||||
*/
|
||||
ftsopts = FTS_NOCHDIR;
|
||||
|
||||
|
@ -111,24 +184,20 @@ ftree_start(void)
|
|||
else
|
||||
ftsopts |= FTS_PHYSICAL;
|
||||
if (Hflag)
|
||||
# ifdef NET2_FTS
|
||||
paxwarn(0, "The -H flag is not supported on this version");
|
||||
# else
|
||||
ftsopts |= FTS_COMFOLLOW;
|
||||
# endif
|
||||
if (Xflag)
|
||||
ftsopts |= FTS_XDEV;
|
||||
|
||||
if ((fthead == NULL) && ((farray[0] = malloc(PAXPATHLEN+2)) == NULL)) {
|
||||
paxwarn(1, "Unable to allocate memory for file name buffer");
|
||||
return(-1);
|
||||
tty_warn(1, "Unable to allocate memory for file name buffer");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ftree_arg() < 0)
|
||||
return(-1);
|
||||
return -1;
|
||||
if (tflag && (atdir_start() < 0))
|
||||
return(-1);
|
||||
return(0);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -140,7 +209,7 @@ ftree_start(void)
|
|||
*/
|
||||
|
||||
int
|
||||
ftree_add(char *str, int chflg)
|
||||
ftree_add(char *str, int isdir)
|
||||
{
|
||||
FTREE *ft;
|
||||
int len;
|
||||
|
@ -149,8 +218,8 @@ ftree_add(char *str, int chflg)
|
|||
* simple check for bad args
|
||||
*/
|
||||
if ((str == NULL) || (*str == '\0')) {
|
||||
paxwarn(0, "Invalid file name argument");
|
||||
return(-1);
|
||||
tty_warn(0, "Invalid file name argument");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -159,23 +228,22 @@ ftree_add(char *str, int chflg)
|
|||
* trailing / the user may pass us. (watch out for / by itself).
|
||||
*/
|
||||
if ((ft = (FTREE *)malloc(sizeof(FTREE))) == NULL) {
|
||||
paxwarn(0, "Unable to allocate memory for filename");
|
||||
return(-1);
|
||||
tty_warn(0, "Unable to allocate memory for filename");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (((len = strlen(str) - 1) > 0) && (str[len] == '/'))
|
||||
str[len] = '\0';
|
||||
ft->fname = str;
|
||||
ft->refcnt = 0;
|
||||
ft->chflg = chflg;
|
||||
ft->refcnt = -isdir;
|
||||
ft->fow = NULL;
|
||||
if (fthead == NULL) {
|
||||
fttail = fthead = ft;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
fttail->fow = ft;
|
||||
fttail = ft;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -198,31 +266,20 @@ ftree_sel(ARCHD *arcn)
|
|||
/*
|
||||
* if -n we are done with this arg, force a skip to the next arg when
|
||||
* pax asks for the next file in next_file().
|
||||
* if -M we don't use fts(3), so the rest of this function is moot.
|
||||
* if -d we tell fts only to match the directory (if the arg is a dir)
|
||||
* and not the entire file tree rooted at that point.
|
||||
*/
|
||||
if (nflag)
|
||||
ftree_skip = 1;
|
||||
|
||||
if (!dflag || (arcn->type != PAX_DIR))
|
||||
if (Mflag || !dflag || (arcn->type != PAX_DIR))
|
||||
return;
|
||||
|
||||
if (ftent != NULL)
|
||||
(void)fts_set(ftsp, ftent, FTS_SKIP);
|
||||
}
|
||||
|
||||
/*
|
||||
* ftree_notsel()
|
||||
* this entry has not been selected by pax.
|
||||
*/
|
||||
|
||||
void
|
||||
ftree_notsel()
|
||||
{
|
||||
if (ftent != NULL)
|
||||
(void)fts_set(ftsp, ftent, FTS_SKIP);
|
||||
}
|
||||
|
||||
/*
|
||||
* ftree_chk()
|
||||
* called at end on pax execution. Prints all those file args that did not
|
||||
|
@ -246,10 +303,11 @@ ftree_chk(void)
|
|||
* that never had a match
|
||||
*/
|
||||
for (ft = fthead; ft != NULL; ft = ft->fow) {
|
||||
if ((ft->refcnt > 0) || ft->chflg)
|
||||
if (ft->refcnt != 0)
|
||||
continue;
|
||||
if (wban == 0) {
|
||||
paxwarn(1,"WARNING! These file names were not selected:");
|
||||
tty_warn(1,
|
||||
"WARNING! These file names were not selected:");
|
||||
++wban;
|
||||
}
|
||||
(void)fprintf(stderr, "%s\n", ft->fname);
|
||||
|
@ -269,14 +327,13 @@ ftree_chk(void)
|
|||
static int
|
||||
ftree_arg(void)
|
||||
{
|
||||
char *pt;
|
||||
|
||||
/*
|
||||
* close off the current file tree
|
||||
*/
|
||||
if (ftsp != NULL) {
|
||||
(void)fts_close(ftsp);
|
||||
ftsp = NULL;
|
||||
ftent = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -285,14 +342,24 @@ ftree_arg(void)
|
|||
*/
|
||||
for(;;) {
|
||||
if (fthead == NULL) {
|
||||
int i, c = EOF;
|
||||
/*
|
||||
* the user didn't supply any args, get the file trees
|
||||
* to process from stdin;
|
||||
*/
|
||||
if (fgets(farray[0], PAXPATHLEN+1, stdin) == NULL)
|
||||
return(-1);
|
||||
if ((pt = strchr(farray[0], '\n')) != NULL)
|
||||
*pt = '\0';
|
||||
for (i = 0; i < PAXPATHLEN + 2;) {
|
||||
c = getchar();
|
||||
if (c == EOF)
|
||||
break;
|
||||
else if (c == sep) {
|
||||
if (i != 0)
|
||||
break;
|
||||
} else
|
||||
farray[0][i++] = c;
|
||||
}
|
||||
if (i == 0)
|
||||
return -1;
|
||||
farray[0][i] = '\0';
|
||||
} else {
|
||||
/*
|
||||
* the user supplied the file args as arguments to pax
|
||||
|
@ -300,27 +367,23 @@ ftree_arg(void)
|
|||
if (ftcur == NULL)
|
||||
ftcur = fthead;
|
||||
else if ((ftcur = ftcur->fow) == NULL)
|
||||
return(-1);
|
||||
if (ftcur->chflg) {
|
||||
/* First fchdir() back... */
|
||||
if (fchdir(cwdfd) < 0) {
|
||||
syswarn(1, errno,
|
||||
"Can't fchdir to starting directory");
|
||||
return(-1);
|
||||
}
|
||||
if (chdir(ftcur->fname) < 0) {
|
||||
syswarn(1, errno, "Can't chdir to %s",
|
||||
ftcur->fname);
|
||||
return(-1);
|
||||
}
|
||||
return -1;
|
||||
|
||||
if (ftcur->refcnt < 0) {
|
||||
/*
|
||||
* chdir entry.
|
||||
* Change directory and retry loop.
|
||||
*/
|
||||
if (ar_dochdir(ftcur->fname))
|
||||
return (-1);
|
||||
continue;
|
||||
} else
|
||||
farray[0] = ftcur->fname;
|
||||
}
|
||||
farray[0] = ftcur->fname;
|
||||
}
|
||||
|
||||
/*
|
||||
* Watch it, fts wants the file arg stored in an array of char
|
||||
* ptrs, with the last one a null. We use a two element array
|
||||
* watch it, fts wants the file arg stored in a array of char
|
||||
* ptrs, with the last one a null. we use a two element array
|
||||
* and set farray[0] to point at the buffer with the file name
|
||||
* in it. We cannot pass all the file args to fts at one shot
|
||||
* as we need to keep a handle on which file arg generates what
|
||||
|
@ -330,7 +393,7 @@ ftree_arg(void)
|
|||
if ((ftsp = fts_open(farray, ftsopts, NULL)) != NULL)
|
||||
break;
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -343,9 +406,151 @@ ftree_arg(void)
|
|||
int
|
||||
next_file(ARCHD *arcn)
|
||||
{
|
||||
int cnt;
|
||||
time_t atime;
|
||||
time_t mtime;
|
||||
#ifndef SMALL
|
||||
static char curdir[PAXPATHLEN+2], curpath[PAXPATHLEN+2];
|
||||
static int curdirlen;
|
||||
|
||||
struct stat statbuf;
|
||||
FTSENT Mftent;
|
||||
#endif /* SMALL */
|
||||
int cnt;
|
||||
time_t atime, mtime;
|
||||
char *curlink;
|
||||
#define MFTENT_DUMMY_DEV UINT_MAX
|
||||
|
||||
curlink = NULL;
|
||||
#ifndef SMALL
|
||||
/*
|
||||
* if parsing an mtree(8) specfile, build up `dummy' ftsent
|
||||
* from specfile info, and jump below to complete setup of arcn.
|
||||
*/
|
||||
if (Mflag) {
|
||||
int skipoptional;
|
||||
|
||||
next_ftnode:
|
||||
skipoptional = 0;
|
||||
if (ftnode == NULL) /* tree is empty */
|
||||
return (-1);
|
||||
|
||||
/* get current name */
|
||||
if (snprintf(curpath, sizeof(curpath), "%s%s%s",
|
||||
curdir, curdirlen ? "/" : "", ftnode->name)
|
||||
>= (int)sizeof(curpath)) {
|
||||
tty_warn(1, "line %lu: %s: %s", (u_long)ftnode->lineno,
|
||||
curdir, strerror(ENAMETOOLONG));
|
||||
return (-1);
|
||||
}
|
||||
ftnode->flags |= F_VISIT; /* mark node visited */
|
||||
|
||||
/* construct dummy FTSENT */
|
||||
Mftent.fts_path = curpath;
|
||||
Mftent.fts_statp = &statbuf;
|
||||
Mftent.fts_pointer = ftnode;
|
||||
ftent = &Mftent;
|
||||
/* look for existing file */
|
||||
if (lstat(Mftent.fts_path, &statbuf) == -1) {
|
||||
if (ftnode->flags & F_OPT)
|
||||
skipoptional = 1;
|
||||
|
||||
/* missing: fake up stat info */
|
||||
memset(&statbuf, 0, sizeof(statbuf));
|
||||
statbuf.st_dev = MFTENT_DUMMY_DEV;
|
||||
statbuf.st_ino = ftnode->lineno;
|
||||
statbuf.st_size = 0;
|
||||
#define NODETEST(t, m) \
|
||||
if (!(t)) { \
|
||||
tty_warn(1, "line %lu: %s: %s not specified", \
|
||||
(u_long)ftnode->lineno, \
|
||||
ftent->fts_path, m); \
|
||||
return -1; \
|
||||
}
|
||||
statbuf.st_mode = nodetoino(ftnode->type);
|
||||
NODETEST(ftnode->flags & F_TYPE, "type");
|
||||
NODETEST(ftnode->flags & F_MODE, "mode");
|
||||
if (!(ftnode->flags & F_TIME))
|
||||
statbuf.st_mtime = starttime;
|
||||
NODETEST(ftnode->flags & (F_GID | F_GNAME), "group");
|
||||
NODETEST(ftnode->flags & (F_UID | F_UNAME), "user");
|
||||
if (ftnode->type == F_BLOCK || ftnode->type == F_CHAR)
|
||||
NODETEST(ftnode->flags & F_DEV,
|
||||
"device number");
|
||||
if (ftnode->type == F_LINK)
|
||||
NODETEST(ftnode->flags & F_SLINK, "symlink");
|
||||
/* don't require F_FLAGS or F_SIZE */
|
||||
#undef NODETEST
|
||||
} else {
|
||||
if (ftnode->flags & F_TYPE && nodetoino(ftnode->type)
|
||||
!= (statbuf.st_mode & S_IFMT)) {
|
||||
tty_warn(1,
|
||||
"line %lu: %s: type mismatch: specfile %s, tree %s",
|
||||
(u_long)ftnode->lineno, ftent->fts_path,
|
||||
inotype(nodetoino(ftnode->type)),
|
||||
inotype(statbuf.st_mode));
|
||||
return -1;
|
||||
}
|
||||
if (ftnode->type == F_DIR && (ftnode->flags & F_OPT))
|
||||
skipoptional = 1;
|
||||
}
|
||||
/*
|
||||
* override settings with those from specfile
|
||||
*/
|
||||
if (ftnode->flags & F_MODE) {
|
||||
statbuf.st_mode &= ~ALLPERMS;
|
||||
statbuf.st_mode |= (ftnode->st_mode & ALLPERMS);
|
||||
}
|
||||
if (ftnode->flags & (F_GID | F_GNAME))
|
||||
statbuf.st_gid = ftnode->st_gid;
|
||||
if (ftnode->flags & (F_UID | F_UNAME))
|
||||
statbuf.st_uid = ftnode->st_uid;
|
||||
#if HAVE_STRUCT_STAT_ST_FLAGS
|
||||
if (ftnode->flags & F_FLAGS)
|
||||
statbuf.st_flags = ftnode->st_flags;
|
||||
#endif
|
||||
if (ftnode->flags & F_TIME)
|
||||
#if BSD4_4 && !HAVE_NBTOOL_CONFIG_H
|
||||
statbuf.st_mtimespec = ftnode->st_mtimespec;
|
||||
#else
|
||||
statbuf.st_mtime = ftnode->st_mtimespec.tv_sec;
|
||||
#endif
|
||||
if (ftnode->flags & F_DEV)
|
||||
statbuf.st_rdev = ftnode->st_rdev;
|
||||
if (ftnode->flags & F_SLINK)
|
||||
curlink = ftnode->slink;
|
||||
/* ignore F_SIZE */
|
||||
|
||||
/*
|
||||
* find next node
|
||||
*/
|
||||
if (ftnode->type == F_DIR && ftnode->child != NULL) {
|
||||
/* directory with unseen child */
|
||||
ftnode = ftnode->child;
|
||||
curdirlen = strlcpy(curdir, curpath, sizeof(curdir));
|
||||
} else do {
|
||||
if (ftnode->next != NULL) {
|
||||
/* next node at current level */
|
||||
ftnode = ftnode->next;
|
||||
} else { /* move back to parent */
|
||||
/* reset time only on first cd.. */
|
||||
if (Mftent.fts_pointer == ftnode && tflag &&
|
||||
(get_atdir(MFTENT_DUMMY_DEV, ftnode->lineno,
|
||||
&mtime, &atime) == 0)) {
|
||||
set_ftime(ftent->fts_path,
|
||||
mtime, atime, 1, 0);
|
||||
}
|
||||
ftnode = ftnode->parent;
|
||||
if (ftnode->parent == ftnode)
|
||||
ftnode = NULL;
|
||||
else {
|
||||
curdirlen -= strlen(ftnode->name) + 1;
|
||||
curdir[curdirlen] = '\0';
|
||||
}
|
||||
}
|
||||
} while (ftnode != NULL && ftnode->flags & F_VISIT);
|
||||
if (skipoptional) /* skip optional entries */
|
||||
goto next_ftnode;
|
||||
goto got_ftent;
|
||||
}
|
||||
#endif /* SMALL */
|
||||
|
||||
/*
|
||||
* ftree_sel() might have set the ftree_skip flag if the user has the
|
||||
|
@ -359,9 +564,11 @@ next_file(ARCHD *arcn)
|
|||
*/
|
||||
ftree_skip = 0;
|
||||
if (ftree_arg() < 0)
|
||||
return(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ftsp == NULL)
|
||||
return -1;
|
||||
/*
|
||||
* loop until we get a valid file to process
|
||||
*/
|
||||
|
@ -372,7 +579,7 @@ next_file(ARCHD *arcn)
|
|||
* we are done
|
||||
*/
|
||||
if (ftree_arg() < 0)
|
||||
return(-1);
|
||||
return -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -398,49 +605,37 @@ next_file(ARCHD *arcn)
|
|||
* remember to force the time (this is -t on a read
|
||||
* directory, not a created directory).
|
||||
*/
|
||||
# ifdef NET2_FTS
|
||||
if (!tflag || (get_atdir(ftent->fts_statb.st_dev,
|
||||
ftent->fts_statb.st_ino, &mtime, &atime) < 0))
|
||||
# else
|
||||
if (!tflag || (get_atdir(ftent->fts_statp->st_dev,
|
||||
ftent->fts_statp->st_ino, &mtime, &atime) < 0))
|
||||
# endif
|
||||
if (!tflag || (get_atdir(
|
||||
ftent->fts_statp->st_dev, ftent->fts_statp->st_ino,
|
||||
&mtime, &atime) < 0))
|
||||
continue;
|
||||
set_ftime(ftent->fts_path, mtime, atime, 1);
|
||||
set_ftime(ftent->fts_path, mtime, atime, 1, 0);
|
||||
continue;
|
||||
case FTS_DC:
|
||||
/*
|
||||
* fts claims a file system cycle
|
||||
*/
|
||||
paxwarn(1,"File system cycle found at %s",ftent->fts_path);
|
||||
tty_warn(1,"File system cycle found at %s",
|
||||
ftent->fts_path);
|
||||
continue;
|
||||
case FTS_DNR:
|
||||
# ifdef NET2_FTS
|
||||
syswarn(1, errno,
|
||||
# else
|
||||
syswarn(1, ftent->fts_errno,
|
||||
# endif
|
||||
syswarn(1, FTS_ERRNO(ftent),
|
||||
"Unable to read directory %s", ftent->fts_path);
|
||||
continue;
|
||||
case FTS_ERR:
|
||||
# ifdef NET2_FTS
|
||||
syswarn(1, errno,
|
||||
# else
|
||||
syswarn(1, ftent->fts_errno,
|
||||
# endif
|
||||
syswarn(1, FTS_ERRNO(ftent),
|
||||
"File system traversal error");
|
||||
continue;
|
||||
case FTS_NS:
|
||||
case FTS_NSOK:
|
||||
# ifdef NET2_FTS
|
||||
syswarn(1, errno,
|
||||
# else
|
||||
syswarn(1, ftent->fts_errno,
|
||||
# endif
|
||||
syswarn(1, FTS_ERRNO(ftent),
|
||||
"Unable to access %s", ftent->fts_path);
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifndef SMALL
|
||||
got_ftent:
|
||||
#endif /* SMALL */
|
||||
/*
|
||||
* ok got a file tree node to process. copy info into arcn
|
||||
* structure (initialize as required)
|
||||
|
@ -449,11 +644,7 @@ next_file(ARCHD *arcn)
|
|||
arcn->pad = 0;
|
||||
arcn->ln_nlen = 0;
|
||||
arcn->ln_name[0] = '\0';
|
||||
# ifdef NET2_FTS
|
||||
arcn->sb = ftent->fts_statb;
|
||||
# else
|
||||
arcn->sb = *(ftent->fts_statp);
|
||||
# endif
|
||||
|
||||
/*
|
||||
* file type based set up and copy into the arcn struct
|
||||
|
@ -492,23 +683,27 @@ next_file(ARCHD *arcn)
|
|||
break;
|
||||
case S_IFLNK:
|
||||
arcn->type = PAX_SLK;
|
||||
if (curlink != NULL) {
|
||||
cnt = strlcpy(arcn->ln_name, curlink,
|
||||
sizeof(arcn->ln_name));
|
||||
/*
|
||||
* have to read the symlink path from the file
|
||||
*/
|
||||
if ((cnt = readlink(ftent->fts_path, arcn->ln_name,
|
||||
PAXPATHLEN - 1)) < 0) {
|
||||
} else if ((cnt =
|
||||
readlink(ftent->fts_path, arcn->ln_name,
|
||||
sizeof(arcn->ln_name) - 1)) < 0) {
|
||||
syswarn(1, errno, "Unable to read symlink %s",
|
||||
ftent->fts_path);
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* set link name length, watch out readlink does not
|
||||
* always NUL terminate the link path
|
||||
* always null terminate the link path
|
||||
*/
|
||||
arcn->ln_name[cnt] = '\0';
|
||||
arcn->ln_nlen = cnt;
|
||||
break;
|
||||
#if 0
|
||||
#ifdef S_IFSOCK
|
||||
case S_IFSOCK:
|
||||
/*
|
||||
* under BSD storing a socket is senseless but we will
|
||||
|
@ -528,8 +723,19 @@ next_file(ARCHD *arcn)
|
|||
/*
|
||||
* copy file name, set file name length
|
||||
*/
|
||||
arcn->nlen = l_strncpy(arcn->name, ftent->fts_path, sizeof(arcn->name) - 1);
|
||||
arcn->name[arcn->nlen] = '\0';
|
||||
arcn->org_name = ftent->fts_path;
|
||||
return(0);
|
||||
arcn->nlen = strlcpy(arcn->name, ftent->fts_path, sizeof(arcn->name));
|
||||
arcn->org_name = arcn->fts_name;
|
||||
strlcpy(arcn->fts_name, ftent->fts_path, sizeof arcn->fts_name);
|
||||
if (strcmp(NM_CPIO, argv0) == 0) {
|
||||
/*
|
||||
* cpio does *not* descend directories listed in the
|
||||
* arguments, unlike pax/tar, so needs special handling
|
||||
* here. failure to do so results in massive amounts
|
||||
* of duplicated files in the output. We kill fts after
|
||||
* the first name is extracted, what a waste.
|
||||
*/
|
||||
ftcur->refcnt = 1;
|
||||
(void)ftree_arg();
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
/* $NetBSD: ftree.h,v 1.5 2003/10/13 07:41:22 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -14,7 +16,7 @@
|
|||
* 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.
|
||||
* 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.
|
||||
*
|
||||
|
@ -31,7 +33,6 @@
|
|||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ftree.h 8.1 (Berkeley) 5/31/93
|
||||
* $FreeBSD: src/bin/pax/ftree.h,v 1.7 2004/04/06 20:06:48 markm Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -43,6 +44,5 @@
|
|||
typedef struct ftree {
|
||||
char *fname; /* file tree name */
|
||||
int refcnt; /* has tree had a selected file? */
|
||||
int chflg; /* change directory flag */
|
||||
struct ftree *fow; /* pointer to next entry on list */
|
||||
} FTREE;
|
|
@ -1,3 +1,5 @@
|
|||
/* $NetBSD: gen_subs.c,v 1.36 2012/08/09 08:09:21 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -14,7 +16,7 @@
|
|||
* 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.
|
||||
* 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.
|
||||
*
|
||||
|
@ -31,22 +33,35 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)gen_subs.c 8.1 (Berkeley) 5/31/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: gen_subs.c,v 1.36 2012/08/09 08:09:21 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include <vis.h>
|
||||
#include <stdio.h>
|
||||
#include <utmp.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <tzfile.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "pax.h"
|
||||
#include "extern.h"
|
||||
|
||||
|
@ -59,17 +74,32 @@ static char sccsid[] = "@(#)gen_subs.c 8.1 (Berkeley) 5/31/93";
|
|||
*/
|
||||
#define MODELEN 20
|
||||
#define DATELEN 64
|
||||
#define SIXMONTHS ((365 / 2) * 86400)
|
||||
#define CURFRMTM "%b %e %H:%M"
|
||||
#define OLDFRMTM "%b %e %Y"
|
||||
#define CURFRMTD "%e %b %H:%M"
|
||||
#define OLDFRMTD "%e %b %Y"
|
||||
#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
|
||||
|
||||
static int d_first = -1;
|
||||
/*
|
||||
* convert time to string
|
||||
*/
|
||||
static void
|
||||
formattime(char *buf, size_t buflen, time_t when)
|
||||
{
|
||||
int error;
|
||||
struct tm tm;
|
||||
(void)localtime_r(&when, &tm);
|
||||
|
||||
if (when + SIXMONTHS <= time(NULL))
|
||||
error = strftime(buf, buflen, OLDFRMT, &tm);
|
||||
else
|
||||
error = strftime(buf, buflen, CURFRMT, &tm);
|
||||
|
||||
if (error == 0)
|
||||
buf[0] = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* ls_list()
|
||||
|
@ -82,7 +112,7 @@ ls_list(ARCHD *arcn, time_t now, FILE *fp)
|
|||
struct stat *sbp;
|
||||
char f_mode[MODELEN];
|
||||
char f_date[DATELEN];
|
||||
const char *timefrmt;
|
||||
const char *user, *group;
|
||||
|
||||
/*
|
||||
* if not verbose, just print the file name
|
||||
|
@ -93,54 +123,33 @@ ls_list(ARCHD *arcn, time_t now, FILE *fp)
|
|||
return;
|
||||
}
|
||||
|
||||
if (d_first < 0)
|
||||
d_first = 0;
|
||||
/*
|
||||
* user wants long mode
|
||||
*/
|
||||
sbp = &(arcn->sb);
|
||||
#if 0
|
||||
strmode(sbp->st_mode, f_mode);
|
||||
#else
|
||||
strcpy(f_mode, "");
|
||||
#endif
|
||||
|
||||
/*
|
||||
* time format based on age compared to the time pax was started.
|
||||
*/
|
||||
if ((sbp->st_mtime + SIXMONTHS) <= now)
|
||||
timefrmt = d_first ? OLDFRMTD : OLDFRMTM;
|
||||
else
|
||||
timefrmt = d_first ? CURFRMTD : CURFRMTM;
|
||||
|
||||
formattime(f_date, sizeof(f_date), arcn->sb.st_mtime);
|
||||
/*
|
||||
* print file mode, link count, uid, gid and time
|
||||
*/
|
||||
#if 0
|
||||
if (strftime(f_date,DATELEN,timefrmt,localtime(&(sbp->st_mtime))) == 0)
|
||||
#endif
|
||||
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));
|
||||
user = user_from_uid(sbp->st_uid, 0);
|
||||
group = group_from_gid(sbp->st_gid, 0);
|
||||
(void)fprintf(fp, "%s%2lu %-*s %-*s ", f_mode,
|
||||
(unsigned long)sbp->st_nlink,
|
||||
UT_NAMESIZE, user ? user : "", UT_GRPSIZE, group ? group : "");
|
||||
|
||||
/*
|
||||
* print device id's for devices, or sizes for other nodes
|
||||
*/
|
||||
if ((arcn->type == PAX_CHR) || (arcn->type == PAX_BLK))
|
||||
# ifdef NET2_STAT
|
||||
(void)fprintf(fp, "%4u,%4u ", major(sbp->st_rdev),
|
||||
minor(sbp->st_rdev));
|
||||
# else
|
||||
(void)fprintf(fp, "%4lu,%4lu ", (unsigned long)major(sbp->st_rdev),
|
||||
(unsigned long)minor(sbp->st_rdev));
|
||||
# endif
|
||||
(void)fprintf(fp, "%4lu,%4lu ", (long) MAJOR(sbp->st_rdev),
|
||||
(long) MINOR(sbp->st_rdev));
|
||||
else {
|
||||
# ifdef NET2_STAT
|
||||
(void)fprintf(fp, "%9lu ", sbp->st_size);
|
||||
# else
|
||||
(void)fprintf(fp, "%9ju ", (uintmax_t)sbp->st_size);
|
||||
# endif
|
||||
(void)fprintf(fp, OFFT_FP("9") " ", (OFFT_T)sbp->st_size);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -150,16 +159,15 @@ ls_list(ARCHD *arcn, time_t now, FILE *fp)
|
|||
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);
|
||||
(void)fprintf(fp, " -> %s\n", arcn->ln_name);
|
||||
else
|
||||
(void)putc('\n', fp);
|
||||
(void)fputc('\n', fp);
|
||||
(void)fflush(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* tty_ls()
|
||||
* print a short summary of file to tty.
|
||||
* print a short summary of file to tty.
|
||||
*/
|
||||
|
||||
void
|
||||
|
@ -167,73 +175,47 @@ ls_tty(ARCHD *arcn)
|
|||
{
|
||||
char f_date[DATELEN];
|
||||
char f_mode[MODELEN];
|
||||
const char *timefrmt;
|
||||
|
||||
if (d_first < 0)
|
||||
d_first = 0;
|
||||
|
||||
if ((arcn->sb.st_mtime + SIXMONTHS) <= time(NULL))
|
||||
timefrmt = d_first ? OLDFRMTD : OLDFRMTM;
|
||||
else
|
||||
timefrmt = d_first ? CURFRMTD : CURFRMTM;
|
||||
|
||||
/*
|
||||
* convert time to string, and print
|
||||
*/
|
||||
#if 0
|
||||
if (strftime(f_date, DATELEN, timefrmt,
|
||||
localtime(&(arcn->sb.st_mtime))) == 0)
|
||||
#endif
|
||||
f_date[0] = '\0';
|
||||
#if 0
|
||||
formattime(f_date, sizeof(f_date), arcn->sb.st_mtime);
|
||||
strmode(arcn->sb.st_mode, f_mode);
|
||||
#else
|
||||
strcpy(f_mode, "");
|
||||
#endif
|
||||
tty_prnt("%s%s %s\n", f_mode, f_date, arcn->name);
|
||||
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())
|
||||
*/
|
||||
|
||||
int
|
||||
l_strncpy(char *dest, const char *src, int len)
|
||||
void
|
||||
safe_print(const char *str, FILE *fp)
|
||||
{
|
||||
char *stop;
|
||||
char *start;
|
||||
char visbuf[5];
|
||||
const char *cp;
|
||||
|
||||
stop = dest + len;
|
||||
start = dest;
|
||||
while ((dest < stop) && (*src != '\0'))
|
||||
*dest++ = *src++;
|
||||
len = dest - start;
|
||||
while (dest < stop)
|
||||
*dest++ = '\0';
|
||||
return(len);
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* asc_ul()
|
||||
* convert hex/octal character string into a u_long. We do not have to
|
||||
* asc_u32()
|
||||
* convert hex/octal character string into a uint32_t. We do not have to
|
||||
* check for overflow! (the headers in all supported formats are not large
|
||||
* enough to create an overflow).
|
||||
* NOTE: strings passed to us are NOT TERMINATED.
|
||||
* Return:
|
||||
* unsigned long value
|
||||
* uint32_t value
|
||||
*/
|
||||
|
||||
u_long
|
||||
asc_ul(char *str, int len, int base)
|
||||
uint32_t
|
||||
asc_u32(char *str, int len, int base)
|
||||
{
|
||||
char *stop;
|
||||
u_long tval = 0;
|
||||
uint32_t tval = 0;
|
||||
|
||||
stop = str + len;
|
||||
|
||||
|
@ -259,24 +241,31 @@ asc_ul(char *str, int len, int base)
|
|||
break;
|
||||
}
|
||||
} else {
|
||||
while ((str < stop) && (*str >= '0') && (*str <= '7'))
|
||||
while ((str < stop) && (*str >= '0') && (*str <= '7'))
|
||||
tval = (tval << 3) + (*str++ - '0');
|
||||
}
|
||||
return(tval);
|
||||
return tval;
|
||||
}
|
||||
|
||||
/*
|
||||
* ul_asc()
|
||||
* convert an unsigned long into an hex/oct ascii string. pads with LEADING
|
||||
* u32_asc()
|
||||
* convert an uintmax_t into an hex/oct ascii string. pads with LEADING
|
||||
* ascii 0's to fill string completely
|
||||
* NOTE: the string created is NOT TERMINATED.
|
||||
*/
|
||||
|
||||
int
|
||||
ul_asc(u_long val, char *str, int len, int base)
|
||||
u32_asc(uintmax_t val, char *str, int len, int base)
|
||||
{
|
||||
char *pt;
|
||||
u_long digit;
|
||||
uint32_t digit;
|
||||
uintmax_t p;
|
||||
|
||||
p = val & TOP_HALF;
|
||||
if (p && p != TOP_HALF)
|
||||
return -1;
|
||||
|
||||
val &= BOTTOM_HALF;
|
||||
|
||||
/*
|
||||
* WARNING str is not '\0' terminated by this routine
|
||||
|
@ -300,7 +289,7 @@ ul_asc(u_long val, char *str, int len, int base)
|
|||
} else {
|
||||
while (pt >= str) {
|
||||
*pt-- = '0' + (char)(val & 0x7);
|
||||
if ((val = (val >> 3)) == (u_long)0)
|
||||
if ((val = (val >> 3)) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -310,27 +299,26 @@ ul_asc(u_long val, char *str, int len, int base)
|
|||
*/
|
||||
while (pt >= str)
|
||||
*pt-- = '0';
|
||||
if (val != (u_long)0)
|
||||
return(-1);
|
||||
return(0);
|
||||
if (val != 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef NET2_STAT
|
||||
/*
|
||||
* asc_uqd()
|
||||
* convert hex/octal character string into a u_quad_t. We do not have to
|
||||
* check for overflow! (the headers in all supported formats are not large
|
||||
* enough to create an overflow).
|
||||
* asc_umax()
|
||||
* convert hex/octal character string into a uintmax. We do
|
||||
* not have to to check for overflow! (the headers in all supported
|
||||
* formats are not large enough to create an overflow).
|
||||
* NOTE: strings passed to us are NOT TERMINATED.
|
||||
* Return:
|
||||
* u_quad_t value
|
||||
* uintmax_t value
|
||||
*/
|
||||
|
||||
u_quad_t
|
||||
asc_uqd(char *str, int len, int base)
|
||||
uintmax_t
|
||||
asc_umax(char *str, int len, int base)
|
||||
{
|
||||
char *stop;
|
||||
u_quad_t tval = 0;
|
||||
uintmax_t tval = 0;
|
||||
|
||||
stop = str + len;
|
||||
|
||||
|
@ -356,24 +344,24 @@ asc_uqd(char *str, int len, int base)
|
|||
break;
|
||||
}
|
||||
} else {
|
||||
while ((str < stop) && (*str >= '0') && (*str <= '7'))
|
||||
while ((str < stop) && (*str >= '0') && (*str <= '7'))
|
||||
tval = (tval << 3) + (*str++ - '0');
|
||||
}
|
||||
return(tval);
|
||||
return tval;
|
||||
}
|
||||
|
||||
/*
|
||||
* uqd_asc()
|
||||
* convert an u_quad_t into a hex/oct ascii string. pads with LEADING
|
||||
* ascii 0's to fill string completely
|
||||
* umax_asc()
|
||||
* convert an uintmax_t into a hex/oct ascii string. pads with
|
||||
* LEADING ascii 0's to fill string completely
|
||||
* NOTE: the string created is NOT TERMINATED.
|
||||
*/
|
||||
|
||||
int
|
||||
uqd_asc(u_quad_t val, char *str, int len, int base)
|
||||
umax_asc(uintmax_t val, char *str, int len, int base)
|
||||
{
|
||||
char *pt;
|
||||
u_quad_t digit;
|
||||
uintmax_t digit;
|
||||
|
||||
/*
|
||||
* WARNING str is not '\0' terminated by this routine
|
||||
|
@ -391,13 +379,13 @@ uqd_asc(u_quad_t val, char *str, int len, int base)
|
|||
*pt-- = '0' + (char)digit;
|
||||
else
|
||||
*pt-- = 'a' + (char)(digit - 10);
|
||||
if ((val = (val >> 4)) == (u_quad_t)0)
|
||||
if ((val = (val >> 4)) == 0)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
while (pt >= str) {
|
||||
*pt-- = '0' + (char)(val & 0x7);
|
||||
if ((val = (val >> 3)) == (u_quad_t)0)
|
||||
if ((val = (val >> 3)) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -407,8 +395,21 @@ uqd_asc(u_quad_t val, char *str, int len, int base)
|
|||
*/
|
||||
while (pt >= str)
|
||||
*pt-- = '0';
|
||||
if (val != (u_quad_t)0)
|
||||
return(-1);
|
||||
return(0);
|
||||
if (val != 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
check_Aflag(void)
|
||||
{
|
||||
|
||||
if (Aflag > 0)
|
||||
return 1;
|
||||
if (Aflag == 0) {
|
||||
Aflag = -1;
|
||||
tty_warn(0,
|
||||
"Removing leading / from absolute path names in the archive");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
|
@ -1,27 +1,40 @@
|
|||
/* $OpenBSD: getoldopt.c,v 1.4 2000/01/22 20:24:51 deraadt Exp $ */
|
||||
/* $NetBSD: getoldopt.c,v 1.3 1995/03/21 09:07:28 cgd Exp $ */
|
||||
/* $NetBSD: getoldopt.c,v 1.23 2012/08/09 11:05:59 christos Exp $ */
|
||||
|
||||
/*-
|
||||
/*
|
||||
* Plug-compatible replacement for getopt() for parsing tar-like
|
||||
* arguments. If the first argument begins with "-", it uses getopt;
|
||||
* otherwise, it uses the old rules used by tar, dump, and ps.
|
||||
*
|
||||
* Written 25 August 1985 by John Gilmore (ihnp4!hoptoad!gnu) and placed
|
||||
* in the Pubic Domain for your edification and enjoyment.
|
||||
* in the Public Domain for your edification and enjoyment.
|
||||
*/
|
||||
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/cdefs.h>
|
||||
#if !defined(lint)
|
||||
__RCSID("$NetBSD: getoldopt.c,v 1.23 2012/08/09 11:05:59 christos Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "compat_getopt.h"
|
||||
#else
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/stat.h>
|
||||
#include "pax.h"
|
||||
#include "extern.h"
|
||||
|
||||
int
|
||||
getoldopt(int argc, char **argv, const char *optstring)
|
||||
getoldopt(int argc, char **argv, const char *optstring,
|
||||
struct option *longopts, int *idx)
|
||||
{
|
||||
static char *key; /* Points to next keyletter */
|
||||
static char use_getopt; /* !=0 if argv[1][0] was '-' */
|
||||
|
@ -31,7 +44,7 @@ getoldopt(int argc, char **argv, const char *optstring)
|
|||
optarg = NULL;
|
||||
|
||||
if (key == NULL) { /* First time */
|
||||
if (argc < 2) return EOF;
|
||||
if (argc < 2) return -1;
|
||||
key = argv[1];
|
||||
if (*key == '-')
|
||||
use_getopt++;
|
||||
|
@ -39,19 +52,28 @@ getoldopt(int argc, char **argv, const char *optstring)
|
|||
optind = 2;
|
||||
}
|
||||
|
||||
if (use_getopt)
|
||||
return getopt(argc, argv, optstring);
|
||||
|
||||
c = *key++;
|
||||
if (c == '\0') {
|
||||
key--;
|
||||
return EOF;
|
||||
c = '\0';
|
||||
if (!use_getopt) {
|
||||
c = *key++;
|
||||
if (c == '\0') {
|
||||
key--;
|
||||
use_getopt = 1;
|
||||
}
|
||||
}
|
||||
if (use_getopt) {
|
||||
if (longopts != NULL) {
|
||||
return getopt_long(argc, argv, optstring,
|
||||
longopts, idx);
|
||||
} else {
|
||||
return getopt(argc, argv, optstring);
|
||||
}
|
||||
}
|
||||
|
||||
place = strchr(optstring, c);
|
||||
|
||||
if (place == NULL || c == ':') {
|
||||
fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
|
||||
return('?');
|
||||
return '?';
|
||||
}
|
||||
|
||||
place++;
|
||||
|
@ -62,9 +84,9 @@ getoldopt(int argc, char **argv, const char *optstring)
|
|||
} else {
|
||||
fprintf(stderr, "%s: %c argument missing\n",
|
||||
argv[0], c);
|
||||
return('?');
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
|
||||
return(c);
|
||||
return c;
|
||||
}
|
2161
bin/pax/options.c
Normal file
2161
bin/pax/options.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,5 @@
|
|||
/* $NetBSD: options.h,v 1.11 2007/04/23 18:40:22 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -14,7 +16,7 @@
|
|||
* 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.
|
||||
* 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.
|
||||
*
|
||||
|
@ -31,7 +33,6 @@
|
|||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)options.h 8.2 (Berkeley) 4/18/94
|
||||
* $FreeBSD: src/bin/pax/options.h,v 1.6 2004/04/06 20:06:48 markm Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -42,52 +43,57 @@
|
|||
#define NM_CPIO "cpio"
|
||||
#define NM_PAX "pax"
|
||||
|
||||
/* special value for -E */
|
||||
#define none "none"
|
||||
|
||||
/*
|
||||
* Constants used to specify the legal sets of flags in pax. For each major
|
||||
* operation mode of pax, a set of illegal flags is defined. If any one of
|
||||
* those illegal flags are found set, we scream and exit
|
||||
*/
|
||||
#define NONE "none"
|
||||
|
||||
/*
|
||||
* flags (one for each option).
|
||||
*/
|
||||
#define AF 0x00000001
|
||||
#define BF 0x00000002
|
||||
#define CF 0x00000004
|
||||
#define DF 0x00000008
|
||||
#define FF 0x00000010
|
||||
#define IF 0x00000020
|
||||
#define KF 0x00000040
|
||||
#define LF 0x00000080
|
||||
#define NF 0x00000100
|
||||
#define OF 0x00000200
|
||||
#define PF 0x00000400
|
||||
#define RF 0x00000800
|
||||
#define SF 0x00001000
|
||||
#define TF 0x00002000
|
||||
#define UF 0x00004000
|
||||
#define VF 0x00008000
|
||||
#define WF 0x00010000
|
||||
#define XF 0x00020000
|
||||
#define CBF 0x00040000 /* nonstandard extension */
|
||||
#define CDF 0x00080000 /* nonstandard extension */
|
||||
#define CEF 0x00100000 /* nonstandard extension */
|
||||
#define CGF 0x00200000 /* nonstandard extension */
|
||||
#define CHF 0x00400000 /* nonstandard extension */
|
||||
#define CLF 0x00800000 /* nonstandard extension */
|
||||
#define CPF 0x01000000 /* nonstandard extension */
|
||||
#define CTF 0x02000000 /* nonstandard extension */
|
||||
#define CUF 0x04000000 /* nonstandard extension */
|
||||
#define CXF 0x08000000
|
||||
#define CYF 0x10000000 /* nonstandard extension */
|
||||
#define CZF 0x20000000 /* nonstandard extension */
|
||||
#define AF 0x000000001ULL
|
||||
#define BF 0x000000002ULL
|
||||
#define CF 0x000000004ULL
|
||||
#define DF 0x000000008ULL
|
||||
#define FF 0x000000010ULL
|
||||
#define IF 0x000000020ULL
|
||||
#define KF 0x000000040ULL
|
||||
#define LF 0x000000080ULL
|
||||
#define NF 0x000000100ULL
|
||||
#define OF 0x000000200ULL
|
||||
#define PF 0x000000400ULL
|
||||
#define RF 0x000000800ULL
|
||||
#define SF 0x000001000ULL
|
||||
#define TF 0x000002000ULL
|
||||
#define UF 0x000004000ULL
|
||||
#define VF 0x000008000ULL
|
||||
#define WF 0x000010000ULL
|
||||
#define XF 0x000020000ULL
|
||||
#define CAF 0x000040000ULL /* nonstandard extension */
|
||||
#define CBF 0x000080000ULL /* nonstandard extension */
|
||||
#define CDF 0x000100000ULL /* nonstandard extension */
|
||||
#define CEF 0x000200000ULL /* nonstandard extension */
|
||||
#define CGF 0x000400000ULL /* nonstandard extension */
|
||||
#define CHF 0x000800000ULL /* nonstandard extension */
|
||||
#define CLF 0x001000000ULL /* nonstandard extension */
|
||||
#define CMF 0x002000000ULL /* nonstandard extension */
|
||||
#define CPF 0x004000000ULL /* nonstandard extension */
|
||||
#define CTF 0x008000000ULL /* nonstandard extension */
|
||||
#define CUF 0x010000000ULL /* nonstandard extension */
|
||||
#define VSF 0x020000000ULL /* non-standard */
|
||||
#define CXF 0x040000000ULL
|
||||
#define CYF 0x080000000ULL /* nonstandard extension */
|
||||
#define CZF 0x100000000ULL /* nonstandard extension */
|
||||
|
||||
/*
|
||||
* ascii string indexed by bit position above (alter the above and you must
|
||||
* alter this string) used to tell the user what flags caused us to complain
|
||||
*/
|
||||
#define FLGCH "abcdfiklnoprstuvwxBDEGHLPTUXYZ"
|
||||
#define FLGCH "abcdfiklnoprstuvwxABDEGHLMPTUVXYZ"
|
||||
|
||||
/*
|
||||
* legal pax operation bit patterns
|
||||
|
@ -104,7 +110,7 @@
|
|||
* Illegal option flag subsets based on pax operation
|
||||
*/
|
||||
|
||||
#define BDEXTR (AF|BF|LF|TF|WF|XF|CBF|CHF|CLF|CPF|CXF)
|
||||
#define BDEXTR (AF|BF|LF|TF|WF|XF|CBF|CHF|CLF|CMF|CPF|CXF)
|
||||
#define BDARCH (CF|KF|LF|NF|PF|RF|CDF|CEF|CYF|CZF)
|
||||
#define BDCOPY (AF|BF|FF|OF|XF|CBF|CEF)
|
||||
#define BDLIST (AF|BF|IF|KF|LF|OF|PF|RF|TF|UF|WF|XF|CBF|CDF|CHF|CLF|CPF|CXF|CYF|CZF)
|
||||
#define BDCOPY (AF|BF|FF|OF|XF|CAF|CBF|CEF)
|
||||
#define BDLIST (AF|BF|IF|KF|LF|OF|PF|RF|TF|UF|WF|XF|CBF|CDF|CHF|CLF|CMF|CPF|CXF|CYF|CZF)
|
|
@ -1,3 +1,5 @@
|
|||
/* $NetBSD: pat_rep.c,v 1.29 2009/04/07 19:52:35 perry Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -14,7 +16,7 @@
|
|||
* 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.
|
||||
* 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.
|
||||
*
|
||||
|
@ -31,24 +33,28 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)pat_rep.c 8.2 (Berkeley) 4/18/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: pat_rep.c,v 1.29 2009/04/07 19:52:35 perry Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#ifdef NET2_REGEX
|
||||
#include <regexp.h>
|
||||
#else
|
||||
#include <regex.h>
|
||||
#endif
|
||||
#include "pax.h"
|
||||
#include "pat_rep.h"
|
||||
#include "extern.h"
|
||||
|
@ -66,21 +72,18 @@ static PATTERN *pattail = NULL; /* file pattern match list tail */
|
|||
static REPLACE *rephead = NULL; /* replacement string list head */
|
||||
static REPLACE *reptail = NULL; /* replacement string list tail */
|
||||
|
||||
static int rep_name(char *, int *, int);
|
||||
static int rep_name(char *, size_t, int *, int);
|
||||
static int tty_rename(ARCHD *);
|
||||
static int fix_path(char *, int *, char *, int);
|
||||
static int fn_match(char *, char *, char **);
|
||||
static int fn_match(char *, char *, char **, int);
|
||||
static char * range_match(char *, int);
|
||||
#ifdef NET2_REGEX
|
||||
static int resub(regexp *, char *, char *, char *);
|
||||
#else
|
||||
static int resub(regex_t *, regmatch_t *, char *, char *, char *);
|
||||
#endif
|
||||
static int checkdotdot(const char *);
|
||||
static int resub(regex_t *, regmatch_t *, char *, char *, char *, char *);
|
||||
|
||||
/*
|
||||
* rep_add()
|
||||
* parses the -s replacement string; compiles the regular expression
|
||||
* and stores the compiled value and it's replacement string together in
|
||||
* and stores the compiled value and its replacement string together in
|
||||
* replacement string list. Input to this function is of the form:
|
||||
* /old/new/pg
|
||||
* The first char in the string specifies the delimiter used by this
|
||||
|
@ -99,26 +102,32 @@ rep_add(char *str)
|
|||
char *pt1;
|
||||
char *pt2;
|
||||
REPLACE *rep;
|
||||
# ifndef NET2_REGEX
|
||||
int res;
|
||||
char rebuf[BUFSIZ];
|
||||
# endif
|
||||
|
||||
/*
|
||||
* throw out the bad parameters
|
||||
*/
|
||||
if ((str == NULL) || (*str == '\0')) {
|
||||
paxwarn(1, "Empty replacement string");
|
||||
return(-1);
|
||||
tty_warn(1, "Empty replacement string");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* first character in the string specifies what the delimiter is for
|
||||
* this expression
|
||||
* this expression.
|
||||
*/
|
||||
if ((pt1 = strchr(str+1, *str)) == NULL) {
|
||||
paxwarn(1, "Invalid replacement string %s", str);
|
||||
return(-1);
|
||||
for (pt1 = str+1; *pt1; pt1++) {
|
||||
if (*pt1 == '\\') {
|
||||
pt1++;
|
||||
continue;
|
||||
}
|
||||
if (*pt1 == *str)
|
||||
break;
|
||||
}
|
||||
if (*pt1 == 0) {
|
||||
tty_warn(1, "Invalid replacement string %s", str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -126,20 +135,17 @@ rep_add(char *str)
|
|||
* and split out the regular expression and try to compile it
|
||||
*/
|
||||
if ((rep = (REPLACE *)malloc(sizeof(REPLACE))) == NULL) {
|
||||
paxwarn(1, "Unable to allocate memory for replacement string");
|
||||
return(-1);
|
||||
tty_warn(1, "Unable to allocate memory for replacement string");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*pt1 = '\0';
|
||||
# ifdef NET2_REGEX
|
||||
if ((rep->rcmp = regcomp(str+1)) == NULL) {
|
||||
# else
|
||||
if ((res = regcomp(&(rep->rcmp), str+1, 0)) != 0) {
|
||||
regerror(res, &(rep->rcmp), rebuf, sizeof(rebuf));
|
||||
paxwarn(1, "%s while compiling regular expression %s", rebuf, str);
|
||||
# endif
|
||||
tty_warn(1, "%s while compiling regular expression %s", rebuf,
|
||||
str);
|
||||
(void)free((char *)rep);
|
||||
return(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -148,19 +154,31 @@ rep_add(char *str)
|
|||
* we then point the node at the new substitution string
|
||||
*/
|
||||
*pt1++ = *str;
|
||||
if ((pt2 = strchr(pt1, *str)) == NULL) {
|
||||
# ifdef NET2_REGEX
|
||||
(void)free((char *)rep->rcmp);
|
||||
# else
|
||||
for (pt2 = pt1; *pt2; pt2++) {
|
||||
if (*pt2 == '\\') {
|
||||
pt2++;
|
||||
continue;
|
||||
}
|
||||
if (*pt2 == *str)
|
||||
break;
|
||||
}
|
||||
if (*pt2 == 0) {
|
||||
regfree(&(rep->rcmp));
|
||||
# endif
|
||||
(void)free((char *)rep);
|
||||
paxwarn(1, "Invalid replacement string %s", str);
|
||||
return(-1);
|
||||
tty_warn(1, "Invalid replacement string %s", str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*pt2 = '\0';
|
||||
rep->nstr = pt1;
|
||||
|
||||
/* Make sure to dup replacement, who knows where it came from! */
|
||||
if ((rep->nstr = strdup(pt1)) == NULL) {
|
||||
regfree(&(rep->rcmp));
|
||||
(void)free((char *)rep);
|
||||
tty_warn(1, "Unable to allocate memory for replacement string");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pt1 = pt2++;
|
||||
rep->flgs = 0;
|
||||
|
||||
|
@ -177,16 +195,17 @@ rep_add(char *str)
|
|||
case 'P':
|
||||
rep->flgs |= PRNT;
|
||||
break;
|
||||
case 's':
|
||||
case 'S':
|
||||
rep->flgs |= SYML;
|
||||
break;
|
||||
default:
|
||||
# ifdef NET2_REGEX
|
||||
(void)free((char *)rep->rcmp);
|
||||
# else
|
||||
regfree(&(rep->rcmp));
|
||||
# endif
|
||||
(void)free((char *)rep);
|
||||
*pt1 = *str;
|
||||
paxwarn(1, "Invalid replacement string option %s", str);
|
||||
return(-1);
|
||||
tty_warn(1, "Invalid replacement string option %s",
|
||||
str);
|
||||
return -1;
|
||||
}
|
||||
++pt2;
|
||||
}
|
||||
|
@ -197,11 +216,11 @@ rep_add(char *str)
|
|||
rep->fow = NULL;
|
||||
if (rephead == NULL) {
|
||||
reptail = rephead = rep;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
reptail->fow = rep;
|
||||
reptail = rep;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -211,12 +230,13 @@ rep_add(char *str)
|
|||
* arguments to pax in the list and read modes). If no patterns are
|
||||
* supplied to pax, all members in the archive will be selected (and the
|
||||
* pattern match list is empty).
|
||||
*
|
||||
* Return:
|
||||
* 0 if the pattern was added to the list, -1 otherwise
|
||||
*/
|
||||
|
||||
int
|
||||
pat_add(char *str, char *chdnam)
|
||||
pat_add(char *str, char *chdn, int flags)
|
||||
{
|
||||
PATTERN *pt;
|
||||
|
||||
|
@ -224,8 +244,8 @@ pat_add(char *str, char *chdnam)
|
|||
* throw out the junk
|
||||
*/
|
||||
if ((str == NULL) || (*str == '\0')) {
|
||||
paxwarn(1, "Empty pattern string");
|
||||
return(-1);
|
||||
tty_warn(1, "Empty pattern string");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -234,24 +254,23 @@ pat_add(char *str, char *chdnam)
|
|||
* node to the end of the pattern list
|
||||
*/
|
||||
if ((pt = (PATTERN *)malloc(sizeof(PATTERN))) == NULL) {
|
||||
paxwarn(1, "Unable to allocate memory for pattern string");
|
||||
return(-1);
|
||||
tty_warn(1, "Unable to allocate memory for pattern string");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pt->pstr = str;
|
||||
pt->pend = NULL;
|
||||
pt->plen = strlen(str);
|
||||
pt->fow = NULL;
|
||||
pt->flgs = 0;
|
||||
pt->chdname = chdnam;
|
||||
|
||||
pt->flgs = flags;
|
||||
pt->chdname = chdn;
|
||||
if (pathead == NULL) {
|
||||
pattail = pathead = pt;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
pattail->fow = pt;
|
||||
pattail = pt;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -274,7 +293,7 @@ pat_chk(void)
|
|||
if (pt->flgs & MTCH)
|
||||
continue;
|
||||
if (!wban) {
|
||||
paxwarn(1, "WARNING! These patterns were not matched:");
|
||||
tty_warn(1, "WARNING! These patterns were not matched:");
|
||||
++wban;
|
||||
}
|
||||
(void)fprintf(stderr, "%s\n", pt->pstr);
|
||||
|
@ -289,9 +308,9 @@ pat_chk(void)
|
|||
*
|
||||
* NOTE: When the -c option is used, we are called when there was no match
|
||||
* by pat_match() (that means we did match before the inverted sense of
|
||||
* the logic). Now this seems really strange at first, but with -c we
|
||||
* need to keep track of those patterns that cause an archive member to NOT
|
||||
* be selected (it found an archive member with a specified pattern)
|
||||
* the logic). Now this seems really strange at first, but with -c we
|
||||
* need to keep track of those patterns that cause an archive member to
|
||||
* NOT be selected (it found an archive member with a specified pattern)
|
||||
* Return:
|
||||
* 0 if the pattern pointed at by arcn->pat was tagged as creating a
|
||||
* match, -1 otherwise.
|
||||
|
@ -308,7 +327,7 @@ pat_sel(ARCHD *arcn)
|
|||
* if no patterns just return
|
||||
*/
|
||||
if ((pathead == NULL) || ((pt = arcn->pat) == NULL))
|
||||
return(0);
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* when we are NOT limited to a single match per pattern mark the
|
||||
|
@ -316,7 +335,7 @@ pat_sel(ARCHD *arcn)
|
|||
*/
|
||||
if (!nflag) {
|
||||
pt->flgs |= MTCH;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -327,7 +346,7 @@ pat_sel(ARCHD *arcn)
|
|||
* with -d, this pattern was already selected and we are done
|
||||
*/
|
||||
if (pt->flgs & DIR_MTCH)
|
||||
return(0);
|
||||
return 0;
|
||||
|
||||
if (!dflag && ((pt->pend != NULL) || (arcn->type == PAX_DIR))) {
|
||||
/*
|
||||
|
@ -347,11 +366,11 @@ pat_sel(ARCHD *arcn)
|
|||
*pt->pend = '\0';
|
||||
|
||||
if ((pt->pstr = strdup(arcn->name)) == NULL) {
|
||||
paxwarn(1, "Pattern select out of memory");
|
||||
tty_warn(1, "Pattern select out of memory");
|
||||
if (pt->pend != NULL)
|
||||
*pt->pend = '/';
|
||||
pt->pend = NULL;
|
||||
return(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -373,14 +392,14 @@ pat_sel(ARCHD *arcn)
|
|||
}
|
||||
pt->flgs = DIR_MTCH | MTCH;
|
||||
arcn->pat = pt;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* we are then done with this pattern, so we delete it from the list
|
||||
* because it can never be used for another match.
|
||||
* Seems kind of strange to do for a -c, but the pax spec is really
|
||||
* vague on the interaction of -c -n and -d. We assume that when -c
|
||||
* vague on the interaction of -c, -n, and -d. We assume that when -c
|
||||
* and the pattern rejects a member (i.e. it matched it) it is done.
|
||||
* In effect we place the order of the flags as having -c last.
|
||||
*/
|
||||
|
@ -395,13 +414,13 @@ pat_sel(ARCHD *arcn)
|
|||
/*
|
||||
* should never happen....
|
||||
*/
|
||||
paxwarn(1, "Pattern list inconsistant");
|
||||
return(-1);
|
||||
tty_warn(1, "Pattern list inconsistent");
|
||||
return -1;
|
||||
}
|
||||
*ppt = pt->fow;
|
||||
(void)free((char *)pt);
|
||||
arcn->pat = NULL;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -429,8 +448,8 @@ pat_match(ARCHD *arcn)
|
|||
*/
|
||||
if (pathead == NULL) {
|
||||
if (nflag && !cflag)
|
||||
return(-1);
|
||||
return(0);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -452,7 +471,8 @@ pat_match(ARCHD *arcn)
|
|||
if ((arcn->name[pt->plen] == '/') &&
|
||||
(strncmp(pt->pstr, arcn->name, pt->plen) == 0))
|
||||
break;
|
||||
} else if (fn_match(pt->pstr, arcn->name, &pt->pend) == 0)
|
||||
} else if (fn_match(pt->pstr, arcn->name, &pt->pend,
|
||||
pt->flgs & NOGLOB_MTCH) == 0)
|
||||
break;
|
||||
pt = pt->fow;
|
||||
}
|
||||
|
@ -462,21 +482,22 @@ pat_match(ARCHD *arcn)
|
|||
* match
|
||||
*/
|
||||
if (pt == NULL)
|
||||
return(cflag ? 0 : 1);
|
||||
return cflag ? 0 : 1;
|
||||
|
||||
/*
|
||||
* We had a match, now when we invert the sense (-c) we reject this
|
||||
* we had a match, now when we invert the sense (-c) we reject this
|
||||
* member. However we have to tag the pattern a being successful, (in a
|
||||
* match, not in selecting an archive member) so we call pat_sel() here.
|
||||
* match, not in selecting an archive member) so we call pat_sel()
|
||||
* here.
|
||||
*/
|
||||
arcn->pat = pt;
|
||||
if (!cflag)
|
||||
return(0);
|
||||
return 0;
|
||||
|
||||
if (pat_sel(arcn) < 0)
|
||||
return(-1);
|
||||
return -1;
|
||||
arcn->pat = NULL;
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -489,7 +510,7 @@ pat_match(ARCHD *arcn)
|
|||
*/
|
||||
|
||||
static int
|
||||
fn_match(char *pattern, char *string, char **pend)
|
||||
fn_match(char *pattern, char *string, char **pend, int noglob)
|
||||
{
|
||||
char c;
|
||||
char test;
|
||||
|
@ -502,25 +523,29 @@ fn_match(char *pattern, char *string, char **pend)
|
|||
* Ok we found an exact match
|
||||
*/
|
||||
if (*string == '\0')
|
||||
return(0);
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Check if it is a prefix match
|
||||
*/
|
||||
if ((dflag == 1) || (*string != '/'))
|
||||
return(-1);
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* It is a prefix match, remember where the trailing
|
||||
* / is located
|
||||
*/
|
||||
*pend = string;
|
||||
return(0);
|
||||
return 0;
|
||||
case '?':
|
||||
if (noglob)
|
||||
goto regular;
|
||||
if ((test = *string++) == '\0')
|
||||
return (-1);
|
||||
break;
|
||||
case '*':
|
||||
if (noglob)
|
||||
goto regular;
|
||||
c = *pattern;
|
||||
/*
|
||||
* Collapse multiple *'s.
|
||||
|
@ -538,12 +563,14 @@ fn_match(char *pattern, char *string, char **pend)
|
|||
* General case, use recursion.
|
||||
*/
|
||||
while ((test = *string) != '\0') {
|
||||
if (!fn_match(pattern, string, pend))
|
||||
if (!fn_match(pattern, string, pend, noglob))
|
||||
return (0);
|
||||
++string;
|
||||
}
|
||||
return (-1);
|
||||
case '[':
|
||||
if (noglob)
|
||||
goto regular;
|
||||
/*
|
||||
* range match
|
||||
*/
|
||||
|
@ -553,6 +580,7 @@ fn_match(char *pattern, char *string, char **pend)
|
|||
break;
|
||||
case '\\':
|
||||
default:
|
||||
regular:
|
||||
if (c != *string++)
|
||||
return (-1);
|
||||
break;
|
||||
|
@ -605,40 +633,23 @@ range_match(char *pattern, int test)
|
|||
*/
|
||||
|
||||
int
|
||||
mod_name(ARCHD *arcn)
|
||||
mod_name(ARCHD *arcn, int flags)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
/*
|
||||
* Strip off leading '/' if appropriate.
|
||||
* Currently, this option is only set for the tar format.
|
||||
*/
|
||||
if (rmleadslash && arcn->name[0] == '/') {
|
||||
if (arcn->name[1] == '\0') {
|
||||
arcn->name[0] = '.';
|
||||
} else {
|
||||
(void)memmove(arcn->name, &arcn->name[1],
|
||||
strlen(arcn->name));
|
||||
arcn->nlen--;
|
||||
if (secure) {
|
||||
if (checkdotdot(arcn->name)) {
|
||||
tty_warn(0, "Ignoring file containing `..' (%s)",
|
||||
arcn->name);
|
||||
return 1;
|
||||
}
|
||||
if (rmleadslash < 2) {
|
||||
rmleadslash = 2;
|
||||
paxwarn(0, "Removing leading / from absolute path names in the archive");
|
||||
}
|
||||
}
|
||||
if (rmleadslash && arcn->ln_name[0] == '/' &&
|
||||
(arcn->type == PAX_HLK || arcn->type == PAX_HRG)) {
|
||||
if (arcn->ln_name[1] == '\0') {
|
||||
arcn->ln_name[0] = '.';
|
||||
} else {
|
||||
(void)memmove(arcn->ln_name, &arcn->ln_name[1],
|
||||
strlen(arcn->ln_name));
|
||||
arcn->ln_nlen--;
|
||||
}
|
||||
if (rmleadslash < 2) {
|
||||
rmleadslash = 2;
|
||||
paxwarn(0, "Removing leading / from absolute path names in the archive");
|
||||
#ifdef notdef
|
||||
if (checkdotdot(arcn->ln_name)) {
|
||||
tty_warn(0, "Ignoring link containing `..' (%s)",
|
||||
arcn->ln_name);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -661,17 +672,21 @@ mod_name(ARCHD *arcn)
|
|||
* call an oracle here. :)
|
||||
*/
|
||||
if (rephead != NULL) {
|
||||
flags |= (flags & RENM) ? PRNT : 0;
|
||||
/*
|
||||
* we have replacement strings, modify the name and the link
|
||||
* name if any.
|
||||
*/
|
||||
if ((res = rep_name(arcn->name, &(arcn->nlen), 1)) != 0)
|
||||
return(res);
|
||||
if ((res = rep_name(arcn->name, sizeof(arcn->name),
|
||||
&(arcn->nlen), flags)) != 0)
|
||||
return res;
|
||||
|
||||
if (((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) ||
|
||||
(arcn->type == PAX_HRG)) &&
|
||||
((res = rep_name(arcn->ln_name, &(arcn->ln_nlen), 0)) != 0))
|
||||
return(res);
|
||||
((res = rep_name(arcn->ln_name,
|
||||
sizeof(arcn->ln_name), &(arcn->ln_nlen),
|
||||
flags | (arcn->type == PAX_SLK ? SYML : 0))) != 0))
|
||||
return res;
|
||||
}
|
||||
|
||||
if (iflag) {
|
||||
|
@ -679,12 +694,45 @@ mod_name(ARCHD *arcn)
|
|||
* perform interactive file rename, then map the link if any
|
||||
*/
|
||||
if ((res = tty_rename(arcn)) != 0)
|
||||
return(res);
|
||||
return res;
|
||||
if ((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) ||
|
||||
(arcn->type == PAX_HRG))
|
||||
sub_name(arcn->ln_name, &(arcn->ln_nlen), sizeof(arcn->ln_name));
|
||||
}
|
||||
return(res);
|
||||
|
||||
/*
|
||||
* Strip off leading '/' if appropriate.
|
||||
* Currently, this option is only set for the tar format.
|
||||
*/
|
||||
if (rmleadslash && arcn->name[0] == '/') {
|
||||
if (arcn->name[1] == '\0') {
|
||||
arcn->name[0] = '.';
|
||||
} else {
|
||||
(void)memmove(arcn->name, &arcn->name[1],
|
||||
strlen(arcn->name));
|
||||
arcn->nlen--;
|
||||
}
|
||||
if (rmleadslash < 2) {
|
||||
rmleadslash = 2;
|
||||
tty_warn(0, "Removing leading / from absolute path names in the archive");
|
||||
}
|
||||
}
|
||||
if (rmleadslash && arcn->ln_name[0] == '/' &&
|
||||
(arcn->type == PAX_HLK || arcn->type == PAX_HRG)) {
|
||||
if (arcn->ln_name[1] == '\0') {
|
||||
arcn->ln_name[0] = '.';
|
||||
} else {
|
||||
(void)memmove(arcn->ln_name, &arcn->ln_name[1],
|
||||
strlen(arcn->ln_name));
|
||||
arcn->ln_nlen--;
|
||||
}
|
||||
if (rmleadslash < 2) {
|
||||
rmleadslash = 2;
|
||||
tty_warn(0, "Removing leading / from absolute path names in the archive");
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -717,7 +765,7 @@ tty_rename(ARCHD *arcn)
|
|||
tty_prnt("or a \"return\" to skip this file.\n");
|
||||
tty_prnt("Input > ");
|
||||
if (tty_read(tmpname, sizeof(tmpname)) < 0)
|
||||
return(-1);
|
||||
return -1;
|
||||
if (strcmp(tmpname, "..") == 0) {
|
||||
tty_prnt("Try again, illegal file name: ..\n");
|
||||
continue;
|
||||
|
@ -734,11 +782,11 @@ tty_rename(ARCHD *arcn)
|
|||
*/
|
||||
if (tmpname[0] == '\0') {
|
||||
tty_prnt("Skipping file.\n");
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
if ((tmpname[0] == '.') && (tmpname[1] == '\0')) {
|
||||
tty_prnt("Processing continues, name unchanged.\n");
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -748,11 +796,10 @@ tty_rename(ARCHD *arcn)
|
|||
*/
|
||||
tty_prnt("Processing continues, name changed to: %s\n", tmpname);
|
||||
res = add_name(arcn->name, arcn->nlen, tmpname);
|
||||
arcn->nlen = l_strncpy(arcn->name, tmpname, sizeof(arcn->name) - 1);
|
||||
arcn->name[arcn->nlen] = '\0';
|
||||
arcn->nlen = strlcpy(arcn->name, tmpname, sizeof(arcn->name));
|
||||
if (res < 0)
|
||||
return(-1);
|
||||
return(0);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -767,7 +814,7 @@ int
|
|||
set_dest(ARCHD *arcn, char *dest_dir, int dir_len)
|
||||
{
|
||||
if (fix_path(arcn->name, &(arcn->nlen), dest_dir, dir_len) < 0)
|
||||
return(-1);
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* It is really hard to deal with symlinks here, we cannot be sure
|
||||
|
@ -775,11 +822,11 @@ set_dest(ARCHD *arcn, char *dest_dir, int dir_len)
|
|||
* leave them alone.
|
||||
*/
|
||||
if ((arcn->type != PAX_HLK) && (arcn->type != PAX_HRG))
|
||||
return(0);
|
||||
return 0;
|
||||
|
||||
if (fix_path(arcn->ln_name, &(arcn->ln_nlen), dest_dir, dir_len) < 0)
|
||||
return(-1);
|
||||
return(0);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -812,8 +859,8 @@ fix_path( char *or_name, int *or_len, char *dir_name, int dir_len)
|
|||
--dest;
|
||||
}
|
||||
if ((len = dest - or_name) > PAXPATHLEN) {
|
||||
paxwarn(1, "File name %s/%s, too long", dir_name, start);
|
||||
return(-1);
|
||||
tty_warn(1, "File name %s/%s, too long", dir_name, start);
|
||||
return -1;
|
||||
}
|
||||
*or_len = len;
|
||||
|
||||
|
@ -831,7 +878,7 @@ fix_path( char *or_name, int *or_len, char *dir_name, int dir_len)
|
|||
*dest-- = *src--;
|
||||
|
||||
*(or_name + len) = '\0';
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -845,6 +892,7 @@ fix_path( char *or_name, int *or_len, char *dir_name, int dir_len)
|
|||
* --Parameters--
|
||||
* name is the file name we are going to apply the regular expressions to
|
||||
* (and may be modified)
|
||||
* namelen the size of the name buffer.
|
||||
* nlen is the length of this name (and is modified to hold the length of
|
||||
* the final string).
|
||||
* prnt is a flag that says whether to print the final result.
|
||||
|
@ -854,7 +902,7 @@ fix_path( char *or_name, int *or_len, char *dir_name, int dir_len)
|
|||
*/
|
||||
|
||||
static int
|
||||
rep_name(char *name, int *nlen, int prnt)
|
||||
rep_name(char *name, size_t namelen, int *nlen, int flags)
|
||||
{
|
||||
REPLACE *pt;
|
||||
char *inpt;
|
||||
|
@ -863,9 +911,7 @@ rep_name(char *name, int *nlen, int prnt)
|
|||
char *rpt;
|
||||
int found = 0;
|
||||
int res;
|
||||
# ifndef NET2_REGEX
|
||||
regmatch_t pm[MAXSUBEXP];
|
||||
# endif
|
||||
char nname[PAXPATHLEN+1]; /* final result of all replacements */
|
||||
char buf1[PAXPATHLEN+1]; /* where we work on the name */
|
||||
|
||||
|
@ -888,15 +934,13 @@ rep_name(char *name, int *nlen, int prnt)
|
|||
*/
|
||||
while (pt != NULL) {
|
||||
do {
|
||||
if ((flags & SYML) && (pt->flgs & SYML))
|
||||
continue;
|
||||
/*
|
||||
* check for a successful substitution, if not go to
|
||||
* the next pattern, or cleanup if we were global
|
||||
*/
|
||||
# ifdef NET2_REGEX
|
||||
if (regexec(pt->rcmp, inpt) == 0)
|
||||
# else
|
||||
if (regexec(&(pt->rcmp), inpt, MAXSUBEXP, pm, 0) != 0)
|
||||
# endif
|
||||
break;
|
||||
|
||||
/*
|
||||
|
@ -907,11 +951,7 @@ rep_name(char *name, int *nlen, int prnt)
|
|||
* do not create a string too long).
|
||||
*/
|
||||
found = 1;
|
||||
# ifdef NET2_REGEX
|
||||
rpt = pt->rcmp->startp[0];
|
||||
# else
|
||||
rpt = inpt + pm[0].rm_so;
|
||||
# endif
|
||||
|
||||
while ((inpt < rpt) && (outpt < endpt))
|
||||
*outpt++ = *inpt++;
|
||||
|
@ -924,16 +964,13 @@ rep_name(char *name, int *nlen, int prnt)
|
|||
* replacement string and place it the prefix in the
|
||||
* final output. If we have problems, skip it.
|
||||
*/
|
||||
# ifdef NET2_REGEX
|
||||
if ((res = resub(pt->rcmp,pt->nstr,outpt,endpt)) < 0) {
|
||||
# else
|
||||
if ((res = resub(&(pt->rcmp),pm,pt->nstr,outpt,endpt))
|
||||
< 0) {
|
||||
# endif
|
||||
if (prnt)
|
||||
paxwarn(1, "Replacement name error %s",
|
||||
if ((res =
|
||||
resub(&(pt->rcmp),pm,pt->nstr,inpt, outpt,endpt)
|
||||
) < 0) {
|
||||
if (flags & PRNT)
|
||||
tty_warn(1, "Replacement name error %s",
|
||||
name);
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
outpt += res;
|
||||
|
||||
|
@ -947,11 +984,7 @@ rep_name(char *name, int *nlen, int prnt)
|
|||
* the final result. Make sure we do not overrun the
|
||||
* output buffer
|
||||
*/
|
||||
# ifdef NET2_REGEX
|
||||
inpt = pt->rcmp->endp[0];
|
||||
# else
|
||||
inpt += pm[0].rm_eo - pm[0].rm_so;
|
||||
# endif
|
||||
|
||||
if ((outpt == endpt) || (*inpt == '\0'))
|
||||
break;
|
||||
|
@ -981,16 +1014,16 @@ rep_name(char *name, int *nlen, int prnt)
|
|||
|
||||
*outpt = '\0';
|
||||
if ((outpt == endpt) && (*inpt != '\0')) {
|
||||
if (prnt)
|
||||
paxwarn(1,"Replacement name too long %s >> %s",
|
||||
if (flags & PRNT)
|
||||
tty_warn(1,"Replacement name too long %s >> %s",
|
||||
name, nname);
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* inform the user of the result if wanted
|
||||
*/
|
||||
if (prnt && (pt->flgs & PRNT)) {
|
||||
if ((flags & PRNT) && (pt->flgs & PRNT)) {
|
||||
if (*nname == '\0')
|
||||
(void)fprintf(stderr,"%s >> <empty string>\n",
|
||||
name);
|
||||
|
@ -1003,73 +1036,53 @@ rep_name(char *name, int *nlen, int prnt)
|
|||
* otherwise copy the new name over the orig name and return
|
||||
*/
|
||||
if (*nname == '\0')
|
||||
return(1);
|
||||
*nlen = l_strncpy(name, nname, PAXPATHLEN + 1);
|
||||
name[PAXPATHLEN] = '\0';
|
||||
return 1;
|
||||
if (flags & RENM)
|
||||
*nlen = strlcpy(name, nname, namelen);
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef NET2_REGEX
|
||||
/*
|
||||
* resub()
|
||||
* apply the replacement to the matched expression. expand out the old
|
||||
* style ed(1) subexpression expansion.
|
||||
* Return:
|
||||
* -1 if error, or the number of characters added to the destination.
|
||||
*/
|
||||
|
||||
/*
|
||||
* checkdotdot()
|
||||
* Return true if a component of the name contains a reference to ".."
|
||||
*/
|
||||
static int
|
||||
resub(regexp *prog, char *src, char *dest, char *destend)
|
||||
checkdotdot(const char *name)
|
||||
{
|
||||
char *spt;
|
||||
char *dpt;
|
||||
char c;
|
||||
int no;
|
||||
int len;
|
||||
const char *p;
|
||||
/* 1. "..{[/],}" */
|
||||
if (name[0] == '.' && name[1] == '.' &&
|
||||
(name[2] == '/' || name[2] == '\0'))
|
||||
return 1;
|
||||
|
||||
spt = src;
|
||||
dpt = dest;
|
||||
while ((dpt < destend) && ((c = *spt++) != '\0')) {
|
||||
if (c == '&')
|
||||
no = 0;
|
||||
else if ((c == '\\') && (*spt >= '0') && (*spt <= '9'))
|
||||
no = *spt++ - '0';
|
||||
else {
|
||||
if ((c == '\\') && ((*spt == '\\') || (*spt == '&')))
|
||||
c = *spt++;
|
||||
*dpt++ = c;
|
||||
continue;
|
||||
}
|
||||
if ((prog->startp[no] == NULL) || (prog->endp[no] == NULL) ||
|
||||
((len = prog->endp[no] - prog->startp[no]) <= 0))
|
||||
continue;
|
||||
/* 2. "*[/]..[/]*" */
|
||||
if (strstr(name, "/../") != NULL)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* copy the subexpression to the destination.
|
||||
* fail if we run out of space or the match string is damaged
|
||||
*/
|
||||
if (len > (destend - dpt))
|
||||
len = destend - dpt;
|
||||
if (l_strncpy(dpt, prog->startp[no], len) != len)
|
||||
return(-1);
|
||||
dpt += len;
|
||||
}
|
||||
return(dpt - dest);
|
||||
/* 3. "*[/].." */
|
||||
for (p = name; *p; p++)
|
||||
continue;
|
||||
if (p - name < 3)
|
||||
return 0;
|
||||
if (p[-1] == '.' && p[-2] == '.' && p[-3] == '/')
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* resub()
|
||||
* apply the replacement to the matched expression. expand out the old
|
||||
* style ed(1) subexpression expansion.
|
||||
* style ed(1) subexpression expansion.
|
||||
* Return:
|
||||
* -1 if error, or the number of characters added to the destination.
|
||||
*/
|
||||
|
||||
static int
|
||||
resub(regex_t *rp, regmatch_t *pm, char *src, char *dest,
|
||||
resub(regex_t *rp, regmatch_t *pm, char *src, char *txt, char *dest,
|
||||
char *destend)
|
||||
{
|
||||
char *spt;
|
||||
|
@ -1089,20 +1102,20 @@ resub(regex_t *rp, regmatch_t *pm, char *src, char *dest,
|
|||
*/
|
||||
if (c == '&') {
|
||||
pmpt = pm;
|
||||
} else if ((c == '\\') && (*spt >= '0') && (*spt <= '9')) {
|
||||
} else if ((c == '\\') && (*spt >= '1') && (*spt <= '9')) {
|
||||
/*
|
||||
* make sure there is a subexpression as specified
|
||||
*/
|
||||
if ((len = *spt++ - '0') > subexcnt)
|
||||
return(-1);
|
||||
return -1;
|
||||
pmpt = pm + len;
|
||||
} else {
|
||||
/*
|
||||
/*
|
||||
* Ordinary character, just copy it
|
||||
*/
|
||||
if ((c == '\\') && ((*spt == '\\') || (*spt == '&')))
|
||||
c = *spt++;
|
||||
*dpt++ = c;
|
||||
if ((c == '\\') && ((*spt == '\\') || (*spt == '&')))
|
||||
c = *spt++;
|
||||
*dpt++ = c;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1118,11 +1131,9 @@ resub(regex_t *rp, regmatch_t *pm, char *src, char *dest,
|
|||
* fail if we run out of space or the match string is damaged
|
||||
*/
|
||||
if (len > (destend - dpt))
|
||||
len = destend - dpt;
|
||||
if (l_strncpy(dpt, src + pmpt->rm_so, len) != len)
|
||||
return(-1);
|
||||
return -1;
|
||||
strncpy(dpt, txt + pmpt->rm_so, len);
|
||||
dpt += len;
|
||||
}
|
||||
return(dpt - dest);
|
||||
return dpt - dest;
|
||||
}
|
||||
#endif
|
|
@ -1,3 +1,5 @@
|
|||
/* $NetBSD: pat_rep.h,v 1.7 2008/02/24 20:42:46 joerg Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -14,7 +16,7 @@
|
|||
* 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.
|
||||
* 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.
|
||||
*
|
||||
|
@ -31,21 +33,19 @@
|
|||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)pat_rep.h 8.1 (Berkeley) 5/31/93
|
||||
* $FreeBSD: src/bin/pax/pat_rep.h,v 1.6 2004/04/06 20:06:48 markm Exp $
|
||||
*/
|
||||
|
||||
#include <regex.h>
|
||||
/*
|
||||
* data structure for storing user supplied replacement strings (-s)
|
||||
*/
|
||||
typedef struct replace {
|
||||
char *nstr; /* the new string we will substitute with */
|
||||
# ifdef NET2_REGEX
|
||||
regexp *rcmp; /* compiled regular expression used to match */
|
||||
# else
|
||||
regex_t rcmp; /* compiled regular expression used to match */
|
||||
# endif
|
||||
int flgs; /* print conversions? global in operation? */
|
||||
#define PRNT 0x1
|
||||
#define GLOB 0x2
|
||||
#define RENM 0x4
|
||||
#define SYML 0x8
|
||||
struct replace *fow; /* pointer to next pattern */
|
||||
} REPLACE;
|
|
@ -1,4 +1,5 @@
|
|||
.\"-
|
||||
.\" $NetBSD: pax.1,v 1.61 2011/06/19 07:34:24 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1992 Keith Muller.
|
||||
.\" Copyright (c) 1992, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
|
@ -14,7 +15,7 @@
|
|||
.\" 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.
|
||||
.\" 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.
|
||||
.\"
|
||||
|
@ -31,9 +32,8 @@
|
|||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)pax.1 8.4 (Berkeley) 4/18/94
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 3, 2004
|
||||
.Dd June 18, 2011
|
||||
.Dt PAX 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -41,147 +41,115 @@
|
|||
.Nd read and write file archives and copy directory hierarchies
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl cdnvz
|
||||
.Bk -words
|
||||
.Op Fl 0cdjnOVvz
|
||||
.Op Fl E Ar limit
|
||||
.Op Fl f Ar archive
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl N Ar dbdir
|
||||
.Op Fl s Ar replstr
|
||||
.Ar ...\&
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl U Ar user
|
||||
.Ar ...\&
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl G Ar group
|
||||
.Ar ...\&
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Oo
|
||||
.Fl T
|
||||
.Sm off
|
||||
.Op Ar from_date
|
||||
.Op Ar ,to_date
|
||||
.Oo , Ar to_date Oc
|
||||
.Sm on
|
||||
.Oc
|
||||
.Ar ...\&
|
||||
.Ek
|
||||
.Op Ar pattern ...\&
|
||||
.Nm
|
||||
.Fl r
|
||||
.Op Fl cdiknuvzDYZ
|
||||
.Bk -words
|
||||
.Op Fl AcDdijknOuVvYZz
|
||||
.Op Fl E Ar limit
|
||||
.Op Fl f Ar archive
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl N Ar dbdir
|
||||
.Op Fl o Ar options
|
||||
.Ar ...\&
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl p Ar string
|
||||
.Ar ...\&
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl s Ar replstr
|
||||
.Ar ...\&
|
||||
.Ek
|
||||
.Op Fl E Ar limit
|
||||
.Bk -words
|
||||
.Op Fl U Ar user
|
||||
.Ar ...\&
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl G Ar group
|
||||
.Ar ...\&
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Oo
|
||||
.Fl T
|
||||
.Sm off
|
||||
.Op Ar from_date
|
||||
.Op Ar ,to_date
|
||||
.Oo , Ar to_date Oc
|
||||
.Sm on
|
||||
.Oc
|
||||
.Ar ...\&
|
||||
.Ek
|
||||
.Op Ar pattern ...\&
|
||||
.Nm
|
||||
.Fl w
|
||||
.Op Fl dituvzHLPX
|
||||
.Bk -words
|
||||
.Op Fl AdHijLMOPtuVvXz
|
||||
.Op Fl b Ar blocksize
|
||||
.Ek
|
||||
.Oo
|
||||
.Op Fl a
|
||||
.Op Fl f Ar archive
|
||||
.Oc
|
||||
.Bk -words
|
||||
.Op Fl x Ar format
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl s Ar replstr
|
||||
.Ar ...\&
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl B Ar bytes
|
||||
.Op Fl N Ar dbdir
|
||||
.Op Fl o Ar options
|
||||
.Ar ...\&
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl s Ar replstr
|
||||
.Ar ...\&
|
||||
.Op Fl U Ar user
|
||||
.Ar ...\&
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl G Ar group
|
||||
.Ar ...\&
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl B Ar bytes
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Oo
|
||||
.Fl T
|
||||
.Sm off
|
||||
.Op Ar from_date
|
||||
.Op Ar ,to_date
|
||||
.Op Ar /[c][m]
|
||||
.Oo , Ar to_date Oc
|
||||
.Oo /[ Cm c ] [ Cm m ] Oc
|
||||
.Sm on
|
||||
.Oc
|
||||
.Ar ...\&
|
||||
.Ek
|
||||
.Op Ar
|
||||
.Op Ar file ...\&
|
||||
.Nm
|
||||
.Fl r
|
||||
.Fl w
|
||||
.Op Fl diklntuvDHLPXYZ
|
||||
.Bk -words
|
||||
.Op Fl ADdHijkLlMnOPtuVvXYZz
|
||||
.Op Fl N Ar dbdir
|
||||
.Op Fl p Ar string
|
||||
.Ar ...\&
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl s Ar replstr
|
||||
.Ar ...\&
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl U Ar user
|
||||
.Ar ...\&
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl G Ar group
|
||||
.Ar ...\&
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Oo
|
||||
.Fl T
|
||||
.Sm off
|
||||
.Op Ar from_date
|
||||
.Op Ar ,to_date
|
||||
.Op Ar /[c][m]
|
||||
.Oo , Ar to_date Oc
|
||||
.Oo /[ Cm c ] [ Cm m ] Oc
|
||||
.Sm on
|
||||
.Oc
|
||||
.Ar ...\&
|
||||
.Ek
|
||||
.Op Ar
|
||||
.Op Ar file ...\&
|
||||
.Ar directory
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility will read, write, and list the members of an archive file,
|
||||
will read, write, and list the members of an archive file,
|
||||
and will copy directory hierarchies.
|
||||
These operations are independent of the specific archive format,
|
||||
and support a wide variety of different archive formats.
|
||||
If the archive file is of the form:
|
||||
.Ar [[user@]host:]file
|
||||
then the archive will be processed using
|
||||
.Xr rmt 8 .
|
||||
.Pp
|
||||
.Nm
|
||||
operation is independent of the specific archive format,
|
||||
and supports a wide variety of different archive formats.
|
||||
A list of supported archive formats can be found under the description of the
|
||||
.Fl x
|
||||
option.
|
||||
|
@ -197,9 +165,10 @@ will operate under:
|
|||
and
|
||||
.Em copy .
|
||||
.Bl -tag -width 6n
|
||||
.It <none>
|
||||
.It Aq none
|
||||
.Em List .
|
||||
Write to
|
||||
.Nm
|
||||
will write to
|
||||
.Dv standard output
|
||||
a table of contents of the members of the archive file read from
|
||||
.Dv standard input ,
|
||||
|
@ -209,7 +178,8 @@ The table of contents contains one filename per line
|
|||
and is written using single line buffering.
|
||||
.It Fl r
|
||||
.Em Read .
|
||||
Extract the members of the archive file read from the
|
||||
.Nm
|
||||
extracts the members of the archive file read from the
|
||||
.Dv standard input ,
|
||||
with pathnames matching the specified
|
||||
.Ar patterns .
|
||||
|
@ -223,7 +193,8 @@ the extracted files are discussed in more detail under the
|
|||
option.
|
||||
.It Fl w
|
||||
.Em Write .
|
||||
Write an archive containing the
|
||||
.Nm
|
||||
writes an archive containing the
|
||||
.Ar file
|
||||
operands to
|
||||
.Dv standard output
|
||||
|
@ -238,7 +209,8 @@ operand is also a directory, the entire file hierarchy rooted
|
|||
at that directory will be included.
|
||||
.It Fl r Fl w
|
||||
.Em Copy .
|
||||
Copy the
|
||||
.Nm
|
||||
copies the
|
||||
.Ar file
|
||||
operands to the destination
|
||||
.Ar directory .
|
||||
|
@ -394,10 +366,7 @@ block the output at a positive decimal integer number of
|
|||
bytes per write to the archive file.
|
||||
The
|
||||
.Ar blocksize
|
||||
must be a multiple of 512 bytes with a maximum of 64512 bytes.
|
||||
Archives larger than 32256 bytes violate the
|
||||
.Tn POSIX
|
||||
standard and will not be portable to all systems.
|
||||
must be a multiple of 512 bytes with a maximum of 32256 bytes.
|
||||
A
|
||||
.Ar blocksize
|
||||
can end with
|
||||
|
@ -458,21 +427,23 @@ operand,
|
|||
will prompt to
|
||||
.Pa /dev/tty
|
||||
giving the name of the file, its file mode and its modification time.
|
||||
The
|
||||
.Nm
|
||||
utility will then read a line from
|
||||
will then read a line from
|
||||
.Pa /dev/tty .
|
||||
If this line is blank, the file or archive member is skipped.
|
||||
If this line consists of a single period, the
|
||||
file or archive member is processed with no modification to its name.
|
||||
Otherwise, its name is replaced with the contents of the line.
|
||||
The
|
||||
.Nm
|
||||
utility will immediately exit with a non-zero exit status if
|
||||
.Dv <EOF>
|
||||
will immediately exit with a non-zero exit status if
|
||||
.Aq Dv EOF
|
||||
is encountered when reading a response or if
|
||||
.Pa /dev/tty
|
||||
cannot be opened for reading and writing.
|
||||
.It Fl j
|
||||
Use
|
||||
.Xr bzip2 1
|
||||
for compression when reading or writing archive files.
|
||||
.It Fl k
|
||||
Do not overwrite existing files.
|
||||
.It Fl l
|
||||
|
@ -481,7 +452,8 @@ Link files.
|
|||
In the
|
||||
.Em copy
|
||||
mode
|
||||
.Pq Fl r w ,
|
||||
.Fl ( r
|
||||
.Fl w ) ,
|
||||
hard links are made between the source and destination file hierarchies
|
||||
whenever possible.
|
||||
.It Fl n
|
||||
|
@ -509,7 +481,8 @@ The
|
|||
option-argument is a string specifying file characteristics to be retained or
|
||||
discarded on extraction.
|
||||
The string consists of the specification characters
|
||||
.Cm a , e , m , o ,
|
||||
.Cm a , e ,
|
||||
.Cm m , o ,
|
||||
and
|
||||
.Cm p .
|
||||
Multiple characteristics can be concatenated within the same string
|
||||
|
@ -536,6 +509,9 @@ flag is the sum of the
|
|||
and
|
||||
.Cm p
|
||||
flags.
|
||||
.\" .It Cm f
|
||||
.\" Do not preserve file flags.
|
||||
.\" By default, file flags are preserved whenever possible.
|
||||
.It Cm m
|
||||
Do not preserve file modification times.
|
||||
By default, file modification times are preserved whenever possible.
|
||||
|
@ -544,7 +520,7 @@ Preserve the user ID and group ID.
|
|||
.It Cm p
|
||||
.Sq Preserve
|
||||
the file mode bits.
|
||||
This intended to be used by a
|
||||
This is intended to be used by a
|
||||
.Em user
|
||||
with regular privileges who wants to preserve all aspects of the file other
|
||||
than the ownership.
|
||||
|
@ -602,12 +578,12 @@ As in
|
|||
.Cm old
|
||||
is a basic regular expression and
|
||||
.Cm new
|
||||
can contain an ampersand (&), \\n (where n is a digit) back-references,
|
||||
can contain an ampersand (\*[Am]), \en (where n is a digit) back-references,
|
||||
or subexpression matching.
|
||||
The
|
||||
.Cm old
|
||||
string may also contain
|
||||
.Dv <newline>
|
||||
.Aq Dv newline
|
||||
characters.
|
||||
Any non-null character can be used as a delimiter (/ is shown here).
|
||||
Multiple
|
||||
|
@ -628,14 +604,16 @@ The optional trailing
|
|||
will cause the final result of a successful substitution to be written to
|
||||
.Dv standard error
|
||||
in the following format:
|
||||
.Dl <original pathname> >> <new pathname>
|
||||
.Dl Ao "original pathname" Ac \*[Gt]\*[Gt] Ao "new pathname" Ac
|
||||
File or archive member names that substitute to the empty string
|
||||
are not selected and will be skipped.
|
||||
.It Fl t
|
||||
Reset the access times of any file or directory read or accessed by
|
||||
.Nm
|
||||
to be the same as they were before being read or accessed by
|
||||
.Nm .
|
||||
.Nm ,
|
||||
if the user has the appropriate permissions required by
|
||||
.Xr utime 3 .
|
||||
.It Fl u
|
||||
Ignore files that are older (having a less recent file modification time)
|
||||
than a pre-existing file or archive member with the same name.
|
||||
|
@ -662,14 +640,15 @@ utility with the
|
|||
option.
|
||||
For pathnames representing a hard link to a previous member of the archive,
|
||||
the output has the format:
|
||||
.Dl <ls -l listing> == <link name>
|
||||
For pathnames representing a symbolic link, the output has the format:
|
||||
.Dl <ls -l listing> => <link name>
|
||||
Where <ls -l listing> is the output format specified by the
|
||||
.Dl Ao "ls -l listing" Ac == Ao "link name" Ac
|
||||
Where
|
||||
.Aq "ls -l listing"
|
||||
is the output format specified by the
|
||||
.Xr ls 1
|
||||
utility when used with the
|
||||
.Fl l
|
||||
option.
|
||||
.Pp
|
||||
Otherwise for all the other operational modes
|
||||
.Em ( read , write ,
|
||||
and
|
||||
|
@ -677,18 +656,20 @@ and
|
|||
pathnames are written and flushed to
|
||||
.Dv standard error
|
||||
without a trailing
|
||||
.Dv <newline>
|
||||
.Aq Dv newline
|
||||
as soon as processing begins on that file or
|
||||
archive member.
|
||||
The trailing
|
||||
.Dv <newline> ,
|
||||
.Aq Dv newline ,
|
||||
is not buffered, and is written only after the file has been read or written.
|
||||
.Pp
|
||||
A final summary of archive operations is printed after they have been
|
||||
completed.
|
||||
.It Fl x Ar format
|
||||
Specify the output archive format, with the default format being
|
||||
.Ar ustar .
|
||||
The
|
||||
.Nm
|
||||
utility currently supports the following formats:
|
||||
currently supports the following formats:
|
||||
.Bl -tag -width "sv4cpio"
|
||||
.It Ar cpio
|
||||
The extended cpio interchange format specified in the
|
||||
|
@ -709,14 +690,18 @@ by this format) which may be truncated by this format is detected by
|
|||
.Nm
|
||||
and is repaired.
|
||||
.It Ar sv4cpio
|
||||
The System V release 4 cpio.
|
||||
The
|
||||
.At V.4
|
||||
cpio.
|
||||
The default blocksize for this format is 5120 bytes.
|
||||
Inode and device information about a file (used for detecting file hard links
|
||||
by this format) which may be truncated by this format is detected by
|
||||
.Nm
|
||||
and is repaired.
|
||||
.It Ar sv4crc
|
||||
The System V release 4 cpio with file crc checksums.
|
||||
The
|
||||
.At V.4
|
||||
cpio with file crc checksums.
|
||||
The default blocksize for this format is 5120 bytes.
|
||||
Inode and device information about a file (used for detecting file hard links
|
||||
by this format) which may be truncated by this format is detected by
|
||||
|
@ -732,11 +717,11 @@ Pathnames stored by this format must be 100 characters or less in length.
|
|||
Only
|
||||
.Em regular
|
||||
files,
|
||||
.Em hard links , soft links ,
|
||||
.Em hard links , soft links ,
|
||||
and
|
||||
.Em directories
|
||||
will be archived (other file system types are not supported).
|
||||
For backwards compatibility with even older tar formats, a
|
||||
.Em directories
|
||||
will be archived (other file types are not supported).
|
||||
For backward compatibility with even older tar formats, a
|
||||
.Fl o
|
||||
option can be used when writing an archive to omit the storage of directories.
|
||||
This option takes the form:
|
||||
|
@ -749,19 +734,22 @@ The default blocksize for this format is 10240 bytes.
|
|||
Pathnames stored by this format must be 250 characters or less in length.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility will detect and report any file that it is unable to store or extract
|
||||
will detect and report any file that it is unable to store or extract
|
||||
as the result of any specific archive format restrictions.
|
||||
The individual archive formats may impose additional restrictions on use.
|
||||
Typical archive format restrictions include (but are not limited to):
|
||||
file pathname length, file size, link pathname length and the type of the file.
|
||||
.It Fl Fl xz
|
||||
Use
|
||||
.Xr xz 1
|
||||
compression, when reading or writing archive files.
|
||||
.It Fl z
|
||||
Use
|
||||
.Xr gzip 1
|
||||
to compress (decompress) the archive while writing (reading).
|
||||
Incompatible with
|
||||
.Fl a .
|
||||
compression, when reading or writing archive files.
|
||||
.It Fl A
|
||||
Do not strip leading `/'s from file names.
|
||||
.It Fl B Ar bytes
|
||||
Limit the number of bytes written to a single archive volume to
|
||||
.Ar bytes .
|
||||
|
@ -790,7 +778,7 @@ This option is the same as the
|
|||
option, except that the file inode change time is checked instead of the
|
||||
file modification time.
|
||||
The file inode change time can be used to select files whose inode information
|
||||
(e.g.\& uid, gid, etc.) is newer than a copy of the file in the destination
|
||||
(e.g. uid, gid, etc.) is newer than a copy of the file in the destination
|
||||
.Ar directory .
|
||||
.It Fl E Ar limit
|
||||
Limit the number of consecutive read faults while trying to read a flawed
|
||||
|
@ -829,7 +817,7 @@ Select a file based on its
|
|||
name, or when starting with a
|
||||
.Cm # ,
|
||||
a numeric gid.
|
||||
A '\\' can be used to escape the
|
||||
A '\e' can be used to escape the
|
||||
.Cm # .
|
||||
Multiple
|
||||
.Fl G
|
||||
|
@ -839,6 +827,75 @@ Follow only command line symbolic links while performing a physical file
|
|||
system traversal.
|
||||
.It Fl L
|
||||
Follow all symbolic links to perform a logical file system traversal.
|
||||
.It Fl M
|
||||
During a
|
||||
.Em write
|
||||
or
|
||||
.Em copy
|
||||
operation, treat the list of files on
|
||||
.Dv standard input
|
||||
as an
|
||||
.Xr mtree 8
|
||||
.Sq specfile
|
||||
specification, and write or copy only those items in the specfile.
|
||||
.Pp
|
||||
If the file exists in the underlying file system, its permissions and
|
||||
modification time will be used unless specifically overridden by the specfile.
|
||||
An error will be raised if the type of entry in the specfile conflicts
|
||||
with that of an existing file.
|
||||
A directory entry that is marked
|
||||
.Sq Sy optional
|
||||
will not be copied (even though its contents will be).
|
||||
.Pp
|
||||
Otherwise, the entry will be
|
||||
.Sq faked-up ,
|
||||
and it is necessary to specify at least the following parameters
|
||||
in the specfile:
|
||||
.Sy type ,
|
||||
.Sy mode ,
|
||||
.Sy gname
|
||||
or
|
||||
.Sy gid ,
|
||||
and
|
||||
.Sy uname
|
||||
or
|
||||
.Sy uid ,
|
||||
.Sy device
|
||||
(in the case of block or character devices), and
|
||||
.Sy link
|
||||
(in the case of symbolic links).
|
||||
If
|
||||
.Sy time
|
||||
isn't provided, the current time will be used.
|
||||
A
|
||||
.Sq faked-up
|
||||
entry that is marked
|
||||
.Sq Sy optional
|
||||
will not be copied.
|
||||
.It Fl N Ar dbdir
|
||||
Except for lookups for the
|
||||
.Fl G
|
||||
and
|
||||
.Fl U
|
||||
options,
|
||||
use the user database text file
|
||||
.Pa master.passwd
|
||||
and group database text file
|
||||
.Pa group
|
||||
from
|
||||
.Ar dbdir ,
|
||||
rather than using the results from the system's
|
||||
.Xr getpwnam 3
|
||||
and
|
||||
.Xr getgrnam 3
|
||||
(and related) library calls.
|
||||
.It Fl O
|
||||
Force the archive to be one volume.
|
||||
If a volume ends prematurely,
|
||||
.Nm
|
||||
will not prompt for a new volume.
|
||||
This option can be useful for
|
||||
automated tasks where error recovery cannot be performed by a human.
|
||||
.It Fl P
|
||||
Do not follow symbolic links, perform a physical file system traversal.
|
||||
This is the default mode.
|
||||
|
@ -882,7 +939,7 @@ the file was last written).
|
|||
The
|
||||
.Ar c
|
||||
specifies the comparison of inode change time (the time when the file
|
||||
inode was last changed; e.g.\& a change of owner, group, mode, etc).
|
||||
inode was last changed; e.g. a change of owner, group, mode, etc).
|
||||
When
|
||||
.Ar c
|
||||
and
|
||||
|
@ -902,8 +959,10 @@ changed during a specified time range will be archived).
|
|||
A time range is made up of six different fields and each field must contain two
|
||||
digits.
|
||||
The format is:
|
||||
.Dl [yy[mm[dd[hh]]]]mm[.ss]
|
||||
.Dl [[[[[cc]yy]mm]dd]hh]mm[\&.ss]
|
||||
Where
|
||||
.Cm cc
|
||||
is the first two digits of the year (the century),
|
||||
.Cm yy
|
||||
is the last two digits of the year,
|
||||
the first
|
||||
|
@ -918,15 +977,15 @@ the second
|
|||
is the minute (from 00 to 59),
|
||||
and
|
||||
.Cm ss
|
||||
is the seconds (from 00 to 59).
|
||||
The minute field
|
||||
is the seconds (from 00 to 61).
|
||||
Only the minute field
|
||||
.Cm mm
|
||||
is required, while the other fields are optional and must be added in the
|
||||
following order:
|
||||
.Dl Cm hh , dd , mm , yy .
|
||||
is required; the others will default to the current system values.
|
||||
The
|
||||
.Cm ss
|
||||
field may be added independently of the other fields.
|
||||
If the century is not specified, it defaults to 1900 for
|
||||
years between 69 and 99, or 2000 for years between 0 and 68.
|
||||
Time ranges are relative to the current time, so
|
||||
.Dl Fl T Ar 1234/cm
|
||||
would select all files with a modification or inode change time
|
||||
|
@ -940,11 +999,15 @@ Select a file based on its
|
|||
name, or when starting with a
|
||||
.Cm # ,
|
||||
a numeric uid.
|
||||
A '\\' can be used to escape the
|
||||
A '\e' can be used to escape the
|
||||
.Cm # .
|
||||
Multiple
|
||||
.Fl U
|
||||
options may be supplied and checking stops with the first match.
|
||||
.It Fl V
|
||||
A final summary of archive operations is printed after they have been
|
||||
completed.
|
||||
Some potentially long-running tape operations are noted.
|
||||
.It Fl X
|
||||
When traversing the file hierarchy specified by a pathname,
|
||||
do not descend into directories that have a different device ID.
|
||||
|
@ -963,6 +1026,24 @@ This option is the same as the
|
|||
.Fl u
|
||||
option, except that the modification time is checked using the
|
||||
pathname created after all the file name modifications have completed.
|
||||
.It Fl 0
|
||||
Use the nul character instead of \en as the file separator when reading
|
||||
files from standard input.
|
||||
.It Fl Fl force-local
|
||||
Do not interpret filenames that contain a `:' as remote files.
|
||||
.It Fl Fl insecure
|
||||
Normally
|
||||
.Nm
|
||||
ignores filenames that contain
|
||||
.Dq ..
|
||||
as a path component.
|
||||
With this option,
|
||||
files that contain
|
||||
.Dq ..
|
||||
can be processed.
|
||||
.It Fl Fl use-compress-program
|
||||
Use the named program as the program to decompress the input or compress
|
||||
the output.
|
||||
.El
|
||||
.Pp
|
||||
The options that operate on the names of files or archive members
|
||||
|
@ -1050,66 +1131,15 @@ options are specified along with the
|
|||
option, a file is not considered selected unless it is newer
|
||||
than the file to which it is compared.
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
utility will exit with one of the following values:
|
||||
will exit with one of the following values:
|
||||
.Bl -tag -width 2n
|
||||
.It 0
|
||||
All files were processed successfully.
|
||||
.It 1
|
||||
An error occurred.
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
The command:
|
||||
.Dl "pax -w -f /dev/sa0 ."
|
||||
copies the contents of the current directory to the device
|
||||
.Pa /dev/sa0 .
|
||||
.Pp
|
||||
The command:
|
||||
.Dl pax -v -f filename
|
||||
gives the verbose table of contents for an archive stored in
|
||||
.Pa filename .
|
||||
.Pp
|
||||
The following commands:
|
||||
.Dl mkdir /tmp/to
|
||||
.Dl cd /tmp/from
|
||||
.Dl pax -rw .\ /tmp/to
|
||||
will copy the entire
|
||||
.Pa /tmp/from
|
||||
directory hierarchy to
|
||||
.Pa /tmp/to .
|
||||
.Pp
|
||||
The command:
|
||||
.Dl pax -r -s ',^//*usr//*,,' -f a.pax
|
||||
reads the archive
|
||||
.Pa a.pax ,
|
||||
with all files rooted in ``/usr'' into the archive extracted relative to the
|
||||
current directory.
|
||||
.Pp
|
||||
The command:
|
||||
.Dl pax -rw -i .\ dest_dir
|
||||
can be used to interactively select the files to copy from the current
|
||||
directory to
|
||||
.Pa dest_dir .
|
||||
.Pp
|
||||
The command:
|
||||
.Dl pax -r -pe -U root -G bin -f a.pax
|
||||
will extract all files from the archive
|
||||
.Pa a.pax
|
||||
which are owned by
|
||||
.Em root
|
||||
with group
|
||||
.Em bin
|
||||
and will preserve all file permissions.
|
||||
.Pp
|
||||
The command:
|
||||
.Dl pax -r -w -v -Y -Z home /backup
|
||||
will update (and list) only those files in the destination directory
|
||||
.Pa /backup
|
||||
which are older (less recent inode change or file modification times) than
|
||||
files with the same name found in the source file tree
|
||||
.Pa home .
|
||||
.Sh DIAGNOSTICS
|
||||
Whenever
|
||||
.Nm
|
||||
cannot create a file or a link when reading an archive or cannot
|
||||
|
@ -1145,9 +1175,73 @@ a diagnostic message is written to
|
|||
and when
|
||||
.Nm
|
||||
completes it will exit with a non-zero exit status.
|
||||
.Sh EXAMPLES
|
||||
The command:
|
||||
.Dl pax -w -f /dev/rst0 \&.
|
||||
copies the contents of the current directory to the device
|
||||
.Pa /dev/rst0 .
|
||||
.Pp
|
||||
The command:
|
||||
.Dl pax -v -f filename
|
||||
gives the verbose table of contents for an archive stored in
|
||||
.Pa filename .
|
||||
.Pp
|
||||
The following commands:
|
||||
.Dl mkdir newdir
|
||||
.Dl cd olddir
|
||||
.Dl pax -rw -pp .\ ../newdir
|
||||
will copy the entire
|
||||
.Pa olddir
|
||||
directory hierarchy to
|
||||
.Pa newdir ,
|
||||
preserving permissions and access times.
|
||||
.Pp
|
||||
When running as root, one may also wish to preserve file
|
||||
ownership when copying directory trees.
|
||||
This can be done with the following commands:
|
||||
.Dl cd olddir
|
||||
.Dl pax -rw -pe .\ ../newdir
|
||||
which will copy the contents of
|
||||
.Pa olddir
|
||||
into
|
||||
.Pa ../newdir ,
|
||||
preserving ownership, permissions and access times.
|
||||
.Pp
|
||||
The command:
|
||||
.Dl pax -r -s ',^//*usr//*,,' -f a.pax
|
||||
reads the archive
|
||||
.Pa a.pax ,
|
||||
with all files rooted in ``/usr'' into the archive extracted relative to the
|
||||
current directory.
|
||||
.Pp
|
||||
The command:
|
||||
.Dl pax -rw -i .\ dest_dir
|
||||
can be used to interactively select the files to copy from the current
|
||||
directory to
|
||||
.Pa dest_dir .
|
||||
.Pp
|
||||
The command:
|
||||
.Dl pax -r -pe -U root -G bin -f a.pax
|
||||
will extract all files from the archive
|
||||
.Pa a.pax
|
||||
which are owned by
|
||||
.Em root
|
||||
with group
|
||||
.Em bin
|
||||
and will preserve all file permissions.
|
||||
.Pp
|
||||
The command:
|
||||
.Dl pax -r -w -v -Y -Z home /backup
|
||||
will update (and list) only those files in the destination directory
|
||||
.Pa /backup
|
||||
which are older (less recent inode change or file modification times) than
|
||||
files with the same name found in the source file tree
|
||||
.Pa home .
|
||||
.Sh SEE ALSO
|
||||
.Xr cpio 1 ,
|
||||
.Xr tar 1
|
||||
.Xr tar 1 ,
|
||||
.Xr symlink 7 ,
|
||||
.Xr mtree 8
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
|
@ -1155,18 +1249,20 @@ utility is a superset of the
|
|||
.St -p1003.2
|
||||
standard.
|
||||
The options
|
||||
.Fl z ,
|
||||
.Fl B ,
|
||||
.Fl D ,
|
||||
.Fl E ,
|
||||
.Fl G ,
|
||||
.Fl H ,
|
||||
.Fl L ,
|
||||
.Fl M ,
|
||||
.Fl O ,
|
||||
.Fl P ,
|
||||
.Fl T ,
|
||||
.Fl U ,
|
||||
.Fl Y ,
|
||||
.Fl Z ,
|
||||
.Fl z ,
|
||||
the archive formats
|
||||
.Ar bcpio ,
|
||||
.Ar sv4cpio ,
|
||||
|
@ -1179,15 +1275,7 @@ and
|
|||
operations are extensions to the
|
||||
.Tn POSIX
|
||||
standard.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility appeared in
|
||||
.Bx 4.4 .
|
||||
.Sh AUTHORS
|
||||
.An Keith Muller
|
||||
at the University of California, San Diego
|
||||
.Sh BUGS
|
||||
The
|
||||
.Nm
|
||||
utility does not recognize multibyte characters.
|
||||
Keith Muller at the University of California, San Diego.
|
||||
Luke Mewburn implemented
|
||||
.Fl M .
|
|
@ -1,3 +1,5 @@
|
|||
/* $NetBSD: pax.c,v 1.47 2011/08/29 14:47:48 joerg Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -14,7 +16,7 @@
|
|||
* 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.
|
||||
* 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.
|
||||
*
|
||||
|
@ -31,31 +33,35 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char const copyright[] =
|
||||
"@(#) Copyright (c) 1992, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)pax.c 8.2 (Berkeley) 4/18/94";
|
||||
#endif /* not lint */
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if !defined(lint)
|
||||
__COPYRIGHT("@(#) Copyright (c) 1992, 1993\
|
||||
The Regents of the University of California. All rights reserved.");
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)pax.c 8.2 (Berkeley) 4/18/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: pax.c,v 1.47 2011/08/29 14:47:48 joerg Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <locale.h>
|
||||
#include <paths.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <paths.h>
|
||||
#include <util.h>
|
||||
#include "pax.h"
|
||||
#include "extern.h"
|
||||
static int gen_init(void);
|
||||
|
@ -70,7 +76,7 @@ static int gen_init(void);
|
|||
int act = ERROR; /* read/write/append/copy */
|
||||
FSUB *frmt = NULL; /* archive format type */
|
||||
int cflag; /* match all EXCEPT pattern/file */
|
||||
int cwdfd; /* starting cwd */
|
||||
int cwdfd = -1; /* starting cwd */
|
||||
int dflag; /* directory member match only */
|
||||
int iflag; /* interactive file/archive rename */
|
||||
int kflag; /* do not overwrite existing files */
|
||||
|
@ -79,9 +85,12 @@ int nflag; /* select first archive member match */
|
|||
int tflag; /* restore access time after read */
|
||||
int uflag; /* ignore older modification time files */
|
||||
int vflag; /* produce verbose output */
|
||||
int Aflag; /* honor absolute path */
|
||||
int Dflag; /* same as uflag except inode change time */
|
||||
int Hflag; /* follow command line symlinks (write only) */
|
||||
int Lflag; /* follow symlinks when writing */
|
||||
int Mflag; /* treat stdin as an mtree(8) specfile */
|
||||
int Vflag; /* produce somewhat verbose output (no listing) */
|
||||
int Xflag; /* archive files with same device id only */
|
||||
int Yflag; /* same as Dflg except after name mode */
|
||||
int Zflag; /* same as uflg except after name mode */
|
||||
|
@ -89,22 +98,29 @@ int vfpart; /* is partial verbose output in progress */
|
|||
int patime = 1; /* preserve file access time */
|
||||
int pmtime = 1; /* preserve file modification times */
|
||||
int nodirs; /* do not create directories as needed */
|
||||
int pfflags = 1; /* preserve file flags */
|
||||
int pmode; /* preserve file mode bits */
|
||||
int pids; /* preserve file uid/gid */
|
||||
int rmleadslash = 0; /* remove leading '/' from pathnames */
|
||||
int exit_val; /* exit value */
|
||||
int docrc; /* check/create file crc */
|
||||
int to_stdout; /* extract to stdout */
|
||||
char *dirptr; /* destination dir in a copy */
|
||||
const char *argv0; /* root of argv[0] */
|
||||
char *ltmfrmt; /* -v locale time format (if any) */
|
||||
const char *argv0; /* root of argv[0] */
|
||||
sigset_t s_mask; /* signal mask for cleanup critical sect */
|
||||
FILE *listf; /* file pointer to print file list to */
|
||||
char *tempfile; /* tempfile to use for mkstemp(3) */
|
||||
char *tempbase; /* basename of tempfile to use for mkstemp(3) */
|
||||
int forcelocal; /* force local operation even if the name
|
||||
* contains a :
|
||||
*/
|
||||
int secure = 1; /* don't extract names that contain .. */
|
||||
|
||||
/*
|
||||
* PAX - Portable Archive Interchange
|
||||
*
|
||||
* A utility to read, write, and write lists of the members of archive
|
||||
* A utility to read, write, and write lists of the members of archive
|
||||
* files and copy directory hierarchies. A variety of archive formats
|
||||
* are supported (some are described in POSIX 1003.1 10.1):
|
||||
*
|
||||
|
@ -131,7 +147,7 @@ char *tempbase; /* basename of tempfile to use for mkstemp(3) */
|
|||
* of times to correct, or try to correct forever.
|
||||
* 1.4 Sparse files (lseek holes) stored on the archive (but stored with blocks
|
||||
* of all zeros will be restored with holes appropriate for the target
|
||||
* file system
|
||||
* filesystem
|
||||
* 1.5 The user is notified whenever something is found during archive
|
||||
* read operations which violates spec (but the read will continue).
|
||||
* 1.6 Multiple archive volumes can be read and may span over different
|
||||
|
@ -185,7 +201,7 @@ char *tempbase; /* basename of tempfile to use for mkstemp(3) */
|
|||
* 3 COPY ENHANCEMENTS
|
||||
* 3.1 Sparse files (lseek holes) can be copied without expanding the holes
|
||||
* into zero filled blocks. The file copy is created with holes which are
|
||||
* appropriate for the target file system
|
||||
* appropriate for the target filesystem
|
||||
* 3.2 Access time as well as modification time on copied file trees can be
|
||||
* preserved with the appropriate -p options.
|
||||
* 3.3 Access time reset with the -t applies to all file nodes (including
|
||||
|
@ -200,9 +216,9 @@ char *tempbase; /* basename of tempfile to use for mkstemp(3) */
|
|||
* more -G options.
|
||||
* 3.8 Symlinks which appear on the command line can be followed (without
|
||||
* following other symlinks; -H flag)
|
||||
* 3.9 File inode change time can be checked against existing file before
|
||||
* 3.9 File inode change time can be checked against existing file before
|
||||
* name modification (-D)
|
||||
* 3.10 File inode change time can be checked against existing file after
|
||||
* 3.10 File inode change time can be checked against existing file after
|
||||
* name modification (-Y)
|
||||
* 3.11 File modification time can be checked against existing file after
|
||||
* name modification (-Z)
|
||||
|
@ -222,21 +238,37 @@ char *tempbase; /* basename of tempfile to use for mkstemp(3) */
|
|||
*/
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
const char *tmpdir;
|
||||
size_t tdlen;
|
||||
int rval;
|
||||
|
||||
setprogname(argv[0]);
|
||||
|
||||
(void) setlocale(LC_ALL, "");
|
||||
listf = stderr;
|
||||
|
||||
/*
|
||||
* parse options, determine operational mode
|
||||
*/
|
||||
options(argc, argv);
|
||||
|
||||
/*
|
||||
* general init
|
||||
*/
|
||||
if ((gen_init() < 0) || (tty_init() < 0))
|
||||
return exit_val;
|
||||
|
||||
/*
|
||||
* Keep a reference to cwd, so we can always come back home.
|
||||
*/
|
||||
cwdfd = open(".", O_RDONLY);
|
||||
if (cwdfd < 0) {
|
||||
syswarn(0, errno, "Can't open current working directory.");
|
||||
return(exit_val);
|
||||
syswarn(1, errno, "Can't open current working directory.");
|
||||
return exit_val;
|
||||
}
|
||||
if (updatepath() == -1)
|
||||
return exit_val;
|
||||
|
||||
/*
|
||||
* Where should we put temporary files?
|
||||
|
@ -248,45 +280,52 @@ main(int argc, char *argv[])
|
|||
tdlen--;
|
||||
tempfile = malloc(tdlen + 1 + sizeof(_TFILE_BASE));
|
||||
if (tempfile == NULL) {
|
||||
paxwarn(1, "Cannot allocate memory for temp file name.");
|
||||
return(exit_val);
|
||||
tty_warn(1, "Cannot allocate memory for temp file name.");
|
||||
return exit_val;
|
||||
}
|
||||
if (tdlen)
|
||||
memcpy(tempfile, tmpdir, tdlen);
|
||||
tempbase = tempfile + tdlen;
|
||||
*tempbase++ = '/';
|
||||
|
||||
/*
|
||||
* parse options, determine operational mode, general init
|
||||
*/
|
||||
options(argc, argv);
|
||||
if ((gen_init() < 0) || (tty_init() < 0))
|
||||
return(exit_val);
|
||||
|
||||
(void)time(&starttime);
|
||||
#ifdef SIGINFO
|
||||
(void)signal(SIGINFO, ar_summary);
|
||||
#endif
|
||||
/*
|
||||
* select a primary operation mode
|
||||
*/
|
||||
switch(act) {
|
||||
switch (act) {
|
||||
case EXTRACT:
|
||||
extract();
|
||||
rval = extract();
|
||||
break;
|
||||
case ARCHIVE:
|
||||
archive();
|
||||
rval = archive();
|
||||
break;
|
||||
case APPND:
|
||||
if (gzip_program != NULL)
|
||||
err(1, "can not gzip while appending");
|
||||
append();
|
||||
err(1, "cannot gzip while appending");
|
||||
rval = append();
|
||||
/*
|
||||
* Check if we tried to append on an empty file and
|
||||
* turned into ARCHIVE mode.
|
||||
*/
|
||||
if (act == -ARCHIVE) {
|
||||
act = ARCHIVE;
|
||||
rval = archive();
|
||||
}
|
||||
break;
|
||||
case COPY:
|
||||
copy();
|
||||
rval = copy();
|
||||
break;
|
||||
default:
|
||||
case LIST:
|
||||
list();
|
||||
rval = list();
|
||||
break;
|
||||
}
|
||||
return(exit_val);
|
||||
if (rval != 0)
|
||||
exit_val = 1;
|
||||
return exit_val;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -298,7 +337,7 @@ main(int argc, char *argv[])
|
|||
* never....
|
||||
*/
|
||||
|
||||
void
|
||||
__dead static void
|
||||
sig_cleanup(int which_sig)
|
||||
{
|
||||
/*
|
||||
|
@ -307,18 +346,22 @@ sig_cleanup(int which_sig)
|
|||
* will clearly see the message on a line by itself.
|
||||
*/
|
||||
vflag = vfpart = 1;
|
||||
#if 0
|
||||
/* ignore this under minix */
|
||||
#ifdef SIGXCPU
|
||||
if (which_sig == SIGXCPU)
|
||||
paxwarn(0, "Cpu time limit reached, cleaning up.");
|
||||
tty_warn(1, "CPU time limit reached, cleaning up.");
|
||||
else
|
||||
#endif
|
||||
paxwarn(0, "Signal caught, cleaning up.");
|
||||
tty_warn(1, "Signal caught, cleaning up.");
|
||||
|
||||
/* delete any open temporary file */
|
||||
if (xtmp_name)
|
||||
(void)unlink(xtmp_name);
|
||||
ar_close();
|
||||
proc_dir();
|
||||
if (tflag)
|
||||
atdir_end();
|
||||
|
||||
(void)raise_default_signal(which_sig);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -331,13 +374,13 @@ sig_cleanup(int which_sig)
|
|||
static int
|
||||
gen_init(void)
|
||||
{
|
||||
#if 0
|
||||
#ifndef __minix
|
||||
struct rlimit reslimit;
|
||||
#endif
|
||||
struct sigaction n_hand;
|
||||
struct sigaction o_hand;
|
||||
|
||||
#if 0
|
||||
#ifndef __minix
|
||||
/*
|
||||
* Really needed to handle large archives. We can run out of memory for
|
||||
* internal tables really fast when we have a whole lot of files...
|
||||
|
@ -364,6 +407,7 @@ gen_init(void)
|
|||
(void)setrlimit(RLIMIT_STACK , &reslimit);
|
||||
}
|
||||
|
||||
#ifdef RLIMIT_RSS
|
||||
/*
|
||||
* not really needed, but doesn't hurt
|
||||
*/
|
||||
|
@ -372,24 +416,40 @@ gen_init(void)
|
|||
(void)setrlimit(RLIMIT_RSS , &reslimit);
|
||||
}
|
||||
#endif
|
||||
#endif /* __minix */
|
||||
|
||||
/*
|
||||
* Handle posix locale
|
||||
*
|
||||
* set user defines time printing format for -v option
|
||||
*/
|
||||
ltmfrmt = getenv("LC_TIME");
|
||||
|
||||
/*
|
||||
* signal handling to reset stored directory times and modes. Since
|
||||
* we deal with broken pipes via failed writes we ignore it. We also
|
||||
* deal with any file size limit thorugh failed writes. Cpu time
|
||||
* deal with any file size limit through failed writes. CPU time
|
||||
* limits are caught and a cleanup is forced.
|
||||
*/
|
||||
|
||||
if ((sigemptyset(&s_mask) < 0) || (sigaddset(&s_mask, SIGTERM) < 0) ||
|
||||
(sigaddset(&s_mask,SIGINT) < 0)||(sigaddset(&s_mask,SIGHUP) < 0) ||
|
||||
(sigaddset(&s_mask,SIGPIPE) < 0)||(sigaddset(&s_mask,SIGQUIT)<0)
|
||||
#if 0
|
||||
|| (sigaddset(&s_mask,SIGXCPU) < 0)||(sigaddset(&s_mask,SIGXFSZ)<0)
|
||||
#endif
|
||||
) {
|
||||
paxwarn(1, "Unable to set up signal mask");
|
||||
return(-1);
|
||||
(sigaddset(&s_mask,SIGPIPE) < 0)||(sigaddset(&s_mask,SIGQUIT)<0)){
|
||||
tty_warn(1, "Unable to set up signal mask");
|
||||
return -1;
|
||||
}
|
||||
#ifdef SIGXCPU
|
||||
if (sigaddset(&s_mask,SIGXCPU) < 0) {
|
||||
tty_warn(1, "Unable to set up signal mask");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#ifdef SIGXFSZ
|
||||
if (sigaddset(&s_mask,SIGXFSZ) < 0) {
|
||||
tty_warn(1, "Unable to set up signal mask");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(&n_hand, 0, sizeof n_hand);
|
||||
n_hand.sa_mask = s_mask;
|
||||
n_hand.sa_flags = 0;
|
||||
|
@ -415,25 +475,22 @@ gen_init(void)
|
|||
(sigaction(SIGQUIT, &o_hand, &o_hand) < 0))
|
||||
goto out;
|
||||
|
||||
#if 0
|
||||
#ifdef SIGXCPU
|
||||
if ((sigaction(SIGXCPU, &n_hand, &o_hand) < 0) &&
|
||||
(o_hand.sa_handler == SIG_IGN) &&
|
||||
(sigaction(SIGXCPU, &o_hand, &o_hand) < 0))
|
||||
goto out;
|
||||
#endif
|
||||
|
||||
n_hand.sa_handler = SIG_IGN;
|
||||
if ((sigaction(SIGPIPE, &n_hand, &o_hand) < 0)
|
||||
#if 0
|
||||
|| (sigaction(SIGXFSZ, &n_hand, &o_hand) < 0)
|
||||
#endif
|
||||
)
|
||||
|
||||
|
||||
if (sigaction(SIGPIPE, &n_hand, &o_hand) < 0)
|
||||
goto out;
|
||||
return(0);
|
||||
#ifdef SIGXFSZ
|
||||
if (sigaction(SIGXFSZ, &n_hand, &o_hand) < 0)
|
||||
goto out;
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
out:
|
||||
syswarn(1, errno, "Unable to set up signal handler");
|
||||
return(-1);
|
||||
return -1;
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
/* $NetBSD: pax.h,v 1.31 2012/08/09 08:09:21 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -14,7 +16,7 @@
|
|||
* 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.
|
||||
* 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.
|
||||
*
|
||||
|
@ -31,32 +33,31 @@
|
|||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)pax.h 8.2 (Berkeley) 4/18/94
|
||||
* $FreeBSD: src/bin/pax/pax.h,v 1.18 2004/04/06 20:06:48 markm Exp $
|
||||
*/
|
||||
|
||||
|
||||
#include <minix/config.h>
|
||||
#include <minix/const.h>
|
||||
#if ! HAVE_NBTOOL_CONFIG_H && !defined(__minix)
|
||||
#define HAVE_LUTIMES 1
|
||||
#define HAVE_STRUCT_STAT_ST_FLAGS 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* BSD PAX global data structures and constants.
|
||||
*/
|
||||
|
||||
#define MAXBLK 64512 /* MAX blocksize supported (posix SPEC) */
|
||||
#define MAXBLK 32256 /* MAX blocksize supported (posix SPEC) */
|
||||
/* WARNING: increasing MAXBLK past 32256 */
|
||||
/* will violate posix spec. */
|
||||
#define MAXBLK_POSIX 32256 /* MAX blocksize supported as per POSIX */
|
||||
#define BLKMULT 512 /* blocksize must be even mult of 512 bytes */
|
||||
/* Don't even think of changing this */
|
||||
#define DEVBLK 8192 /* default read blksize for devices */
|
||||
#define FILEBLK 10240 /* default read blksize for files */
|
||||
#define PAXPATHLEN 3072 /* maximum path length for pax. MUST be */
|
||||
/* longer than the system PATH_MAX */
|
||||
/* longer than the system MAXPATHLEN */
|
||||
|
||||
/*
|
||||
* Pax modes of operation
|
||||
*/
|
||||
#define ERROR -1 /* nothing selected */
|
||||
#define ERROR -1 /* nothing selected */
|
||||
#define LIST 0 /* List the file in an archive */
|
||||
#define EXTRACT 1 /* extract the files in an archive */
|
||||
#define ARCHIVE 2 /* write a new archive */
|
||||
|
@ -71,11 +72,69 @@
|
|||
#define ISBLK 2 /* block device */
|
||||
#define ISTAPE 3 /* tape drive */
|
||||
#define ISPIPE 4 /* pipe/socket */
|
||||
#ifdef SUPPORT_RMT
|
||||
#define ISRMT 5 /* rmt */
|
||||
#endif
|
||||
|
||||
typedef struct archd ARCHD;
|
||||
typedef struct fsub FSUB;
|
||||
typedef struct oplist OPLIST;
|
||||
typedef struct pattern PATTERN;
|
||||
/*
|
||||
* Pattern matching structure
|
||||
*
|
||||
* Used to store command line patterns
|
||||
*/
|
||||
typedef struct pattern {
|
||||
char *pstr; /* pattern to match, user supplied */
|
||||
char *pend; /* end of a prefix match */
|
||||
char *chdname; /* the dir to change to if not NULL. */
|
||||
int plen; /* length of pstr */
|
||||
int flgs; /* processing/state flags */
|
||||
#define MTCH 0x1 /* pattern has been matched */
|
||||
#define DIR_MTCH 0x2 /* pattern matched a directory */
|
||||
#define NOGLOB_MTCH 0x4 /* non-globbing match */
|
||||
struct pattern *fow; /* next pattern */
|
||||
} PATTERN;
|
||||
|
||||
/*
|
||||
* General Archive Structure (used internal to pax)
|
||||
*
|
||||
* This structure is used to pass information about archive members between
|
||||
* the format independent routines and the format specific routines. When
|
||||
* new archive formats are added, they must accept requests and supply info
|
||||
* encoded in a structure of this type. The name fields are declared statically
|
||||
* here, as there is only ONE of these floating around, size is not a major
|
||||
* consideration. Eventually converting the name fields to a dynamic length
|
||||
* may be required if and when the supporting operating system removes all
|
||||
* restrictions on the length of pathnames it will resolve.
|
||||
*/
|
||||
typedef struct {
|
||||
int nlen; /* file name length */
|
||||
char name[PAXPATHLEN+1]; /* file name */
|
||||
int ln_nlen; /* link name length */
|
||||
char ln_name[PAXPATHLEN+1]; /* name to link to (if any) */
|
||||
char *org_name; /* orig name in file system */
|
||||
char fts_name[PAXPATHLEN+1]; /* name from fts (for *org_name) */
|
||||
char *tmp_name; /* tmp name used to restore */
|
||||
PATTERN *pat; /* ptr to pattern match (if any) */
|
||||
struct stat sb; /* stat buffer see stat(2) */
|
||||
off_t pad; /* bytes of padding after file xfer */
|
||||
off_t skip; /* bytes of real data after header */
|
||||
/* IMPORTANT. The st_size field does */
|
||||
/* not always indicate the amount of */
|
||||
/* data following the header. */
|
||||
u_long crc; /* file crc */
|
||||
int type; /* type of file node */
|
||||
#define PAX_DIR 1 /* directory */
|
||||
#define PAX_CHR 2 /* character device */
|
||||
#define PAX_BLK 3 /* block device */
|
||||
#define PAX_REG 4 /* regular file */
|
||||
#define PAX_SLK 5 /* symbolic link */
|
||||
#define PAX_SCK 6 /* socket */
|
||||
#define PAX_FIF 7 /* fifo */
|
||||
#define PAX_HLK 8 /* hard link */
|
||||
#define PAX_HRG 9 /* hard link to a regular file */
|
||||
#define PAX_CTG 10 /* high performance file */
|
||||
#define PAX_GLL 11 /* GNU long symlink */
|
||||
#define PAX_GLF 12 /* GNU long file */
|
||||
} ARCHD;
|
||||
|
||||
/*
|
||||
* Format Specific Routine Table
|
||||
|
@ -87,13 +146,13 @@ typedef struct pattern PATTERN;
|
|||
* independent of the archive format. Data flow in and out of the format
|
||||
* dependent routines pass pointers to ARCHD structure (described below).
|
||||
*/
|
||||
struct fsub {
|
||||
typedef struct {
|
||||
const char *name; /* name of format, this is the name the user */
|
||||
/* gives to -x option to select it. */
|
||||
int bsz; /* default block size. used when the user */
|
||||
/* does not specify a blocksize for writing */
|
||||
/* Appends continue to with the blocksize */
|
||||
/* the archive is currently using. */
|
||||
/* the archive is currently using.*/
|
||||
int hsz; /* Header size in bytes. this is the size of */
|
||||
/* the smallest header this format supports. */
|
||||
/* Headers are assumed to fit in a BLKMULT. */
|
||||
|
@ -118,19 +177,18 @@ struct fsub {
|
|||
int (*st_rd)(void); /* initialize routine for read. so format */
|
||||
/* can set up tables etc before it starts */
|
||||
/* reading an archive */
|
||||
int (*rd)(ARCHD *, char *);
|
||||
/* read header routine. passed a pointer to */
|
||||
/* ARCHD. It must extract the info from the */
|
||||
/* format and store it in the ARCHD struct. */
|
||||
/* This routine is expected to fill all the */
|
||||
/* fields in the ARCHD (including stat buf) */
|
||||
/* 0 is returned when a valid header is */
|
||||
/* found. -1 when not valid. This routine */
|
||||
/* set the skip and pad fields so the format */
|
||||
/* independent routines know the amount of */
|
||||
/* padding and the number of bytes of data */
|
||||
/* which follow the header. This info is */
|
||||
/* used skip to the next file header */
|
||||
int (*rd) /* read header routine. passed a pointer to */
|
||||
(ARCHD *, char *); /* ARCHD. It must extract the info */
|
||||
/* from the format and store it in the ARCHD */
|
||||
/* struct. This routine is expected to fill */
|
||||
/* all the fields in the ARCHD (including */
|
||||
/* stat buf). 0 is returned when a valid */
|
||||
/* header is found. -1 when not valid. This */
|
||||
/* routine set the skip and pad fields so the */
|
||||
/* format independent routines know the */
|
||||
/* amount of padding and the number of bytes */
|
||||
/* of data which follow the header. This info */
|
||||
/* is used to skip to the next file header */
|
||||
off_t (*end_rd)(void); /* read cleanup. Allows format to clean up */
|
||||
/* and MUST RETURN THE LENGTH OF THE TRAILER */
|
||||
/* RECORD (so append knows how many bytes */
|
||||
|
@ -149,103 +207,77 @@ struct fsub {
|
|||
int (*end_wr)(void); /* end write. write the trailer and do any */
|
||||
/* other format specific functions needed */
|
||||
/* at the end of an archive write */
|
||||
int (*trail_cpio)(ARCHD *);
|
||||
int (*trail_tar)(char *, int, int *);
|
||||
/* returns 0 if a valid trailer, -1 if not */
|
||||
/* For formats which encode the trailer */
|
||||
/* outside of a valid header, a return value */
|
||||
/* of 1 indicates that the block passed to */
|
||||
/* it can never contain a valid header (skip */
|
||||
/* this block, no point in looking at it) */
|
||||
int (*rd_data)(ARCHD *, int, off_t *);
|
||||
/* read/process file data from the archive */
|
||||
int (*wr_data)(ARCHD *, int, off_t *);
|
||||
/* write/process file data to the archive */
|
||||
int (*trail) /* returns 0 if a valid trailer, -1 if not */
|
||||
(char *, int, int *); /* For formats which encode the */
|
||||
/* trailer outside of a valid header, a */
|
||||
/* return value of 1 indicates that the block */
|
||||
/* passed to it can never contain a valid */
|
||||
/* header (skip this block, no point in */
|
||||
/* looking at it) */
|
||||
int (*subtrail) /* read/process file data from the archive */
|
||||
(ARCHD *); /* this function is called for trailers */
|
||||
/* inside headers. */
|
||||
int (*rd_data) /* read/process file data from the archive */
|
||||
(ARCHD *, int, off_t *);
|
||||
int (*wr_data) /* write/process file data to the archive */
|
||||
(ARCHD *, int, off_t *);
|
||||
int (*options)(void); /* process format specific options (-o) */
|
||||
};
|
||||
|
||||
/*
|
||||
* Pattern matching structure
|
||||
*
|
||||
* Used to store command line patterns
|
||||
*/
|
||||
struct pattern {
|
||||
char *pstr; /* pattern to match, user supplied */
|
||||
char *pend; /* end of a prefix match */
|
||||
char *chdname; /* the dir to change to if not NULL. */
|
||||
int plen; /* length of pstr */
|
||||
int flgs; /* processing/state flags */
|
||||
#define MTCH 0x1 /* pattern has been matched */
|
||||
#define DIR_MTCH 0x2 /* pattern matched a directory */
|
||||
struct pattern *fow; /* next pattern */
|
||||
};
|
||||
|
||||
/*
|
||||
* General Archive Structure (used internal to pax)
|
||||
*
|
||||
* This structure is used to pass information about archive members between
|
||||
* the format independent routines and the format specific routines. When
|
||||
* new archive formats are added, they must accept requests and supply info
|
||||
* encoded in a structure of this type. The name fields are declared statically
|
||||
* here, as there is only ONE of these floating around, size is not a major
|
||||
* consideration. Eventually converting the name fields to a dynamic length
|
||||
* may be required if and when the supporting operating system removes all
|
||||
* restrictions on the length of pathnames it will resolve.
|
||||
*/
|
||||
struct archd {
|
||||
int nlen; /* file name length */
|
||||
char name[PAXPATHLEN+1]; /* file name */
|
||||
int ln_nlen; /* link name length */
|
||||
char ln_name[PAXPATHLEN+1]; /* name to link to (if any) */
|
||||
char *org_name; /* orig name in file system */
|
||||
PATTERN *pat; /* ptr to pattern match (if any) */
|
||||
struct stat sb; /* stat buffer see stat(2) */
|
||||
off_t pad; /* bytes of padding after file xfer */
|
||||
off_t skip; /* bytes of real data after header */
|
||||
/* IMPORTANT. The st_size field does */
|
||||
/* not always indicate the amount of */
|
||||
/* data following the header. */
|
||||
u_long crc; /* file crc */
|
||||
int type; /* type of file node */
|
||||
#define PAX_DIR 1 /* directory */
|
||||
#define PAX_CHR 2 /* character device */
|
||||
#define PAX_BLK 3 /* block device */
|
||||
#define PAX_REG 4 /* regular file */
|
||||
#define PAX_SLK 5 /* symbolic link */
|
||||
#define PAX_SCK 6 /* socket */
|
||||
#define PAX_FIF 7 /* fifo */
|
||||
#define PAX_HLK 8 /* hard link */
|
||||
#define PAX_HRG 9 /* hard link to a regular file */
|
||||
#define PAX_CTG 10 /* high performance file */
|
||||
};
|
||||
} FSUB;
|
||||
|
||||
/*
|
||||
* Format Specific Options List
|
||||
*
|
||||
* Used to pass format options to the format options handler
|
||||
*/
|
||||
struct oplist {
|
||||
typedef struct oplist {
|
||||
char *name; /* option variable name e.g. name= */
|
||||
char *value; /* value for option variable */
|
||||
struct oplist *fow; /* next option */
|
||||
};
|
||||
} OPLIST;
|
||||
|
||||
/*
|
||||
* General Macros
|
||||
*/
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
#endif
|
||||
|
||||
#ifdef HOSTPROG
|
||||
# include "pack_dev.h" /* explicitly use NetBSD's macros */
|
||||
# define MAJOR(x) major_netbsd(x)
|
||||
# define MINOR(x) minor_netbsd(x)
|
||||
# define TODEV(x, y) makedev_netbsd((x), (y))
|
||||
#else
|
||||
# define MAJOR(x) major(x)
|
||||
# define MINOR(x) minor(x)
|
||||
# define TODEV(x, y) makedev((x), (y))
|
||||
#endif
|
||||
#define TODEV(x, y) makedev((x), (y))
|
||||
|
||||
/*
|
||||
* General Defines
|
||||
*/
|
||||
#define HEX 16
|
||||
#define OCT 8
|
||||
#define _PAX_ 1
|
||||
#define HEX 16
|
||||
#define OCT 8
|
||||
#define _PAX_ 1
|
||||
|
||||
/*
|
||||
* Pathname base component of the temporary file template, to be created in
|
||||
* ${TMPDIR} or, as a fall-back, _PATH_TMP.
|
||||
*/
|
||||
#define _TFILE_BASE "paxXXXXXXXXXX"
|
||||
|
||||
#define err(c, str) { perror(str); exit(c); }
|
||||
#define setpassent(a) setpwent()
|
||||
#define setgroupent(a) setgrent()
|
||||
/*
|
||||
* Macros to manipulate off_t as uintmax_t
|
||||
*/
|
||||
#define OFFT_F "%" PRIuMAX
|
||||
#define OFFT_FP(x) "%" x PRIuMAX
|
||||
#define OFFT_T uintmax_t
|
||||
#define ASC_OFFT(x,y,z) asc_umax(x,y,z)
|
||||
#define OFFT_ASC(w,x,y,z) umax_asc((uintmax_t)w,x,y,z)
|
||||
#define OFFT_OCT(w,x,y,z) umax_oct((uintmax_t)w,x,y,z)
|
||||
#define STRTOOFFT(x,y,z) strtoimax(x,y,z)
|
||||
#define OFFT_MAX INTMAX_MAX
|
||||
|
||||
#define TOP_HALF 0xffffffff00000000ULL
|
||||
#define BOTTOM_HALF 0x00000000ffffffffULL
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
/* $NetBSD: sel_subs.c,v 1.24 2011/08/31 16:24:54 plunky Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -14,7 +16,7 @@
|
|||
* 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.
|
||||
* 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.
|
||||
*
|
||||
|
@ -31,28 +33,40 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)sel_subs.c 8.1 (Berkeley) 5/31/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: sel_subs.c,v 1.24 2011/08/31 16:24:54 plunky Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <pwd.h>
|
||||
#include <time.h>
|
||||
#include <grp.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <tzfile.h>
|
||||
|
||||
#include "pax.h"
|
||||
#include "sel_subs.h"
|
||||
#include "extern.h"
|
||||
|
||||
static int str_sec(char *, time_t *);
|
||||
static int str_sec(const char *, time_t *);
|
||||
static int usr_match(ARCHD *);
|
||||
static int grp_match(ARCHD *);
|
||||
static int trng_match(ARCHD *);
|
||||
|
@ -79,15 +93,15 @@ sel_chk(ARCHD *arcn)
|
|||
if (((usrtb != NULL) && usr_match(arcn)) ||
|
||||
((grptb != NULL) && grp_match(arcn)) ||
|
||||
((trhead != NULL) && trng_match(arcn)))
|
||||
return(1);
|
||||
return(0);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
* add an entry, the user supplies either the name or the uid/gid starting with
|
||||
* a # on the command line. A \# will escape the #.
|
||||
*/
|
||||
|
||||
|
@ -110,11 +124,12 @@ usr_add(char *str)
|
|||
* create the table if it doesn't exist
|
||||
*/
|
||||
if ((str == NULL) || (*str == '\0'))
|
||||
return(-1);
|
||||
return -1;
|
||||
if ((usrtb == NULL) &&
|
||||
((usrtb = (USRT **)calloc(USR_TB_SZ, sizeof(USRT *))) == NULL)) {
|
||||
paxwarn(1, "Unable to allocate memory for user selection table");
|
||||
return(-1);
|
||||
((usrtb = (USRT **)calloc(USR_TB_SZ, sizeof(USRT *))) == NULL)) {
|
||||
tty_warn(1,
|
||||
"Unable to allocate memory for user selection table");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -127,16 +142,12 @@ usr_add(char *str)
|
|||
if ((str[0] == '\\') && (str[1] == '#'))
|
||||
++str;
|
||||
if ((pw = getpwnam(str)) == NULL) {
|
||||
paxwarn(1, "Unable to find uid for user: %s", str);
|
||||
return(-1);
|
||||
tty_warn(1, "Unable to find uid for user: %s", str);
|
||||
return -1;
|
||||
}
|
||||
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();
|
||||
|
||||
/*
|
||||
|
@ -146,7 +157,7 @@ usr_add(char *str)
|
|||
if ((pt = usrtb[indx]) != NULL) {
|
||||
while (pt != NULL) {
|
||||
if (pt->uid == uid)
|
||||
return(0);
|
||||
return 0;
|
||||
pt = pt->fow;
|
||||
}
|
||||
}
|
||||
|
@ -158,10 +169,10 @@ usr_add(char *str)
|
|||
pt->uid = uid;
|
||||
pt->fow = usrtb[indx];
|
||||
usrtb[indx] = pt;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
paxwarn(1, "User selection table out of memory");
|
||||
return(-1);
|
||||
tty_warn(1, "User selection table out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -182,14 +193,14 @@ usr_match(ARCHD *arcn)
|
|||
pt = usrtb[((unsigned)arcn->sb.st_uid) % USR_TB_SZ];
|
||||
while (pt != NULL) {
|
||||
if (pt->uid == arcn->sb.st_uid)
|
||||
return(0);
|
||||
return 0;
|
||||
pt = pt->fow;
|
||||
}
|
||||
|
||||
/*
|
||||
* not found
|
||||
*/
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -211,11 +222,12 @@ grp_add(char *str)
|
|||
* create the table if it doesn't exist
|
||||
*/
|
||||
if ((str == NULL) || (*str == '\0'))
|
||||
return(-1);
|
||||
return -1;
|
||||
if ((grptb == NULL) &&
|
||||
((grptb = (GRPT **)calloc(GRP_TB_SZ, sizeof(GRPT *))) == NULL)) {
|
||||
paxwarn(1, "Unable to allocate memory fo group selection table");
|
||||
return(-1);
|
||||
((grptb = (GRPT **)calloc(GRP_TB_SZ, sizeof(GRPT *))) == NULL)) {
|
||||
tty_warn(1,
|
||||
"Unable to allocate memory fo group selection table");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -228,16 +240,13 @@ grp_add(char *str)
|
|||
if ((str[0] == '\\') && (str[1] == '#'))
|
||||
++str;
|
||||
if ((gr = getgrnam(str)) == NULL) {
|
||||
paxwarn(1,"Cannot determine gid for group name: %s", str);
|
||||
return(-1);
|
||||
tty_warn(1,
|
||||
"Cannot determine gid for group name: %s", str);
|
||||
return -1;
|
||||
}
|
||||
gid = gr->gr_gid;
|
||||
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();
|
||||
|
||||
/*
|
||||
|
@ -247,7 +256,7 @@ grp_add(char *str)
|
|||
if ((pt = grptb[indx]) != NULL) {
|
||||
while (pt != NULL) {
|
||||
if (pt->gid == gid)
|
||||
return(0);
|
||||
return 0;
|
||||
pt = pt->fow;
|
||||
}
|
||||
}
|
||||
|
@ -259,10 +268,10 @@ grp_add(char *str)
|
|||
pt->gid = gid;
|
||||
pt->fow = grptb[indx];
|
||||
grptb[indx] = pt;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
paxwarn(1, "Group selection table out of memory");
|
||||
return(-1);
|
||||
tty_warn(1, "Group selection table out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -283,14 +292,14 @@ grp_match(ARCHD *arcn)
|
|||
pt = grptb[((unsigned)arcn->sb.st_gid) % GRP_TB_SZ];
|
||||
while (pt != NULL) {
|
||||
if (pt->gid == arcn->sb.st_gid)
|
||||
return(0);
|
||||
return 0;
|
||||
pt = pt->fow;
|
||||
}
|
||||
|
||||
/*
|
||||
* not found
|
||||
*/
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -301,11 +310,11 @@ grp_match(ARCHD *arcn)
|
|||
* -T flag). The user may specify any number of different file time ranges.
|
||||
* Time ranges are checked one at a time until a match is found (if at all).
|
||||
* If the file has a mtime (and/or ctime) which lies within one of the time
|
||||
* ranges, the file is selected. Time ranges may have a lower and/or an upper
|
||||
* ranges, the file is selected. Time ranges may have a lower and/or a upper
|
||||
* value. These ranges are inclusive. When no time ranges are supplied to pax
|
||||
* with the -T option, all members in the archive will be selected by the time
|
||||
* range routines. When only a lower range is supplied, only files with a
|
||||
* mtime (and/or ctime) equal to or younger are selected. When only an upper
|
||||
* mtime (and/or ctime) equal to or younger are selected. When only a upper
|
||||
* range is supplied, only files with a mtime (and/or ctime) equal to or older
|
||||
* are selected. When the lower time range is equal to the upper time range,
|
||||
* only files with a mtime (or ctime) of exactly that time are selected.
|
||||
|
@ -335,8 +344,8 @@ trng_add(char *str)
|
|||
* throw out the badly formed time ranges
|
||||
*/
|
||||
if ((str == NULL) || (*str == '\0')) {
|
||||
paxwarn(1, "Empty time range string");
|
||||
return(-1);
|
||||
tty_warn(1, "Empty time range string");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -362,20 +371,20 @@ trng_add(char *str)
|
|||
++dot;
|
||||
continue;
|
||||
}
|
||||
paxwarn(1, "Improperly specified time range: %s", str);
|
||||
tty_warn(1, "Improperly specified time range: %s", str);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate space for the time range and store the limits
|
||||
*/
|
||||
if ((pt = (TIME_RNG *)malloc(sizeof(TIME_RNG))) == NULL) {
|
||||
paxwarn(1, "Unable to allocate memory for time range");
|
||||
return(-1);
|
||||
if ((pt = malloc(sizeof(TIME_RNG))) == NULL) {
|
||||
tty_warn(1, "Unable to allocate memory for time range");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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'))
|
||||
|
@ -393,8 +402,9 @@ trng_add(char *str)
|
|||
pt->flgs |= CMPCTME;
|
||||
break;
|
||||
default:
|
||||
paxwarn(1, "Bad option %c with time range %s",
|
||||
tty_warn(1, "Bad option %c with time range %s",
|
||||
*flgpt, str);
|
||||
free(pt);
|
||||
goto out;
|
||||
}
|
||||
++flgpt;
|
||||
|
@ -410,8 +420,8 @@ trng_add(char *str)
|
|||
* add lower limit
|
||||
*/
|
||||
if (str_sec(str, &(pt->low_time)) < 0) {
|
||||
paxwarn(1, "Illegal lower time range %s", str);
|
||||
(void)free((char *)pt);
|
||||
tty_warn(1, "Illegal lower time range %s", str);
|
||||
free(pt);
|
||||
goto out;
|
||||
}
|
||||
pt->flgs |= HASLOW;
|
||||
|
@ -422,8 +432,8 @@ trng_add(char *str)
|
|||
* add upper limit
|
||||
*/
|
||||
if (str_sec(up_pt, &(pt->high_time)) < 0) {
|
||||
paxwarn(1, "Illegal upper time range %s", up_pt);
|
||||
(void)free((char *)pt);
|
||||
tty_warn(1, "Illegal upper time range %s", up_pt);
|
||||
free(pt);
|
||||
goto out;
|
||||
}
|
||||
pt->flgs |= HASHIGH;
|
||||
|
@ -433,10 +443,11 @@ trng_add(char *str)
|
|||
*/
|
||||
if (pt->flgs & HASLOW) {
|
||||
if (pt->low_time > pt->high_time) {
|
||||
paxwarn(1, "Upper %s and lower %s time overlap",
|
||||
up_pt, str);
|
||||
(void)free((char *)pt);
|
||||
return(-1);
|
||||
tty_warn(1,
|
||||
"Upper %s and lower %s time overlap",
|
||||
up_pt, str);
|
||||
free(pt);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -444,15 +455,15 @@ trng_add(char *str)
|
|||
pt->fow = NULL;
|
||||
if (trhead == NULL) {
|
||||
trtail = trhead = pt;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
trtail->fow = pt;
|
||||
trtail = pt;
|
||||
return(0);
|
||||
return 0;
|
||||
|
||||
out:
|
||||
paxwarn(1, "Time range format is: [yy[mm[dd[hh]]]]mm[.ss][/[c][m]]");
|
||||
return(-1);
|
||||
tty_warn(1, "Time range format is: [yy[mm[dd[hh]]]]mm[.ss][/[c][m]]");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -519,8 +530,8 @@ trng_match(ARCHD *arcn)
|
|||
}
|
||||
|
||||
if (pt == NULL)
|
||||
return(1);
|
||||
return(0);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -531,75 +542,76 @@ trng_match(ARCHD *arcn)
|
|||
* 0 if converted ok, -1 otherwise
|
||||
*/
|
||||
|
||||
#define ATOI2(s) ((s) += 2, ((s)[-2] - '0') * 10 + ((s)[-1] - '0'))
|
||||
|
||||
static int
|
||||
str_sec(char *str, time_t *tval)
|
||||
str_sec(const char *p, time_t *tval)
|
||||
{
|
||||
struct tm *lt;
|
||||
char *dot = NULL;
|
||||
const char *dot, *t;
|
||||
int yearset, len;
|
||||
|
||||
for (t = p, dot = NULL; *t; ++t) {
|
||||
if (isdigit((unsigned char)*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)
|
||||
return(-1);
|
||||
if ((lt->tm_sec = ATOI2(dot)) > 61)
|
||||
return(-1);
|
||||
} else
|
||||
lt->tm_sec = 0;
|
||||
|
||||
switch (strlen(str)) {
|
||||
if (dot != NULL) {
|
||||
len = strlen(dot);
|
||||
if (len != 3)
|
||||
return -1;
|
||||
++dot;
|
||||
lt->tm_sec = ATOI2(dot);
|
||||
} else {
|
||||
len = 0;
|
||||
lt->tm_sec = 0;
|
||||
}
|
||||
|
||||
yearset = 0;
|
||||
switch (strlen(p) - len) {
|
||||
case 12:
|
||||
lt->tm_year = ATOI2(p) * 100 - TM_YEAR_BASE;
|
||||
yearset = 1;
|
||||
/* FALLTHROUGH */
|
||||
case 10:
|
||||
/*
|
||||
* year (yy)
|
||||
* watch out for year 2000
|
||||
*/
|
||||
if ((lt->tm_year = ATOI2(str)) < 69)
|
||||
lt->tm_year += 100;
|
||||
str += 2;
|
||||
if (yearset) {
|
||||
lt->tm_year += ATOI2(p);
|
||||
} else {
|
||||
yearset = ATOI2(p);
|
||||
if (yearset < 69)
|
||||
lt->tm_year = yearset + 2000 - TM_YEAR_BASE;
|
||||
else
|
||||
lt->tm_year = yearset + 1900 - TM_YEAR_BASE;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case 8:
|
||||
/*
|
||||
* month (mm)
|
||||
* watch out months are from 0 - 11 internally
|
||||
*/
|
||||
if ((lt->tm_mon = ATOI2(str)) > 12)
|
||||
return(-1);
|
||||
lt->tm_mon = ATOI2(p);
|
||||
--lt->tm_mon;
|
||||
str += 2;
|
||||
/* FALLTHROUGH */
|
||||
case 6:
|
||||
/*
|
||||
* day (dd)
|
||||
*/
|
||||
if ((lt->tm_mday = ATOI2(str)) > 31)
|
||||
return(-1);
|
||||
str += 2;
|
||||
lt->tm_mday = ATOI2(p);
|
||||
/* FALLTHROUGH */
|
||||
case 4:
|
||||
/*
|
||||
* hour (hh)
|
||||
*/
|
||||
if ((lt->tm_hour = ATOI2(str)) > 23)
|
||||
return(-1);
|
||||
str += 2;
|
||||
lt->tm_hour = ATOI2(p);
|
||||
/* FALLTHROUGH */
|
||||
case 2:
|
||||
/*
|
||||
* minute (mm)
|
||||
*/
|
||||
if ((lt->tm_min = ATOI2(str)) > 59)
|
||||
return(-1);
|
||||
lt->tm_min = ATOI2(p);
|
||||
break;
|
||||
default:
|
||||
return(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* convert broken-down time to GMT clock time seconds
|
||||
*/
|
||||
if ((*tval = mktime(lt)) == -1)
|
||||
return(-1);
|
||||
return(0);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
/* $NetBSD: sel_subs.h,v 1.6 2003/10/13 07:41:22 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -14,7 +16,7 @@
|
|||
* 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.
|
||||
* 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.
|
||||
*
|
||||
|
@ -31,7 +33,6 @@
|
|||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)sel_subs.h 8.1 (Berkeley) 5/31/93
|
||||
* $FreeBSD: src/bin/pax/sel_subs.h,v 1.6 2004/04/06 20:06:48 markm Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -55,8 +56,6 @@ typedef struct grpt {
|
|||
* data structure for storing user supplied time ranges (-T option)
|
||||
*/
|
||||
|
||||
#define ATOI2(s) ((((s)[0] - '0') * 10) + ((s)[1] - '0'))
|
||||
|
||||
typedef struct time_rng {
|
||||
time_t low_time; /* lower inclusive time limit */
|
||||
time_t high_time; /* higher inclusive time limit */
|
|
@ -1,3 +1,5 @@
|
|||
/* $NetBSD: tables.c,v 1.30 2008/01/10 04:24:51 tls Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -14,7 +16,7 @@
|
|||
* 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.
|
||||
* 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.
|
||||
*
|
||||
|
@ -31,21 +33,31 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)tables.c 8.1 (Berkeley) 5/31/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: tables.c,v 1.30 2008/01/10 04:24:51 tls Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <paths.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include "pax.h"
|
||||
#include "tables.h"
|
||||
#include "extern.h"
|
||||
|
@ -61,7 +73,7 @@ static char sccsid[] = "@(#)tables.c 8.1 (Berkeley) 5/31/93";
|
|||
* large archives. These database routines carefully combine memory usage and
|
||||
* temporary file storage in ways which will not significantly impact runtime
|
||||
* performance while allowing the largest possible archives to be handled.
|
||||
* Trying to force the fit to the POSIX databases routines was not considered
|
||||
* Trying to force the fit to the POSIX database routines was not considered
|
||||
* time well spent.
|
||||
*/
|
||||
|
||||
|
@ -70,8 +82,10 @@ static FTM **ftab = NULL; /* file time table for updating arch */
|
|||
static NAMT **ntab = NULL; /* interactive rename storage table */
|
||||
static DEVT **dtab = NULL; /* device/inode mapping tables */
|
||||
static ATDIR **atab = NULL; /* file tree directory time reset table */
|
||||
#ifdef DIRS_USE_FILE
|
||||
static int dirfd = -1; /* storage for setting created dir time/mode */
|
||||
static u_long dircnt; /* entries in dir time/mode storage */
|
||||
#endif
|
||||
static int ffd = -1; /* tmp file for file time table name storage */
|
||||
|
||||
static DEVT *chk_dev(dev_t, int);
|
||||
|
@ -103,12 +117,12 @@ int
|
|||
lnk_start(void)
|
||||
{
|
||||
if (ltab != NULL)
|
||||
return(0);
|
||||
if ((ltab = (HRDLNK **)calloc(L_TAB_SZ, sizeof(HRDLNK *))) == NULL) {
|
||||
paxwarn(1, "Cannot allocate memory for hard link table");
|
||||
return(-1);
|
||||
return 0;
|
||||
if ((ltab = (HRDLNK **)calloc(L_TAB_SZ, sizeof(HRDLNK *))) == NULL) {
|
||||
tty_warn(1, "Cannot allocate memory for hard link table");
|
||||
return -1;
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -131,12 +145,12 @@ chk_lnk(ARCHD *arcn)
|
|||
u_int indx;
|
||||
|
||||
if (ltab == NULL)
|
||||
return(-1);
|
||||
return -1;
|
||||
/*
|
||||
* ignore those nodes that cannot have hard links
|
||||
*/
|
||||
if ((arcn->type == PAX_DIR) || (arcn->sb.st_nlink <= 1))
|
||||
return(0);
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* hash inode number and look for this file
|
||||
|
@ -144,7 +158,7 @@ chk_lnk(ARCHD *arcn)
|
|||
indx = ((unsigned)arcn->sb.st_ino) % L_TAB_SZ;
|
||||
if ((pt = ltab[indx]) != NULL) {
|
||||
/*
|
||||
* it's hash chain in not empty, walk down looking for it
|
||||
* its hash chain is not empty, walk down looking for it
|
||||
*/
|
||||
ppt = &(ltab[indx]);
|
||||
while (pt != NULL) {
|
||||
|
@ -162,9 +176,8 @@ chk_lnk(ARCHD *arcn)
|
|||
* handle hardlinks to regular files differently than
|
||||
* other links.
|
||||
*/
|
||||
arcn->ln_nlen = l_strncpy(arcn->ln_name, pt->name,
|
||||
sizeof(arcn->ln_name) - 1);
|
||||
arcn->ln_name[arcn->ln_nlen] = '\0';
|
||||
arcn->ln_nlen = strlcpy(arcn->ln_name, pt->name,
|
||||
sizeof(arcn->ln_name));
|
||||
if (arcn->type == PAX_REG)
|
||||
arcn->type = PAX_HRG;
|
||||
else
|
||||
|
@ -179,7 +192,7 @@ chk_lnk(ARCHD *arcn)
|
|||
(void)free((char *)pt->name);
|
||||
(void)free((char *)pt);
|
||||
}
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,20 +207,20 @@ chk_lnk(ARCHD *arcn)
|
|||
pt->nlink = arcn->sb.st_nlink;
|
||||
pt->fow = ltab[indx];
|
||||
ltab[indx] = pt;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
(void)free((char *)pt);
|
||||
}
|
||||
|
||||
paxwarn(1, "Hard link table out of memory");
|
||||
return(-1);
|
||||
tty_warn(1, "Hard link table out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* purg_lnk
|
||||
* remove reference for a file that we may have added to the data base as
|
||||
* a potential source for hard links. We ended up not using the file, so
|
||||
* we do not want to accidently point another file at it later on.
|
||||
* we do not want to accidentally point another file at it later on.
|
||||
*/
|
||||
|
||||
void
|
||||
|
@ -258,10 +271,10 @@ purg_lnk(ARCHD *arcn)
|
|||
|
||||
/*
|
||||
* lnk_end()
|
||||
* Pull apart an existing link table so we can reuse it. We do this between
|
||||
* pull apart a existing link table so we can reuse it. We do this between
|
||||
* read and write phases of append with update. (The format may have
|
||||
* used the link table, and we need to start with a fresh table for the
|
||||
* write phase).
|
||||
* write phase
|
||||
*/
|
||||
|
||||
void
|
||||
|
@ -304,14 +317,14 @@ lnk_end(void)
|
|||
* An append with an -u must read the archive and store the modification time
|
||||
* for every file on that archive before starting the write phase. It is clear
|
||||
* that this is one HUGE database. To save memory space, the actual file names
|
||||
* are stored in a scatch file and indexed by an in memory hash table. The
|
||||
* are stored in a scratch file and indexed by an in-memory hash table. The
|
||||
* hash table is indexed by hashing the file path. The nodes in the table store
|
||||
* the length of the filename and the lseek offset within the scratch file
|
||||
* where the actual name is stored. Since there are never any deletions to this
|
||||
* table, fragmentation of the scratch file is never an issue. Lookups seem to
|
||||
* where the actual name is stored. Since there are never any deletions from this
|
||||
* table, fragmentation of the scratch file is never a issue. Lookups seem to
|
||||
* not exhibit any locality at all (files in the database are rarely
|
||||
* looked up more than once...). So caching is just a waste of memory. The
|
||||
* only limitation is the amount of scatch file space available to store the
|
||||
* looked up more than once...), so caching is just a waste of memory. The
|
||||
* only limitation is the amount of scratch file space available to store the
|
||||
* path names.
|
||||
*/
|
||||
|
||||
|
@ -327,12 +340,11 @@ lnk_end(void)
|
|||
int
|
||||
ftime_start(void)
|
||||
{
|
||||
|
||||
if (ftab != NULL)
|
||||
return(0);
|
||||
if ((ftab = (FTM **)calloc(F_TAB_SZ, sizeof(FTM *))) == NULL) {
|
||||
paxwarn(1, "Cannot allocate memory for file time table");
|
||||
return(-1);
|
||||
return 0;
|
||||
if ((ftab = (FTM **)calloc(F_TAB_SZ, sizeof(FTM *))) == NULL) {
|
||||
tty_warn(1, "Cannot allocate memory for file time table");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -340,14 +352,14 @@ ftime_start(void)
|
|||
* so it will get removed on exit
|
||||
*/
|
||||
memcpy(tempbase, _TFILE_BASE, sizeof(_TFILE_BASE));
|
||||
if ((ffd = mkstemp(tempfile)) < 0) {
|
||||
if ((ffd = mkstemp(tempfile)) == -1) {
|
||||
syswarn(1, errno, "Unable to create temporary file: %s",
|
||||
tempfile);
|
||||
return(-1);
|
||||
return -1;
|
||||
}
|
||||
(void)unlink(tempfile);
|
||||
|
||||
return(0);
|
||||
(void)unlink(tempfile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -374,7 +386,7 @@ chk_ftime(ARCHD *arcn)
|
|||
* no info, go ahead and add to archive
|
||||
*/
|
||||
if (ftab == NULL)
|
||||
return(0);
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* hash the pathname and look up in table
|
||||
|
@ -396,12 +408,12 @@ chk_ftime(ARCHD *arcn)
|
|||
if (lseek(ffd,pt->seek,SEEK_SET) != pt->seek) {
|
||||
syswarn(1, errno,
|
||||
"Failed ftime table seek");
|
||||
return(-1);
|
||||
return -1;
|
||||
}
|
||||
if (read(ffd, ckname, namelen) != namelen) {
|
||||
if (xread(ffd, ckname, namelen) != namelen) {
|
||||
syswarn(1, errno,
|
||||
"Failed ftime table read");
|
||||
return(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -426,12 +438,12 @@ chk_ftime(ARCHD *arcn)
|
|||
* file is newer
|
||||
*/
|
||||
pt->mtime = arcn->sb.st_mtime;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* file is older
|
||||
*/
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -444,22 +456,22 @@ chk_ftime(ARCHD *arcn)
|
|||
* offset. add the file to the head of the hash chain
|
||||
*/
|
||||
if ((pt->seek = lseek(ffd, (off_t)0, SEEK_END)) >= 0) {
|
||||
if (write(ffd, arcn->name, namelen) == namelen) {
|
||||
if (xwrite(ffd, arcn->name, namelen) == namelen) {
|
||||
pt->mtime = arcn->sb.st_mtime;
|
||||
pt->namelen = namelen;
|
||||
pt->fow = ftab[indx];
|
||||
ftab[indx] = pt;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
syswarn(1, errno, "Failed write to file time table");
|
||||
} else
|
||||
syswarn(1, errno, "Failed seek on file time table");
|
||||
} else
|
||||
paxwarn(1, "File time table ran out of memory");
|
||||
tty_warn(1, "File time table ran out of memory");
|
||||
|
||||
if (pt != NULL)
|
||||
(void)free((char *)pt);
|
||||
return(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -485,12 +497,13 @@ int
|
|||
name_start(void)
|
||||
{
|
||||
if (ntab != NULL)
|
||||
return(0);
|
||||
if ((ntab = (NAMT **)calloc(N_TAB_SZ, sizeof(NAMT *))) == NULL) {
|
||||
paxwarn(1, "Cannot allocate memory for interactive rename table");
|
||||
return(-1);
|
||||
return 0;
|
||||
if ((ntab = (NAMT **)calloc(N_TAB_SZ, sizeof(NAMT *))) == NULL) {
|
||||
tty_warn(1,
|
||||
"Cannot allocate memory for interactive rename table");
|
||||
return -1;
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -512,8 +525,8 @@ add_name(char *oname, int onamelen, char *nname)
|
|||
/*
|
||||
* should never happen
|
||||
*/
|
||||
paxwarn(0, "No interactive rename table, links may fail\n");
|
||||
return(0);
|
||||
tty_warn(0, "No interactive rename table, links may fail\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -534,14 +547,14 @@ add_name(char *oname, int onamelen, char *nname)
|
|||
* the user just input (if it is different)
|
||||
*/
|
||||
if (strcmp(nname, pt->nname) == 0)
|
||||
return(0);
|
||||
return 0;
|
||||
|
||||
(void)free((char *)pt->nname);
|
||||
if ((pt->nname = strdup(nname)) == NULL) {
|
||||
paxwarn(1, "Cannot update rename table");
|
||||
return(-1);
|
||||
tty_warn(1, "Cannot update rename table");
|
||||
return -1;
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -553,14 +566,14 @@ add_name(char *oname, int onamelen, char *nname)
|
|||
if ((pt->nname = strdup(nname)) != NULL) {
|
||||
pt->fow = ntab[indx];
|
||||
ntab[indx] = pt;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
(void)free((char *)pt->oname);
|
||||
}
|
||||
(void)free((char *)pt);
|
||||
}
|
||||
paxwarn(1, "Interactive rename table out of memory");
|
||||
return(-1);
|
||||
tty_warn(1, "Interactive rename table out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -594,8 +607,7 @@ sub_name(char *oname, int *onamelen, size_t onamesize)
|
|||
* found it, replace it with the new name
|
||||
* and return (we know that oname has enough space)
|
||||
*/
|
||||
*onamelen = l_strncpy(oname, pt->nname, onamesize - 1);
|
||||
oname[*onamelen] = '\0';
|
||||
*onamelen = strlcpy(oname, pt->nname, onamesize);
|
||||
return;
|
||||
}
|
||||
pt = pt->fow;
|
||||
|
@ -658,12 +670,12 @@ int
|
|||
dev_start(void)
|
||||
{
|
||||
if (dtab != NULL)
|
||||
return(0);
|
||||
if ((dtab = (DEVT **)calloc(D_TAB_SZ, sizeof(DEVT *))) == NULL) {
|
||||
paxwarn(1, "Cannot allocate memory for device mapping table");
|
||||
return(-1);
|
||||
return 0;
|
||||
if ((dtab = (DEVT **)calloc(D_TAB_SZ, sizeof(DEVT *))) == NULL) {
|
||||
tty_warn(1, "Cannot allocate memory for device mapping table");
|
||||
return -1;
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -680,8 +692,8 @@ int
|
|||
add_dev(ARCHD *arcn)
|
||||
{
|
||||
if (chk_dev(arcn->sb.st_dev, 1) == NULL)
|
||||
return(-1);
|
||||
return(0);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -704,7 +716,7 @@ chk_dev(dev_t dev, int add)
|
|||
u_int indx;
|
||||
|
||||
if (dtab == NULL)
|
||||
return(NULL);
|
||||
return NULL;
|
||||
/*
|
||||
* look to see if this device is already in the table
|
||||
*/
|
||||
|
@ -717,7 +729,7 @@ chk_dev(dev_t dev, int add)
|
|||
* found it, return a pointer to it
|
||||
*/
|
||||
if (pt != NULL)
|
||||
return(pt);
|
||||
return pt;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -725,7 +737,7 @@ chk_dev(dev_t dev, int add)
|
|||
* to see if a device number is being used.
|
||||
*/
|
||||
if (add == 0)
|
||||
return(NULL);
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* allocate a node for this device and add it to the front of the hash
|
||||
|
@ -733,14 +745,14 @@ chk_dev(dev_t dev, int add)
|
|||
* list must be NULL.
|
||||
*/
|
||||
if ((pt = (DEVT *)malloc(sizeof(DEVT))) == NULL) {
|
||||
paxwarn(1, "Device map table out of memory");
|
||||
return(NULL);
|
||||
tty_warn(1, "Device map table out of memory");
|
||||
return NULL;
|
||||
}
|
||||
pt->dev = dev;
|
||||
pt->list = NULL;
|
||||
pt->fow = dtab[indx];
|
||||
dtab[indx] = pt;
|
||||
return(pt);
|
||||
return pt;
|
||||
}
|
||||
/*
|
||||
* map_dev()
|
||||
|
@ -767,7 +779,7 @@ map_dev(ARCHD *arcn, u_long dev_mask, u_long ino_mask)
|
|||
ino_t nino;
|
||||
|
||||
if (dtab == NULL)
|
||||
return(0);
|
||||
return 0;
|
||||
/*
|
||||
* check for device and inode truncation, and extract the truncated
|
||||
* bit pattern.
|
||||
|
@ -798,7 +810,7 @@ map_dev(ARCHD *arcn, u_long dev_mask, u_long ino_mask)
|
|||
*/
|
||||
arcn->sb.st_dev = dpt->dev;
|
||||
arcn->sb.st_ino = nino;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
|
@ -806,7 +818,7 @@ map_dev(ARCHD *arcn, u_long dev_mask, u_long ino_mask)
|
|||
* form of truncation, we do not need a remap
|
||||
*/
|
||||
if (!trc_ino && !trc_dev)
|
||||
return(0);
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* we have truncation, have to add this as a device to remap
|
||||
|
@ -864,20 +876,21 @@ map_dev(ARCHD *arcn, u_long dev_mask, u_long ino_mask)
|
|||
pt->list = dpt;
|
||||
arcn->sb.st_dev = lastdev;
|
||||
arcn->sb.st_ino = nino;
|
||||
return(0);
|
||||
return 0;
|
||||
|
||||
bad:
|
||||
paxwarn(1, "Unable to fix truncated inode/device field when storing %s",
|
||||
tty_warn(1,
|
||||
"Unable to fix truncated inode/device field when storing %s",
|
||||
arcn->name);
|
||||
paxwarn(0, "Archive may create improper hard links when extracted");
|
||||
return(0);
|
||||
tty_warn(0, "Archive may create improper hard links when extracted");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* directory access/mod time reset table routines (for directories READ by pax)
|
||||
*
|
||||
* The pax -t flag requires that access times of archive files to be the same
|
||||
* before being read by pax. For regular files, access time is restored after
|
||||
* as before being read by pax. For regular files, access time is restored after
|
||||
* the file has been copied. This database provides the same functionality for
|
||||
* directories read during file tree traversal. Restoring directory access time
|
||||
* is more complex than files since directories may be read several times until
|
||||
|
@ -901,12 +914,13 @@ int
|
|||
atdir_start(void)
|
||||
{
|
||||
if (atab != NULL)
|
||||
return(0);
|
||||
if ((atab = (ATDIR **)calloc(A_TAB_SZ, sizeof(ATDIR *))) == NULL) {
|
||||
paxwarn(1,"Cannot allocate space for directory access time table");
|
||||
return(-1);
|
||||
return 0;
|
||||
if ((atab = (ATDIR **)calloc(A_TAB_SZ, sizeof(ATDIR *))) == NULL) {
|
||||
tty_warn(1,
|
||||
"Cannot allocate space for directory access time table");
|
||||
return -1;
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -938,7 +952,7 @@ atdir_end(void)
|
|||
* not read by pax. Read time reset is controlled by -t.
|
||||
*/
|
||||
for (; pt != NULL; pt = pt->fow)
|
||||
set_ftime(pt->name, pt->mtime, pt->atime, 1);
|
||||
set_ftime(pt->name, pt->mtime, pt->atime, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -962,7 +976,7 @@ add_atdir(char *fname, dev_t dev, ino_t ino, time_t mtime, time_t atime)
|
|||
* return (the older entry always has the correct time). The only
|
||||
* way this will happen is when the same subtree can be traversed by
|
||||
* different args to pax and the -n option is aborting fts out of a
|
||||
* subtree before all the post-order visits have been made).
|
||||
* subtree before all the post-order visits have been made.
|
||||
*/
|
||||
indx = ((unsigned)ino) % A_TAB_SZ;
|
||||
if ((pt = atab[indx]) != NULL) {
|
||||
|
@ -995,7 +1009,7 @@ add_atdir(char *fname, dev_t dev, ino_t ino, time_t mtime, time_t atime)
|
|||
(void)free((char *)pt);
|
||||
}
|
||||
|
||||
paxwarn(1, "Directory access time reset table ran out of memory");
|
||||
tty_warn(1, "Directory access time reset table ran out of memory");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1018,13 +1032,13 @@ get_atdir(dev_t dev, ino_t ino, time_t *mtime, time_t *atime)
|
|||
u_int indx;
|
||||
|
||||
if (atab == NULL)
|
||||
return(-1);
|
||||
return -1;
|
||||
/*
|
||||
* hash by inode and search the chain for an inode and device match
|
||||
*/
|
||||
indx = ((unsigned)ino) % A_TAB_SZ;
|
||||
if ((pt = atab[indx]) == NULL)
|
||||
return(-1);
|
||||
return -1;
|
||||
|
||||
ppt = &(atab[indx]);
|
||||
while (pt != NULL) {
|
||||
|
@ -1041,7 +1055,7 @@ get_atdir(dev_t dev, ino_t ino, time_t *mtime, time_t *atime)
|
|||
* return if we did not find it.
|
||||
*/
|
||||
if (pt == NULL)
|
||||
return(-1);
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* found it. return the times and remove the entry from the table.
|
||||
|
@ -1051,7 +1065,7 @@ get_atdir(dev_t dev, ino_t ino, time_t *mtime, time_t *atime)
|
|||
*atime = pt->atime;
|
||||
(void)free((char *)pt->name);
|
||||
(void)free((char *)pt);
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1077,6 +1091,10 @@ get_atdir(dev_t dev, ino_t ino, time_t *mtime, time_t *atime)
|
|||
* then the file name.
|
||||
*/
|
||||
|
||||
#ifndef DIRS_USE_FILE
|
||||
static DIRDATA *dirdata_head;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* dir_start()
|
||||
* set up the directory time and file mode storage for directories CREATED
|
||||
|
@ -1088,9 +1106,9 @@ get_atdir(dev_t dev, ino_t ino, time_t *mtime, time_t *atime)
|
|||
int
|
||||
dir_start(void)
|
||||
{
|
||||
|
||||
#ifdef DIRS_USE_FILE
|
||||
if (dirfd != -1)
|
||||
return(0);
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* unlink the file so it goes away at termination by itself
|
||||
|
@ -1098,11 +1116,14 @@ dir_start(void)
|
|||
memcpy(tempbase, _TFILE_BASE, sizeof(_TFILE_BASE));
|
||||
if ((dirfd = mkstemp(tempfile)) >= 0) {
|
||||
(void)unlink(tempfile);
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
paxwarn(1, "Unable to create temporary file for directory times: %s",
|
||||
tty_warn(1, "Unable to create temporary file for directory times: %s",
|
||||
tempfile);
|
||||
return(-1);
|
||||
return -1;
|
||||
#else
|
||||
return (0);
|
||||
#endif /* DIRS_USE_FILE */
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1112,7 +1133,7 @@ dir_start(void)
|
|||
* frc_mode is a flag that says whether to force the setting of the mode
|
||||
* (ignoring the user set values for preserving file mode). Frc_mode is
|
||||
* for the case where we created a file and found that the resulting
|
||||
* directory was not writeable and the user asked for file modes to NOT
|
||||
* directory was not writable and the user asked for file modes to NOT
|
||||
* be preserved. (we have to preserve what was created by default, so we
|
||||
* have to force the setting at the end. this is stated explicitly in the
|
||||
* pax spec)
|
||||
|
@ -1121,8 +1142,23 @@ dir_start(void)
|
|||
void
|
||||
add_dir(char *name, int nlen, struct stat *psb, int frc_mode)
|
||||
{
|
||||
#ifdef DIRS_USE_FILE
|
||||
DIRDATA dblk;
|
||||
#else
|
||||
DIRDATA *dblk;
|
||||
#endif
|
||||
char realname[MAXPATHLEN], *rp;
|
||||
|
||||
if (havechd && *name != '/') {
|
||||
if ((rp = realpath(name, realname)) == NULL) {
|
||||
tty_warn(1, "Cannot canonicalize %s", name);
|
||||
return;
|
||||
}
|
||||
name = rp;
|
||||
nlen = strlen(name);
|
||||
}
|
||||
|
||||
#ifdef DIRS_USE_FILE
|
||||
if (dirfd < 0)
|
||||
return;
|
||||
|
||||
|
@ -1131,7 +1167,8 @@ add_dir(char *name, int nlen, struct stat *psb, int frc_mode)
|
|||
* in the trailer
|
||||
*/
|
||||
if ((dblk.npos = lseek(dirfd, 0L, SEEK_CUR)) < 0) {
|
||||
paxwarn(1,"Unable to store mode and times for directory: %s",name);
|
||||
tty_warn(1,
|
||||
"Unable to store mode and times for directory: %s",name);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1142,15 +1179,46 @@ add_dir(char *name, int nlen, struct stat *psb, int frc_mode)
|
|||
dblk.mode = psb->st_mode & 0xffff;
|
||||
dblk.mtime = psb->st_mtime;
|
||||
dblk.atime = psb->st_atime;
|
||||
#if HAVE_STRUCT_STAT_ST_FLAGS
|
||||
dblk.fflags = psb->st_flags;
|
||||
#else
|
||||
dblk.fflags = 0;
|
||||
#endif
|
||||
dblk.frc_mode = frc_mode;
|
||||
if ((write(dirfd, name, dblk.nlen) == dblk.nlen) &&
|
||||
(write(dirfd, (char *)&dblk, sizeof(dblk)) == sizeof(dblk))) {
|
||||
if ((xwrite(dirfd, name, dblk.nlen) == dblk.nlen) &&
|
||||
(xwrite(dirfd, (char *)&dblk, sizeof(dblk)) == sizeof(dblk))) {
|
||||
++dircnt;
|
||||
return;
|
||||
}
|
||||
|
||||
paxwarn(1,"Unable to store mode and times for created directory: %s",name);
|
||||
tty_warn(1,
|
||||
"Unable to store mode and times for created directory: %s",name);
|
||||
return;
|
||||
#else
|
||||
|
||||
if ((dblk = malloc(sizeof(*dblk))) == NULL ||
|
||||
(dblk->name = strdup(name)) == NULL) {
|
||||
tty_warn(1,
|
||||
"Unable to store mode and times for directory: %s",name);
|
||||
if (dblk != NULL)
|
||||
free(dblk);
|
||||
return;
|
||||
}
|
||||
|
||||
dblk->mode = psb->st_mode & 0xffff;
|
||||
dblk->mtime = psb->st_mtime;
|
||||
dblk->atime = psb->st_atime;
|
||||
#if HAVE_STRUCT_STAT_ST_FLAGS
|
||||
dblk->fflags = psb->st_flags;
|
||||
#else
|
||||
dblk->fflags = 0;
|
||||
#endif
|
||||
dblk->frc_mode = frc_mode;
|
||||
|
||||
dblk->next = dirdata_head;
|
||||
dirdata_head = dblk;
|
||||
return;
|
||||
#endif /* DIRS_USE_FILE */
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1162,6 +1230,7 @@ add_dir(char *name, int nlen, struct stat *psb, int frc_mode)
|
|||
void
|
||||
proc_dir(void)
|
||||
{
|
||||
#ifdef DIRS_USE_FILE
|
||||
char name[PAXPATHLEN+1];
|
||||
DIRDATA dblk;
|
||||
u_long cnt;
|
||||
|
@ -1178,11 +1247,11 @@ proc_dir(void)
|
|||
*/
|
||||
if (lseek(dirfd, -((off_t)sizeof(dblk)), SEEK_CUR) < 0)
|
||||
break;
|
||||
if (read(dirfd,(char *)&dblk, sizeof(dblk)) != sizeof(dblk))
|
||||
if (xread(dirfd,(char *)&dblk, sizeof(dblk)) != sizeof(dblk))
|
||||
break;
|
||||
if (lseek(dirfd, dblk.npos, SEEK_SET) < 0)
|
||||
break;
|
||||
if (read(dirfd, name, dblk.nlen) != dblk.nlen)
|
||||
if (xread(dirfd, name, dblk.nlen) != dblk.nlen)
|
||||
break;
|
||||
if (lseek(dirfd, dblk.npos, SEEK_SET) < 0)
|
||||
break;
|
||||
|
@ -1194,14 +1263,38 @@ proc_dir(void)
|
|||
if (pmode || dblk.frc_mode)
|
||||
set_pmode(name, dblk.mode);
|
||||
if (patime || pmtime)
|
||||
set_ftime(name, dblk.mtime, dblk.atime, 0);
|
||||
set_ftime(name, dblk.mtime, dblk.atime, 0, 0);
|
||||
if (pfflags)
|
||||
set_chflags(name, dblk.fflags);
|
||||
}
|
||||
|
||||
(void)close(dirfd);
|
||||
dirfd = -1;
|
||||
if (cnt != dircnt)
|
||||
paxwarn(1,"Unable to set mode and times for created directories");
|
||||
tty_warn(1,
|
||||
"Unable to set mode and times for created directories");
|
||||
return;
|
||||
#else
|
||||
DIRDATA *dblk;
|
||||
|
||||
for (dblk = dirdata_head; dblk != NULL; dblk = dirdata_head) {
|
||||
dirdata_head = dblk->next;
|
||||
|
||||
/*
|
||||
* frc_mode set, make sure we set the file modes even if
|
||||
* the user didn't ask for it (see file_subs.c for more info)
|
||||
*/
|
||||
if (pmode || dblk->frc_mode)
|
||||
set_pmode(dblk->name, dblk->mode);
|
||||
if (patime || pmtime)
|
||||
set_ftime(dblk->name, dblk->mtime, dblk->atime, 0, 0);
|
||||
if (pfflags)
|
||||
set_chflags(dblk->name, dblk->fflags);
|
||||
|
||||
free(dblk->name);
|
||||
free(dblk);
|
||||
}
|
||||
#endif /* DIRS_USE_FILE */
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1280,5 +1373,5 @@ st_hash(char *name, int len, int tabsz)
|
|||
/*
|
||||
* return the result mod the table size
|
||||
*/
|
||||
return(key % tabsz);
|
||||
return key % tabsz;
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
/* $NetBSD: tables.h,v 1.10 2007/04/29 20:23:34 msaitoh Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -14,7 +16,7 @@
|
|||
* 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.
|
||||
* 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.
|
||||
*
|
||||
|
@ -31,7 +33,6 @@
|
|||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)tables.h 8.1 (Berkeley) 5/31/93
|
||||
* $FreeBSD: src/bin/pax/tables.h,v 1.10 2004/04/06 20:06:48 markm Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -132,7 +133,7 @@ typedef struct dlist {
|
|||
} DLIST;
|
||||
|
||||
/*
|
||||
* ftree directory access time reset table. When we are done with with a
|
||||
* ftree directory access time reset table. When we are done with a
|
||||
* subtree we reset the access and mod time of the directory when the tflag is
|
||||
* set. Not really explicitly specified in the pax spec, but easy and fast to
|
||||
* do (and this may have even been intended in the spec, it is not clear).
|
||||
|
@ -160,10 +161,16 @@ typedef struct atdir {
|
|||
*/
|
||||
|
||||
typedef struct dirdata {
|
||||
#ifdef DIRS_USE_FILE
|
||||
int nlen; /* length of the directory name (includes \0) */
|
||||
off_t npos; /* position in file where this dir name starts */
|
||||
#else
|
||||
char *name; /* file name */
|
||||
struct dirdata *next;
|
||||
#endif
|
||||
mode_t mode; /* file mode to restore */
|
||||
time_t mtime; /* mtime to set */
|
||||
time_t atime; /* atime to set */
|
||||
long fflags; /* file flags to set */
|
||||
int frc_mode; /* do we force mode settings? */
|
||||
} DIRDATA;
|
|
@ -1,4 +1,5 @@
|
|||
.\"-
|
||||
.\" $NetBSD: tar.1,v 1.33 2012/03/22 07:58:17 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1996 SigmaSoft, Th. Lockert
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
|
@ -10,11 +11,6 @@
|
|||
.\" 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 SigmaSoft, Th. Lockert.
|
||||
.\" 4. The name of the author may not be used to endorse or promote products
|
||||
.\" derived from this software without specific prior written permission
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
|
@ -27,58 +23,53 @@
|
|||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $OpenBSD: tar.1,v 1.33 2001/05/01 17:58:01 aaron Exp $
|
||||
.\" $FreeBSD$
|
||||
.\" OpenBSD: tar.1,v 1.28 2000/11/09 23:58:56 aaron Exp
|
||||
.\"
|
||||
.Dd February 7, 2001
|
||||
.Dd June 18, 2011
|
||||
.Dt TAR 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm tar
|
||||
.Nd tape archiver
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Nm tar
|
||||
.Sm off
|
||||
.Op Fl
|
||||
.Brq Cm crtux
|
||||
.Op Cm befhjmopqsvwyzHLOPXZ014578
|
||||
.Oo \&- Oc {crtux} Op Fl 014578befHhjklmOoPpqSvwXZz
|
||||
.Sm on
|
||||
.Op Ar blocksize
|
||||
.Op Ar archive
|
||||
.Op Ar replstr
|
||||
.Op Ar blocksize
|
||||
.\" XXX how to do this right?
|
||||
.Op Fl C Ar directory
|
||||
.Op Fl I Ar file
|
||||
.Op Ar
|
||||
.Op Fl s Ar replstr
|
||||
.Op Fl T Ar file
|
||||
.Op Ar file ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
command creates, adds files to, or extracts files from an
|
||||
archive file in
|
||||
.Nm
|
||||
.Dq tar
|
||||
format.
|
||||
A
|
||||
.Nm
|
||||
archive is often stored on a magnetic tape, but can be
|
||||
A tar archive is often stored on a magnetic tape, but can be
|
||||
stored equally well on a floppy, CD-ROM, or in a regular disk file.
|
||||
.Pp
|
||||
One of the following flags must be present:
|
||||
.Bl -tag -width indent
|
||||
.It Fl c
|
||||
.Bl -tag -width Ar
|
||||
.It Fl c , Fl Fl create
|
||||
Create new archive, or overwrite an existing archive,
|
||||
adding the specified files to it.
|
||||
.It Fl r
|
||||
.It Fl r , Fl Fl append
|
||||
Append the named new files to existing archive.
|
||||
Note that this will only work on media on which an end-of-file mark
|
||||
can be overwritten.
|
||||
.It Fl t
|
||||
.It Fl t , Fl Fl list
|
||||
List contents of archive.
|
||||
If any files are named on the
|
||||
command line, only those files will be listed.
|
||||
.It Fl u
|
||||
.It Fl u , Fl Fl update
|
||||
Alias for
|
||||
.Fl r .
|
||||
.It Fl x
|
||||
.It Fl x , Fl Fl extract , Fl Fl get
|
||||
Extract files from archive.
|
||||
If any files are named on the
|
||||
command line, only those files will be extracted from the
|
||||
|
@ -94,39 +85,51 @@ The file mode is subject to modification by the
|
|||
.Pp
|
||||
In addition to the flags mentioned above, any of the following
|
||||
flags may be used:
|
||||
.Bl -tag -width indent
|
||||
.It Fl b Ar "blocking factor"
|
||||
Set blocking factor to use for the archive, with 512 byte blocks.
|
||||
.Bl -tag -width Ar
|
||||
.It Fl b Ar "blocking factor" , Fl Fl block-size Ar "blocking factor"
|
||||
Set blocking factor to use for the archive.
|
||||
.Nm
|
||||
uses 512 byte blocks.
|
||||
The default is 20, the maximum is 126.
|
||||
Archives with a blocking factor larger 63 violate the
|
||||
.Tn POSIX
|
||||
standard and will not be portable to all systems.
|
||||
.It Fl e
|
||||
Stop after first error.
|
||||
.It Fl f Ar archive
|
||||
.It Fl f Ar archive , Fl Fl file Ar archive
|
||||
Filename where the archive is stored.
|
||||
Defaults to
|
||||
.Pa /dev/sa0 .
|
||||
.It Fl h
|
||||
.Pa /dev/rst0 .
|
||||
If the archive is of the form:
|
||||
.Ar [[user@]host:]file
|
||||
then the archive will be processed using
|
||||
.Xr rmt 8 .
|
||||
.It Fl h , Fl Fl dereference
|
||||
Follow symbolic links as if they were normal files
|
||||
or directories.
|
||||
.It Fl j
|
||||
Compress archives using
|
||||
.Xr bzip2 1 .
|
||||
.It Fl m
|
||||
.It Fl j, Fl Fl bzip2, Fl Fl bunzip2
|
||||
Use
|
||||
.Xr bzip2 1
|
||||
for compression of the archive.
|
||||
This option is a GNU extension.
|
||||
.It Fl k , Fl Fl keep-old-files
|
||||
Keep existing files; don't overwrite them from archive.
|
||||
.It Fl l , Fl Fl one-file-system
|
||||
Do not descend across mount points.
|
||||
.\" should be '-X'
|
||||
.It Fl m , Fl Fl modification-time
|
||||
Do not preserve modification time.
|
||||
.It Fl O
|
||||
Write old-style
|
||||
.Pq non- Ns Tn POSIX
|
||||
archives.
|
||||
.It Fl o
|
||||
Do not write directory information that the older (V7) style
|
||||
When creating and appending to an archive, write old-style (non-POSIX) archives.
|
||||
When extracting from an archive, extract to standard output.
|
||||
.It Fl o , Fl Fl portability , Fl Fl old-archive
|
||||
Don't write directory information that the older (V7) style
|
||||
.Nm
|
||||
is unable to decode.
|
||||
This implies the
|
||||
.Fl O
|
||||
flag.
|
||||
.It Fl p
|
||||
.It Fl p , Fl Fl preserve-permissions , Fl Fl preserve
|
||||
Preserve user and group ID as well as file mode regardless of
|
||||
the current
|
||||
.Xr umask 2 .
|
||||
|
@ -135,7 +138,7 @@ the superuser.
|
|||
Only meaningful in conjunction with the
|
||||
.Fl x
|
||||
flag.
|
||||
.It Fl q
|
||||
.It Fl q , Fl Fl fast-read
|
||||
Select the first archive member that matches each
|
||||
.Ar pattern
|
||||
operand.
|
||||
|
@ -143,6 +146,10 @@ No more than one archive member is matched for each
|
|||
.Ar pattern .
|
||||
When members of type directory are matched, the file hierarchy rooted at that
|
||||
directory is also matched.
|
||||
.It Fl S , Fl Fl sparse
|
||||
This flag has no effect as
|
||||
.Nm
|
||||
always generates sparse files.
|
||||
.It Fl s Ar replstr
|
||||
Modify the file or archive member names specified by the
|
||||
.Ar pattern
|
||||
|
@ -154,25 +161,20 @@ using the syntax of the
|
|||
.Xr ed 1
|
||||
utility regular expressions.
|
||||
The format of these regular expressions are:
|
||||
.Dl /old/new/[gp]
|
||||
.Dl /old/new/[gps]
|
||||
As in
|
||||
.Xr ed 1 ,
|
||||
.Cm old
|
||||
is a basic regular expression and
|
||||
.Cm new
|
||||
can contain an ampersand
|
||||
.Pq Ql & ,
|
||||
.Li \e Ns Ar n
|
||||
(where
|
||||
.Ar n
|
||||
is a digit) back-references,
|
||||
can contain an ampersand (\*[Am]), \en (where n is a digit) back-references,
|
||||
or subexpression matching.
|
||||
The
|
||||
.Cm old
|
||||
string may also contain newline characters.
|
||||
Any non-null character can be used as a delimiter
|
||||
.Ql ( /
|
||||
is shown here).
|
||||
string may also contain
|
||||
.Aq Dv newline
|
||||
characters.
|
||||
Any non-null character can be used as a delimiter (/ is shown here).
|
||||
Multiple
|
||||
.Fl s
|
||||
expressions can be specified.
|
||||
|
@ -189,73 +191,126 @@ option.
|
|||
The optional trailing
|
||||
.Cm p
|
||||
will cause the final result of a successful substitution to be written to
|
||||
standard error
|
||||
.Dv standard error
|
||||
in the following format:
|
||||
.Pp
|
||||
.Dl <original pathname> >> <new pathname>
|
||||
.Pp
|
||||
.Dl \*[Lt]original pathname\*[Gt] \*[Gt]\*[Gt] \*[Lt]new pathname\*[Gt]
|
||||
File or archive member names that substitute to the empty string
|
||||
are not selected and will be skipped.
|
||||
The substitutions are applied by default to the destination hard and symbolic
|
||||
links.
|
||||
The optional trailing
|
||||
.Cm s
|
||||
prevents the substitutions from being performed on symbolic link destinations.
|
||||
.It Fl v
|
||||
Verbose operation mode.
|
||||
.It Fl w
|
||||
.It Fl w , Fl Fl interactive , Fl Fl confirmation
|
||||
Interactively rename files.
|
||||
This option causes
|
||||
.Nm
|
||||
to prompt the user for the filename to use when storing or
|
||||
extracting files in an archive.
|
||||
.It Fl y
|
||||
Compress archives using
|
||||
.Xr bzip2 1 .
|
||||
.It Fl z
|
||||
Compress archive using
|
||||
.It Fl Fl xz
|
||||
Compress/decompress archive using
|
||||
.Xr xz 1 .
|
||||
.It Fl z , Fl Fl gzip , Fl Fl gunzip
|
||||
Compress/decompress archive using
|
||||
.Xr gzip 1 .
|
||||
.It Fl C Ar directory
|
||||
.It Fl B , Fl Fl read-full-blocks
|
||||
Reassemble small reads into full blocks (For reading from 4.2BSD pipes).
|
||||
.It Fl C Ar directory , Fl Fl directory Ar directory
|
||||
This is a positional argument which sets the working directory for the
|
||||
following files.
|
||||
When extracting, files will be extracted into
|
||||
the specified directory; when creating, the specified files will be matched
|
||||
from the directory.
|
||||
This argument and its parameter may also appear in a file list specified by
|
||||
.Fl T .
|
||||
.It Fl H
|
||||
Follow symlinks given on command line only.
|
||||
.It Fl L
|
||||
Follow all symlinks.
|
||||
.It Fl P
|
||||
Only follow symlinks given on command line.
|
||||
.Pp
|
||||
Note SysVr3/i386 picked up ISC/SCO UNIX compatibility which implemented
|
||||
.Dq Fl F Ar file
|
||||
which was defined as obtaining a list of command line switches and files
|
||||
on which to operate from the specified file,
|
||||
but SunOS-5 uses
|
||||
.Dq Fl I Ar file
|
||||
because they use
|
||||
.Sq Fl F
|
||||
to mean something else.
|
||||
We might someday provide SunOS-5 compatibility
|
||||
but it makes little sense to confuse things with ISC/SCO compatibility.
|
||||
.\".It Fl L
|
||||
.\"Do not follow any symlinks (do the opposite of
|
||||
.\".Fl h ).
|
||||
.It Fl P , Fl Fl absolute-paths
|
||||
Do not strip leading slashes
|
||||
.Pq Ql /
|
||||
.Pq Sq /
|
||||
from pathnames.
|
||||
The default is to strip leading slashes.
|
||||
.It Fl I Ar file
|
||||
This is a positional argument which reads the names of files to
|
||||
archive or extract from the given file, one per line.
|
||||
.It Fl X
|
||||
Do not cross mount points in the file system.
|
||||
.It Fl Z
|
||||
Compress archive using
|
||||
.Xr compress 1 .
|
||||
.It Fl T Ar file , Fl Fl files-from Ar file
|
||||
Read the names of files to archive or extract from the given file, one
|
||||
per line.
|
||||
A line may also specify the positional argument
|
||||
.Dq Fl C Ar directory .
|
||||
.It Fl X Ar file , Fl Fl exclude-from Ar file
|
||||
Exclude files matching the shell glob patterns listed in the given file.
|
||||
.\" exclude should be '-E' and '-X' should be one-file-system
|
||||
.Pp
|
||||
Note that it would be more standard to use this option to mean ``do not
|
||||
cross filesystem mount points.''
|
||||
.It Fl Z , Fl Fl compress , Fl Fl uncompress
|
||||
Compress archive using compress.
|
||||
.It Fl Fl strict
|
||||
Do not enable GNU tar extensions such as long filenames and long link names.
|
||||
.It Fl Fl atime-preserve
|
||||
Preserve file access times.
|
||||
.It Fl Fl chroot
|
||||
.Fn chroot
|
||||
to the current directory before extracting files.
|
||||
Use with
|
||||
.Fl x
|
||||
and
|
||||
.Fl h
|
||||
to make absolute symlinks relative to the current directory.
|
||||
.It Fl Fl unlink
|
||||
Ignored, only accepted for compatibility with other
|
||||
.Nm
|
||||
implementations.
|
||||
.Nm
|
||||
always unlinks files before creating them.
|
||||
.It Fl Fl use-compress-program Ar program
|
||||
Use the named program as the program to decompress the input.
|
||||
.It Fl Fl force-local
|
||||
Do not interpret filenames that contain a
|
||||
.Sq \&:
|
||||
as remote files.
|
||||
.It Fl Fl insecure
|
||||
Normally
|
||||
.Nm
|
||||
ignores filenames that contain
|
||||
.Dq ..
|
||||
as a path component.
|
||||
With this option, files that contain
|
||||
.Dq ..
|
||||
can be processed.
|
||||
.It Fl Fl no-recursion
|
||||
Cause files of type directory being copied or archived, or archive members of
|
||||
type directory being extracted, to match only the directory file or archive
|
||||
member and not the file hierarchy rooted at the directory.
|
||||
.El
|
||||
.Pp
|
||||
The options
|
||||
.Op Fl 014578
|
||||
can be used to select one of the compiled-in backup devices,
|
||||
.Pa /dev/rst Ns Ar N .
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width TMPDIR
|
||||
.It Ev TMPDIR
|
||||
Path in which to store temporary files.
|
||||
.It Ev TAPE
|
||||
Default tape device to use instead of
|
||||
.Pa /dev/sa0 .
|
||||
.El
|
||||
.Pa /dev/rstN .
|
||||
.Sh FILES
|
||||
.Bl -tag -width "/dev/sa0"
|
||||
.It Pa /dev/sa0
|
||||
.Bl -tag -width "/dev/rst0"
|
||||
.It Pa /dev/rst0
|
||||
default archive name
|
||||
.El
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Sh DIAGNOSTICS
|
||||
.Nm
|
||||
utility will exit with one of the following values:
|
||||
will exit with one of the following values:
|
||||
.Bl -tag -width 2n
|
||||
.It 0
|
||||
All files were processed successfully.
|
||||
|
@ -291,12 +346,6 @@ or error,
|
|||
.Nm
|
||||
may have only partially created the archive which may violate the
|
||||
specific archive format specification.
|
||||
.Sh COMPATIBILITY
|
||||
The
|
||||
.Fl L
|
||||
flag is not portable to other versions of
|
||||
.Nm
|
||||
where it may have a different meaning.
|
||||
.Sh SEE ALSO
|
||||
.Xr cpio 1 ,
|
||||
.Xr pax 1
|
||||
|
@ -306,5 +355,4 @@ A
|
|||
command first appeared in
|
||||
.At v7 .
|
||||
.Sh AUTHORS
|
||||
.An Keith Muller
|
||||
at the University of California, San Diego.
|
||||
Keith Muller at the University of California, San Diego.
|
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,5 @@
|
|||
/* $NetBSD: tar.h,v 1.9 2004/05/11 17:12:26 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -14,7 +16,7 @@
|
|||
* 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.
|
||||
* 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.
|
||||
*
|
||||
|
@ -31,7 +33,6 @@
|
|||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)tar.h 8.2 (Berkeley) 4/18/94
|
||||
* $FreeBSD: src/bin/pax/tar.h,v 1.7 2004/04/06 20:06:49 markm Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -41,13 +42,13 @@
|
|||
#define TNMSZ 100 /* size of name field */
|
||||
#ifdef _PAX_
|
||||
#define NULLCNT 2 /* number of null blocks in trailer */
|
||||
#define CHK_OFFSET 148 /* start of checksum field */
|
||||
#define CHK_OFFSET 148 /* start of chksum field */
|
||||
#define BLNKSUM 256L /* sum of checksum field using ' ' */
|
||||
#endif /* _PAX_ */
|
||||
|
||||
/*
|
||||
* Values used in typeflag field in all tar formats
|
||||
* (only REGTYPE, LNKTYPE and SYMTYPE are used in old BSD tar headers)
|
||||
* (only REGTYPE, LNKTYPE and SYMTYPE are used in old bsd tar headers)
|
||||
*/
|
||||
#define REGTYPE '0' /* Regular File */
|
||||
#define AREGTYPE '\0' /* Regular File */
|
||||
|
@ -59,6 +60,12 @@
|
|||
#define FIFOTYPE '6' /* FIFO */
|
||||
#define CONTTYPE '7' /* high perf file */
|
||||
|
||||
/*
|
||||
* GNU tar compatibility;
|
||||
*/
|
||||
#define LONGLINKTYPE 'K' /* Long Symlink */
|
||||
#define LONGNAMETYPE 'L' /* Long File */
|
||||
|
||||
/*
|
||||
* Mode field encoding of the different file types - values in octal
|
||||
*/
|
||||
|
@ -88,8 +95,8 @@
|
|||
*/
|
||||
typedef struct {
|
||||
char name[TNMSZ]; /* name of entry */
|
||||
char mode[8]; /* mode */
|
||||
char uid[8]; /* uid */
|
||||
char mode[8]; /* mode */
|
||||
char uid[8]; /* uid */
|
||||
char gid[8]; /* gid */
|
||||
char size[12]; /* size */
|
||||
char mtime[12]; /* modification time */
|
||||
|
@ -108,12 +115,12 @@ typedef struct {
|
|||
/*
|
||||
* default device names
|
||||
*/
|
||||
#define DEV_0 "/dev/rmt0"
|
||||
#define DEV_1 "/dev/rmt1"
|
||||
#define DEV_4 "/dev/rmt4"
|
||||
#define DEV_5 "/dev/rmt5"
|
||||
#define DEV_7 "/dev/rmt7"
|
||||
#define DEV_8 "/dev/rmt8"
|
||||
extern char DEV_0[];
|
||||
extern char DEV_1[];
|
||||
extern char DEV_4[];
|
||||
extern char DEV_5[];
|
||||
extern char DEV_7[];
|
||||
extern char DEV_8[];
|
||||
#endif /* _PAX_ */
|
||||
|
||||
/*
|
||||
|
@ -127,8 +134,8 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
char name[TNMSZ]; /* name of entry */
|
||||
char mode[8]; /* mode */
|
||||
char uid[8]; /* uid */
|
||||
char mode[8]; /* mode */
|
||||
char uid[8]; /* uid */
|
||||
char gid[8]; /* gid */
|
||||
char size[12]; /* size */
|
||||
char mtime[12]; /* modification time */
|
|
@ -1,3 +1,5 @@
|
|||
/* $NetBSD: tty_subs.c,v 1.19 2007/04/23 18:40:22 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -14,7 +16,7 @@
|
|||
* 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.
|
||||
* 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.
|
||||
*
|
||||
|
@ -31,16 +33,27 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if HAVE_NBTOOL_CONFIG_H
|
||||
#include "nbtool_config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)tty_subs.c 8.2 (Berkeley) 4/18/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: tty_subs.c,v 1.19 2007/04/23 18:40:22 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -52,14 +65,14 @@ static char sccsid[] = "@(#)tty_subs.c 8.2 (Berkeley) 4/18/94";
|
|||
* routines that deal with I/O to and from the user
|
||||
*/
|
||||
|
||||
#define DEVTTY "/dev/tty" /* device for interactive i/o */
|
||||
#define DEVTTY "/dev/tty" /* device for interactive i/o */
|
||||
static FILE *ttyoutf = NULL; /* output pointing at control tty */
|
||||
static FILE *ttyinf = NULL; /* input pointing at control tty */
|
||||
|
||||
/*
|
||||
* tty_init()
|
||||
* try to open the controlling terminal (if any) for this process. if the
|
||||
* open fails, future ops that require user input will get an EOF
|
||||
* Try to open the controlling terminal (if any) for this process. If the
|
||||
* open fails, future ops that require user input will get an EOF.
|
||||
*/
|
||||
|
||||
int
|
||||
|
@ -70,17 +83,17 @@ tty_init(void)
|
|||
if ((ttyfd = open(DEVTTY, O_RDWR)) >= 0) {
|
||||
if ((ttyoutf = fdopen(ttyfd, "w")) != NULL) {
|
||||
if ((ttyinf = fdopen(ttyfd, "r")) != NULL)
|
||||
return(0);
|
||||
return 0;
|
||||
(void)fclose(ttyoutf);
|
||||
}
|
||||
(void)close(ttyfd);
|
||||
}
|
||||
|
||||
if (iflag) {
|
||||
paxwarn(1, "Fatal error, cannot open %s", DEVTTY);
|
||||
return(-1);
|
||||
tty_warn(1, "Fatal error, cannot open %s", DEVTTY);
|
||||
return -1;
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -115,7 +128,7 @@ tty_read(char *str, int len)
|
|||
char *pt;
|
||||
|
||||
if ((--len <= 0) || (ttyinf == NULL) || (fgets(str,len,ttyinf) == NULL))
|
||||
return(-1);
|
||||
return -1;
|
||||
*(str + len) = '\0';
|
||||
|
||||
/*
|
||||
|
@ -123,17 +136,17 @@ tty_read(char *str, int len)
|
|||
*/
|
||||
if ((pt = strchr(str, '\n')) != NULL)
|
||||
*pt = '\0';
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* paxwarn()
|
||||
* tty_warn()
|
||||
* write a warning message to stderr. if "set" the exit value of pax
|
||||
* will be non-zero.
|
||||
*/
|
||||
|
||||
void
|
||||
paxwarn(int set, const char *fmt, ...)
|
||||
tty_warn(int set, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
@ -143,8 +156,7 @@ paxwarn(int set, const char *fmt, ...)
|
|||
* when vflag we better ship out an extra \n to get this message on a
|
||||
* line by itself
|
||||
*/
|
||||
if (vflag && vfpart) {
|
||||
(void)fflush(listf);
|
||||
if ((Vflag || vflag) && vfpart) {
|
||||
(void)fputc('\n', stderr);
|
||||
vfpart = 0;
|
||||
}
|
||||
|
@ -171,9 +183,8 @@ syswarn(int set, int errnum, const char *fmt, ...)
|
|||
* when vflag we better ship out an extra \n to get this message on a
|
||||
* line by itself
|
||||
*/
|
||||
if (vflag && vfpart) {
|
||||
(void)fflush(listf);
|
||||
(void)fputc('\n', stderr);
|
||||
if ((Vflag || vflag) && vfpart) {
|
||||
(void)fputc('\n', stdout);
|
||||
vfpart = 0;
|
||||
}
|
||||
(void)fprintf(stderr, "%s: ", argv0);
|
||||
|
@ -184,6 +195,6 @@ syswarn(int set, int errnum, const char *fmt, ...)
|
|||
* format and print the errno
|
||||
*/
|
||||
if (errnum > 0)
|
||||
(void)fprintf(stderr, " <%s>", strerror(errnum));
|
||||
(void)fprintf(stderr, " (%s)", strerror(errnum));
|
||||
(void)fputc('\n', stderr);
|
||||
}
|
|
@ -17,7 +17,7 @@ SUBDIR= add_route arp ash at backup banner basename btrace cal \
|
|||
lpd ls lspci mail MAKEDEV \
|
||||
mesg mined mkfifo \
|
||||
mkproto mount mt netconf nice acknm nohup \
|
||||
nonamed od paste patch pax \
|
||||
nonamed od paste patch \
|
||||
ping postinstall poweroff pr prep printf printroot \
|
||||
profile progressbar pr_routes ps pwd pwdauth \
|
||||
ramdisk rarpd rawspeed rcp rdate readclock \
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 5/31/93
|
||||
# $FreeBSD$
|
||||
|
||||
# To install on versions prior to BSD 4.4 the following may have to be
|
||||
# defined with CFLAGS +=
|
||||
#
|
||||
# -DNET2_STAT Use NET2 or older stat structure. The version of the
|
||||
# stat structure is easily determined by looking at the
|
||||
# basic type of an off_t (often defined in the file:
|
||||
# /usr/include/sys/types.h). If off_t is a long (and is
|
||||
# NOT A quad) then you must define NET2_STAT.
|
||||
# This define is important, as if you do have a quad_t
|
||||
# off_t and define NET2_STAT, pax will compile but will
|
||||
# NOT RUN PROPERLY.
|
||||
#
|
||||
# -DNET2_FTS Use the older NET2 fts. To identify the version,
|
||||
# examine the file: /usr/include/fts.h. If FTS_COMFOLLOW
|
||||
# is not defined then you must define NET2_FTS.
|
||||
# Pax may not compile if this not (un)defined properly.
|
||||
#
|
||||
# -DNET2_REGEX Use the older regexp.h not regex.h. The regex version
|
||||
# is determined by looking at the value returned by
|
||||
# regexec() (man 3 regexec). If regexec return a 1 for
|
||||
# success (and NOT a 0 for success) you have the older
|
||||
# regex routines and must define NET2_REGEX.
|
||||
# Pax may not compile if this not (un)defined 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 fgetln.c
|
||||
|
||||
MAN= pax.1 cpio.1
|
||||
BINDIR=/bin
|
||||
SYMLINKS+= $(BINDIR)/$(PROG) /usr/bin/$(PROG)
|
||||
LINKS+= ${BINDIR}/pax ${BINDIR}/cpio
|
||||
|
||||
CPPFLAGS+= -DNET2_STAT=1
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -1,430 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Keith Muller of the University of California, San Diego.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)cache.c 8.1 (Berkeley) 5/31/93";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include "pax.h"
|
||||
#include "cache.h"
|
||||
#include "extern.h"
|
||||
|
||||
/*
|
||||
* routines that control user, group, uid and gid caches (for the archive
|
||||
* member print routine).
|
||||
* IMPORTANT:
|
||||
* these routines cache BOTH hits and misses, a major performance improvement
|
||||
*/
|
||||
|
||||
static int pwopn = 0; /* is password file open */
|
||||
static int gropn = 0; /* is group file open */
|
||||
static UIDC **uidtb = NULL; /* uid to name cache */
|
||||
static GIDC **gidtb = NULL; /* gid to name cache */
|
||||
static UIDC **usrtb = NULL; /* user name to uid cache */
|
||||
static GIDC **grptb = NULL; /* group name to gid cache */
|
||||
|
||||
/*
|
||||
* uidtb_start
|
||||
* creates an an empty uidtb
|
||||
* Return:
|
||||
* 0 if ok, -1 otherwise
|
||||
*/
|
||||
|
||||
int
|
||||
uidtb_start(void)
|
||||
{
|
||||
static int fail = 0;
|
||||
|
||||
if (uidtb != NULL)
|
||||
return(0);
|
||||
if (fail)
|
||||
return(-1);
|
||||
if ((uidtb = (UIDC **)calloc(UID_SZ, sizeof(UIDC *))) == NULL) {
|
||||
++fail;
|
||||
paxwarn(1, "Unable to allocate memory for user id cache table");
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* gidtb_start
|
||||
* creates an an empty gidtb
|
||||
* Return:
|
||||
* 0 if ok, -1 otherwise
|
||||
*/
|
||||
|
||||
int
|
||||
gidtb_start(void)
|
||||
{
|
||||
static int fail = 0;
|
||||
|
||||
if (gidtb != NULL)
|
||||
return(0);
|
||||
if (fail)
|
||||
return(-1);
|
||||
if ((gidtb = (GIDC **)calloc(GID_SZ, sizeof(GIDC *))) == NULL) {
|
||||
++fail;
|
||||
paxwarn(1, "Unable to allocate memory for group id cache table");
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* usrtb_start
|
||||
* creates an an empty usrtb
|
||||
* Return:
|
||||
* 0 if ok, -1 otherwise
|
||||
*/
|
||||
|
||||
int
|
||||
usrtb_start(void)
|
||||
{
|
||||
static int fail = 0;
|
||||
|
||||
if (usrtb != NULL)
|
||||
return(0);
|
||||
if (fail)
|
||||
return(-1);
|
||||
if ((usrtb = (UIDC **)calloc(UNM_SZ, sizeof(UIDC *))) == NULL) {
|
||||
++fail;
|
||||
paxwarn(1, "Unable to allocate memory for user name cache table");
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* grptb_start
|
||||
* creates an an empty grptb
|
||||
* Return:
|
||||
* 0 if ok, -1 otherwise
|
||||
*/
|
||||
|
||||
int
|
||||
grptb_start(void)
|
||||
{
|
||||
static int fail = 0;
|
||||
|
||||
if (grptb != NULL)
|
||||
return(0);
|
||||
if (fail)
|
||||
return(-1);
|
||||
if ((grptb = (GIDC **)calloc(GNM_SZ, sizeof(GIDC *))) == NULL) {
|
||||
++fail;
|
||||
paxwarn(1,"Unable to allocate memory for group name cache table");
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* name_uid()
|
||||
* caches the name (if any) for the uid. If frc set, we always return the
|
||||
* the stored name (if valid or invalid match). We use a simple hash table.
|
||||
* Return
|
||||
* Pointer to stored name (or an empty string).
|
||||
*/
|
||||
|
||||
const char *
|
||||
name_uid(uid_t uid, int frc)
|
||||
{
|
||||
struct passwd *pw;
|
||||
UIDC *ptr;
|
||||
|
||||
if ((uidtb == NULL) && (uidtb_start() < 0))
|
||||
return("");
|
||||
|
||||
/*
|
||||
* see if we have this uid cached
|
||||
*/
|
||||
ptr = uidtb[uid % UID_SZ];
|
||||
if ((ptr != NULL) && (ptr->valid > 0) && (ptr->uid == uid)) {
|
||||
/*
|
||||
* have an entry for this uid
|
||||
*/
|
||||
if (frc || (ptr->valid == VALID))
|
||||
return(ptr->name);
|
||||
return("");
|
||||
}
|
||||
|
||||
/*
|
||||
* No entry for this uid, we will add it
|
||||
*/
|
||||
if (!pwopn) {
|
||||
setpassent(1);
|
||||
++pwopn;
|
||||
}
|
||||
if (ptr == NULL)
|
||||
ptr = uidtb[uid % UID_SZ] = (UIDC *)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 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 {
|
||||
/*
|
||||
* there is an entry for this uid in the password file
|
||||
*/
|
||||
if (ptr == NULL)
|
||||
return(pw->pw_name);
|
||||
ptr->uid = uid;
|
||||
(void)strncpy(ptr->name, pw->pw_name, UNMLEN - 1);
|
||||
ptr->name[UNMLEN-1] = '\0';
|
||||
ptr->valid = VALID;
|
||||
}
|
||||
return(ptr->name);
|
||||
}
|
||||
|
||||
/*
|
||||
* name_gid()
|
||||
* caches the name (if any) for the gid. If frc set, we always return the
|
||||
* the stored name (if valid or invalid match). We use a simple hash table.
|
||||
* Return
|
||||
* Pointer to stored name (or an empty string).
|
||||
*/
|
||||
|
||||
const char *
|
||||
name_gid(gid_t gid, int frc)
|
||||
{
|
||||
struct group *gr;
|
||||
GIDC *ptr;
|
||||
|
||||
if ((gidtb == NULL) && (gidtb_start() < 0))
|
||||
return("");
|
||||
|
||||
/*
|
||||
* see if we have this gid cached
|
||||
*/
|
||||
ptr = gidtb[gid % GID_SZ];
|
||||
if ((ptr != NULL) && (ptr->valid > 0) && (ptr->gid == gid)) {
|
||||
/*
|
||||
* have an entry for this gid
|
||||
*/
|
||||
if (frc || (ptr->valid == VALID))
|
||||
return(ptr->name);
|
||||
return("");
|
||||
}
|
||||
|
||||
/*
|
||||
* No entry for this gid, we will add it
|
||||
*/
|
||||
if (!gropn) {
|
||||
setgroupent(1);
|
||||
++gropn;
|
||||
}
|
||||
if (ptr == NULL)
|
||||
ptr = gidtb[gid % GID_SZ] = (GIDC *)malloc(sizeof(GIDC));
|
||||
|
||||
if ((gr = getgrgid(gid)) == NULL) {
|
||||
/*
|
||||
* no match for this gid in the local group file, put in
|
||||
* a string that is the gid in numeric format
|
||||
*/
|
||||
if (ptr == 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 {
|
||||
/*
|
||||
* there is an entry for this group in the group file
|
||||
*/
|
||||
if (ptr == NULL)
|
||||
return(gr->gr_name);
|
||||
ptr->gid = gid;
|
||||
(void)strncpy(ptr->name, gr->gr_name, GNMLEN - 1);
|
||||
ptr->name[GNMLEN-1] = '\0';
|
||||
ptr->valid = VALID;
|
||||
}
|
||||
return(ptr->name);
|
||||
}
|
||||
|
||||
/*
|
||||
* uid_name()
|
||||
* caches the uid for a given user name. We use a simple hash table.
|
||||
* Return
|
||||
* the uid (if any) for a user name, or a -1 if no match can be found
|
||||
*/
|
||||
|
||||
int
|
||||
uid_name(char *name, uid_t *uid)
|
||||
{
|
||||
struct passwd *pw;
|
||||
UIDC *ptr;
|
||||
int namelen;
|
||||
|
||||
/*
|
||||
* return -1 for mangled names
|
||||
*/
|
||||
if (((namelen = strlen(name)) == 0) || (name[0] == '\0'))
|
||||
return(-1);
|
||||
if ((usrtb == NULL) && (usrtb_start() < 0))
|
||||
return(-1);
|
||||
|
||||
/*
|
||||
* look up in hash table, if found and valid return the uid,
|
||||
* if found and invalid, return a -1
|
||||
*/
|
||||
ptr = usrtb[st_hash(name, namelen, UNM_SZ)];
|
||||
if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) {
|
||||
if (ptr->valid == INVALID)
|
||||
return(-1);
|
||||
*uid = ptr->uid;
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (!pwopn) {
|
||||
setpassent(1);
|
||||
++pwopn;
|
||||
}
|
||||
|
||||
if (ptr == NULL)
|
||||
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,
|
||||
* or store the matching uid
|
||||
*/
|
||||
if (ptr == NULL) {
|
||||
if ((pw = getpwnam(name)) == NULL)
|
||||
return(-1);
|
||||
*uid = pw->pw_uid;
|
||||
return(0);
|
||||
}
|
||||
(void)strncpy(ptr->name, name, UNMLEN - 1);
|
||||
ptr->name[UNMLEN-1] = '\0';
|
||||
if ((pw = getpwnam(name)) == NULL) {
|
||||
ptr->valid = INVALID;
|
||||
return(-1);
|
||||
}
|
||||
ptr->valid = VALID;
|
||||
*uid = ptr->uid = pw->pw_uid;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* gid_name()
|
||||
* caches the gid for a given group name. We use a simple hash table.
|
||||
* Return
|
||||
* the gid (if any) for a group name, or a -1 if no match can be found
|
||||
*/
|
||||
|
||||
int
|
||||
gid_name(char *name, gid_t *gid)
|
||||
{
|
||||
struct group *gr;
|
||||
GIDC *ptr;
|
||||
int namelen;
|
||||
|
||||
/*
|
||||
* return -1 for mangled names
|
||||
*/
|
||||
if (((namelen = strlen(name)) == 0) || (name[0] == '\0'))
|
||||
return(-1);
|
||||
if ((grptb == NULL) && (grptb_start() < 0))
|
||||
return(-1);
|
||||
|
||||
/*
|
||||
* look up in hash table, if found and valid return the uid,
|
||||
* if found and invalid, return a -1
|
||||
*/
|
||||
ptr = grptb[st_hash(name, namelen, GID_SZ)];
|
||||
if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) {
|
||||
if (ptr->valid == INVALID)
|
||||
return(-1);
|
||||
*gid = ptr->gid;
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (!gropn) {
|
||||
setgroupent(1);
|
||||
++gropn;
|
||||
}
|
||||
if (ptr == NULL)
|
||||
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,
|
||||
* or store the matching gid
|
||||
*/
|
||||
if (ptr == NULL) {
|
||||
if ((gr = getgrnam(name)) == NULL)
|
||||
return(-1);
|
||||
*gid = gr->gr_gid;
|
||||
return(0);
|
||||
}
|
||||
|
||||
(void)strncpy(ptr->name, name, GNMLEN - 1);
|
||||
ptr->name[GNMLEN-1] = '\0';
|
||||
if ((gr = getgrnam(name)) == NULL) {
|
||||
ptr->valid = INVALID;
|
||||
return(-1);
|
||||
}
|
||||
ptr->valid = VALID;
|
||||
*gid = ptr->gid = gr->gr_gid;
|
||||
return(0);
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Keith Muller of the University of California, San Diego.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)cache.h 8.1 (Berkeley) 5/31/93
|
||||
* $FreeBSD: src/bin/pax/cache.h,v 1.9 2004/04/06 20:06:48 markm Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* Constants and data structures used to implement group and password file
|
||||
* caches. Traditional passwd/group cache routines perform quite poorly with
|
||||
* archives. The chances of hitting a valid lookup with an archive is quite a
|
||||
* bit worse than with files already resident on the file system. These misses
|
||||
* create a MAJOR performance cost. To address this problem, these routines
|
||||
* cache both hits and misses.
|
||||
*
|
||||
* NOTE: name lengths must be as large as those stored in ANY PROTOCOL and
|
||||
* as stored in the passwd and group files. CACHE SIZES MUST BE PRIME
|
||||
*/
|
||||
#define UNMLEN 32 /* >= user name found in any protocol */
|
||||
#define GNMLEN 32 /* >= group name found in any protocol */
|
||||
#define UID_SZ 317 /* size of user_name/uid cache */
|
||||
#define UNM_SZ 317 /* size of user_name/uid cache */
|
||||
#define GID_SZ 251 /* size of gid cache */
|
||||
#define GNM_SZ 317 /* size of group name cache */
|
||||
#define VALID 1 /* entry and name are valid */
|
||||
#define INVALID 2 /* entry valid, name NOT valid */
|
||||
|
||||
/*
|
||||
* Node structures used in the user, group, uid, and gid caches.
|
||||
*/
|
||||
|
||||
typedef struct uidc {
|
||||
int valid; /* is this a valid or a miss entry */
|
||||
char name[UNMLEN]; /* uid name */
|
||||
uid_t uid; /* cached uid */
|
||||
} UIDC;
|
||||
|
||||
typedef struct gidc {
|
||||
int valid; /* is this a valid or a miss entry */
|
||||
char name[GNMLEN]; /* gid name */
|
||||
gid_t gid; /* cached gid */
|
||||
} GIDC;
|
|
@ -1,38 +0,0 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
char *
|
||||
fgetln(FILE *fp, size_t *lenp)
|
||||
{
|
||||
#define EXTRA 80
|
||||
char *buf = NULL;
|
||||
int used = 0, len = 0, remain = 0, final = 0;
|
||||
while(!final) {
|
||||
char *b;
|
||||
int r;
|
||||
if(remain < EXTRA) {
|
||||
int newlen;
|
||||
char *newbuf;
|
||||
newlen = len + EXTRA;
|
||||
if(!(newbuf = realloc(buf, newlen))) {
|
||||
if(buf) free(buf);
|
||||
return NULL;
|
||||
}
|
||||
buf = newbuf;
|
||||
len = newlen;
|
||||
remain += EXTRA;
|
||||
}
|
||||
buf[used] = '\0';
|
||||
if(!fgets(buf + used, remain, fp))
|
||||
break;
|
||||
r = strlen(buf+used);
|
||||
used += r;
|
||||
remain -= r;
|
||||
len += r;
|
||||
}
|
||||
*lenp = len;
|
||||
return buf;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -9,7 +9,7 @@ SUBDIR+= libcompat_minix libc libblockdriver libchardriver \
|
|||
libz libfetch libvtreefs libaudiodriver libmthread \
|
||||
libexec libdevman libusb libminlib libasyn \
|
||||
libddekit libminixfs libbdev libelf libminc libcrypt libterminfo \
|
||||
libvassert libutil libbz2 libprop \
|
||||
libvassert libutil libbz2 libprop librmt \
|
||||
libnetsock libpuffs libsffs libhgfs libvboxfs
|
||||
|
||||
SUBDIR+= ../external/public-domain/xz/lib
|
||||
|
|
16
lib/librmt/Makefile
Normal file
16
lib/librmt/Makefile
Normal file
|
@ -0,0 +1,16 @@
|
|||
# $NetBSD: Makefile,v 1.9 2007/05/28 12:06:21 tls Exp $
|
||||
|
||||
.ifndef __MINIX
|
||||
USE_FORT?= yes # network protocol library
|
||||
.endif
|
||||
|
||||
NOPIC= # defined
|
||||
NOPROFILE= # defined
|
||||
|
||||
LIB= rmt
|
||||
SRCS= rmtlib.c
|
||||
MAN= rmtops.3
|
||||
|
||||
CPPFLAGS+= -D_REENTRANT
|
||||
|
||||
.include <bsd.lib.mk>
|
20
lib/librmt/README
Normal file
20
lib/librmt/README
Normal file
|
@ -0,0 +1,20 @@
|
|||
# $NetBSD: README,v 1.2 1998/01/09 04:12:19 perry Exp $
|
||||
|
||||
README
|
||||
|
||||
This is the remote mag tape library. It allows a program that uses
|
||||
Unix system calls to transparently use a file (usually a tape drive) on
|
||||
another system via /etc/rmt, simply by including <rmt.h>. It is
|
||||
particularly useful with tar and dd, and is supplied with GNU tar.
|
||||
|
||||
This package has evolved somewhat over the years. My thanks to the
|
||||
people who did most of the original work, and those who've contributed
|
||||
bug fixes; appropriate credit is in the man page and source files.
|
||||
|
||||
Enjoy,
|
||||
|
||||
Arnold Robbins
|
||||
Emory U. Computing Center
|
||||
arnold@emoryu1.cc.emory.edu
|
||||
gatech!emoryu1!arnold
|
||||
+1 404 727 7636
|
30
lib/librmt/pathnames.h
Normal file
30
lib/librmt/pathnames.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/* $NetBSD: pathnames.h,v 1.2 2008/05/29 14:51:25 mrg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Matthew R. Green
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define _PATH_RSH "/usr/bin/rsh"
|
||||
#define _PATH_RMT "/etc/rmt"
|
896
lib/librmt/rmtlib.c
Normal file
896
lib/librmt/rmtlib.c
Normal file
|
@ -0,0 +1,896 @@
|
|||
/* $NetBSD: rmtlib.c,v 1.26 2012/03/21 10:10:37 matt Exp $ */
|
||||
|
||||
/*
|
||||
* rmt --- remote tape emulator subroutines
|
||||
*
|
||||
* Originally written by Jeff Lee, modified some by Arnold Robbins
|
||||
*
|
||||
* WARNING: The man page rmt(8) for /etc/rmt documents the remote mag
|
||||
* tape protocol which rdump and rrestore use. Unfortunately, the man
|
||||
* page is *WRONG*. The author of the routines I'm including originally
|
||||
* wrote his code just based on the man page, and it didn't work, so he
|
||||
* went to the rdump source to figure out why. The only thing he had to
|
||||
* change was to check for the 'F' return code in addition to the 'E',
|
||||
* and to separate the various arguments with \n instead of a space. I
|
||||
* personally don't think that this is much of a problem, but I wanted to
|
||||
* point it out.
|
||||
* -- Arnold Robbins
|
||||
*
|
||||
* Redone as a library that can replace open, read, write, etc, by
|
||||
* Fred Fish, with some additional work by Arnold Robbins.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MAXUNIT --- Maximum number of remote tape file units
|
||||
*
|
||||
* READ --- Return the number of the read side file descriptor
|
||||
* WRITE --- Return the number of the write side file descriptor
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: rmtlib.c,v 1.26 2012/03/21 10:10:37 matt Exp $");
|
||||
|
||||
#define RMTIOCTL 1
|
||||
/* #define USE_REXEC 1 */ /* rexec code courtesy of Dan Kegel, srs!dan */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef RMTIOCTL
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mtio.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <err.h>
|
||||
|
||||
#ifdef USE_REXEC
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
#define __RMTLIB_PRIVATE
|
||||
#include <rmt.h> /* get prototypes for remapped functions */
|
||||
|
||||
#include "pathnames.h"
|
||||
|
||||
static int _rmt_close(int);
|
||||
static int _rmt_ioctl(int, unsigned long, void *);
|
||||
static off_t _rmt_lseek(int, off_t, int);
|
||||
static int _rmt_open(const char *, int, int);
|
||||
static ssize_t _rmt_read(int, void *, size_t);
|
||||
static ssize_t _rmt_write(int, const void *, size_t);
|
||||
static int command(int, const char *);
|
||||
static int remdev(const char *);
|
||||
static void rmtabort(int);
|
||||
static int status(int);
|
||||
|
||||
|
||||
#define BUFMAGIC 64 /* a magic number for buffer sizes */
|
||||
#define MAXUNIT 4
|
||||
|
||||
#define READ(fd) (Ctp[fd][0])
|
||||
#define WRITE(fd) (Ptc[fd][1])
|
||||
|
||||
static int Ctp[MAXUNIT][2] = { {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1} };
|
||||
static int Ptc[MAXUNIT][2] = { {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1} };
|
||||
|
||||
|
||||
/*
|
||||
* rmtabort --- close off a remote tape connection
|
||||
*/
|
||||
static void
|
||||
rmtabort(int fildes)
|
||||
{
|
||||
|
||||
close(READ(fildes));
|
||||
close(WRITE(fildes));
|
||||
READ(fildes) = -1;
|
||||
WRITE(fildes) = -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* command --- attempt to perform a remote tape command
|
||||
*/
|
||||
static int
|
||||
command(int fildes, const char *buf)
|
||||
{
|
||||
size_t blen;
|
||||
sig_t pstat;
|
||||
|
||||
_DIAGASSERT(buf != NULL);
|
||||
|
||||
/*
|
||||
* save current pipe status and try to make the request
|
||||
*/
|
||||
|
||||
blen = strlen(buf);
|
||||
pstat = signal(SIGPIPE, SIG_IGN);
|
||||
if ((size_t)write(WRITE(fildes), buf, blen) == blen) {
|
||||
signal(SIGPIPE, pstat);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* something went wrong. close down and go home
|
||||
*/
|
||||
|
||||
signal(SIGPIPE, pstat);
|
||||
rmtabort(fildes);
|
||||
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* status --- retrieve the status from the pipe
|
||||
*/
|
||||
static int
|
||||
status(int fildes)
|
||||
{
|
||||
int i;
|
||||
char c, *cp;
|
||||
char buffer[BUFMAGIC];
|
||||
|
||||
/*
|
||||
* read the reply command line
|
||||
*/
|
||||
|
||||
for (i = 0, cp = buffer; i < BUFMAGIC; i++, cp++) {
|
||||
if (read(READ(fildes), cp, 1) != 1) {
|
||||
rmtabort(fildes);
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
if (*cp == '\n') {
|
||||
*cp = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == BUFMAGIC) {
|
||||
rmtabort(fildes);
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* check the return status
|
||||
*/
|
||||
|
||||
for (cp = buffer; *cp; cp++)
|
||||
if (*cp != ' ')
|
||||
break;
|
||||
|
||||
if (*cp == 'E' || *cp == 'F') {
|
||||
errno = atoi(cp + 1);
|
||||
while (read(READ(fildes), &c, 1) == 1)
|
||||
if (c == '\n')
|
||||
break;
|
||||
|
||||
if (*cp == 'F')
|
||||
rmtabort(fildes);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* check for mis-synced pipes
|
||||
*/
|
||||
|
||||
if (*cp != 'A') {
|
||||
rmtabort(fildes);
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return atoi(cp + 1);
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_REXEC
|
||||
/*
|
||||
* _rmt_rexec
|
||||
*
|
||||
* execute /etc/rmt on a remote system using rexec().
|
||||
* Return file descriptor of bidirectional socket for stdin and stdout
|
||||
* If username is NULL, or an empty string, uses current username.
|
||||
*
|
||||
* ADR: By default, this code is not used, since it requires that
|
||||
* the user have a .netrc file in his/her home directory, or that the
|
||||
* application designer be willing to have rexec prompt for login and
|
||||
* password info. This may be unacceptable, and .rhosts files for use
|
||||
* with rsh are much more common on BSD systems.
|
||||
*/
|
||||
|
||||
static int _rmt_rexec(const char *, const char *);
|
||||
|
||||
static int
|
||||
_rmt_rexec(const char *host, const char *user)
|
||||
{
|
||||
struct servent *rexecserv;
|
||||
|
||||
_DIAGASSERT(host != NULL);
|
||||
/* user may be NULL */
|
||||
|
||||
rexecserv = getservbyname("exec", "tcp");
|
||||
if (rexecserv == NULL)
|
||||
errx(1, "exec/tcp: service not available.");
|
||||
if ((user != NULL) && *user == '\0')
|
||||
user = NULL;
|
||||
return rexec(&host, rexecserv->s_port, user, NULL,
|
||||
"/etc/rmt", NULL);
|
||||
}
|
||||
#endif /* USE_REXEC */
|
||||
|
||||
|
||||
/*
|
||||
* _rmt_open --- open a magtape device on system specified, as given user
|
||||
*
|
||||
* file name has the form [user@]system:/dev/????
|
||||
#ifdef COMPAT
|
||||
* file name has the form system[.user]:/dev/????
|
||||
#endif
|
||||
*/
|
||||
|
||||
#define MAXHOSTLEN 257 /* BSD allows very long host names... */
|
||||
|
||||
static int
|
||||
/*ARGSUSED*/
|
||||
_rmt_open(const char *path, int oflag, int mode)
|
||||
{
|
||||
int i;
|
||||
char buffer[BUFMAGIC];
|
||||
char host[MAXHOSTLEN];
|
||||
char device[BUFMAGIC];
|
||||
char login[BUFMAGIC];
|
||||
char *sys, *dev, *user;
|
||||
const char *rshpath, *rsh;
|
||||
|
||||
_DIAGASSERT(path != NULL);
|
||||
|
||||
sys = host;
|
||||
dev = device;
|
||||
user = login;
|
||||
|
||||
/*
|
||||
* first, find an open pair of file descriptors
|
||||
*/
|
||||
|
||||
for (i = 0; i < MAXUNIT; i++)
|
||||
if (READ(i) == -1 && WRITE(i) == -1)
|
||||
break;
|
||||
|
||||
if (i == MAXUNIT) {
|
||||
errno = EMFILE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* pull apart system and device, and optional user
|
||||
* don't munge original string
|
||||
* if COMPAT is defined, also handle old (4.2) style person.site notation.
|
||||
*/
|
||||
|
||||
while (*path != '@'
|
||||
#ifdef COMPAT
|
||||
&& *path != '.'
|
||||
#endif
|
||||
&& *path != ':') {
|
||||
*sys++ = *path++;
|
||||
}
|
||||
*sys = '\0';
|
||||
path++;
|
||||
|
||||
if (*(path - 1) == '@') {
|
||||
(void)strncpy(user, host, sizeof(login) - 1);
|
||||
/* saw user part of user@host */
|
||||
sys = host; /* start over */
|
||||
while (*path != ':') {
|
||||
*sys++ = *path++;
|
||||
}
|
||||
*sys = '\0';
|
||||
path++;
|
||||
}
|
||||
#ifdef COMPAT
|
||||
else if (*(path - 1) == '.') {
|
||||
while (*path != ':') {
|
||||
*user++ = *path++;
|
||||
}
|
||||
*user = '\0';
|
||||
path++;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
*user = '\0';
|
||||
|
||||
while (*path) {
|
||||
*dev++ = *path++;
|
||||
}
|
||||
*dev = '\0';
|
||||
|
||||
#ifdef USE_REXEC
|
||||
/*
|
||||
* Execute the remote command using rexec
|
||||
*/
|
||||
READ(i) = WRITE(i) = _rmt_rexec(host, login);
|
||||
if (READ(i) < 0)
|
||||
return -1;
|
||||
#else
|
||||
/*
|
||||
* setup the pipes for the 'rsh' command and fork
|
||||
*/
|
||||
|
||||
if (pipe(Ptc[i]) == -1 || pipe(Ctp[i]) == -1)
|
||||
return -1;
|
||||
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
return -1;
|
||||
|
||||
case 0:
|
||||
close(0);
|
||||
dup(Ptc[i][0]);
|
||||
close(Ptc[i][0]); close(Ptc[i][1]);
|
||||
close(1);
|
||||
dup(Ctp[i][1]);
|
||||
close(Ctp[i][0]); close(Ctp[i][1]);
|
||||
(void) setuid(getuid());
|
||||
(void) setgid(getgid());
|
||||
|
||||
if ((rshpath = getenv("RCMD_CMD")) == NULL)
|
||||
rshpath = _PATH_RSH;
|
||||
if ((rsh = strrchr(rshpath, '/')) == NULL)
|
||||
rsh = rshpath;
|
||||
else
|
||||
rsh++;
|
||||
|
||||
if (*login) {
|
||||
execl(rshpath, rsh, host, "-l", login, _PATH_RMT, NULL);
|
||||
} else {
|
||||
execl(rshpath, rsh, host, _PATH_RMT, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* bad problems if we get here
|
||||
*/
|
||||
|
||||
err(1, "Cannnot exec %s", rshpath);
|
||||
/*FALLTHROUGH*/
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
close(Ptc[i][0]); close(Ctp[i][1]);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* now attempt to open the tape device
|
||||
*/
|
||||
|
||||
(void)snprintf(buffer, sizeof(buffer), "O%s\n%d\n", device, oflag);
|
||||
if (command(i, buffer) == -1 || status(i) == -1)
|
||||
return -1;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* _rmt_close --- close a remote magtape unit and shut down
|
||||
*/
|
||||
static int
|
||||
_rmt_close(int fildes)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (command(fildes, "C\n") != -1) {
|
||||
rc = status(fildes);
|
||||
|
||||
rmtabort(fildes);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* _rmt_read --- read a buffer from a remote tape
|
||||
*/
|
||||
static ssize_t
|
||||
_rmt_read(int fildes, void *buf, size_t nbyte)
|
||||
{
|
||||
size_t rc;
|
||||
int rv;
|
||||
ssize_t nread;
|
||||
char *p;
|
||||
char buffer[BUFMAGIC];
|
||||
|
||||
_DIAGASSERT(buf != NULL);
|
||||
|
||||
(void)snprintf(buffer, sizeof buffer, "R%zu\n", nbyte);
|
||||
if (command(fildes, buffer) == -1 || (rv = status(fildes)) == -1)
|
||||
return -1;
|
||||
|
||||
if (rv > (int)nbyte)
|
||||
rv = (int)nbyte;
|
||||
|
||||
for (rc = rv, p = buf; rc > 0; rc -= nread, p += nread) {
|
||||
if ((nread = read(READ(fildes), p, rc)) <= 0) {
|
||||
rmtabort(fildes);
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* _rmt_write --- write a buffer to the remote tape
|
||||
*/
|
||||
static ssize_t
|
||||
_rmt_write(int fildes, const void *buf, size_t nbyte)
|
||||
{
|
||||
char buffer[BUFMAGIC];
|
||||
sig_t pstat;
|
||||
|
||||
_DIAGASSERT(buf != NULL);
|
||||
|
||||
(void)snprintf(buffer, sizeof buffer, "W%zu\n", nbyte);
|
||||
if (command(fildes, buffer) == -1)
|
||||
return -1;
|
||||
|
||||
pstat = signal(SIGPIPE, SIG_IGN);
|
||||
if ((size_t)write(WRITE(fildes), buf, nbyte) == nbyte) {
|
||||
signal(SIGPIPE, pstat);
|
||||
return status(fildes);
|
||||
}
|
||||
|
||||
signal(SIGPIPE, pstat);
|
||||
rmtabort(fildes);
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* _rmt_lseek --- perform an imitation lseek operation remotely
|
||||
*/
|
||||
static off_t
|
||||
_rmt_lseek(int fildes, off_t offset, int whence)
|
||||
{
|
||||
char buffer[BUFMAGIC];
|
||||
|
||||
/*LONGLONG*/
|
||||
(void)snprintf(buffer, sizeof buffer, "L%lld\n%d\n", (long long)offset,
|
||||
whence);
|
||||
if (command(fildes, buffer) == -1)
|
||||
return -1;
|
||||
|
||||
return status(fildes);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* _rmt_ioctl --- perform raw tape operations remotely
|
||||
*/
|
||||
#ifdef RMTIOCTL
|
||||
static int
|
||||
_rmt_ioctl(int fildes, unsigned long op, void *arg)
|
||||
{
|
||||
char c;
|
||||
int rv;
|
||||
size_t rc;
|
||||
ssize_t cnt;
|
||||
char buffer[BUFMAGIC], *p;
|
||||
struct mtop *mtop = arg;
|
||||
|
||||
_DIAGASSERT(arg != NULL);
|
||||
|
||||
/*
|
||||
* MTIOCOP is the easy one. nothing is transfered in binary
|
||||
*/
|
||||
|
||||
if (op == MTIOCTOP) {
|
||||
(void)snprintf(buffer, sizeof buffer, "I%d\n%d\n",
|
||||
mtop->mt_op, mtop->mt_count);
|
||||
if (command(fildes, buffer) == -1)
|
||||
return -1;
|
||||
return status(fildes);
|
||||
}
|
||||
|
||||
/*
|
||||
* we can only handle 2 ops, if not the other one, punt
|
||||
*/
|
||||
|
||||
if (op != MTIOCGET) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* grab the status and read it directly into the structure
|
||||
* this assumes that the status buffer is (hopefully) not
|
||||
* padded and that 2 shorts fit in a long without any word
|
||||
* alignment problems, ie - the whole struct is contiguous
|
||||
* NOTE - this is probably NOT a good assumption.
|
||||
*/
|
||||
|
||||
if (command(fildes, "S") == -1 || (rv = status(fildes)) == -1)
|
||||
return -1;
|
||||
|
||||
memset(arg, 0, sizeof(struct mtget));
|
||||
for (rc = rv, p = arg; rc > 0; rc -= cnt, p += cnt) {
|
||||
if ((cnt = read(READ(fildes), p, rc)) <= 0) {
|
||||
rmtabort(fildes);
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* now we check for byte position. mt_type is a small integer field
|
||||
* (normally) so we will check its magnitude. if it is larger than
|
||||
* 256, we will assume that the bytes are swapped and go through
|
||||
* and reverse all the bytes
|
||||
*/
|
||||
|
||||
if (((struct mtget *)(void *)p)->mt_type < 256)
|
||||
return 0;
|
||||
|
||||
for (cnt = 0; cnt < rv; cnt += 2) {
|
||||
c = p[cnt];
|
||||
p[cnt] = p[cnt + 1];
|
||||
p[cnt + 1] = c;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* RMTIOCTL */
|
||||
|
||||
|
||||
/*
|
||||
* Added routines to replace open(), close(), lseek(), ioctl(), etc.
|
||||
* The preprocessor can be used to remap these the rmtopen(), etc
|
||||
* thus minimizing source changes:
|
||||
*
|
||||
* #ifdef <something>
|
||||
* # define access rmtaccess
|
||||
* # define close rmtclose
|
||||
* # define creat rmtcreat
|
||||
* # define dup rmtdup
|
||||
* # define fcntl rmtfcntl
|
||||
* # define fstat rmtfstat
|
||||
* # define ioctl rmtioctl
|
||||
* # define isatty rmtisatty
|
||||
* # define lseek rmtlseek
|
||||
* # define lstat rmtlstat
|
||||
* # define open rmtopen
|
||||
* # define read rmtread
|
||||
* # define stat rmtstat
|
||||
* # define write rmtwrite
|
||||
* #endif
|
||||
*
|
||||
* -- Fred Fish
|
||||
*
|
||||
* ADR --- I set up a <rmt.h> include file for this
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Note that local vs remote file descriptors are distinquished
|
||||
* by adding a bias to the remote descriptors. This is a quick
|
||||
* and dirty trick that may not be portable to some systems.
|
||||
*/
|
||||
|
||||
#define REM_BIAS 128
|
||||
|
||||
|
||||
/*
|
||||
* Test pathname to see if it is local or remote. A remote device
|
||||
* is any string that contains ":/dev/". Returns 1 if remote,
|
||||
* 0 otherwise.
|
||||
*/
|
||||
|
||||
static int
|
||||
remdev(const char *path)
|
||||
{
|
||||
|
||||
_DIAGASSERT(path != NULL);
|
||||
|
||||
if ((path = strchr(path, ':')) != NULL) {
|
||||
if (strncmp(path + 1, "/dev/", 5) == 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Open a local or remote file. Looks just like open(2) to
|
||||
* caller.
|
||||
*/
|
||||
int
|
||||
rmtopen(const char *path, int oflag, ...)
|
||||
{
|
||||
mode_t mode;
|
||||
int fd;
|
||||
va_list ap;
|
||||
va_start(ap, oflag);
|
||||
|
||||
mode = va_arg(ap, mode_t);
|
||||
va_end(ap);
|
||||
|
||||
_DIAGASSERT(path != NULL);
|
||||
|
||||
if (remdev(path)) {
|
||||
fd = _rmt_open(path, oflag, (int)mode);
|
||||
|
||||
return (fd == -1) ? -1 : (fd + REM_BIAS);
|
||||
} else {
|
||||
return open(path, oflag, mode);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test pathname for specified access. Looks just like access(2)
|
||||
* to caller.
|
||||
*/
|
||||
|
||||
int
|
||||
rmtaccess(const char *path, int amode)
|
||||
{
|
||||
|
||||
_DIAGASSERT(path != NULL);
|
||||
|
||||
if (remdev(path)) {
|
||||
return 0; /* Let /etc/rmt find out */
|
||||
} else {
|
||||
return access(path, amode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Isrmt. Let a programmer know he has a remote device.
|
||||
*/
|
||||
int
|
||||
isrmt(int fd)
|
||||
{
|
||||
int unbias = fd - REM_BIAS;
|
||||
|
||||
return (fd >= REM_BIAS) && unbias < MAXUNIT &&
|
||||
(WRITE(unbias) != -1 || READ(unbias) != -1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read from stream. Looks just like read(2) to caller.
|
||||
*/
|
||||
ssize_t
|
||||
rmtread(int fildes, void *buf, size_t nbyte)
|
||||
{
|
||||
|
||||
_DIAGASSERT(buf != NULL);
|
||||
|
||||
if (isrmt(fildes)) {
|
||||
return _rmt_read(fildes - REM_BIAS, buf, nbyte);
|
||||
} else {
|
||||
return read(fildes, buf, nbyte);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write to stream. Looks just like write(2) to caller.
|
||||
*/
|
||||
ssize_t
|
||||
rmtwrite(int fildes, const void *buf, size_t nbyte)
|
||||
{
|
||||
|
||||
_DIAGASSERT(buf != NULL);
|
||||
|
||||
if (isrmt(fildes)) {
|
||||
return _rmt_write(fildes - REM_BIAS, buf, nbyte);
|
||||
} else {
|
||||
return write(fildes, buf, nbyte);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform lseek on file. Looks just like lseek(2) to caller.
|
||||
*/
|
||||
off_t
|
||||
rmtlseek(int fildes, off_t offset, int whence)
|
||||
{
|
||||
|
||||
if (isrmt(fildes)) {
|
||||
return _rmt_lseek(fildes - REM_BIAS, offset, whence);
|
||||
} else {
|
||||
return lseek(fildes, offset, whence);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Close a file. Looks just like close(2) to caller.
|
||||
*/
|
||||
int
|
||||
rmtclose(int fildes)
|
||||
{
|
||||
|
||||
if (isrmt(fildes)) {
|
||||
return _rmt_close(fildes - REM_BIAS);
|
||||
} else {
|
||||
return close(fildes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Do ioctl on file. Looks just like ioctl(2) to caller.
|
||||
*/
|
||||
int
|
||||
rmtioctl(int fildes, unsigned long request, ...)
|
||||
{
|
||||
void *arg;
|
||||
va_list ap;
|
||||
va_start(ap, request);
|
||||
|
||||
arg = va_arg(ap, void *);
|
||||
va_end(ap);
|
||||
|
||||
/* XXX: arg may be NULL ? */
|
||||
|
||||
if (isrmt(fildes)) {
|
||||
#ifdef RMTIOCTL
|
||||
return _rmt_ioctl(fildes - REM_BIAS, request, arg);
|
||||
#else
|
||||
errno = EOPNOTSUPP;
|
||||
return -1; /* For now (fnf) */
|
||||
#endif
|
||||
} else {
|
||||
return ioctl(fildes, request, arg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Duplicate an open file descriptor. Looks just like dup(2)
|
||||
* to caller.
|
||||
*/
|
||||
int
|
||||
rmtdup(int fildes)
|
||||
{
|
||||
|
||||
if (isrmt(fildes)) {
|
||||
errno = EOPNOTSUPP;
|
||||
return -1; /* For now (fnf) */
|
||||
} else {
|
||||
return dup(fildes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get file status. Looks just like fstat(2) to caller.
|
||||
*/
|
||||
int
|
||||
rmtfstat(int fildes, struct stat *buf)
|
||||
{
|
||||
|
||||
_DIAGASSERT(buf != NULL);
|
||||
|
||||
if (isrmt(fildes)) {
|
||||
errno = EOPNOTSUPP;
|
||||
return -1; /* For now (fnf) */
|
||||
} else {
|
||||
return fstat(fildes, buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get file status. Looks just like stat(2) to caller.
|
||||
*/
|
||||
int
|
||||
rmtstat(const char *path, struct stat *buf)
|
||||
{
|
||||
|
||||
_DIAGASSERT(path != NULL);
|
||||
_DIAGASSERT(buf != NULL);
|
||||
|
||||
if (remdev(path)) {
|
||||
errno = EOPNOTSUPP;
|
||||
return -1; /* For now (fnf) */
|
||||
} else {
|
||||
return stat(path, buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create a file from scratch. Looks just like creat(2) to the caller.
|
||||
*/
|
||||
int
|
||||
rmtcreat(const char *path, mode_t mode)
|
||||
{
|
||||
|
||||
_DIAGASSERT(path != NULL);
|
||||
|
||||
if (remdev(path)) {
|
||||
return rmtopen(path, O_WRONLY | O_CREAT, mode);
|
||||
} else {
|
||||
return open(path, O_CREAT | O_TRUNC | O_WRONLY, mode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Rmtfcntl. Do a remote fcntl operation.
|
||||
*/
|
||||
int
|
||||
rmtfcntl(int fd, int cmd, ...)
|
||||
{
|
||||
void *arg;
|
||||
va_list ap;
|
||||
va_start(ap, cmd);
|
||||
|
||||
arg = va_arg(ap, void *);
|
||||
va_end(ap);
|
||||
|
||||
/* XXX: arg may be NULL ? */
|
||||
|
||||
if (isrmt(fd)) {
|
||||
errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
} else {
|
||||
return fcntl(fd, cmd, arg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Rmtisatty. Do the isatty function.
|
||||
*/
|
||||
int
|
||||
rmtisatty(int fd)
|
||||
{
|
||||
|
||||
if (isrmt(fd))
|
||||
return 0;
|
||||
else
|
||||
return isatty(fd);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get file status, even if symlink. Looks just like lstat(2) to caller.
|
||||
*/
|
||||
int
|
||||
rmtlstat(const char *path, struct stat *buf)
|
||||
{
|
||||
|
||||
_DIAGASSERT(path != NULL);
|
||||
_DIAGASSERT(buf != NULL);
|
||||
|
||||
if (remdev(path)) {
|
||||
errno = EOPNOTSUPP;
|
||||
return -1; /* For now (fnf) */
|
||||
} else {
|
||||
return lstat(path, buf);
|
||||
}
|
||||
}
|
182
lib/librmt/rmtops.3
Normal file
182
lib/librmt/rmtops.3
Normal file
|
@ -0,0 +1,182 @@
|
|||
.\" $NetBSD: rmtops.3,v 1.14 2010/03/22 22:00:37 joerg Exp $
|
||||
.\"
|
||||
.Dd October 16, 2001
|
||||
.Dt RMTOPS 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm rmtops
|
||||
.Nd access tape drives on remote machines
|
||||
.Sh LIBRARY
|
||||
Remote Magnetic Tape Library (librmt, -lrmt)
|
||||
.Sh SYNOPSIS
|
||||
.In rmt.h
|
||||
.In sys/stat.h
|
||||
.Ft int
|
||||
.Fn isrmt "int fd"
|
||||
.Ft int
|
||||
.Fn rmtaccess "char *file" "int mode"
|
||||
.Ft int
|
||||
.Fn rmtclose "int fd"
|
||||
.Ft int
|
||||
.Fn rmtcreat "char *file" "int mode"
|
||||
.Ft int
|
||||
.Fn rmtdup "int fd"
|
||||
.Ft int
|
||||
.Fn rmtfcntl "int fd" "int cmd" "int arg"
|
||||
.Ft int
|
||||
.Fn rmtfstat "int fd" "struct stat *buf"
|
||||
.Ft int
|
||||
.Fn rmtioctl "int fd" "int request" "char *argp"
|
||||
.Ft int
|
||||
.Fn rmtisatty "int fd"
|
||||
.Ft long
|
||||
.Fn rmtlseek "int fd" "long offset" "int whence"
|
||||
.Ft int
|
||||
.Fn rmtlstat "char *file" "struct stat *buf"
|
||||
.Ft int
|
||||
.Fn rmtopen "char *file" "int flags" "int mode"
|
||||
.Ft int
|
||||
.Fn rmtread "int fd" "char *buf" "int nbytes"
|
||||
.Ft int
|
||||
.Fn rmtstat "char *file" "struct stat *buf"
|
||||
.Ft int
|
||||
.Fn rmtwrite "int fd" "char *buf" "int nbytes"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
library provides a simple means of transparently accessing tape drives
|
||||
on remote machines via
|
||||
.Xr rsh 1
|
||||
and
|
||||
.Xr rmt 8 .
|
||||
These routines are used like their corresponding system calls, but
|
||||
allow the user to open up a tape drive on a remote system on which he
|
||||
or she has an account and the appropriate remote permissions.
|
||||
.Pp
|
||||
A remote tape drive file name has the form
|
||||
.Dl [user@]hostname:/dev/???
|
||||
where
|
||||
.Em system
|
||||
is the remote system,
|
||||
.Em /dev/???
|
||||
is the particular drive on the remote system (raw, blocked, rewinding,
|
||||
non-rewinding, etc.), and the optional
|
||||
.Em user
|
||||
is the login name to be used on the remote system, if different from
|
||||
the current user's login name.
|
||||
.\" .Pp
|
||||
.\" The library source code may be optionally compiled to recognize the
|
||||
.\" old
|
||||
.\" .Bx 4.2 ,
|
||||
.\" remote syntax
|
||||
.\" .sp
|
||||
.\" hostname[.user]:/dev/???
|
||||
.\" .sp
|
||||
.\" By default, only the first form (introduced in
|
||||
.\" .Bx 4.3 )
|
||||
.\" is recognized.
|
||||
.Pp
|
||||
For transparency, the user should include the file
|
||||
.In rmt.h ,
|
||||
which has the following defines in it:
|
||||
.Bd -literal
|
||||
#define access rmtaccess
|
||||
#define close rmtclose
|
||||
#define creat rmtcreat
|
||||
#define dup rmtdup
|
||||
#define fcntl rmtfcntl
|
||||
#define fstat rmtfstat
|
||||
#define ioctl rmtioctl
|
||||
#define isatty rmtisatty
|
||||
#define lseek rmtlseek
|
||||
#define lstat rmtlstat
|
||||
#define open rmtopen
|
||||
#define read rmtread
|
||||
#define stat rmtstat
|
||||
#define write rmtwrite
|
||||
.Ed
|
||||
.Pp
|
||||
This allows the programmer to use
|
||||
.Xr open 2 ,
|
||||
.Xr close 2 ,
|
||||
.Xr read 2 ,
|
||||
.Xr write 2 ,
|
||||
etc. in their normal fashion, with the
|
||||
.Nm
|
||||
routines taking care of differentiating between local and remote files.
|
||||
This file should be included
|
||||
.Em before
|
||||
including the file
|
||||
.Pa \*[Lt]sys/stat.h\*[Gt] ,
|
||||
since it redefines the identifier ``stat'' which is used to declare
|
||||
objects of type
|
||||
.Em "struct stat" .
|
||||
.Pp
|
||||
The routines differentiate between local and remote file descriptors
|
||||
by adding a bias (currently 128) to the file descriptor of the pipe.
|
||||
The programmer, if he or she must know if a file is remote, should use
|
||||
.Fn isrmt .
|
||||
.Sh ENVIRONMENT
|
||||
The RCMD_CMD environment variable can be set to the name or pathname
|
||||
of a program to use, instead of
|
||||
.Pa /usr/bin/rsh ,
|
||||
and must have the same calling conventions as
|
||||
.Xr rsh 1 .
|
||||
.Sh FILES
|
||||
.Bl -tag -width /usr/lib/librmt.a -compact
|
||||
.It Pa /usr/lib/librmt.a
|
||||
remote tape library
|
||||
.El
|
||||
.Sh DIAGNOSTICS
|
||||
Several of these routines will return \-1 and set
|
||||
.Va errno
|
||||
to EOPNOTSUPP, if they are given a remote file name or a file descriptor
|
||||
on an open remote file (e.g.,
|
||||
.Fn rmtdup ) .
|
||||
.Sh SEE ALSO
|
||||
.Xr rcp 1 ,
|
||||
.Xr rsh 1 ,
|
||||
.Xr rmt 8
|
||||
.Pp
|
||||
And the appropriate system calls in section 2.
|
||||
.\" .Sh CONFIGURATION OPTIONS
|
||||
.\" The library may be compiled to allow the use of
|
||||
.\" .Bx 4.2 -style
|
||||
.\" remote file names. This is not recommended.
|
||||
.\" .Pp
|
||||
.\" By default, the library opens two pipes to
|
||||
.\" .Xr rsh 1 .
|
||||
.\" It may optionally be compiled to use
|
||||
.\" .Xr rexec 3 ,
|
||||
.\" instead. Doing so requires the use of a
|
||||
.\" .Em .netrc
|
||||
.\" file in the user's home directory, or that the application designer be
|
||||
.\" willing to have
|
||||
.\" .Xr rexec 3
|
||||
.\" prompt the user for a login name and password on the remote host.
|
||||
.Sh AUTHORS
|
||||
Jeff Lee wrote the original routines for accessing tape drives via
|
||||
.Xr rmt 8 .
|
||||
.Pp
|
||||
Fred Fish redid them into a general purpose library.
|
||||
.Pp
|
||||
Arnold Robbins added the ability to specify a user name on the remote
|
||||
system, the
|
||||
.Pa \*[Lt]rmt.h\*[Gt]
|
||||
include file, this man page, cleaned up the library a little, and made
|
||||
the appropriate changes for
|
||||
.Bx 4.3 .
|
||||
.Pp
|
||||
Dan Kegel contributed the code to use the
|
||||
.Xr rexec 3
|
||||
library routine.
|
||||
.Sh BUGS
|
||||
There is no way to use remote tape drives with
|
||||
.Xr stdio 3 ,
|
||||
short of recompiling it entirely to use these routines.
|
||||
.Pp
|
||||
The
|
||||
.Xr rmt 8
|
||||
protocol is not very capable.
|
||||
In particular, it relies on TCP/IP sockets for error
|
||||
free transmission, and does no data validation of its own.
|
|
@ -2,6 +2,8 @@
|
|||
# Timestamp in UTC,minixpath,netbsdpath
|
||||
# minixpath: path in Minix source tree (starting from /usr/src/)
|
||||
# netbsdpath: path in BSD source tree (starting from src/)
|
||||
2012/10/17 12:00:00,lib/librmt
|
||||
2012/10/17 12:00:00,bin/pax
|
||||
2012/10/17 12:00:00,tools/mtree
|
||||
2012/10/17 12:00:00,tools/cksum
|
||||
2012/10/17 12:00:00,usr.bin/cksum
|
||||
|
|
|
@ -15,6 +15,7 @@ SUBDIR= host-mkdep .WAIT compat .WAIT \
|
|||
.WAIT awk \
|
||||
.WAIT tic \
|
||||
.WAIT lex \
|
||||
.WAIT pax \
|
||||
.WAIT gmake .WAIT gmp .WAIT mpfr .WAIT mpc .WAIT binutils .WAIT gcc \
|
||||
cat file pwd_mkdb stat zic \
|
||||
|
||||
|
|
6
tools/pax/Makefile
Normal file
6
tools/pax/Makefile
Normal file
|
@ -0,0 +1,6 @@
|
|||
# $NetBSD: Makefile,v 1.2 2002/12/08 20:20:04 thorpej Exp $
|
||||
|
||||
HOSTPROGNAME= ${_TOOL_PREFIX}pax
|
||||
HOST_SRCDIR= bin/pax
|
||||
|
||||
.include "${.CURDIR}/../Makefile.host"
|
Loading…
Reference in a new issue