Sync up with OpenBSD. Too many changes to note, but the major features
are: * Implement cpio compatibility mode when pax is invoked as cpio * Extend tar compatibility mode to cover many of the GNU tar single-letter options (bzip2 mode, aka -y/-j is not present in OpenBSD). When invoked as tar, pax is now full-featured enough for use by the ports collection to extract distfiles and create packages. * Many bug fixes to the operation of pax and the tar compatibility modes * Code fixes for things like correct string buffer termination. I tried to preserve existing FreeBSD fixes to this utility; please let me know if I have inadvertently spammed something.
This commit is contained in:
parent
7ecc59e45d
commit
6f2ea93cf4
@ -26,8 +26,11 @@
|
||||
# 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 options.c pat_rep.c pax.c sel_subs.c tables.c tar.c\
|
||||
tty_subs.c
|
||||
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
|
||||
#XXX NOTYET
|
||||
#MAN= pax.1 tar.1 cpio.1
|
||||
#LINKS= ${BINDIR}/pax ${BINDIR}/tar ${BINDIR}/pax ${BINDIR}/cpio
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
@ -57,6 +57,7 @@ static const char rcsid[] =
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "pax.h"
|
||||
#include "options.h"
|
||||
#include "extern.h"
|
||||
|
||||
/*
|
||||
@ -159,6 +160,9 @@ ar_open(name)
|
||||
if (arfd < 0)
|
||||
return(-1);
|
||||
|
||||
if (chdname != NULL)
|
||||
if (chdir(chdname) != 0)
|
||||
syswarn(1, errno, "Failed chdir to %s", chdname);
|
||||
/*
|
||||
* set up is based on device type
|
||||
*/
|
||||
@ -307,18 +311,12 @@ void
|
||||
ar_close()
|
||||
#endif
|
||||
{
|
||||
FILE *outf;
|
||||
|
||||
if (arfd < 0) {
|
||||
did_io = io_ok = flcnt = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (act == LIST)
|
||||
outf = stdout;
|
||||
else
|
||||
outf = stderr;
|
||||
|
||||
/*
|
||||
* Close archive file. This may take a LONG while on tapes (we may be
|
||||
* forced to wait for the rewind to complete) so tell the user what is
|
||||
@ -327,11 +325,11 @@ ar_close()
|
||||
*/
|
||||
if (vflag && (artyp == ISTAPE)) {
|
||||
if (vfpart)
|
||||
(void)putc('\n', outf);
|
||||
(void)fprintf(outf,
|
||||
(void)putc('\n', listf);
|
||||
(void)fprintf(listf,
|
||||
"%s: Waiting for tape drive close to complete...",
|
||||
argv0);
|
||||
(void)fflush(outf);
|
||||
(void)fflush(listf);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -357,9 +355,9 @@ ar_close()
|
||||
(void)close(arfd);
|
||||
|
||||
if (vflag && (artyp == ISTAPE)) {
|
||||
(void)fputs("done.\n", outf);
|
||||
(void)fputs("done.\n", listf);
|
||||
vfpart = 0;
|
||||
(void)fflush(outf);
|
||||
(void)fflush(listf);
|
||||
}
|
||||
arfd = -1;
|
||||
|
||||
@ -385,7 +383,7 @@ ar_close()
|
||||
* Print out a summary of I/O for this archive volume.
|
||||
*/
|
||||
if (vfpart) {
|
||||
(void)putc('\n', outf);
|
||||
(void)putc('\n', listf);
|
||||
vfpart = 0;
|
||||
}
|
||||
|
||||
@ -396,24 +394,27 @@ ar_close()
|
||||
*/
|
||||
if (frmt == NULL) {
|
||||
# ifdef NET2_STAT
|
||||
(void)fprintf(outf, "%s: unknown format, %lu bytes skipped.\n",
|
||||
(void)fprintf(listf, "%s: unknown format, %lu bytes skipped.\n",
|
||||
# else
|
||||
(void)fprintf(outf, "%s: unknown format, %qu bytes skipped.\n",
|
||||
(void)fprintf(listf, "%s: unknown format, %qu bytes skipped.\n",
|
||||
# endif
|
||||
argv0, rdcnt);
|
||||
(void)fflush(outf);
|
||||
(void)fflush(listf);
|
||||
flcnt = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
(void)fprintf(outf,
|
||||
if (strcmp(NM_CPIO, argv0) == 0)
|
||||
(void)fprintf(listf, "%qu blocks\n", (rdcnt ? rdcnt : wrcnt) / 5120);
|
||||
else if (strcmp(NM_TAR, argv0) != 0)
|
||||
(void)fprintf(listf,
|
||||
# ifdef NET2_STAT
|
||||
"%s: %s vol %d, %lu files, %lu bytes read, %lu bytes written.\n",
|
||||
# else
|
||||
"%s: %s vol %d, %lu files, %qu bytes read, %qu bytes written.\n",
|
||||
# endif
|
||||
argv0, frmt->name, arvol-1, flcnt, rdcnt, wrcnt);
|
||||
(void)fflush(outf);
|
||||
(void)fflush(listf);
|
||||
flcnt = 0;
|
||||
}
|
||||
|
||||
@ -1184,7 +1185,7 @@ ar_next()
|
||||
if (sigprocmask(SIG_SETMASK, &o_mask, NULL) < 0)
|
||||
syswarn(0, errno, "Unable to restore signal mask");
|
||||
|
||||
if (done || !wr_trail)
|
||||
if (done || !wr_trail || strcmp(NM_TAR, argv0) == 0)
|
||||
return(-1);
|
||||
|
||||
tty_prnt("\nATTENTION! %s archive volume change required.\n", argv0);
|
||||
|
@ -130,7 +130,7 @@ list()
|
||||
if ((res = mod_name(arcn)) < 0)
|
||||
break;
|
||||
if (res == 0)
|
||||
ls_list(arcn, now);
|
||||
ls_list(arcn, now, stdout);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -171,6 +171,7 @@ extract()
|
||||
ARCHD archd;
|
||||
struct stat sb;
|
||||
int fd;
|
||||
time_t now;
|
||||
|
||||
arcn = &archd;
|
||||
/*
|
||||
@ -189,6 +190,8 @@ extract()
|
||||
if (iflag && (name_start() < 0))
|
||||
return;
|
||||
|
||||
now = time(NULL);
|
||||
|
||||
/*
|
||||
* step through each entry on the archive until the format read routine
|
||||
* says it is done
|
||||
@ -276,10 +279,22 @@ extract()
|
||||
}
|
||||
|
||||
if (vflag) {
|
||||
(void)fputs(arcn->name, stderr);
|
||||
vfpart = 1;
|
||||
if (vflag > 1)
|
||||
ls_list(arcn, now, listf);
|
||||
else {
|
||||
(void)fputs(arcn->name, listf);
|
||||
vfpart = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* if required, chdir around.
|
||||
*/
|
||||
if ((arcn->pat != NULL) && (arcn->pat->chdname != NULL))
|
||||
if (chdir(arcn->pat->chdname) != 0)
|
||||
syswarn(1, errno, "Cannot chdir to %s",
|
||||
arcn->pat->chdname);
|
||||
|
||||
/*
|
||||
* all ok, extract this member based on type
|
||||
*/
|
||||
@ -299,7 +314,7 @@ extract()
|
||||
purg_lnk(arcn);
|
||||
|
||||
if (vflag && vfpart) {
|
||||
(void)putc('\n', stderr);
|
||||
(void)putc('\n', listf);
|
||||
vfpart = 0;
|
||||
}
|
||||
continue;
|
||||
@ -320,11 +335,19 @@ extract()
|
||||
res = (*frmt->rd_data)(arcn, fd, &cnt);
|
||||
file_close(arcn, fd);
|
||||
if (vflag && vfpart) {
|
||||
(void)putc('\n', stderr);
|
||||
(void)putc('\n', listf);
|
||||
vfpart = 0;
|
||||
}
|
||||
if (!res)
|
||||
(void)rd_skip(cnt + arcn->pad);
|
||||
|
||||
/*
|
||||
* if required, chdir around.
|
||||
*/
|
||||
if ((arcn->pat != NULL) && (arcn->pat->chdname != NULL))
|
||||
if (fchdir(cwdfd) != 0)
|
||||
syswarn(1, errno,
|
||||
"Can't fchdir to starting directory");
|
||||
}
|
||||
|
||||
/*
|
||||
@ -361,6 +384,7 @@ wr_archive(arcn, is_app)
|
||||
off_t cnt;
|
||||
int (*wrf)();
|
||||
int fd = -1;
|
||||
time_t now;
|
||||
|
||||
/*
|
||||
* if this format supports hard link storage, start up the database
|
||||
@ -388,6 +412,8 @@ wr_archive(arcn, is_app)
|
||||
*/
|
||||
wr_one = is_app;
|
||||
|
||||
now = time(NULL);
|
||||
|
||||
/*
|
||||
* while there are files to archive, process them one at at time
|
||||
*/
|
||||
@ -457,8 +483,12 @@ wr_archive(arcn, is_app)
|
||||
}
|
||||
|
||||
if (vflag) {
|
||||
(void)fputs(arcn->name, stderr);
|
||||
vfpart = 1;
|
||||
if (vflag > 1)
|
||||
ls_list(arcn, now, listf);
|
||||
else {
|
||||
(void)fputs(arcn->name, listf);
|
||||
vfpart = 1;
|
||||
}
|
||||
}
|
||||
++flcnt;
|
||||
|
||||
@ -477,7 +507,7 @@ wr_archive(arcn, is_app)
|
||||
* so we are done messing with this file
|
||||
*/
|
||||
if (vflag && vfpart) {
|
||||
(void)putc('\n', stderr);
|
||||
(void)putc('\n', listf);
|
||||
vfpart = 0;
|
||||
}
|
||||
rdfile_close(arcn, &fd);
|
||||
@ -495,7 +525,7 @@ wr_archive(arcn, is_app)
|
||||
res = (*frmt->wr_data)(arcn, fd, &cnt);
|
||||
rdfile_close(arcn, &fd);
|
||||
if (vflag && vfpart) {
|
||||
(void)putc('\n', stderr);
|
||||
(void)putc('\n', listf);
|
||||
vfpart = 0;
|
||||
}
|
||||
if (res < 0)
|
||||
@ -612,7 +642,7 @@ append()
|
||||
* reading the archive may take a long time. If verbose tell the user
|
||||
*/
|
||||
if (vflag) {
|
||||
(void)fprintf(stderr,
|
||||
(void)fprintf(listf,
|
||||
"%s: Reading archive to position at the end...", argv0);
|
||||
vfpart = 1;
|
||||
}
|
||||
@ -674,7 +704,7 @@ append()
|
||||
* tell the user we are done reading.
|
||||
*/
|
||||
if (vflag && vfpart) {
|
||||
(void)fputs("done.\n", stderr);
|
||||
(void)fputs("done.\n", listf);
|
||||
vfpart = 0;
|
||||
}
|
||||
|
||||
@ -872,7 +902,7 @@ copy()
|
||||
}
|
||||
|
||||
if (vflag) {
|
||||
(void)fputs(arcn->name, stderr);
|
||||
(void)fputs(arcn->name, listf);
|
||||
vfpart = 1;
|
||||
}
|
||||
++flcnt;
|
||||
@ -887,7 +917,7 @@ copy()
|
||||
res = chk_same(arcn);
|
||||
if (res <= 0) {
|
||||
if (vflag && vfpart) {
|
||||
(void)putc('\n', stderr);
|
||||
(void)putc('\n', listf);
|
||||
vfpart = 0;
|
||||
}
|
||||
continue;
|
||||
@ -907,7 +937,7 @@ copy()
|
||||
if (res < 0)
|
||||
purg_lnk(arcn);
|
||||
if (vflag && vfpart) {
|
||||
(void)putc('\n', stderr);
|
||||
(void)putc('\n', listf);
|
||||
vfpart = 0;
|
||||
}
|
||||
continue;
|
||||
@ -937,7 +967,7 @@ copy()
|
||||
rdfile_close(arcn, &fdsrc);
|
||||
|
||||
if (vflag && vfpart) {
|
||||
(void)putc('\n', stderr);
|
||||
(void)putc('\n', listf);
|
||||
vfpart = 0;
|
||||
}
|
||||
}
|
||||
@ -988,6 +1018,7 @@ next_head(arcn)
|
||||
register int hsz;
|
||||
register int in_resync = 0; /* set when we are in resync mode */
|
||||
int cnt = 0; /* counter for trailer function */
|
||||
int first = 1; /* on 1st read, EOF isn't premature. */
|
||||
|
||||
/*
|
||||
* set up initial conditions, we want a whole frmt->hsz block as we
|
||||
@ -1005,6 +1036,17 @@ next_head(arcn)
|
||||
if ((ret = rd_wrbuf(hdend, res)) == res)
|
||||
break;
|
||||
|
||||
/*
|
||||
* If we read 0 bytes (EOF) from an archive when we
|
||||
* expect to find a header, we have stepped upon
|
||||
* an archive without the customary block of zeroes
|
||||
* end marker. It's just stupid to error out on
|
||||
* them, so exit gracefully.
|
||||
*/
|
||||
if (first && ret == 0)
|
||||
return(-1);
|
||||
first = 0;
|
||||
|
||||
/*
|
||||
* some kind of archive read problem, try to resync the
|
||||
* storage device, better give the user the bad news.
|
||||
|
@ -47,6 +47,7 @@ static const char rcsid[] =
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "pax.h"
|
||||
@ -111,6 +112,11 @@ wr_start()
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* we only allow wrblksz to be used with all archive operations
|
||||
|
@ -388,7 +388,8 @@ uid_name(name, uid)
|
||||
}
|
||||
|
||||
if (ptr == NULL)
|
||||
ptr = (UIDC *)malloc(sizeof(UIDC));
|
||||
ptr = usrtb[st_hash(name, namelen, UNM_SZ)] =
|
||||
(UIDC *)malloc(sizeof(UIDC));
|
||||
|
||||
/*
|
||||
* no match, look it up, if no match store it as an invalid entry,
|
||||
@ -457,7 +458,8 @@ gid_name(name, gid)
|
||||
++gropn;
|
||||
}
|
||||
if (ptr == NULL)
|
||||
ptr = (GIDC *)malloc(sizeof(GIDC));
|
||||
ptr = grptb[st_hash(name, namelen, GID_SZ)] =
|
||||
(GIDC *)malloc(sizeof(GIDC));
|
||||
|
||||
/*
|
||||
* no match, look it up, if no match store it as an invalid entry,
|
||||
|
295
bin/pax/cpio.1
Normal file
295
bin/pax/cpio.1
Normal file
@ -0,0 +1,295 @@
|
||||
.\"
|
||||
.\" Copyright (c) 1997 SigmaSoft, Th. Lockert
|
||||
.\" 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.
|
||||
.\" 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
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\" $OpenBSD: cpio.1,v 1.16 2001/05/01 17:58:01 aaron Exp $
|
||||
.\"
|
||||
.Dd February 16, 1997
|
||||
.Dt CPIO 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm cpio
|
||||
.Nd copy file archives in and out
|
||||
.Sh SYNOPSIS
|
||||
.Nm cpio
|
||||
.Fl o
|
||||
.Op Fl aABcLvzZ
|
||||
.Op Fl C Ar bytes
|
||||
.Op Fl F Ar archive
|
||||
.Op Fl H Ar format
|
||||
.Op Fl O Ar archive
|
||||
.Ar "< name-list"
|
||||
.Op Ar "> archive"
|
||||
.Nm cpio
|
||||
.Fl i
|
||||
.Op Fl bBcdfmrsStuvzZ6
|
||||
.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 Ar "< archive"
|
||||
.Nm cpio
|
||||
.Fl p
|
||||
.Op Fl adlLmuv
|
||||
.Ar destination-directory
|
||||
.Ar "< name-list"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
command copies files to and from a
|
||||
.Nm
|
||||
archive.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl o
|
||||
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 Ds
|
||||
.It Fl a
|
||||
Reset the access times on files that have been copied to the
|
||||
archive.
|
||||
.It Fl A
|
||||
Append to the specified archive.
|
||||
.It Fl B
|
||||
Set block size of output to 5120 bytes.
|
||||
.It Fl c
|
||||
Use ASCII format for
|
||||
.Nm
|
||||
header for portability.
|
||||
.It Fl C Ar bytes
|
||||
Set the block size of output to
|
||||
.Ar bytes .
|
||||
.It Fl F Ar archive
|
||||
.It Fl O Ar archive
|
||||
Use the specified file name as the archive to write to.
|
||||
.It Fl H Ar format
|
||||
Write the archive in the specified format.
|
||||
Recognized formats are:
|
||||
.Pp
|
||||
.Bl -tag -width sv4cpio -compact
|
||||
.It Ar bcpio
|
||||
Old binary
|
||||
.Nm
|
||||
format.
|
||||
.It Ar cpio
|
||||
Old octal character
|
||||
.Nm
|
||||
format.
|
||||
.It Ar sv4cpio
|
||||
SVR4 hex
|
||||
.Nm
|
||||
format.
|
||||
.It Ar tar
|
||||
Old tar 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
|
||||
format.
|
||||
.It Fl Z
|
||||
Compress archive using
|
||||
.Xr compress 1
|
||||
format.
|
||||
.El
|
||||
.It Fl i
|
||||
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 Ds
|
||||
.It Fl b
|
||||
Do byte and word swapping after reading in data from the
|
||||
archive, for restoring archives created on systems with
|
||||
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 ASCII format.
|
||||
.It Fl C Ar bytes
|
||||
Read archive written with a block size of
|
||||
.Ar bytes .
|
||||
.It Fl d
|
||||
Create any intermediate directories as needed during
|
||||
restore.
|
||||
.It Fl E Ar file
|
||||
Read list of file name patterns to extract or list from
|
||||
.Ar file .
|
||||
.It Fl f
|
||||
Restore all files except those matching the
|
||||
.Ar patterns
|
||||
given on the command line.
|
||||
.It Fl F Ar archive
|
||||
.It Fl I Ar archive
|
||||
Use the specified file as the input for the archive.
|
||||
.It Fl H Ar format
|
||||
Read an archive of the specified format.
|
||||
Recognized formats are:
|
||||
.Pp
|
||||
.Bl -tag -width sv4cpio -compact
|
||||
.It Ar bcpio
|
||||
Old binary
|
||||
.Nm
|
||||
format.
|
||||
.It Ar cpio
|
||||
Old octal character
|
||||
.Nm
|
||||
format.
|
||||
.It Ar sv4cpio
|
||||
SVR4 hex
|
||||
.Nm
|
||||
format.
|
||||
.It Ar tar
|
||||
Old tar format.
|
||||
.It Ar ustar
|
||||
POSIX ustar format.
|
||||
.El
|
||||
.It Fl m
|
||||
Restore modification times on files.
|
||||
.It Fl r
|
||||
Rename restored files interactively.
|
||||
.It Fl s
|
||||
Swap bytes after reading data from the archive.
|
||||
.It Fl S
|
||||
Swap words after reading data from the archive.
|
||||
.It Fl t
|
||||
Only list the contents of the archive, no files or
|
||||
directories will be created.
|
||||
.It Fl u
|
||||
Overwrite files even when the file in the archive is
|
||||
older than the one that will be overwritten.
|
||||
.It Fl v
|
||||
Be verbose about operations.
|
||||
List filenames as they are copied in from the archive.
|
||||
.It Fl z
|
||||
Uncompress archive using
|
||||
.Xr gzip 1
|
||||
format.
|
||||
.It Fl Z
|
||||
Uncompress archive using
|
||||
.Xr compress 1
|
||||
format.
|
||||
.It Fl 6
|
||||
Process old-style
|
||||
.Nm
|
||||
format archives.
|
||||
.El
|
||||
.It Fl p
|
||||
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 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
|
||||
When possible, link files rather than creating an
|
||||
extra copy.
|
||||
.It Fl L
|
||||
Follow symbolic links.
|
||||
.It Fl m
|
||||
Restore modification times on files.
|
||||
.It Fl u
|
||||
Overwrite files even when the original file being copied is
|
||||
older than the one that will be overwritten.
|
||||
.It Fl v
|
||||
Be verbose about operations.
|
||||
List filenames as they are copied.
|
||||
.El
|
||||
.El
|
||||
.Sh ERRORS
|
||||
.Nm
|
||||
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
|
||||
.Pp
|
||||
Whenever
|
||||
.Nm
|
||||
cannot create a file or a link when extracting an archive or cannot
|
||||
find a file while writing an archive, or cannot preserve the user
|
||||
ID, group ID, file mode, or access and modification times when the
|
||||
.Fl p
|
||||
option is specified, a diagnostic message is written to standard
|
||||
error and a non-zero exit value will be returned, but processing
|
||||
will continue.
|
||||
In the case where
|
||||
.Nm
|
||||
cannot create a link to a file,
|
||||
.Nm
|
||||
will not create a second copy of the file.
|
||||
.Pp
|
||||
If the extraction of a file from an archive is prematurely terminated
|
||||
by a signal or error,
|
||||
.Nm
|
||||
may have only partially extracted the file the user wanted.
|
||||
Additionally, the file modes of extracted files and directories may
|
||||
have incorrect file bits, and the modification and access times may
|
||||
be wrong.
|
||||
.Pp
|
||||
If the creation of an archive is prematurely terminated by a signal
|
||||
or error,
|
||||
.Nm
|
||||
may have only partially created the archive which may violate the
|
||||
specific archive format specification.
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width Fl
|
||||
.It Ev TMPDIR
|
||||
Path in which to store temporary files.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr pax 1 ,
|
||||
.Xr tar 1
|
||||
.Sh AUTHORS
|
||||
Keith Muller at the University of California, San Diego.
|
||||
.Sh BUGS
|
||||
The
|
||||
.Fl s
|
||||
and
|
||||
.Fl S
|
||||
options are currently not implemented.
|
@ -146,6 +146,7 @@ int unlnk_exist __P((register char *, register int));
|
||||
int chk_path __P((register char *, uid_t, gid_t));
|
||||
void set_ftime __P((char *fnm, time_t mtime, time_t atime, int frc));
|
||||
int set_ids __P((char *, uid_t, gid_t));
|
||||
int set_lids __P((char *, uid_t, gid_t));
|
||||
void set_pmode __P((char *, mode_t));
|
||||
int file_write __P((int, char *, register int, int *, int *, int, char *));
|
||||
void file_flush __P((int, char *, int));
|
||||
@ -156,7 +157,7 @@ int set_crc __P((register ARCHD *, register int));
|
||||
* ftree.c
|
||||
*/
|
||||
int ftree_start __P((void));
|
||||
int ftree_add __P((register char *));
|
||||
int ftree_add __P((register char *, int));
|
||||
void ftree_sel __P((register ARCHD *));
|
||||
void ftree_chk __P((void));
|
||||
int next_file __P((register ARCHD *));
|
||||
@ -164,9 +165,8 @@ int next_file __P((register ARCHD *));
|
||||
/*
|
||||
* gen_subs.c
|
||||
*/
|
||||
void ls_list __P((register ARCHD *, time_t));
|
||||
void ls_list __P((register ARCHD *, time_t, FILE *));
|
||||
void ls_tty __P((register ARCHD *));
|
||||
void zf_strncpy __P((register char *, register char *, int));
|
||||
int l_strncpy __P((register char *, register char *, int));
|
||||
u_long asc_ul __P((register char *, int, register int));
|
||||
int ul_asc __P((u_long, register char *, register int, register int));
|
||||
@ -175,6 +175,11 @@ u_quad_t asc_uqd __P((register char *, int, register int));
|
||||
int uqd_asc __P((u_quad_t, register char *, register int, register int));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* getoldopt.c
|
||||
*/
|
||||
int getoldopt __P((int, char **, char *));
|
||||
|
||||
/*
|
||||
* options.c
|
||||
*/
|
||||
@ -184,12 +189,13 @@ void options __P((register int, register char **));
|
||||
OPLIST * opt_next __P((void));
|
||||
int opt_add __P((register char *));
|
||||
int bad_opt __P((void));
|
||||
char *chdname;
|
||||
|
||||
/*
|
||||
* pat_rep.c
|
||||
*/
|
||||
int rep_add __P((register char *));
|
||||
int pat_add __P((char *));
|
||||
int pat_add __P((char *, char *));
|
||||
void pat_chk __P((void));
|
||||
int pat_sel __P((register ARCHD *));
|
||||
int pat_match __P((register ARCHD *));
|
||||
@ -202,6 +208,7 @@ int set_dest __P((register ARCHD *, char *, int));
|
||||
extern int act;
|
||||
extern FSUB *frmt;
|
||||
extern int cflag;
|
||||
extern int cwdfd;
|
||||
extern int dflag;
|
||||
extern int iflag;
|
||||
extern int kflag;
|
||||
@ -219,12 +226,15 @@ extern int Zflag;
|
||||
extern int vfpart;
|
||||
extern int patime;
|
||||
extern int pmtime;
|
||||
extern int nodirs;
|
||||
extern int pmode;
|
||||
extern int pids;
|
||||
extern int rmleadslash;
|
||||
extern int exit_val;
|
||||
extern int docrc;
|
||||
extern char *dirptr;
|
||||
extern char *argv0;
|
||||
extern FILE *listf;
|
||||
extern char *tempfile;
|
||||
extern char *tempbase;
|
||||
|
||||
@ -250,7 +260,7 @@ int ftime_start __P((void));
|
||||
int chk_ftime __P((register ARCHD *));
|
||||
int name_start __P((void));
|
||||
int add_name __P((register char *, int, char *));
|
||||
void sub_name __P((register char *, int *));
|
||||
void sub_name __P((register char *, int *, size_t));
|
||||
int dev_start __P((void));
|
||||
int add_dev __P((register ARCHD *));
|
||||
int map_dev __P((register ARCHD *, u_long, u_long));
|
||||
|
@ -54,6 +54,7 @@ static const char rcsid[] =
|
||||
#include <sys/uio.h>
|
||||
#include <stdlib.h>
|
||||
#include "pax.h"
|
||||
#include "options.h"
|
||||
#include "extern.h"
|
||||
|
||||
static int
|
||||
@ -122,7 +123,7 @@ file_creat(arcn)
|
||||
file_mode)) >= 0)
|
||||
break;
|
||||
oerrno = errno;
|
||||
if (chk_path(arcn->name,arcn->sb.st_uid,arcn->sb.st_gid) < 0) {
|
||||
if (nodirs || chk_path(arcn->name,arcn->sb.st_uid,arcn->sb.st_gid) < 0) {
|
||||
syswarn(1, oerrno, "Unable to create %s", arcn->name);
|
||||
return(-1);
|
||||
}
|
||||
@ -356,7 +357,7 @@ mk_link(to, to_sb, from, ign)
|
||||
if (link(to, from) == 0)
|
||||
break;
|
||||
oerrno = errno;
|
||||
if (chk_path(from, to_sb->st_uid, to_sb->st_gid) == 0)
|
||||
if (!nodirs && chk_path(from, to_sb->st_uid, to_sb->st_gid) == 0)
|
||||
continue;
|
||||
if (!ign) {
|
||||
syswarn(1, oerrno, "Could not link to %s from %s", to,
|
||||
@ -431,8 +432,7 @@ node_creat(arcn)
|
||||
arcn->name);
|
||||
return(-1);
|
||||
case PAX_SLK:
|
||||
if ((res = symlink(arcn->ln_name, arcn->name)) == 0)
|
||||
return(0);
|
||||
res = symlink(arcn->ln_name, arcn->name);
|
||||
break;
|
||||
case PAX_CTG:
|
||||
case PAX_HLK:
|
||||
@ -465,7 +465,7 @@ node_creat(arcn)
|
||||
if (++pass <= 1)
|
||||
continue;
|
||||
|
||||
if (chk_path(arcn->name,arcn->sb.st_uid,arcn->sb.st_gid) < 0) {
|
||||
if (nodirs || chk_path(arcn->name,arcn->sb.st_uid,arcn->sb.st_gid) < 0) {
|
||||
syswarn(1, oerrno, "Could not create: %s", arcn->name);
|
||||
return(-1);
|
||||
}
|
||||
@ -475,10 +475,18 @@ node_creat(arcn)
|
||||
* we were able to create the node. set uid/gid, modes and times
|
||||
*/
|
||||
if (pids)
|
||||
res = set_ids(arcn->name, arcn->sb.st_uid, arcn->sb.st_gid);
|
||||
res = ((arcn->type == PAX_SLK) ?
|
||||
set_lids(arcn->name, arcn->sb.st_uid, arcn->sb.st_gid) :
|
||||
set_ids(arcn->name, arcn->sb.st_uid, arcn->sb.st_gid));
|
||||
else
|
||||
res = 0;
|
||||
|
||||
/*
|
||||
* symlinks are done now.
|
||||
*/
|
||||
if (arcn->type == PAX_SLK)
|
||||
return(0);
|
||||
|
||||
/*
|
||||
* IMPORTANT SECURITY NOTE:
|
||||
* if not preserving mode or we cannot set uid/gid, then PROHIBIT any
|
||||
@ -489,7 +497,7 @@ node_creat(arcn)
|
||||
if (pmode)
|
||||
set_pmode(arcn->name, arcn->sb.st_mode);
|
||||
|
||||
if (arcn->type == PAX_DIR) {
|
||||
if (arcn->type == PAX_DIR && strcmp(NM_CPIO, argv0) != 0) {
|
||||
/*
|
||||
* Dirs must be processed again at end of extract to set times
|
||||
* and modes to agree with those stored in the archive. However
|
||||
@ -752,7 +760,46 @@ set_ids(fnm, uid, gid)
|
||||
#endif
|
||||
{
|
||||
if (chown(fnm, uid, gid) < 0) {
|
||||
syswarn(1, errno, "Unable to set file uid/gid of %s", fnm);
|
||||
/*
|
||||
* ignore EPERM unless in verbose mode or being run by root.
|
||||
* if running as pax, POSIX requires a warning.
|
||||
*/
|
||||
if (strcmp(NM_PAX, argv0) == 0 || errno != EPERM || vflag ||
|
||||
geteuid() == 0)
|
||||
syswarn(1, errno, "Unable to set file uid/gid of %s",
|
||||
fnm);
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* set_lids()
|
||||
* set the uid and gid of a file system node
|
||||
* Return:
|
||||
* 0 when set, -1 on failure
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
int
|
||||
set_lids(char *fnm, uid_t uid, gid_t gid)
|
||||
#else
|
||||
int
|
||||
set_lids(fnm, uid, gid)
|
||||
char *fnm;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
#endif
|
||||
{
|
||||
if (lchown(fnm, uid, gid) < 0) {
|
||||
/*
|
||||
* ignore EPERM unless in verbose mode or being run by root.
|
||||
* if running as pax, POSIX requires a warning.
|
||||
*/
|
||||
if (strcmp(NM_PAX, argv0) == 0 || errno != EPERM || vflag ||
|
||||
geteuid() == 0)
|
||||
syswarn(1, errno, "Unable to set file uid/gid of %s",
|
||||
fnm);
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
|
@ -152,11 +152,12 @@ ftree_start()
|
||||
|
||||
#ifdef __STDC__
|
||||
int
|
||||
ftree_add(register char *str)
|
||||
ftree_add(register char *str, int chflg)
|
||||
#else
|
||||
int
|
||||
ftree_add(str)
|
||||
ftree_add(str, chflg)
|
||||
register char *str;
|
||||
int chflg;
|
||||
#endif
|
||||
{
|
||||
register FTREE *ft;
|
||||
@ -184,6 +185,7 @@ ftree_add(str)
|
||||
str[len] = '\0';
|
||||
ft->fname = str;
|
||||
ft->refcnt = 0;
|
||||
ft->chflg = chflg;
|
||||
ft->fow = NULL;
|
||||
if (fthead == NULL) {
|
||||
fttail = fthead = ft;
|
||||
@ -261,7 +263,7 @@ ftree_chk()
|
||||
* that never had a match
|
||||
*/
|
||||
for (ft = fthead; ft != NULL; ft = ft->fow) {
|
||||
if (ft->refcnt > 0)
|
||||
if ((ft->refcnt > 0) || ft->chflg)
|
||||
continue;
|
||||
if (wban == 0) {
|
||||
paxwarn(1,"WARNING! These file names were not selected:");
|
||||
@ -321,7 +323,21 @@ ftree_arg()
|
||||
ftcur = fthead;
|
||||
else if ((ftcur = ftcur->fow) == NULL)
|
||||
return(-1);
|
||||
farray[0] = ftcur->fname;
|
||||
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);
|
||||
}
|
||||
continue;
|
||||
} else
|
||||
farray[0] = ftcur->fname;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -538,7 +554,7 @@ next_file(arcn)
|
||||
/*
|
||||
* copy file name, set file name length
|
||||
*/
|
||||
arcn->nlen = l_strncpy(arcn->name, ftent->fts_path, PAXPATHLEN+1);
|
||||
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);
|
||||
|
@ -47,5 +47,6 @@
|
||||
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;
|
||||
|
@ -83,12 +83,13 @@ static int d_first = -1;
|
||||
|
||||
#ifdef __STDC__
|
||||
void
|
||||
ls_list(register ARCHD *arcn, time_t now)
|
||||
ls_list(register ARCHD *arcn, time_t now, FILE *fp)
|
||||
#else
|
||||
void
|
||||
ls_list(arcn, now)
|
||||
ls_list(arcn, now, fp)
|
||||
register ARCHD *arcn;
|
||||
time_t now;
|
||||
FILE *fp;
|
||||
#endif
|
||||
{
|
||||
register struct stat *sbp;
|
||||
@ -100,8 +101,8 @@ ls_list(arcn, now)
|
||||
* if not verbose, just print the file name
|
||||
*/
|
||||
if (!vflag) {
|
||||
(void)printf("%s\n", arcn->name);
|
||||
(void)fflush(stdout);
|
||||
(void)fprintf(fp, "%s\n", arcn->name);
|
||||
(void)fflush(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -126,8 +127,8 @@ ls_list(arcn, now)
|
||||
*/
|
||||
if (strftime(f_date,DATELEN,timefrmt,localtime(&(sbp->st_mtime))) == 0)
|
||||
f_date[0] = '\0';
|
||||
(void)printf("%s%2u %-*s %-*s ", f_mode, sbp->st_nlink, UT_NAMESIZE,
|
||||
name_uid(sbp->st_uid, 1), UT_GRPSIZE,
|
||||
(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));
|
||||
|
||||
/*
|
||||
@ -135,31 +136,31 @@ ls_list(arcn, now)
|
||||
*/
|
||||
if ((arcn->type == PAX_CHR) || (arcn->type == PAX_BLK))
|
||||
# ifdef NET2_STAT
|
||||
(void)printf("%4u,%4u ", MAJOR(sbp->st_rdev),
|
||||
(void)fprintf(fp, "%4u,%4u ", MAJOR(sbp->st_rdev),
|
||||
MINOR(sbp->st_rdev));
|
||||
# else
|
||||
(void)printf("%4lu,%4lu ", (unsigned long)MAJOR(sbp->st_rdev),
|
||||
(void)fprintf(fp, "%4lu,%4lu ", (unsigned long)MAJOR(sbp->st_rdev),
|
||||
(unsigned long)MINOR(sbp->st_rdev));
|
||||
# endif
|
||||
else {
|
||||
# ifdef NET2_STAT
|
||||
(void)printf("%9lu ", sbp->st_size);
|
||||
(void)fprintf(fp, "%9lu ", sbp->st_size);
|
||||
# else
|
||||
(void)printf("%9qu ", sbp->st_size);
|
||||
(void)fprintf(fp, "%9qu ", sbp->st_size);
|
||||
# endif
|
||||
}
|
||||
|
||||
/*
|
||||
* print name and link info for hard and soft links
|
||||
*/
|
||||
(void)printf("%s %s", f_date, arcn->name);
|
||||
(void)fprintf(fp, "%s %s", f_date, arcn->name);
|
||||
if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG))
|
||||
(void)printf(" == %s\n", arcn->ln_name);
|
||||
(void)fprintf(fp, " == %s\n", arcn->ln_name);
|
||||
else if (arcn->type == PAX_SLK)
|
||||
(void)printf(" => %s\n", arcn->ln_name);
|
||||
(void)fprintf(fp, " => %s\n", arcn->ln_name);
|
||||
else
|
||||
(void)putchar('\n');
|
||||
(void)fflush(stdout);
|
||||
(void)putc('\n', fp);
|
||||
(void)fflush(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -200,41 +201,13 @@ ls_tty(arcn)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* zf_strncpy()
|
||||
* copy src to dest up to len chars (stopping at first '\0'), when src is
|
||||
* shorter than len, pads to len with '\0'. big performance win (and
|
||||
* a lot easier to code) over strncpy(), then a strlen() then a
|
||||
* memset(). (or doing the memset() first).
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
void
|
||||
zf_strncpy(register char *dest, register char *src, int len)
|
||||
#else
|
||||
void
|
||||
zf_strncpy(dest, src, len)
|
||||
register char *dest;
|
||||
register char *src;
|
||||
int len;
|
||||
#endif
|
||||
{
|
||||
register char *stop;
|
||||
|
||||
stop = dest + len;
|
||||
while ((dest < stop) && (*src != '\0'))
|
||||
*dest++ = *src++;
|
||||
while (dest < stop)
|
||||
*dest++ = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* l_strncpy()
|
||||
* copy src to dest up to len chars (stopping at first '\0')
|
||||
* 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() then a strlen()
|
||||
* doing a strncpy(), a strlen(), and then a possible memset())
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
@ -255,9 +228,10 @@ l_strncpy(dest, src, len)
|
||||
start = dest;
|
||||
while ((dest < stop) && (*src != '\0'))
|
||||
*dest++ = *src++;
|
||||
if (dest < stop)
|
||||
*dest = '\0';
|
||||
return(dest - start);
|
||||
len = dest - start;
|
||||
while (dest < stop)
|
||||
*dest++ = '\0';
|
||||
return(len);
|
||||
}
|
||||
|
||||
/*
|
||||
|
71
bin/pax/getoldopt.c
Normal file
71
bin/pax/getoldopt.c
Normal file
@ -0,0 +1,71 @@
|
||||
/* $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 $ */
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static const char rcsid[] = "$FreeBSD$";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int
|
||||
getoldopt(argc, argv, optstring)
|
||||
int argc;
|
||||
char **argv;
|
||||
char *optstring;
|
||||
{
|
||||
static char *key; /* Points to next keyletter */
|
||||
static char use_getopt; /* !=0 if argv[1][0] was '-' */
|
||||
char c;
|
||||
char *place;
|
||||
|
||||
optarg = NULL;
|
||||
|
||||
if (key == NULL) { /* First time */
|
||||
if (argc < 2) return EOF;
|
||||
key = argv[1];
|
||||
if (*key == '-')
|
||||
use_getopt++;
|
||||
else
|
||||
optind = 2;
|
||||
}
|
||||
|
||||
if (use_getopt)
|
||||
return getopt(argc, argv, optstring);
|
||||
|
||||
c = *key++;
|
||||
if (c == '\0') {
|
||||
key--;
|
||||
return EOF;
|
||||
}
|
||||
place = strchr(optstring, c);
|
||||
|
||||
if (place == NULL || c == ':') {
|
||||
fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
|
||||
return('?');
|
||||
}
|
||||
|
||||
place++;
|
||||
if (*place == ':') {
|
||||
if (optind < argc) {
|
||||
optarg = argv[optind];
|
||||
optind++;
|
||||
} else {
|
||||
fprintf(stderr, "%s: %c argument missing\n",
|
||||
argv[0], c);
|
||||
return('?');
|
||||
}
|
||||
}
|
||||
|
||||
return(c);
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
/*-
|
||||
/*
|
||||
* Copyright (c) 1992 Keith Muller.
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
@ -48,9 +48,11 @@ static const char rcsid[] =
|
||||
#include <sys/mtio.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <paths.h>
|
||||
#include "pax.h"
|
||||
#include "options.h"
|
||||
#include "cpio.h"
|
||||
@ -69,17 +71,23 @@ static int no_op __P((void));
|
||||
static void printflg __P((unsigned int));
|
||||
static int c_frmt __P((const void *, const void *));
|
||||
static off_t str_offt __P((char *));
|
||||
static char *getline __P((FILE *fp));
|
||||
static void pax_options __P((register int, register char **));
|
||||
static void pax_usage __P((void));
|
||||
static void tar_options __P((register int, register char **));
|
||||
static void tar_usage __P((void));
|
||||
#ifdef notdef
|
||||
static void cpio_options __P((register int, register char **));
|
||||
static void cpio_usage __P((void));
|
||||
#endif
|
||||
|
||||
/* errors from getline */
|
||||
#define GETLINE_FILE_CORRUPT 1
|
||||
#define GETLINE_OUT_OF_MEM 2
|
||||
static int getline_error;
|
||||
|
||||
|
||||
#define GZIP_CMD "gzip" /* command to run as gzip */
|
||||
#define COMPRESS_CMD "compress" /* command to run as compress */
|
||||
#define BZIP2_CMD "bzip2" /* command to run as gzip */
|
||||
|
||||
/*
|
||||
* Format specific routine table - MUST BE IN SORTED ORDER BY NAME
|
||||
@ -121,7 +129,11 @@ FSUB fsub[] = {
|
||||
ustar_rd, tar_endrd, ustar_stwr, ustar_wr, tar_endwr, tar_trail,
|
||||
rd_wrfile, wr_rdfile, bad_opt},
|
||||
};
|
||||
#define F_TAR 4 /* format when called as tar */
|
||||
#define F_OCPIO 0 /* format when called as cpio -6 */
|
||||
#define F_ACPIO 1 /* format when called as cpio -c */
|
||||
#define F_CPIO 3 /* format when called as cpio */
|
||||
#define F_OTAR 4 /* format when called as tar -o */
|
||||
#define F_TAR 5 /* format when called as tar */
|
||||
#define DEFLT 5 /* default write format from list above */
|
||||
|
||||
/*
|
||||
@ -158,10 +170,8 @@ options(argc, argv)
|
||||
|
||||
if (strcmp(NM_TAR, argv0) == 0)
|
||||
return(tar_options(argc, argv));
|
||||
# ifdef notdef
|
||||
else if (strcmp(NM_CPIO, argv0) == 0)
|
||||
return(cpio_options(argc, argv));
|
||||
# endif
|
||||
/*
|
||||
* assume pax as the default
|
||||
*/
|
||||
@ -368,7 +378,7 @@ pax_options(argc, argv)
|
||||
*/
|
||||
tmp.name = optarg;
|
||||
if ((frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
|
||||
sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt))) {
|
||||
sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt)) != NULL) {
|
||||
flg |= XF;
|
||||
break;
|
||||
}
|
||||
@ -500,7 +510,6 @@ pax_options(argc, argv)
|
||||
Zflag = 1;
|
||||
flg |= CZF;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
pax_usage();
|
||||
break;
|
||||
@ -514,6 +523,7 @@ pax_options(argc, argv)
|
||||
*/
|
||||
if (ISLIST(flg)) {
|
||||
act = LIST;
|
||||
listf = stdout;
|
||||
bflg = flg & BDLIST;
|
||||
} else if (ISEXTRACT(flg)) {
|
||||
act = EXTRACT;
|
||||
@ -549,7 +559,7 @@ pax_options(argc, argv)
|
||||
case LIST:
|
||||
case EXTRACT:
|
||||
for (; optind < argc; optind++)
|
||||
if (pat_add(argv[optind]) < 0)
|
||||
if (pat_add(argv[optind], NULL) < 0)
|
||||
pax_usage();
|
||||
break;
|
||||
case COPY:
|
||||
@ -563,7 +573,7 @@ pax_options(argc, argv)
|
||||
case ARCHIVE:
|
||||
case APPND:
|
||||
for (; optind < argc; optind++)
|
||||
if (ftree_add(argv[optind]) < 0)
|
||||
if (ftree_add(argv[optind], 0) < 0)
|
||||
pax_usage();
|
||||
/*
|
||||
* no read errors allowed on updates/append operation!
|
||||
@ -590,35 +600,37 @@ tar_options(argc, argv)
|
||||
register char **argv;
|
||||
#endif
|
||||
{
|
||||
register char *cp;
|
||||
register int c;
|
||||
int fstdin = 0;
|
||||
int Oflag = 0;
|
||||
int nincfiles = 0;
|
||||
int incfiles_max = 0;
|
||||
struct incfile {
|
||||
char *file;
|
||||
char *dir;
|
||||
};
|
||||
struct incfile *incfiles = NULL;
|
||||
|
||||
/*
|
||||
* Set default values.
|
||||
*/
|
||||
rmleadslash = 1;
|
||||
|
||||
if (argc < 2)
|
||||
tar_usage();
|
||||
/*
|
||||
* process option flags
|
||||
*/
|
||||
++argv;
|
||||
for (cp = *argv++; *cp != '\0'; ++cp) {
|
||||
switch (*cp) {
|
||||
case '-':
|
||||
/*
|
||||
* skip over -
|
||||
*/
|
||||
break;
|
||||
while ((c = getoldopt(argc, argv,
|
||||
"b:cef:hjmopqruts:vwxyzBC:HI:LOPXZ014578")) != -1) {
|
||||
switch(c) {
|
||||
case 'b':
|
||||
/*
|
||||
* specify blocksize
|
||||
* specify blocksize in 512-byte blocks
|
||||
*/
|
||||
if (*argv == NULL) {
|
||||
paxwarn(1,"blocksize must be specified with 'b'");
|
||||
if ((wrblksz = (int)str_offt(optarg)) <= 0) {
|
||||
paxwarn(1, "Invalid block size %s", optarg);
|
||||
tar_usage();
|
||||
}
|
||||
if ((wrblksz = (int)str_offt(*argv)) <= 0) {
|
||||
paxwarn(1, "Invalid block size %s", *argv);
|
||||
tar_usage();
|
||||
}
|
||||
++argv;
|
||||
wrblksz *= 512; /* XXX - check for int oflow */
|
||||
break;
|
||||
case 'c':
|
||||
/*
|
||||
@ -636,21 +648,29 @@ tar_options(argc, argv)
|
||||
/*
|
||||
* filename where the archive is stored
|
||||
*/
|
||||
if (*argv == NULL) {
|
||||
paxwarn(1, "filename must be specified with 'f'");
|
||||
tar_usage();
|
||||
}
|
||||
if ((argv[0][0] == '-') && (argv[0][1]== '\0')) {
|
||||
if ((optarg[0] == '-') && (optarg[1]== '\0')) {
|
||||
/*
|
||||
* treat a - as stdin
|
||||
*/
|
||||
++argv;
|
||||
++fstdin;
|
||||
arcname = (char *)0;
|
||||
fstdin = 1;
|
||||
arcname = NULL;
|
||||
break;
|
||||
}
|
||||
fstdin = 0;
|
||||
arcname = *argv++;
|
||||
arcname = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
/*
|
||||
* follow symlinks
|
||||
*/
|
||||
Lflag = 1;
|
||||
break;
|
||||
case 'j':
|
||||
case 'y':
|
||||
/*
|
||||
* use bzip2. Non standard option.
|
||||
*/
|
||||
gzip_program = BZIP2_CMD;
|
||||
break;
|
||||
case 'm':
|
||||
/*
|
||||
@ -661,16 +681,21 @@ tar_options(argc, argv)
|
||||
case 'o':
|
||||
if (opt_add("write_opt=nodir") < 0)
|
||||
tar_usage();
|
||||
case 'O':
|
||||
Oflag = 1;
|
||||
break;
|
||||
case 'p':
|
||||
/*
|
||||
* preserve user id, group id, file
|
||||
* mode, access/modification times
|
||||
* preserve uid/gid and file mode, regardless of umask
|
||||
*/
|
||||
pids = 1;
|
||||
pmode = 1;
|
||||
patime = 1;
|
||||
pmtime = 1;
|
||||
pids = 1;
|
||||
break;
|
||||
case 'q':
|
||||
/*
|
||||
* select first match for a pattern only
|
||||
*/
|
||||
nflag = 1;
|
||||
break;
|
||||
case 'r':
|
||||
case 'u':
|
||||
@ -679,6 +704,15 @@ tar_options(argc, argv)
|
||||
*/
|
||||
act = APPND;
|
||||
break;
|
||||
case 's':
|
||||
/*
|
||||
* file name substitution name pattern
|
||||
*/
|
||||
if (rep_add(optarg) < 0) {
|
||||
tar_usage();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
/*
|
||||
* list contents of the tape
|
||||
@ -689,7 +723,7 @@ tar_options(argc, argv)
|
||||
/*
|
||||
* verbose operation mode
|
||||
*/
|
||||
vflag = 1;
|
||||
vflag++;
|
||||
break;
|
||||
case 'w':
|
||||
/*
|
||||
@ -699,9 +733,11 @@ tar_options(argc, argv)
|
||||
break;
|
||||
case 'x':
|
||||
/*
|
||||
* write an archive
|
||||
* extract an archive, preserving mode,
|
||||
* and mtime if possible.
|
||||
*/
|
||||
act = EXTRACT;
|
||||
pmtime = 1;
|
||||
break;
|
||||
case 'z':
|
||||
/*
|
||||
@ -714,12 +750,29 @@ tar_options(argc, argv)
|
||||
* Nothing to do here, this is pax default
|
||||
*/
|
||||
break;
|
||||
case 'C':
|
||||
chdname = optarg;
|
||||
break;
|
||||
case 'H':
|
||||
/*
|
||||
* follow command line symlinks only
|
||||
*/
|
||||
Hflag = 1;
|
||||
break;
|
||||
case 'I':
|
||||
if (++nincfiles > incfiles_max) {
|
||||
incfiles_max = nincfiles + 3;
|
||||
incfiles = realloc(incfiles,
|
||||
sizeof(*incfiles) * incfiles_max);
|
||||
if (incfiles == NULL) {
|
||||
paxwarn(0, "Unable to allocate space "
|
||||
"for option list");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
incfiles[nincfiles - 1].file = optarg;
|
||||
incfiles[nincfiles - 1].dir = chdname;
|
||||
break;
|
||||
case 'L':
|
||||
/*
|
||||
* follow symlinks
|
||||
@ -728,9 +781,9 @@ tar_options(argc, argv)
|
||||
break;
|
||||
case 'P':
|
||||
/*
|
||||
* do not follow symlinks
|
||||
* do not remove leading '/' from pathnames
|
||||
*/
|
||||
Lflag = 0;
|
||||
rmleadslash = 0;
|
||||
break;
|
||||
case 'X':
|
||||
/*
|
||||
@ -767,12 +820,29 @@ tar_options(argc, argv)
|
||||
break;
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
/* Traditional tar behaviour (pax uses stderr unless in list mode) */
|
||||
if (fstdin == 1 && act == ARCHIVE)
|
||||
listf = stderr;
|
||||
else
|
||||
listf = stdout;
|
||||
|
||||
/* Traditional tar behaviour (pax wants to read file list from stdin) */
|
||||
if ((act == ARCHIVE || act == APPND) && argc == 0 && nincfiles == 0)
|
||||
exit(0);
|
||||
|
||||
/*
|
||||
* if we are writing (ARCHIVE) specify tar, otherwise run like pax
|
||||
* (unless -o specified)
|
||||
*/
|
||||
if (act == ARCHIVE)
|
||||
frmt = &(fsub[F_TAR]);
|
||||
if (act == ARCHIVE || act == APPND)
|
||||
frmt = &(fsub[Oflag ? F_OTAR : F_TAR]);
|
||||
else if (Oflag) {
|
||||
paxwarn(1, "The -O/-o options are only valid when writing an archive");
|
||||
tar_usage(); /* only valid when writing */
|
||||
}
|
||||
|
||||
/*
|
||||
* process the args as they are interpreted by the operation mode
|
||||
@ -781,15 +851,132 @@ tar_options(argc, argv)
|
||||
case LIST:
|
||||
case EXTRACT:
|
||||
default:
|
||||
while (*argv != NULL)
|
||||
if (pat_add(*argv++) < 0)
|
||||
tar_usage();
|
||||
{
|
||||
int sawpat = 0;
|
||||
char *file, *dir = NULL;
|
||||
|
||||
while (nincfiles || *argv != NULL) {
|
||||
/*
|
||||
* If we queued up any include files,
|
||||
* pull them in now. Otherwise, check
|
||||
* for -I and -C positional flags.
|
||||
* Anything else must be a file to
|
||||
* extract.
|
||||
*/
|
||||
if (nincfiles) {
|
||||
file = incfiles->file;
|
||||
dir = incfiles->dir;
|
||||
incfiles++;
|
||||
nincfiles--;
|
||||
} else if (strcmp(*argv, "-I") == 0) {
|
||||
if (*++argv == NULL)
|
||||
break;
|
||||
file = *argv++;
|
||||
dir = chdname;
|
||||
} else
|
||||
file = NULL;
|
||||
if (file != NULL) {
|
||||
FILE *fp;
|
||||
char *str;
|
||||
|
||||
if (strcmp(file, "-") == 0)
|
||||
fp = stdin;
|
||||
else if ((fp = fopen(file, "r")) == NULL) {
|
||||
paxwarn(1, "Unable to open file '%s' for read", file);
|
||||
tar_usage();
|
||||
}
|
||||
while ((str = getline(fp)) != NULL) {
|
||||
if (pat_add(str, dir) < 0)
|
||||
tar_usage();
|
||||
sawpat = 1;
|
||||
}
|
||||
if (strcmp(file, "-") != 0)
|
||||
fclose(fp);
|
||||
if (getline_error) {
|
||||
paxwarn(1, "Problem with file '%s'", file);
|
||||
tar_usage();
|
||||
}
|
||||
} else if (strcmp(*argv, "-C") == 0) {
|
||||
if (*++argv == NULL)
|
||||
break;
|
||||
chdname = *argv++;
|
||||
} else if (pat_add(*argv++, chdname) < 0)
|
||||
tar_usage();
|
||||
else
|
||||
sawpat = 1;
|
||||
}
|
||||
/*
|
||||
* if patterns were added, we are doing chdir()
|
||||
* on a file-by-file basis, else, just one
|
||||
* global chdir (if any) after opening input.
|
||||
*/
|
||||
if (sawpat > 0)
|
||||
chdname = NULL;
|
||||
}
|
||||
break;
|
||||
case ARCHIVE:
|
||||
case APPND:
|
||||
while (*argv != NULL)
|
||||
if (ftree_add(*argv++) < 0)
|
||||
if (chdname != NULL) { /* initial chdir() */
|
||||
if (ftree_add(chdname, 1) < 0)
|
||||
tar_usage();
|
||||
}
|
||||
|
||||
while (nincfiles || *argv != NULL) {
|
||||
char *file, *dir = NULL;
|
||||
|
||||
/*
|
||||
* If we queued up any include files, pull them in
|
||||
* now. Otherwise, check for -I and -C positional
|
||||
* flags. Anything else must be a file to include
|
||||
* in the archive.
|
||||
*/
|
||||
if (nincfiles) {
|
||||
file = incfiles->file;
|
||||
dir = incfiles->dir;
|
||||
incfiles++;
|
||||
nincfiles--;
|
||||
} else if (strcmp(*argv, "-I") == 0) {
|
||||
if (*++argv == NULL)
|
||||
break;
|
||||
file = *argv++;
|
||||
dir = NULL;
|
||||
} else
|
||||
file = NULL;
|
||||
if (file != NULL) {
|
||||
FILE *fp;
|
||||
char *str;
|
||||
|
||||
/* Set directory if needed */
|
||||
if (dir) {
|
||||
if (ftree_add(dir, 1) < 0)
|
||||
tar_usage();
|
||||
}
|
||||
|
||||
if (strcmp(file, "-") == 0)
|
||||
fp = stdin;
|
||||
else if ((fp = fopen(file, "r")) == NULL) {
|
||||
paxwarn(1, "Unable to open file '%s' for read", file);
|
||||
tar_usage();
|
||||
}
|
||||
while ((str = getline(fp)) != NULL) {
|
||||
if (ftree_add(str, 0) < 0)
|
||||
tar_usage();
|
||||
}
|
||||
if (strcmp(file, "-") != 0)
|
||||
fclose(fp);
|
||||
if (getline_error) {
|
||||
paxwarn(1, "Problem with file '%s'",
|
||||
file);
|
||||
tar_usage();
|
||||
}
|
||||
} else if (strcmp(*argv, "-C") == 0) {
|
||||
if (*++argv == NULL)
|
||||
break;
|
||||
if (ftree_add(*argv++, 1) < 0)
|
||||
tar_usage();
|
||||
} else if (ftree_add(*argv++, 0) < 0)
|
||||
tar_usage();
|
||||
}
|
||||
/*
|
||||
* no read errors allowed on updates/append operation!
|
||||
*/
|
||||
@ -799,11 +986,43 @@ tar_options(argc, argv)
|
||||
if (!fstdin && ((arcname == NULL) || (*arcname == '\0'))) {
|
||||
arcname = getenv("TAPE");
|
||||
if ((arcname == NULL) || (*arcname == '\0'))
|
||||
arcname = DEV_8;
|
||||
arcname = _PATH_DEFTAPE;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef notdef
|
||||
int
|
||||
mkpath(path)
|
||||
char *path;
|
||||
{
|
||||
struct stat sb;
|
||||
register char *slash;
|
||||
int done = 0;
|
||||
|
||||
slash = path;
|
||||
|
||||
while (!done) {
|
||||
slash += strspn(slash, "/");
|
||||
slash += strcspn(slash, "/");
|
||||
|
||||
done = (*slash == '\0');
|
||||
*slash = '\0';
|
||||
|
||||
if (stat(path, &sb)) {
|
||||
if (errno != ENOENT || mkdir(path, 0777)) {
|
||||
paxwarn(1, "%s", path);
|
||||
return (-1);
|
||||
}
|
||||
} else if (!S_ISDIR(sb.st_mode)) {
|
||||
syswarn(1, ENOTDIR, "%s", path);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (!done)
|
||||
*slash = '/';
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
* cpio_options()
|
||||
* look at the user specified flags. set globals as required and check if
|
||||
@ -820,8 +1039,257 @@ cpio_options(argc, argv)
|
||||
register char **argv;
|
||||
#endif
|
||||
{
|
||||
register int c, i;
|
||||
char *str;
|
||||
FSUB tmp;
|
||||
FILE *fp;
|
||||
|
||||
kflag = 1;
|
||||
pids = 1;
|
||||
pmode = 1;
|
||||
pmtime = 0;
|
||||
arcname = NULL;
|
||||
dflag = 1;
|
||||
act = -1;
|
||||
nodirs = 1;
|
||||
while ((c=getopt(argc,argv,"abcdfiklmoprstuvzABC:E:F:H:I:LO:SZ6")) != -1)
|
||||
switch (c) {
|
||||
case 'a':
|
||||
/*
|
||||
* preserve access time on files read
|
||||
*/
|
||||
tflag = 1;
|
||||
break;
|
||||
case 'b':
|
||||
/*
|
||||
* swap bytes and half-words when reading data
|
||||
*/
|
||||
break;
|
||||
case 'c':
|
||||
/*
|
||||
* ASCII cpio header
|
||||
*/
|
||||
frmt = &(fsub[F_ACPIO]);
|
||||
break;
|
||||
case 'd':
|
||||
/*
|
||||
* create directories as needed
|
||||
*/
|
||||
nodirs = 0;
|
||||
break;
|
||||
case 'f':
|
||||
/*
|
||||
* invert meaning of pattern list
|
||||
*/
|
||||
cflag = 1;
|
||||
break;
|
||||
case 'i':
|
||||
/*
|
||||
* restore an archive
|
||||
*/
|
||||
act = EXTRACT;
|
||||
break;
|
||||
case 'k':
|
||||
break;
|
||||
case 'l':
|
||||
/*
|
||||
* use links instead of copies when possible
|
||||
*/
|
||||
lflag = 1;
|
||||
break;
|
||||
case 'm':
|
||||
/*
|
||||
* preserve modification time
|
||||
*/
|
||||
pmtime = 1;
|
||||
break;
|
||||
case 'o':
|
||||
/*
|
||||
* create an archive
|
||||
*/
|
||||
act = ARCHIVE;
|
||||
frmt = &(fsub[F_CPIO]);
|
||||
break;
|
||||
case 'p':
|
||||
/*
|
||||
* copy-pass mode
|
||||
*/
|
||||
act = COPY;
|
||||
break;
|
||||
case 'r':
|
||||
/*
|
||||
* interactively rename files
|
||||
*/
|
||||
iflag = 1;
|
||||
break;
|
||||
case 's':
|
||||
/*
|
||||
* swap bytes after reading data
|
||||
*/
|
||||
break;
|
||||
case 't':
|
||||
/*
|
||||
* list contents of archive
|
||||
*/
|
||||
act = LIST;
|
||||
listf = stdout;
|
||||
break;
|
||||
case 'u':
|
||||
/*
|
||||
* replace newer files
|
||||
*/
|
||||
kflag = 0;
|
||||
break;
|
||||
case 'v':
|
||||
/*
|
||||
* verbose operation mode
|
||||
*/
|
||||
vflag = 1;
|
||||
break;
|
||||
case 'z':
|
||||
/*
|
||||
* use gzip. Non standard option.
|
||||
*/
|
||||
gzip_program = GZIP_CMD;
|
||||
break;
|
||||
case 'A':
|
||||
/*
|
||||
* append mode
|
||||
*/
|
||||
act = APPND;
|
||||
break;
|
||||
case 'B':
|
||||
/*
|
||||
* Use 5120 byte block size
|
||||
*/
|
||||
wrblksz = 5120;
|
||||
break;
|
||||
case 'C':
|
||||
/*
|
||||
* set block size in bytes
|
||||
*/
|
||||
wrblksz = atoi(optarg);
|
||||
break;
|
||||
case 'E':
|
||||
/*
|
||||
* file with patterns to extract or list
|
||||
*/
|
||||
if ((fp = fopen(optarg, "r")) == NULL) {
|
||||
paxwarn(1, "Unable to open file '%s' for read", optarg);
|
||||
cpio_usage();
|
||||
}
|
||||
while ((str = getline(fp)) != NULL) {
|
||||
pat_add(str, NULL);
|
||||
}
|
||||
fclose(fp);
|
||||
if (getline_error) {
|
||||
paxwarn(1, "Problem with file '%s'", optarg);
|
||||
cpio_usage();
|
||||
}
|
||||
break;
|
||||
case 'F':
|
||||
case 'I':
|
||||
case 'O':
|
||||
/*
|
||||
* filename where the archive is stored
|
||||
*/
|
||||
if ((optarg[0] == '-') && (optarg[1]== '\0')) {
|
||||
/*
|
||||
* treat a - as stdin
|
||||
*/
|
||||
arcname = NULL;
|
||||
break;
|
||||
}
|
||||
arcname = optarg;
|
||||
break;
|
||||
case 'H':
|
||||
/*
|
||||
* specify an archive format on write
|
||||
*/
|
||||
tmp.name = optarg;
|
||||
if ((frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
|
||||
sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt)) != NULL)
|
||||
break;
|
||||
paxwarn(1, "Unknown -H format: %s", optarg);
|
||||
(void)fputs("cpio: Known -H formats are:", stderr);
|
||||
for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
|
||||
(void)fprintf(stderr, " %s", fsub[i].name);
|
||||
(void)fputs("\n\n", stderr);
|
||||
cpio_usage();
|
||||
break;
|
||||
case 'L':
|
||||
/*
|
||||
* follow symbolic links
|
||||
*/
|
||||
Lflag = 1;
|
||||
break;
|
||||
case 'S':
|
||||
/*
|
||||
* swap halfwords after reading data
|
||||
*/
|
||||
break;
|
||||
case 'Z':
|
||||
/*
|
||||
* use compress. Non standard option.
|
||||
*/
|
||||
gzip_program = COMPRESS_CMD;
|
||||
break;
|
||||
case '6':
|
||||
/*
|
||||
* process Version 6 cpio format
|
||||
*/
|
||||
frmt = &(fsub[F_OCPIO]);
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
cpio_usage();
|
||||
break;
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
/*
|
||||
* process the args as they are interpreted by the operation mode
|
||||
*/
|
||||
switch (act) {
|
||||
case LIST:
|
||||
case EXTRACT:
|
||||
while (*argv != NULL)
|
||||
if (pat_add(*argv++, NULL) < 0)
|
||||
cpio_usage();
|
||||
break;
|
||||
case COPY:
|
||||
if (*argv == NULL) {
|
||||
paxwarn(0, "Destination directory was not supplied");
|
||||
cpio_usage();
|
||||
}
|
||||
dirptr = *argv;
|
||||
if (mkpath(dirptr) < 0)
|
||||
cpio_usage();
|
||||
--argc;
|
||||
++argv;
|
||||
/* FALL THROUGH */
|
||||
case ARCHIVE:
|
||||
case APPND:
|
||||
if (*argv != NULL)
|
||||
cpio_usage();
|
||||
/*
|
||||
* no read errors allowed on updates/append operation!
|
||||
*/
|
||||
maxflt = 0;
|
||||
while ((str = getline(stdin)) != NULL) {
|
||||
ftree_add(str, NULL);
|
||||
}
|
||||
if (getline_error) {
|
||||
paxwarn(1, "Problem while reading stdin");
|
||||
cpio_usage();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cpio_usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* printflg()
|
||||
@ -841,7 +1309,7 @@ printflg(flg)
|
||||
int pos = 0;
|
||||
|
||||
(void)fprintf(stderr,"%s: Invalid combination of options:", argv0);
|
||||
while ((nxt = ffs(flg))) {
|
||||
while ((nxt = ffs(flg)) != 0) {
|
||||
flg = flg >> nxt;
|
||||
pos += nxt;
|
||||
(void)fprintf(stderr, " -%c", flgch[pos-1]);
|
||||
@ -946,6 +1414,10 @@ opt_add(str)
|
||||
paxwarn(0, "Invalid option name");
|
||||
return(-1);
|
||||
}
|
||||
if ((str = strdup(str)) == NULL) {
|
||||
paxwarn(0, "Unable to allocate space for option list");
|
||||
return(-1);
|
||||
}
|
||||
frpt = endpt = str;
|
||||
|
||||
/*
|
||||
@ -958,10 +1430,12 @@ opt_add(str)
|
||||
*endpt = '\0';
|
||||
if ((pt = strchr(frpt, '=')) == NULL) {
|
||||
paxwarn(0, "Invalid options format");
|
||||
free(str);
|
||||
return(-1);
|
||||
}
|
||||
if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
|
||||
paxwarn(0, "Unable to allocate space for option list");
|
||||
free(str);
|
||||
return(-1);
|
||||
}
|
||||
*pt++ = '\0';
|
||||
@ -1065,6 +1539,35 @@ str_offt(val)
|
||||
return(num);
|
||||
}
|
||||
|
||||
#ifdef __STDC__
|
||||
char *
|
||||
getline(FILE *f)
|
||||
#else
|
||||
char *
|
||||
getline(f)
|
||||
FILE *f;
|
||||
#endif
|
||||
{
|
||||
char *name, *temp;
|
||||
size_t len;
|
||||
|
||||
name = fgetln(f, &len);
|
||||
if (!name) {
|
||||
getline_error = ferror(f) ? GETLINE_FILE_CORRUPT : 0;
|
||||
return(0);
|
||||
}
|
||||
if (name[len-1] != '\n')
|
||||
len++;
|
||||
temp = malloc(len);
|
||||
if (!temp) {
|
||||
getline_error = GETLINE_OUT_OF_MEM;
|
||||
return(0);
|
||||
}
|
||||
memcpy(temp, name, len-1);
|
||||
temp[len-1] = 0;
|
||||
return(temp);
|
||||
}
|
||||
|
||||
/*
|
||||
* no_op()
|
||||
* for those option functions where the archive format has nothing to do.
|
||||
@ -1135,13 +1638,13 @@ void
|
||||
tar_usage()
|
||||
#endif
|
||||
{
|
||||
(void)fputs("usage: tar -{txru}[cevfbmopwzBHLPXZ014578] [tapefile] ",
|
||||
(void)fputs("usage: tar [-]{crtux}[-befhjmopqsvwyzHLOPXZ014578] [blocksize] ",
|
||||
stderr);
|
||||
(void)fputs("[blocksize] file1 file2...\n", stderr);
|
||||
(void)fputs("[archive] [replstr] [-C directory] [-I file] [file ...]\n",
|
||||
stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef notdef
|
||||
/*
|
||||
* cpio_usage()
|
||||
* print the usage summary to the user
|
||||
@ -1155,6 +1658,10 @@ void
|
||||
cpio_usage()
|
||||
#endif
|
||||
{
|
||||
(void)fputs("usage: cpio -o [-aABcLvVzZ] [-C bytes] [-H format] [-O archive]\n", stderr);
|
||||
(void)fputs(" [-F archive] < name-list [> archive]\n", stderr);
|
||||
(void)fputs(" cpio -i [-bBcdfmnrsStuvVzZ6] [-C bytes] [-E file] [-H format]\n", stderr);
|
||||
(void)fputs(" [-I archive] [-F archive] [pattern...] [< archive]\n", stderr);
|
||||
(void)fputs(" cpio -p [-adlLmuvV] destination-directory < name-list\n", stderr);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
@ -49,6 +49,7 @@ static const char rcsid[] =
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#ifdef NET2_REGEX
|
||||
#include <regexp.h>
|
||||
#else
|
||||
@ -228,11 +229,12 @@ rep_add(str)
|
||||
|
||||
#ifdef __STDC__
|
||||
int
|
||||
pat_add(char *str)
|
||||
pat_add(char *str, char *chdname)
|
||||
#else
|
||||
int
|
||||
pat_add(str)
|
||||
pat_add(str, chdname)
|
||||
char *str;
|
||||
char *chdname;
|
||||
#endif
|
||||
{
|
||||
register PATTERN *pt;
|
||||
@ -260,6 +262,8 @@ pat_add(str)
|
||||
pt->plen = strlen(str);
|
||||
pt->fow = NULL;
|
||||
pt->flgs = 0;
|
||||
pt->chdname = chdname;
|
||||
|
||||
if (pathead == NULL) {
|
||||
pattail = pathead = pt;
|
||||
return(0);
|
||||
@ -616,7 +620,7 @@ range_match(pattern, test)
|
||||
int negate;
|
||||
int ok = 0;
|
||||
|
||||
if ((negate = (*pattern == '!')))
|
||||
if ((negate = (*pattern == '!')) != 0)
|
||||
++pattern;
|
||||
|
||||
while ((c = *pattern++) != ']') {
|
||||
@ -662,6 +666,38 @@ mod_name(arcn)
|
||||
{
|
||||
register int res = 0;
|
||||
|
||||
/*
|
||||
* Strip off leading '/' if appropriate.
|
||||
* Currently, this option is only set for the tar format.
|
||||
*/
|
||||
if (rmleadslash && arcn->name[0] == '/') {
|
||||
if (arcn->name[1] == '\0') {
|
||||
arcn->name[0] = '.';
|
||||
} else {
|
||||
(void)memmove(arcn->name, &arcn->name[1],
|
||||
strlen(arcn->name));
|
||||
arcn->nlen--;
|
||||
}
|
||||
if (rmleadslash < 2) {
|
||||
rmleadslash = 2;
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* IMPORTANT: We have a problem. what do we do with symlinks?
|
||||
* Modifying a hard link name makes sense, as we know the file it
|
||||
@ -703,7 +739,7 @@ mod_name(arcn)
|
||||
return(res);
|
||||
if ((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) ||
|
||||
(arcn->type == PAX_HRG))
|
||||
sub_name(arcn->ln_name, &(arcn->ln_nlen));
|
||||
sub_name(arcn->ln_name, &(arcn->ln_nlen), sizeof(arcn->ln_name));
|
||||
}
|
||||
return(res);
|
||||
}
|
||||
@ -775,8 +811,8 @@ tty_rename(arcn)
|
||||
*/
|
||||
tty_prnt("Processing continues, name changed to: %s\n", tmpname);
|
||||
res = add_name(arcn->name, arcn->nlen, tmpname);
|
||||
arcn->nlen = l_strncpy(arcn->name, tmpname, PAXPATHLEN+1);
|
||||
arcn->name[PAXPATHLEN] = '\0';
|
||||
arcn->nlen = l_strncpy(arcn->name, tmpname, sizeof(arcn->name) - 1);
|
||||
arcn->name[arcn->nlen] = '\0';
|
||||
if (res < 0)
|
||||
return(-1);
|
||||
return(0);
|
||||
|
@ -403,7 +403,10 @@ 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 32256 bytes.
|
||||
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.
|
||||
A
|
||||
.Ar blocksize
|
||||
can end with
|
||||
@ -1130,6 +1133,9 @@ and
|
||||
operations are extensions to the
|
||||
.Tn POSIX
|
||||
standard.
|
||||
.Sh SEE ALSO
|
||||
.Xr tar 1 ,
|
||||
.Xr cpio 1
|
||||
.Sh AUTHORS
|
||||
.An Keith Muller
|
||||
at the University of California, San Diego
|
||||
|
@ -55,6 +55,7 @@ static const char rcsid[] =
|
||||
#include <sys/resource.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <locale.h>
|
||||
#include <paths.h>
|
||||
#include <signal.h>
|
||||
@ -75,6 +76,7 @@ static int gen_init __P((void));
|
||||
int act = DEFOP; /* read/write/append/copy */
|
||||
FSUB *frmt = NULL; /* archive format type */
|
||||
int cflag; /* match all EXCEPT pattern/file */
|
||||
int cwdfd; /* starting cwd */
|
||||
int dflag; /* directory member match only */
|
||||
int iflag; /* interactive file/archive rename */
|
||||
int kflag; /* do not overwrite existing files */
|
||||
@ -92,15 +94,18 @@ int Zflag; /* same as uflg except after name mode */
|
||||
int vfpart; /* is partial verbose output in progress */
|
||||
int patime = 1; /* preserve file access time */
|
||||
int pmtime = 1; /* preserve file modification times */
|
||||
int nodirs; /* do not create directories as needed */
|
||||
int pmode; /* preserve file mode bits */
|
||||
int pids; /* preserve file uid/gid */
|
||||
int rmleadslash = 0; /* remove leading '/' from pathnames */
|
||||
int exit_val; /* exit value */
|
||||
int docrc; /* check/create file crc */
|
||||
char *dirptr; /* destination dir in a copy */
|
||||
char *argv0; /* root of argv[0] */
|
||||
sigset_t s_mask; /* signal mask for cleanup critical sect */
|
||||
FILE *listf = stderr; /* file pointer to print file list to */
|
||||
char *tempfile; /* tempfile to use for mkstemp(3) */
|
||||
char *tempbase; /* basename of tempfile to use for mkstemp(3) */
|
||||
sigset_t s_mask; /* signal mask for cleanup critical sect */
|
||||
|
||||
/*
|
||||
* PAX - Portable Archive Interchange
|
||||
@ -236,6 +241,14 @@ main(argc, argv)
|
||||
size_t tdlen;
|
||||
|
||||
(void) setlocale(LC_ALL, "");
|
||||
/*
|
||||
* Keep a reference to cwd, so we can always come back home.
|
||||
*/
|
||||
cwdfd = open(".", O_RDONLY);
|
||||
if (cwdfd < 0) {
|
||||
syswarn(0, errno, "Can't open current working directory.");
|
||||
return(exit_val);
|
||||
}
|
||||
|
||||
/*
|
||||
* Where should we put temporary files?
|
||||
@ -389,6 +402,7 @@ gen_init()
|
||||
paxwarn(1, "Unable to set up signal mask");
|
||||
return(-1);
|
||||
}
|
||||
memset(&n_hand, 0, sizeof n_hand);
|
||||
n_hand.sa_mask = s_mask;
|
||||
n_hand.sa_flags = 0;
|
||||
n_hand.sa_handler = sig_cleanup;
|
||||
|
@ -42,9 +42,10 @@
|
||||
* BSD PAX global data structures and constants.
|
||||
*/
|
||||
|
||||
#define MAXBLK 32256 /* MAX blocksize supported (posix SPEC) */
|
||||
#define MAXBLK 64512 /* 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 */
|
||||
@ -164,6 +165,7 @@ typedef struct {
|
||||
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 */
|
||||
|
@ -180,8 +180,8 @@ chk_lnk(arcn)
|
||||
* other links.
|
||||
*/
|
||||
arcn->ln_nlen = l_strncpy(arcn->ln_name, pt->name,
|
||||
PAXPATHLEN+1);
|
||||
arcn->ln_name[PAXPATHLEN] = '\0';
|
||||
sizeof(arcn->ln_name) - 1);
|
||||
arcn->ln_name[arcn->ln_nlen] = '\0';
|
||||
if (arcn->type == PAX_REG)
|
||||
arcn->type = PAX_HRG;
|
||||
else
|
||||
@ -624,12 +624,13 @@ add_name(oname, onamelen, nname)
|
||||
|
||||
#ifdef __STDC__
|
||||
void
|
||||
sub_name(register char *oname, int *onamelen)
|
||||
sub_name(register char *oname, int *onamelen, size_t onamesize)
|
||||
#else
|
||||
void
|
||||
sub_name(oname, onamelen)
|
||||
sub_name(oname, onamelen, onamesize)
|
||||
register char *oname;
|
||||
int *onamelen;
|
||||
size_t onamesize;
|
||||
#endif
|
||||
{
|
||||
register NAMT *pt;
|
||||
@ -653,8 +654,8 @@ sub_name(oname, onamelen)
|
||||
* found it, replace it with the new name
|
||||
* and return (we know that oname has enough space)
|
||||
*/
|
||||
*onamelen = l_strncpy(oname, pt->nname, PAXPATHLEN+1);
|
||||
oname[PAXPATHLEN] = '\0';
|
||||
*onamelen = l_strncpy(oname, pt->nname, onamesize - 1);
|
||||
oname[*onamelen] = '\0';
|
||||
return;
|
||||
}
|
||||
pt = pt->fow;
|
||||
|
293
bin/pax/tar.1
Normal file
293
bin/pax/tar.1
Normal file
@ -0,0 +1,293 @@
|
||||
.\"
|
||||
.\" Copyright (c) 1996 SigmaSoft, Th. Lockert
|
||||
.\" 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.
|
||||
.\" 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
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\" $OpenBSD: tar.1,v 1.33 2001/05/01 17:58:01 aaron Exp $
|
||||
.\"
|
||||
.Dd February 7, 2001
|
||||
.Dt TAR 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm tar
|
||||
.Nd tape archiver
|
||||
.Sh SYNOPSIS
|
||||
.Nm tar
|
||||
.Sm off
|
||||
.Oo \&- Oc {crtux} Op befhmopqsvwzHLOPXZ014578
|
||||
.Sm on
|
||||
.Op Ar blocksize
|
||||
.Op Ar archive
|
||||
.Op Ar replstr
|
||||
.\" XXX how to do this right?
|
||||
.Op Fl C Ar directory
|
||||
.Op Fl I Ar file
|
||||
.Op Ar file ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
command creates, adds files to, or extracts files from an
|
||||
archive file in
|
||||
.Dq tar
|
||||
format.
|
||||
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 Ar
|
||||
.It Fl c
|
||||
Create new archive, or overwrite an existing archive,
|
||||
adding the specified files to it.
|
||||
.It Fl r
|
||||
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
|
||||
List contents of archive.
|
||||
If any files are named on the
|
||||
command line, only those files will be listed.
|
||||
.It Fl u
|
||||
Alias for
|
||||
.Fl r .
|
||||
.It Fl x
|
||||
Extract files from archive.
|
||||
If any files are named on the
|
||||
command line, only those files will be extracted from the
|
||||
archive.
|
||||
If more than one copy of a file exists in the
|
||||
archive, later copies will overwrite earlier copies during
|
||||
extraction.
|
||||
The file mode and modification time are preserved
|
||||
if possible.
|
||||
The file mode is subject to modification by the
|
||||
.Xr umask 2 .
|
||||
.El
|
||||
.Pp
|
||||
In addition to the flags mentioned above, any of the following
|
||||
flags may be used:
|
||||
.Bl -tag -width Ar
|
||||
.It Fl b 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
|
||||
Filename where the archive is stored.
|
||||
Defaults to
|
||||
.Pa /dev/rst0 .
|
||||
.It Fl h
|
||||
Follow symbolic links as if they were normal files
|
||||
or directories.
|
||||
.It Fl j
|
||||
Compress archives using bzip2.
|
||||
.It Fl m
|
||||
Do not preserve modification time.
|
||||
.It Fl O
|
||||
Write old-style (non-POSIX) archives.
|
||||
.It Fl o
|
||||
Don't write directory information that the older (V7) style
|
||||
.Nm
|
||||
is unable to decode.
|
||||
This implies the
|
||||
.Fl O
|
||||
flag.
|
||||
.It Fl p
|
||||
Preserve user and group ID as well as file mode regardless of
|
||||
the current
|
||||
.Xr umask 2 .
|
||||
The setuid and setgid bits are only preserved if the user is
|
||||
the superuser.
|
||||
Only meaningful in conjunction with the
|
||||
.Fl x
|
||||
flag.
|
||||
.It Fl q
|
||||
Select the first archive member that matches each
|
||||
.Ar pattern
|
||||
operand.
|
||||
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 Ar replstr
|
||||
Modify the file or archive member names specified by the
|
||||
.Ar pattern
|
||||
or
|
||||
.Ar file
|
||||
operands according to the substitution expression
|
||||
.Ar replstr ,
|
||||
using the syntax of the
|
||||
.Xr ed 1
|
||||
utility regular expressions.
|
||||
The format of these regular expressions are:
|
||||
.Dl /old/new/[gp]
|
||||
As in
|
||||
.Xr ed 1 ,
|
||||
.Cm old
|
||||
is a basic regular expression and
|
||||
.Cm new
|
||||
can contain an ampersand (&), \\n (where n is a digit) back-references,
|
||||
or subexpression matching.
|
||||
The
|
||||
.Cm old
|
||||
string may also contain
|
||||
.Dv <newline>
|
||||
characters.
|
||||
Any non-null character can be used as a delimiter (/ is shown here).
|
||||
Multiple
|
||||
.Fl s
|
||||
expressions can be specified.
|
||||
The expressions are applied in the order they are specified on the
|
||||
command line, terminating with the first successful substitution.
|
||||
The optional trailing
|
||||
.Cm g
|
||||
continues to apply the substitution expression to the pathname substring
|
||||
which starts with the first character following the end of the last successful
|
||||
substitution.
|
||||
The first unsuccessful substitution stops the operation of the
|
||||
.Cm g
|
||||
option.
|
||||
The optional trailing
|
||||
.Cm p
|
||||
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>
|
||||
File or archive member names that substitute to the empty string
|
||||
are not selected and will be skipped.
|
||||
.It Fl v
|
||||
Verbose operation mode.
|
||||
.It Fl w
|
||||
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 bzip2.
|
||||
.It Fl z
|
||||
Compress archive using gzip.
|
||||
.It Fl C 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.
|
||||
.It Fl H
|
||||
Follow symlinks given on command line only.
|
||||
.It Fl L
|
||||
Follow all symlinks.
|
||||
.It Fl P
|
||||
Do not strip leading slashes
|
||||
.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 compress.
|
||||
.El
|
||||
.Pp
|
||||
The options
|
||||
.Op Fl 014578
|
||||
can be used to select one of the compiled-in backup devices,
|
||||
.Pa /dev/rstN .
|
||||
.Sh DIAGNOSTICS
|
||||
.Nm
|
||||
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
|
||||
.Pp
|
||||
Whenever
|
||||
.Nm
|
||||
cannot create a file or a link when extracting an archive or cannot
|
||||
find a file while writing an archive, or cannot preserve the user
|
||||
ID, group ID, file mode, or access and modification times when the
|
||||
.Fl p
|
||||
option is specified, a diagnostic message is written to standard
|
||||
error and a non-zero exit value will be returned, but processing
|
||||
will continue.
|
||||
In the case where
|
||||
.Nm
|
||||
cannot create a link to a file,
|
||||
.Nm
|
||||
will not create a second copy of the file.
|
||||
.Pp
|
||||
If the extraction of a file from an archive is prematurely terminated
|
||||
by a signal or error,
|
||||
.Nm
|
||||
may have only partially extracted the file the user wanted.
|
||||
Additionally, the file modes of extracted files and directories may
|
||||
have incorrect file bits, and the modification and access times may
|
||||
be wrong.
|
||||
.Pp
|
||||
If the creation of an archive is prematurely terminated by a signal
|
||||
or error,
|
||||
.Nm
|
||||
may have only partially created the archive which may violate the
|
||||
specific archive format specification.
|
||||
.Sh FILES
|
||||
.Bl -tag -width "/dev/rst0"
|
||||
.It Pa /dev/rst0
|
||||
default archive name
|
||||
.El
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width Fl
|
||||
.It Ev TMPDIR
|
||||
Path in which to store temporary files.
|
||||
.It Ev TAPE
|
||||
Default tape device to use instead of
|
||||
.Pa /dev/rst0 .
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr cpio 1 ,
|
||||
.Xr pax 1
|
||||
.Sh AUTHORS
|
||||
Keith Muller at the University of California, San Diego.
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
command first appeared in
|
||||
.At v7 .
|
||||
.Sh CAVEATS
|
||||
The
|
||||
.Fl L
|
||||
flag is not portable to other versions of
|
||||
.Nm
|
||||
where it may have a different meaning.
|
@ -162,7 +162,7 @@ tar_trail(buf, in_resync, cnt)
|
||||
* ul_oct()
|
||||
* convert an unsigned long to an octal string. many oddball field
|
||||
* termination characters are used by the various versions of tar in the
|
||||
* different fields. term selects which kind to use. str is BLANK padded
|
||||
* different fields. term selects which kind to use. str is '0' padded
|
||||
* at the front to len. we are unable to use only one format as many old
|
||||
* tar readers are very cranky about this.
|
||||
* Return:
|
||||
@ -215,7 +215,7 @@ ul_oct(val, str, len, term)
|
||||
}
|
||||
|
||||
while (pt >= str)
|
||||
*pt-- = ' ';
|
||||
*pt-- = '0';
|
||||
if (val != (u_long)0)
|
||||
return(-1);
|
||||
return(0);
|
||||
@ -226,7 +226,7 @@ ul_oct(val, str, len, term)
|
||||
* uqd_oct()
|
||||
* convert an u_quad_t to an octal string. one of many oddball field
|
||||
* termination characters are used by the various versions of tar in the
|
||||
* different fields. term selects which kind to use. str is BLANK padded
|
||||
* different fields. term selects which kind to use. str is '0' padded
|
||||
* at the front to len. we are unable to use only one format as many old
|
||||
* tar readers are very cranky about this.
|
||||
* Return:
|
||||
@ -279,7 +279,7 @@ uqd_oct(val, str, len, term)
|
||||
}
|
||||
|
||||
while (pt >= str)
|
||||
*pt-- = ' ';
|
||||
*pt-- = '0';
|
||||
if (val != (u_quad_t)0)
|
||||
return(-1);
|
||||
return(0);
|
||||
@ -453,13 +453,17 @@ tar_rd(arcn, buf)
|
||||
* copy out the name and values in the stat buffer
|
||||
*/
|
||||
hd = (HD_TAR *)buf;
|
||||
arcn->nlen = l_strncpy(arcn->name, hd->name, sizeof(hd->name));
|
||||
arcn->nlen = l_strncpy(arcn->name, hd->name, sizeof(arcn->name) - 1);
|
||||
arcn->name[arcn->nlen] = '\0';
|
||||
arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode,sizeof(hd->mode),OCT) &
|
||||
0xfff);
|
||||
arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT);
|
||||
arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT);
|
||||
arcn->sb.st_size = (size_t)asc_ul(hd->size, sizeof(hd->size), OCT);
|
||||
#ifdef NET2_STAT
|
||||
arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT);
|
||||
#else
|
||||
arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT);
|
||||
#endif
|
||||
arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
|
||||
arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
|
||||
|
||||
@ -478,7 +482,7 @@ tar_rd(arcn, buf)
|
||||
*/
|
||||
arcn->type = PAX_SLK;
|
||||
arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
|
||||
sizeof(hd->linkname));
|
||||
sizeof(arcn->ln_name) - 1);
|
||||
arcn->ln_name[arcn->ln_nlen] = '\0';
|
||||
arcn->sb.st_mode |= S_IFLNK;
|
||||
break;
|
||||
@ -490,7 +494,7 @@ tar_rd(arcn, buf)
|
||||
arcn->type = PAX_HLK;
|
||||
arcn->sb.st_nlink = 2;
|
||||
arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
|
||||
sizeof(hd->linkname));
|
||||
sizeof(arcn->ln_name) - 1);
|
||||
arcn->ln_name[arcn->ln_nlen] = '\0';
|
||||
|
||||
/*
|
||||
@ -499,6 +503,16 @@ tar_rd(arcn, buf)
|
||||
*/
|
||||
arcn->sb.st_mode |= S_IFREG;
|
||||
break;
|
||||
case DIRTYPE:
|
||||
/*
|
||||
* It is a directory, set the mode for -v printing
|
||||
*/
|
||||
arcn->type = PAX_DIR;
|
||||
arcn->sb.st_mode |= S_IFDIR;
|
||||
arcn->sb.st_nlink = 2;
|
||||
arcn->ln_name[0] = '\0';
|
||||
arcn->ln_nlen = 0;
|
||||
break;
|
||||
case AREGTYPE:
|
||||
case REGTYPE:
|
||||
default:
|
||||
@ -607,7 +621,7 @@ tar_wr(arcn)
|
||||
len = arcn->nlen;
|
||||
if (arcn->type == PAX_DIR)
|
||||
++len;
|
||||
if (len > sizeof(hd->name)) {
|
||||
if (len >= sizeof(hd->name)) {
|
||||
paxwarn(1, "File name too long for tar %s", arcn->name);
|
||||
return(1);
|
||||
}
|
||||
@ -621,7 +635,8 @@ tar_wr(arcn)
|
||||
* a header)
|
||||
*/
|
||||
hd = (HD_TAR *)hdblk;
|
||||
zf_strncpy(hd->name, arcn->name, sizeof(hd->name));
|
||||
l_strncpy(hd->name, arcn->name, sizeof(hd->name) - 1);
|
||||
hd->name[sizeof(hd->name) - 1] = '\0';
|
||||
arcn->pad = 0;
|
||||
|
||||
if (arcn->type == PAX_DIR) {
|
||||
@ -640,7 +655,8 @@ tar_wr(arcn)
|
||||
* no data follows this file, so no pad
|
||||
*/
|
||||
hd->linkflag = SYMTYPE;
|
||||
zf_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname));
|
||||
l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1);
|
||||
hd->linkname[sizeof(hd->linkname) - 1] = '\0';
|
||||
if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
|
||||
goto out;
|
||||
} else if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) {
|
||||
@ -648,7 +664,8 @@ tar_wr(arcn)
|
||||
* no data follows this file, so no pad
|
||||
*/
|
||||
hd->linkflag = LNKTYPE;
|
||||
zf_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname));
|
||||
l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1);
|
||||
hd->linkname[sizeof(hd->linkname) - 1] = '\0';
|
||||
if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
|
||||
goto out;
|
||||
} else {
|
||||
@ -685,7 +702,7 @@ tar_wr(arcn)
|
||||
* to be written
|
||||
*/
|
||||
if (ul_oct(tar_chksm(hdblk, sizeof(HD_TAR)), hd->chksum,
|
||||
sizeof(hd->chksum), 2))
|
||||
sizeof(hd->chksum), 3))
|
||||
goto out;
|
||||
if (wr_rdbuf(hdblk, sizeof(HD_TAR)) < 0)
|
||||
return(-1);
|
||||
@ -818,6 +835,7 @@ ustar_rd(arcn, buf)
|
||||
arcn->org_name = arcn->name;
|
||||
arcn->sb.st_nlink = 1;
|
||||
arcn->pat = NULL;
|
||||
arcn->nlen = 0;
|
||||
hd = (HD_USTAR *)buf;
|
||||
|
||||
/*
|
||||
@ -826,12 +844,12 @@ ustar_rd(arcn, buf)
|
||||
*/
|
||||
dest = arcn->name;
|
||||
if (*(hd->prefix) != '\0') {
|
||||
cnt = l_strncpy(arcn->name, hd->prefix, sizeof(hd->prefix));
|
||||
dest = arcn->name + arcn->nlen;
|
||||
cnt = l_strncpy(dest, hd->prefix, sizeof(arcn->name) - 2);
|
||||
dest += cnt;
|
||||
*dest++ = '/';
|
||||
cnt++;
|
||||
}
|
||||
arcn->nlen = l_strncpy(dest, hd->name, sizeof(hd->name));
|
||||
arcn->nlen += cnt;
|
||||
arcn->nlen = cnt + l_strncpy(dest, hd->name, sizeof(arcn->name) - cnt);
|
||||
arcn->name[arcn->nlen] = '\0';
|
||||
|
||||
/*
|
||||
@ -840,7 +858,11 @@ ustar_rd(arcn, buf)
|
||||
*/
|
||||
arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode, sizeof(hd->mode), OCT) &
|
||||
0xfff);
|
||||
arcn->sb.st_size = (size_t)asc_ul(hd->size, sizeof(hd->size), OCT);
|
||||
#ifdef NET2_STAT
|
||||
arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT);
|
||||
#else
|
||||
arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT);
|
||||
#endif
|
||||
arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
|
||||
arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
|
||||
|
||||
@ -920,7 +942,7 @@ ustar_rd(arcn, buf)
|
||||
* copy the link name
|
||||
*/
|
||||
arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
|
||||
sizeof(hd->linkname));
|
||||
sizeof(arcn->ln_name) - 1);
|
||||
arcn->ln_name[arcn->ln_nlen] = '\0';
|
||||
break;
|
||||
case CONTTYPE:
|
||||
@ -1002,7 +1024,7 @@ ustar_wr(arcn)
|
||||
* occur, we remove the / and copy the first part to the prefix
|
||||
*/
|
||||
*pt = '\0';
|
||||
zf_strncpy(hd->prefix, arcn->name, sizeof(hd->prefix));
|
||||
l_strncpy(hd->prefix, arcn->name, sizeof(hd->prefix) - 1);
|
||||
*pt++ = '/';
|
||||
} else
|
||||
memset(hd->prefix, 0, sizeof(hd->prefix));
|
||||
@ -1011,7 +1033,8 @@ ustar_wr(arcn)
|
||||
* copy the name part. this may be the whole path or the part after
|
||||
* the prefix
|
||||
*/
|
||||
zf_strncpy(hd->name, pt, sizeof(hd->name));
|
||||
l_strncpy(hd->name, pt, sizeof(hd->name) - 1);
|
||||
hd->name[sizeof(hd->name) - 1] = '\0';
|
||||
|
||||
/*
|
||||
* set the fields in the header that are type dependent
|
||||
@ -1054,7 +1077,8 @@ ustar_wr(arcn)
|
||||
hd->typeflag = SYMTYPE;
|
||||
else
|
||||
hd->typeflag = LNKTYPE;
|
||||
zf_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname));
|
||||
l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1);
|
||||
hd->linkname[sizeof(hd->linkname) - 1] = '\0';
|
||||
memset(hd->devmajor, 0, sizeof(hd->devmajor));
|
||||
memset(hd->devminor, 0, sizeof(hd->devminor));
|
||||
if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
|
||||
@ -1087,8 +1111,8 @@ ustar_wr(arcn)
|
||||
break;
|
||||
}
|
||||
|
||||
zf_strncpy(hd->magic, TMAGIC, TMAGLEN);
|
||||
zf_strncpy(hd->version, TVERSION, TVERSLEN);
|
||||
l_strncpy(hd->magic, TMAGIC, TMAGLEN);
|
||||
l_strncpy(hd->version, TVERSION, TVERSLEN);
|
||||
|
||||
/*
|
||||
* set the remaining fields. Some versions want all 16 bits of mode
|
||||
@ -1099,8 +1123,8 @@ ustar_wr(arcn)
|
||||
ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3) ||
|
||||
ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3))
|
||||
goto out;
|
||||
zf_strncpy(hd->uname,name_uid(arcn->sb.st_uid, 0),sizeof(hd->uname));
|
||||
zf_strncpy(hd->gname,name_gid(arcn->sb.st_gid, 0),sizeof(hd->gname));
|
||||
l_strncpy(hd->uname,name_uid(arcn->sb.st_uid, 0),sizeof(hd->uname));
|
||||
l_strncpy(hd->gname,name_gid(arcn->sb.st_gid, 0),sizeof(hd->gname));
|
||||
|
||||
/*
|
||||
* calculate and store the checksum write the header to the archive
|
||||
@ -1154,7 +1178,7 @@ name_split(name, len)
|
||||
* check to see if the file name is small enough to fit in the name
|
||||
* field. if so just return a pointer to the name.
|
||||
*/
|
||||
if (len <= TNMSZ)
|
||||
if (len < TNMSZ)
|
||||
return(name);
|
||||
if (len > (TPFSZ + TNMSZ))
|
||||
return(NULL);
|
||||
|
@ -189,6 +189,7 @@ paxwarn(set, fmt, va_alist)
|
||||
* line by itself
|
||||
*/
|
||||
if (vflag && vfpart) {
|
||||
(void)fflush(listf);
|
||||
(void)fputc('\n', stderr);
|
||||
vfpart = 0;
|
||||
}
|
||||
@ -229,6 +230,7 @@ syswarn(set, errnum, fmt, va_alist)
|
||||
* line by itself
|
||||
*/
|
||||
if (vflag && vfpart) {
|
||||
(void)fflush(listf);
|
||||
(void)fputc('\n', stderr);
|
||||
vfpart = 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user