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:
Kris Kennaway 2001-05-08 06:19:06 +00:00
parent 84b00588d8
commit b1787dec81
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=76351
21 changed files with 1562 additions and 209 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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