commit a9c833353fb9c4350636b7476269e5dcb437c147
parent 7b91f7051126bfa3648b2b6a2ba3c251f75686b4
Author: sin <sin@2f30.org>
Date: Wed, 21 May 2014 12:25:50 +0100
Remove tar
Diffstat:
D | tar/NOTES | | | 61 | ------------------------------------------------------------- |
D | tar/mkfile | | | 9 | --------- |
D | tar/tar.1 | | | 481 | ------------------------------------------------------------------------------- |
D | tar/tar.c | | | 3216 | ------------------------------------------------------------------------------- |
D | tar/tar.dfl | | | 9 | --------- |
5 files changed, 0 insertions(+), 3776 deletions(-)
diff --git a/tar/NOTES b/tar/NOTES
@@ -1,61 +0,0 @@
-Notes for the tar utility
-=========================
-
-- tar is able to extract many GNU tar format archives; notably, large file
- sizes, user and group ids, and long file and link names are supported.
- Multivolume archives, sparse files, and incremental backups are not
- supported. Thus for extraction for GNU tar archives, this tar behaves
- identically to our cpio (and can extract GNU tar format archives written
- by cpio).
-
- tar is also able to update GNU tar format archives so that GNU tar can
- read them, but it does not use any of the GNU extensions then; thus file
- names are limited to 99 characters. It currently does not allow the
- creation of new GNU tar format archives; use cpio if you want to do
- that.
-
-- The multivolume format is identically to that in cpio (both our and SVr4
- derived implementations) and incompatible to that in System V tar. Besides
- the obvious advantage of interoperability, the format can be easily read
- with standard Unix tools if no special support in tar or cpio is available
- on foreign platforms (see the manual page). A disadvantage is that no
- volume numbers are stored on the media, the user has to ensure the
- correct order of parts himself.
-
-- Although the archives written by tar are intended to be compatible with
- the tar format given in IEEE Std. 1003.1, 1996 (POSIX.1), extraction of
- archives is not compliant with this standard since we use the numerical
- uid and gid fields instead of the symbolic uname and gname fields when
- restoring ownership of files. This is done because use of the symbolic
- fields can easily lead to conflicts if the numerical user id of a user
- that has no local name stored in the archive is identical to the local
- numeric user id of a user whose symbolic name is mapped to a different
- uid than that stored in the archive, e. g.
-
- name on tape uid on tape local name local uid result
- foo 100 foo 101 101
- bar 101 (none) (none) 101
-
- Use of the numeric fields avoids such clashes, at least if extraction
- takes place in an empty directory, and allows mapping of user ids using
- the 'find' and 'chown' utilities after extraction.
-
- In the wording of the standard, this is not 'a privileged, protection-
- preserving version of the utility' (10.1.1, p. 235, l. 202-203).
-
-- Extraction does not conform to the tar(XCU) specification (LEGACY) in
- The Single UNIX Specification, Version 2, The Open Group 1997, since
- the 'x' key described there demands extraction with the same modes as
- on the tape if the files are newly created, which is not done by this
- implementation (as well as by any traditional Unix implementation
- known to me) unless the 'p' key is also given. The modes of existing
- files are also not preserved since such files are always removed before
- extraction of the corresponding archived file by this implementation.
-
- This conflict between standard and implementations actually existed
- already with the System V Interface Definition, Third and Fourth
- Editions, tar(AU_CMD), which demand the same behavior as SUSv2; it
- seems that no System V implementation has ever fulfilled USL's own
- specification for tar.
-
- Gunnar Ritter 9/22/03
diff --git a/tar/mkfile b/tar/mkfile
@@ -1,9 +0,0 @@
-BIN = tar
-OBJ = tar.o
-LOCAL_CFLAGS = -DTARDFL=\"$DFLDIR/tar\" -DSHELL=\"$SHELL\" -DSV3BIN=\"$BINDIR\" -DDEFBIN=\"$BINDIR\"
-INSTALL_BIN = tar
-INSTALL_MAN1 = tar.1
-INSTALL_DFL = tar.dfl
-DEPS = libcommon
-
-<$mkbuild/mk.default
diff --git a/tar/tar.1 b/tar/tar.1
@@ -1,481 +0,0 @@
-.\"
-.\" Derived from tar(1), Unix 32V:
-.\" Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" Redistributions of source code and documentation must retain the
-.\" above copyright notice, this list of conditions and the following
-.\" disclaimer.
-.\" 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.
-.\" All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed or owned by Caldera
-.\" International, Inc.
-.\" Neither the name of Caldera International, Inc. nor the names of
-.\" other contributors may be used to endorse or promote products
-.\" derived from this software without specific prior written permission.
-.\"
-.\" USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
-.\" INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. 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.
-.\"
-.\" Sccsid @(#)tar.1 1.46 (gritter) 3/1/05
-.TH TAR 1 "3/1/05" "Heirloom Toolchest" "User Commands"
-.SH NAME
-tar \- tape archiver
-.SH SYNOPSIS
-\fBtar\fR [\ \fIkey\fR\ ] [\ \fIfiles\fR\ ]
-.SH DESCRIPTION
-.I Tar
-saves and restores files
-on magtape or other media.
-Its actions are controlled by the
-.I key
-argument.
-The
-.I key
-is a string of characters containing
-at most one function letter and possibly
-one or more function modifiers.
-Other arguments to the command are file or directory
-names specifying which files are to be dumped or restored.
-In all cases, appearance of a directory name refers to
-the files and (recursively) subdirectories of that directory.
-.PP
-The function portion of
-the key is specified by one of the following letters;
-use of the leading hyphen is optional:
-.TP 8
-.B \-r
-The named files
-are written
-on the end of the tape.
-The
-.B \-c
-function implies this.
-.TP 8
-.B \-x
-The named files are extracted from the tape.
-If the named file matches a directory whose contents
-had been written onto the tape, this directory is (recursively) extracted.
-The owner and mode are restored (if possible).
-If no file argument is given, the entire content of the
-tape is extracted.
-Note that if multiple entries specifying the same file
-are on the tape, the last one overwrites
-all earlier.
-Existing target files are removed
-before the file in the archive is extracted.
-.TP 8
-.B \-t
-The names of the specified files are listed each time they occur
-on the tape.
-If no file argument is given,
-all of the names on the tape are listed.
-.TP 8
-.B \-u
-The named files are added to the tape if either they
-are not already there or have
-been modified since last put on the tape.
-.TP 8
-.B \-c
-Create a new tape; writing begins on the beginning
-of the tape instead of after the last file.
-This command implies
-.B \-r.
-.PP
-The following characters may be used in addition to the letter
-which selects the function desired.
-.TP 10
-.BI 0 \&...\& 9
-This
-modifier selects the drive on which the tape (or other media) is mounted.
-Each number selects an `archive\fIN\fR=' entry in
-.IR /etc/default/tar ,
-which is followed by up to four fields:
-device name,
-blocking factor,
-size in kilobytes,
-and tape flag (`n' or `N' for no tape).
-The entry `archive=' is the default
-if neither this modifier nor the
-.B f
-key is given
-and the
-.I TAPE
-environment variable is not present.
-The following example sets up a tape,
-a 1.44 MB floppy drive
-for use with `0', using a blocking factor of 18,
-and a 1.2 MB floppy drive for use with `1',
-using a blocking factor of 15:
-.sp
- archive=/dev/rmt/c0s0 20 0
-.br
- archive0=/dev/dsk/f03ht 18 1440 N
-.br
- archive1=/dev/dsk/f15ht 15 1200 N
-.TP 10
-.B v
-Normally
-.I tar
-does its work silently.
-The
-.B v
-(verbose)
-option causes it to type the name of each file it treats
-preceded by the function letter.
-With the
-.B t
-function,
-.B v
-gives more information about the
-tape entries than just the name.
-.TP 10
-.B w
-causes
-.I tar
-to print the action to be taken followed by file name, then
-wait for user confirmation. If a word beginning with `y'
-is given, the action is performed. Any other input means
-don't do it.
-.TP 10
-.B f
-causes
-.I tar
-to use the next argument as the name of the archive instead
-of the default (see the description for the `0\&...\&9' key above).
-If the name of the file is `\-', tar writes to
-standard output or reads from standard input, whichever is
-appropriate. Thus,
-.I tar
-can be used as the head or tail of a filter chain.
-.I Tar
-can also be used to move hierarchies with the command
-.sp
- cd fromdir; tar cf \- . | (cd todir; tar xfp \-)
-.TP 10
-.B b
-causes
-.I tar
-to use the next argument as the blocking factor for tape
-records. The default is device dependent.
-This option should only be used with raw magnetic tape archives (See
-.B f
-above).
-.TP 10
-.B l
-tells
-.I tar
-to complain if it cannot resolve all of the links
-to the files dumped. If this is not specified, no
-error messages are printed.
-.TP 10
-.B o
-causes
-.I tar
-to set the owner and group of restored files
-to those of the invoking user
-instead of those specified in the archive.
-This is the default
-unless the caller is the super-user.
-.TP 10
-.B p
-causes
-.I tar
-to set the permission bits of extracted files
-exactly to those given in the archive;
-normally, the current
-.I umask
-is applied.
-.TP 10
-.B i
-tells
-.I tar
-not to exit when a directory checksum error is encountered.
-.TP 10
-.B e
-tells
-.I tar
-to exit at several minor error conditions
-that normally cause only a warning.
-.TP 10
-.B n
-tells
-.I tar
-that the input file is not a tape.
-This causes block sizes to be
-reported in kilobytes instead of tape blocks with the `v' modifier.
-.TP 10
-.B m
-causes
-.I tar
-not to restore modification times on extracted files;
-the modification time is the time when the file was restored.
-.TP 10
-.B h
-causes
-.I tar
-to store the target of a symbolic link in the archive
-and to follow symbolic links to directories
-instead of storing the link itself.
-.TP 10
-.B L
-Same as
-.BR h .
-.TP 10
-.B A
-causes
-.I tar
-to strip a leading `/' when storing and restoring pathnames,
-i.\|e. to store and extract relative names instead of absolute ones.
-.TP 10
-.B k
-can be used to create and extract multi-volume archives.
-The next unevaluated argument is used as the maximum size in kilobytes
-for each part.
-If the archive does not fit on one medium,
-the user is prompted for the next.
-The same sizes must be given for creation and extraction
-of multi-volume archives.
-.TP 10
-.B B
-causes
-.I tar
-to repeat a
-.IR read (2)
-operation if it gets fewer data than expected.
-This is useful when reading from pipes, network transports etc.,
-and is enabled per default if reading from standard input,
-pipes, or sockets.
-.TP 10
-.B F
-specifies the name of a file with additional pathnames
-in the next unevaluated argument.
-Each line of this file must contain a pathname
-(without any leading or trailing white-space)
-that is put into the archive
-before further files specified on the command line.
-.TP 10
-.B X
-specifies the name of a file
-that contains pathnames to be excluded,
-in the same format as with
-.BR F .
-This option may be specified multiple times,
-causing pathnames contained in any of the files
-to be excluded.
-.PP
-.I Tar
-also accepts the following options
-intermixed with the file
-.IR names :
-.TP 10
-\fB\-C\fI dir\fR
-Change the working directory to
-.I dir
-before archiving the file
-.I name
-immediately following
-.IR dir ;
-.I name
-is interpreted relative to
-.IR dir .
-.TP 10
-\fB\-I\fI file\fR
-Specifies a file with additional pathnames
-as described for the
-.B F
-key above,
-inserted at the current position in the archive.
-.PP
-The archive format written by
-.I tar
-is expected to be compatible
-with the `Extended tar Format' as defined in
-IEEE Std. 1003.1, 1996,
-although the numerical
-.I uid
-and
-.I gid
-fields are always used for extraction,
-ignoring the symbolic
-.I uname
-and
-.I gname
-fields.
-.PP
-IEEE Std. 1003.1, 2001
-.I pax
-format extended headers are created by
-.I tar
-under the following circumstances:
-A path name exceeds 255 bytes
-or does not contain a slash character at an appropriate position,
-and does not contain non-UTF-8 characters;
-the name of a linked file exceeds 100 bytes;
-a file is larger than 8\ GB;
-a user or group ID exceeds the number 2097151.
-When updating GNU or old format archives,
-no extended headers are created
-and any path names are limited to 100 bytes.
-Most GNU extensions are supported when reading archives,
-and Sun extensions also for appending.
-.PP
-Multi-volume archives are splitted single-volume archives.
-For an archive created with
-.sp
- tar cfk /dev/dsk/f03ht 1440 \fIinput\fR
-.sp
-it is thus possible to generate a single-volume archive by executing
-.sp
- dd if=/dev/dsk/f03ht bs=1k count=1440 >>singlevolume
-.sp
-once for each floppy disk.
-.PP
-On archives compressed with
-.IR bzip2 (1),
-.IR compress (1),
-.IR gzip (1),
-or
-.IR xz (1),
-the appropriate decompression program is run automatically
-with the
-.I t
-and
-.I x
-keys.
-.PP
-The following keys are supported as extensions:
-.TP 10
-.B z
-causes
-.I tar
-to pipe its output through
-.IR gzip (1)
-when creating archives.
-When reading archives,
-this option is ignored.
-.TP 10
-.B j
-Similar to
-.IR z ,
-but using
-.IR bzip2 (1)
-as compression program.
-.TP 10
-.B J
-Similar to
-.IR z ,
-but using
-.IR xz (1)
-as compression program.
-.TP 10
-.B Z
-Similar to
-.IR z ,
-but using
-.IR compress (1)
-as compression program.
-.SH EXAMPLES
-List the contents of a software distribution archive:
-.in +2
-.sp
-tar tvf distribution.tar.gz
-.in -2
-.PP
-Extract a software distribution archive,
-preserving file permissions,
-but setting the owner of all extracted files
-to the invoking user
-(even if invoked by
-.IR root ):
-.in +2
-.sp
-tar xfop distribution.tar.gz
-.in -2
-.PP
-Write the current directory to the default archive location:
-.in +2
-.sp
-tar c .
-.sp
-.in -2
-If the default location is a floppy drive,
-the archive is split across multiple volumes if necessary.
-.PP
-Create a
-.IR gzip (1)
-compressed archive of the directory
-.I project
-and its contents:
-.in +2
-.sp
-tar cf \- project | gzip \-c > project.tar.gz
-.in -2
-.SH "ENVIRONMENT VARIABLES"
-.TP 10
-.BR LANG ", " LC_ALL
-See
-.IR locale (7).
-.TP 10
-.B LC_TIME
-Used for the time string printed with when the keys
-.B tv
-are given.
-.TP 10
-.B SYSV3
-If set,
-old tar format archives are created with `c',
-and the meaning of the `e' key is changed
-such that archiving is aborted
-if a file cannot fit on a single volume
-of a multi-volume archive.
-.TP 10
-.B TAPE
-Used as default archive
-if neither the `f' nor the `0\&...\&9' keys are present.
-.SH FILES
-/etc/default/tar
-.br
-/tmp/tar*
-.SH "SEE ALSO"
-cpio(1),
-ls(1),
-pax(1),
-umask(2)
-.SH DIAGNOSTICS
-Complaints about bad key characters and tape read/write errors.
-.PP
-Complaints if enough memory is not available to hold
-the link tables.
-.SH NOTES
-There is no way to ask for the
-.IR n -th
-occurrence of a file.
-.PP
-Tape errors are handled ungracefully.
-.PP
-The
-.B u
-option can be slow.
-.PP
-Use of the
-.B r
-and
-.B u
-options with tape devices requires
-drives capable of writing between filemarks.
diff --git a/tar/tar.c b/tar/tar.c
@@ -1,3216 +0,0 @@
-/*
- * Changes by Gunnar Ritter, Freiburg i. Br., Germany, March 2003.
- */
-/* from Unix 32V /usr/src/cmd/tar.c */
-/*
- * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * Redistributions of source code and documentation must retain the
- * above copyright notice, this list of conditions and the following
- * disclaimer.
- * 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.
- * All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed or owned by Caldera
- * International, Inc.
- * Neither the name of Caldera International, Inc. nor the names of
- * other contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
- * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE
- * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if __GNUC__ >= 3 && __GNUC_MINOR__ >= 4 || __GNUC__ >= 4
-#define USED __attribute__ ((used))
-#elif defined __GNUC__
-#define USED __attribute__ ((unused))
-#else
-#define USED
-#endif
-static const char sccsid[] USED = "@(#)tar.sl 1.180 (gritter) 10/9/10";
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifdef __linux__
-#include <linux/fd.h>
-#if !defined (__UCLIBC__) && !defined (__dietlibc__)
-#include <linux/fs.h>
-#endif /* !__UCLIBC__, !__dietlibc__ */
-#undef WNOHANG
-#undef WUNTRACED
-#undef P_ALL
-#undef P_PID
-#undef P_PGID
-#ifdef __dietlibc__
-#undef NR_OPEN
-#undef PATH_MAX
-#endif /* __dietlibc__ */
-#endif /* __linux__ */
-#include <sys/wait.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <time.h>
-#include <utime.h>
-#include <stdio.h>
-#include <dirent.h>
-#include <signal.h>
-#include "sigset.h"
-#include <string.h>
-#include <stdlib.h>
-#include <malloc.h>
-#include <libgen.h>
-#include <errno.h>
-#include <pwd.h>
-#include <grp.h>
-#include <inttypes.h>
-#include <iblok.h>
-#include <locale.h>
-#include <alloca.h>
-
-#include <sys/ioctl.h>
-
-#if defined (__linux__) || defined (__sun) || defined (__FreeBSD__) || \
- defined (__hpux) || defined (_AIX) || defined (__NetBSD__) || \
- defined (__OpenBSD__) || defined (__DragonFly__) || defined (__APPLE__)
-#ifndef __G__
-#include <sys/mtio.h>
-#endif
-#else /* SVR4.2MP */
-#include <sys/scsi.h>
-#include <sys/st01.h>
-#endif /* SVR4.2MP */
-
-#ifdef _AIX
-#include <sys/sysmacros.h>
-#endif
-
-#if !defined (major) && !defined (__G__)
-#include <sys/mkdev.h>
-#endif /* !major */
-
-#include <getdir.h>
-#include <asciitype.h>
-#include <atoll.h>
-#include <memalign.h>
-
-#ifdef __GLIBC__
-#ifdef _IO_getc_unlocked
-#undef getc
-#define getc(f) _IO_getc_unlocked(f)
-#endif
-#ifdef _IO_putc_unlocked
-#undef putc
-#define putc(c, f) _IO_putc_unlocked(c, f)
-#endif
-#endif
-
-#if defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || \
- defined (__DragonFly__) || defined (__APPLE__)
-/*
- * For whatever reason, FreeBSD casts the return values of major() and
- * minor() to signed values so that normal limit comparisons will fail.
- */
-static unsigned long
-mymajor(long dev)
-{
- return major(dev) & 0xFFFFFFFFUL;
-}
-#undef major
-#define major(a) mymajor(a)
-static unsigned long
-myminor(long dev)
-{
- return minor(dev) & 0xFFFFFFFFUL;
-}
-#undef minor
-#define minor(a) myminor(a)
-#endif /* __FreeBSD__, __NetBSD__, __OpenBSD__, __DragonFly__, __APPLE__ */
-
-#define TBLOCK 512
-#define MAXBLF (SSIZE_MAX/TBLOCK)
-static int NBLOCK = 20;
-#define NAMSIZ 100
-#define PFXSIZ 155
-#define MAGSIZ 6
-#define TIMSIZ 12
-static union hblock {
- char dummy[TBLOCK];
- struct header {
- char name[NAMSIZ];
- char mode[8];
- char uid[8];
- char gid[8];
- char size[12];
- char mtime[TIMSIZ];
- char chksum[8];
- char linkflag;
- char linkname[NAMSIZ];
- char magic[MAGSIZ];
- char version[2];
- char uname[32];
- char gname[32];
- char devmajor[8];
- char devminor[8];
- char prefix[PFXSIZ];
- } dbuf;
-} dblock, *tbuf;
-
-static struct internal_header {
- char *name;
- long namesize;
- char *rname;
- char *linkname;
- char *rlinkname;
- long linksize;
-} hbuf;
-
-static struct islot {
- struct islot *left; /* left link */
- struct islot *right; /* right link */
- struct islot *nextp; /* ordered list link */
- ino_t inum; /* inode number */
- int count; /* count of links found */
- char *pathname;/* name of first link encountered */
-} *ihead; /* ordered list for report with 'l' */
-static struct islot *inull; /* splay tree null element */
-
-struct dslot {
- struct dslot *nextp; /* next device */
- struct islot *itree; /* inode slots */
- dev_t devnum; /* real device id */
-};
-static struct dslot *devices;/* devices list */
-
-static enum paxrec {
- PR_NONE = 0000,
- PR_ATIME = 0001,
- PR_GID = 0002,
- PR_LINKPATH = 0004,
- PR_MTIME = 0010,
- PR_PATH = 0020,
- PR_SIZE = 0040,
- PR_UID = 0100,
- PR_SUN_DEVMAJOR = 0200,
- PR_SUN_DEVMINOR = 0400
-} paxrec, globrec;
-
-static struct stat globst;
-
-static int rflag, xflag, vflag, tflag, mt, cflag, mflag, nflag, kflag;
-static int oflag, hflag, pflag, iflag, eflag, Aflag, Bflag, Eflag;
-enum {
- B_UNSPEC = 0,
- B_AUTO = 1,
- B_DEFN = 2,
- B_USER = 3
-} bflag;
-static int gnuflag = -1;
-static int oldflag = -1;
-static long long volsize;
-static char *Fflag, *Xflag;
-static int term, chksum, wflag, recno, first, linkerrok;
-static int freemem = 1;
-static int nblock = 1;
-static struct stat mtstat;
-static int tapeblock = -1;
-static int writerror;
-
-static int workdir;
-
-static off_t low;
-static off_t high;
-
-static FILE *tfile;
-
-static const char *usefile;
-
-struct magtape {
- const char *device;
- long block;
- long long size;
- int nflag;
-};
-
-static struct magtape magtapes[] = {
- { NULL, 1, 0, 0 },
- { NULL, 1, 0, 0 },
- { NULL, 1, 0, 0 },
- { NULL, 1, 0, 0 },
- { NULL, 1, 0, 0 },
- { NULL, 1, 0, 0 },
- { NULL, 1, 0, 0 },
- { NULL, 1, 0, 0 },
- { NULL, 1, 0, 0 },
- { NULL, 1, 0, 0 },
- { NULL, 1, 0, 0 },
- { NULL, 0, 0, 0 }
-};
-
-static int hadtape;
-
-static int maybezip;
-
-static enum {
- POSTORDER = 0,
- PREORDER = 1
-} order;
-
-static char *progname;
-extern int sysv3;
-
-static dev_t *vis_dev;
-static ino_t *vis_ino;
-static int vis_max;
-
-static long files;
-static long gotcha;
-
-static int midfile;
-
-static uid_t myuid;
-static gid_t mygid;
-
-static long long rdtotal;
-static long long wrtotal;
-
-static int N = 300;
-
-static void usage(void);
-static void ckusefile(void);
-static void cktxru(int);
-static void dorep(char *[]);
-static void doarg(char *);
-static int endtape(int);
-static void tgetdir(struct stat *);
-static void tgetnam(void);
-static void tgetgnu(char **, long *);
-static void tgetpax(struct stat *, long long *, long long *);
-static enum paxrec tgetrec(char **, char **, char **);
-static long long tgetval(const char *, int);
-static void passtape(struct stat *);
-static void putfile(const char *, const char *, int, int);
-static void putreg(const char *, const char *, int, struct stat *);
-static int putsym(const char *, const char *, char **, size_t);
-static void wrhdr(const char *, const char *, struct stat *);
-static void wrpax(const char *, const char *, struct stat *);
-static void addrec(char **, long *, long *,
- const char *, const char *, long long);
-static void paxnam(struct header *, const char *);
-static void doxtract(char *[]);
-static int xtrreg(const char *, struct stat *);
-static int xtrlink(const char *, struct stat *, int);
-static int xtrdev(const char *, struct stat *, mode_t);
-static int xtrdir(const char *, struct stat *);
-static void dotable(char *[]);
-static void putempty(void);
-static void longt(register struct stat *, int);
-static void pmode(register struct stat *, int);
-static void tselect(int *, struct stat *);
-static int checkdir(register char *, struct stat *);
-static void onsig(int);
-static void tomodes(const char *, register struct stat *);
-static int checksum(int);
-static int checkw(int, const char *, struct stat *, int);
-static int response(void);
-static int checkupdate(const char *, struct stat *);
-static void done(int);
-static int prefix(register const char *, register const char *);
-static off_t lookup(const char *);
-static off_t bsrch(const char *, int, off_t, off_t);
-static int cmp(const char *, const char *, size_t);
-static int readtape(char *);
-static int writetape(const char *);
-static void backtape(int);
-static void flushtape(void);
-static void *srealloc(void *, size_t);
-static void *smalloc(size_t);
-static void *scalloc(size_t, size_t);
-static void *bfalloc(size_t);
-static char *nameof(struct header *, char *);
-static int mkname(struct header *, const char *);
-static char *linkof(struct header *, char *);
-static int mklink(struct header *, const char *, const char *);
-static void blocksof(const char *, struct stat *, long long *, long long *);
-static void tchown(int (*)(const char *, uid_t, gid_t),
- const char *, uid_t, gid_t);
-static void edone(int);
-static ssize_t mtread(void *, size_t);
-static ssize_t mtwrite(const void *, size_t);
-static void newvolume(void);
-static void goback(int);
-static void getpath(const char *, char **, char **, size_t *, size_t *);
-static void setpath(const char *, char **, char **,
- size_t, size_t *, size_t *);
-static void defaults(void);
-static void settape(int);
-static void suprmsg(void);
-static void odirect(void);
-static void domtstat(void);
-static int checkzip(const char *, int);
-static int redirect(const char *, const char *, int);
-static const char *getuser(uid_t);
-static const char *getgroup(gid_t);
-static char *sstrdup(const char *);
-static void fromfile(const char *);
-static void readexcl(const char *);
-static void creatfile(void);
-static mode_t cmask(struct stat *, int);
-static struct islot *isplay(ino_t, struct islot *);
-static struct islot *ifind(ino_t, struct islot **);
-static void iput(struct islot *, struct islot **);
-static struct dslot *dfind(struct dslot **, dev_t);
-static char *sequence(void);
-static void docomp(const char *);
-static int jflag, Jflag, zflag, Zflag;
-static int utf8(const char *);
-static void settmp(char *, size_t, const char *);
-
-int
-main(int argc, char *argv[])
-{
- char *cp;
-
- progname = basename(argv[0]);
- setlocale(LC_TIME, "");
- if (getenv("SYSV3") != NULL)
- sysv3 = 2;
- if (argc < 2)
- usage();
-
- if ((myuid = getuid()) != 0)
- oflag = 1;
- mygid = getgid();
- tfile = NULL;
- inull = scalloc(1, sizeof *inull);
- inull->left = inull->right = inull;
- defaults();
- argv[argc] = 0;
- argv++;
- for (cp = *argv++; *cp; cp++)
- switch(*cp) {
- case 'f':
- usefile = *argv++;
- hadtape++;
- break;
- case 'c':
- if (sysv3 > 1 && Eflag == 0)
- oldflag = 1;
- cflag++;
- rflag++;
- cktxru('r');
- break;
- case 'X':
- Xflag = *argv++;
- if (Xflag == NULL) {
- fprintf(stderr, "%s: exclude file must be "
- "specified with 'X' option\n",
- progname);
- done(1);
- }
- creatfile();
- readexcl(Xflag);
- break;
- case 'u':
- creatfile();
- /*FALLTHRU*/
- case 'r':
- cktxru(*cp);
- rflag++;
- break;
- case 'v':
- vflag++;
- break;
- case 'w':
- wflag++;
- break;
- case 'x':
- cktxru(*cp);
- xflag++;
- break;
- case 't':
- cktxru(*cp);
- tflag++;
- break;
- case 'm':
- mflag++;
- break;
- case '-':
- break;
- case '0':
- case '1': case '2': case '3':
- case '4': case '5': case '6':
- case '7': case '8': case '9':
- settape(*cp);
- hadtape++;
- break;
- case 'b':
- bflag = B_USER;
- if (*argv == NULL)
- goto invblk;
- nblock = atoi(*argv++);
- if (nblock <= 0 || (long)nblock > MAXBLF) {
- invblk: fprintf(stderr,
- "%s: invalid blocksize. (Max %ld)\n",
- progname, (long)MAXBLF);
- done(1);
- }
- break;
- case 'l':
- linkerrok++;
- break;
- case 'o':
- oflag++;
- break;
- case 'h': case 'L':
- hflag++;
- break;
- case 'p':
- pflag++;
- break;
- case 'i':
- iflag++;
- break;
- case 'e':
- eflag++;
- break;
- case 'A':
- Aflag++;
- break;
- case 'E':
- Eflag++;
- oldflag = -1;
- break;
- case 'F':
- Fflag = *argv++;
- if (Fflag == NULL) {
- fprintf(stderr,
- "%s: F requires a file name.\n",
- progname);
- done(1);
- }
- break;
- case 'k':
- if (*argv == NULL || (volsize = atoll(*argv)) < 250) {
- fprintf(stderr, "%s: sizes below %dk "
- "not supported\n", progname,
- 250);
- done(1);
- }
- volsize *= 1024;
- kflag = 1;
- argv++;
- /*FALLTHRU*/
- case 'n':
- nflag = 2;
- break;
- case 'B':
- Bflag = 1;
- break;
- case 'z':
- zflag = 1;
- jflag = 0;
- Jflag = 0;
- Zflag = 0;
- break;
- case 'j':
- jflag = 1;
- Jflag = 0;
- zflag = 0;
- Zflag = 0;
- break;
- case 'J':
- Jflag = 1;
- jflag = 0;
- zflag = 0;
- Zflag = 0;
- break;
- case 'Z':
- Zflag = 1;
- jflag = 0;
- Jflag = 0;
- zflag = 0;
- break;
- default:
- fprintf(stderr, "%s: %c: unknown option\n",
- progname, *cp & 0377);
- usage();
- }
-
- if (hadtape == 0) {
- if ((cp = getenv("TAPE")) != NULL)
- usefile = sstrdup(cp);
- else
- settape(0);
- }
- /*if (Fflag && Xflag) {
- fprintf(stderr, "%s: specify only one of X or F.\n", progname);
- usage();
- } our implementation doesn't need to enforce this */
- if ((rflag || volsize) && (workdir = open(".", O_RDONLY)) < 0) {
- fprintf(stderr, "%s: cannot open working directory\n",
- progname);
- done(1);
- }
- fcntl(workdir, F_SETFD, FD_CLOEXEC);
- for (files = 0; argv[files]; files++);
- if (rflag) {
- if (cflag && tfile != NULL && Xflag == 0) {
- usage();
- done(1);
- }
- if (argv[0] == NULL && Fflag == NULL) {
- fprintf(stderr, "%s: Missing filenames\n",
- progname);
- done(1);
- }
- if (cflag == 0 && (jflag || Jflag || zflag || Zflag)) {
- fprintf(stderr, "%s: can only create "
- "compressed archives\n",
- progname);
- done(1);
- }
- ckusefile();
- if (strcmp(usefile, "-") == 0) {
- if (cflag == 0) {
- fprintf(stderr, "%s: can only create "
- "standard output archives\n",
- progname);
- done(1);
- }
- mt = dup(1);
- }
- else if ((mt = open(usefile, O_RDWR)) < 0) {
- if (cflag == 0 || (mt = creat(usefile, 0666)) < 0) {
- fprintf(stderr, "%s: cannot open %s.\n",
- progname, usefile);
- done(1);
- }
- }
- domtstat();
- if (jflag || Jflag || zflag || Zflag)
- docomp(Jflag ? "xz" : jflag ? "bzip2" : Zflag ? "compress" : "gzip");
- dorep(argv);
- }
- else if (xflag) {
- ckusefile();
- if (strcmp(usefile, "-") == 0) {
- mt = dup(0);
- Bflag = 1;
- } else if ((mt = open(usefile, O_RDONLY)) < 0) {
- fprintf(stderr, "%s: cannot open %s.\n",
- progname, usefile);
- done(1);
- }
- maybezip = 1;
- domtstat();
- doxtract(argv);
- }
- else if (tflag) {
- ckusefile();
- if (strcmp(usefile, "-") == 0) {
- mt = dup(0);
- Bflag = 1;
- } else if ((mt = open(usefile, O_RDONLY)) < 0) {
- fprintf(stderr, "%s: cannot open %s.\n",
- progname, usefile);
- done(1);
- }
- maybezip = 1;
- domtstat();
- dotable(argv);
- }
- else
- usage();
- done(0);
- /*NOTREACHED*/
- return 0;
-}
-
-static void
-usage(void)
-{
- fprintf(stderr, "Usage: %s -{txruc}[0-9vfbk[FX]hLiBelmnopwA] "
- "[tapefile] [blocksize] [tapesize] [argfile] "
- "[exclude-file] [-I include-file] files ...\n",
- progname);
- done(1);
-}
-
-static void
-ckusefile(void)
-{
- if (usefile == NULL) {
- fprintf(stderr, "%s: device argument required\n", progname);
- done(1);
- }
-}
-
-static void
-cktxru(int c)
-{
- static int txruflag;
-
- if (c == 't' || c == 'x' || c == 'r' || c == 'u') {
- if (txruflag) {
- fprintf(stderr, "%s: specify only one of [txru].\n",
- progname);
- usage();
- }
- txruflag = c;
- }
-}
-
-static void
-dorep(char *argv[])
-{
- struct stat stbuf;
-
- if (!cflag || Xflag) {
- if (!cflag) {
- tgetdir(&stbuf);
- do {
- passtape(&stbuf);
- tgetdir(&stbuf);
- } while (!endtape(1));
- }
- if (tfile != NULL) {
- char tname[PATH_MAX+1];
- int tfd;
- pid_t pid;
- fflush(tfile);
- rewind(tfile);
- settmp(tname, sizeof tname, "%s/tarXXXXXX");
- if ((tfd = mkstemp(tname)) < 0) {
- fprintf(stderr, "%s: cannot create temporary "
- "file (%s)\n", progname, tname);
- done(1);
- }
- unlink(tname);
- fcntl(tfd, F_SETFD, FD_CLOEXEC);
- switch (pid = fork()) {
- case -1:
- fprintf(stderr, "%s: cannot fork\n", progname);
- done(1);
- /*NOTREACHED*/
- case 0:
- dup2(fileno(tfile), 0);
- dup2(tfd, 1);
- execl(SHELL, "sh", "-c",
- "PATH=" SV3BIN ":" DEFBIN ":$PATH; "
- "LC_ALL=C export LC_ALL; "
- /*
- * +2 sorts by file name first, for
- * binary search.
- * +0 sorts by key (X overrides u).
- * +1nr sorts by modtime (newer files
- * first).
- */
- "sort +2 +0 -1 +1nr -2 | uniq -2",
- NULL);
- fprintf(stderr, "%s: cannot execute %s\n",
- progname, SHELL);
- _exit(0177);
- }
- while (waitpid(pid, NULL, 0) != pid);
- fclose(tfile);
- lseek(tfd, 0, SEEK_SET);
- tfile = fdopen(tfd, "r");
- fstat(fileno(tfile), &stbuf);
- high = stbuf.st_size;
- }
- }
-
- suprmsg();
- if (sigset(SIGHUP, SIG_IGN) != SIG_IGN)
- sigset(SIGINT, onsig);
- if (sigset(SIGHUP, SIG_IGN) != SIG_IGN)
- sigset(SIGHUP, onsig);
- if (sigset(SIGQUIT, SIG_IGN) != SIG_IGN)
- sigset(SIGQUIT, onsig);
-/*
- if (sigset(SIGTERM, SIG_IGN) != SIG_IGN)
- sigset(SIGTERM, onsig);
-*/
- odirect();
- if (Fflag)
- fromfile(Fflag);
- while (*argv && !term) {
- if (argv[0][0] == '-' && argv[0][1] == 'C' &&
- argv[0][2] == '\0' && argv[1]) {
- if (chdir(argv[1]) < 0)
- fprintf(stderr, "%s: can't change directories "
- "to %s: %s\n",
- progname, argv[0],
- strerror(errno));
- argv += 2;
- if (argv[0] == NULL)
- break;
- }
- if (argv[0][0] == '-' && argv[0][1] == 'I' &&
- argv[0][2] == '\0') {
- if (argv[1]) {
- fromfile(argv[1]);
- argv += 2;
- } else {
- fprintf(stderr, "%s: missing file name "
- "for -I flag.\n",
- progname);
- done(1);
- }
- } else {
- doarg(*argv++);
- goback(workdir);
- }
- }
- putempty();
- putempty();
- flushtape();
- if (linkerrok == 1)
- for (; ihead != NULL; ihead = ihead->nextp)
- if (ihead->count != 0)
- fprintf(stderr, "Missing links to %s\n",
- ihead->pathname);
-}
-
-static void
-doarg(char *arg)
-{
- register char *cp, *cp2;
-
- cp2 = arg;
- for (cp = arg; *cp; cp++)
- if (*cp == '/')
- cp2 = cp;
- if (cp2 != arg) {
- *cp2 = '\0';
- chdir(arg);
- *cp2 = '/';
- cp2++;
- }
- putfile(arg, cp2, workdir, 0);
-}
-
-static int
-endtape(int rew)
-{
- if (hbuf.name[0] == '\0') {
- if (rew)
- backtape(rew);
- return(1);
- }
- else
- return(0);
-}
-
-static void
-tgetdir(register struct stat *sp)
-{
- long long lval1, lval2;
-
- readtape( (char *) &dblock);
- if (dblock.dbuf.name[0] && gnuflag < 0)
- if ((gnuflag=memcmp(dblock.dbuf.magic, "ustar \0", 8)==0)!=0)
- Eflag = 0;
- if (dblock.dbuf.name[0] && oldflag < 0)
- if ((oldflag=memcmp(dblock.dbuf.magic, "ustar", 5)!=0)!=0)
- Eflag = 0;
- if (hbuf.name)
- hbuf.name[0] = '\0';
- if (hbuf.linkname)
- hbuf.linkname[0] = '\0';
- paxrec = globrec;
- *sp = globst;
- while (gnuflag==0 && oldflag==0 && (dblock.dbuf.linkflag == 'x' ||
- dblock.dbuf.linkflag == 'g' ||
- dblock.dbuf.linkflag == 'X' /* sun */))
- tgetpax(sp, &lval1, &lval2);
- tgetnam();
- if (hbuf.name[0] == '\0')
- return;
- sp->st_mode = tgetval(dblock.dbuf.mode, sizeof dblock.dbuf.mode)&07777;
- if ((paxrec & PR_UID) == 0)
- sp->st_uid = tgetval(dblock.dbuf.uid, sizeof dblock.dbuf.uid);
- if ((paxrec & PR_GID) == 0)
- sp->st_gid = tgetval(dblock.dbuf.gid, sizeof dblock.dbuf.gid);
- if ((paxrec & PR_SIZE) == 0)
- sp->st_size =
- tgetval(dblock.dbuf.size, sizeof dblock.dbuf.size);
- if ((paxrec & PR_MTIME) == 0)
- sp->st_mtime =
- tgetval(dblock.dbuf.mtime, sizeof dblock.dbuf.mtime);
- sscanf(dblock.dbuf.chksum, "%o", &chksum);
- if (chksum != checksum(0) && chksum != checksum(1)) {
- fprintf(stderr, "%s: directory checksum error\n", progname);
- if (iflag == 0)
- done(2);
- }
- if ((paxrec & PR_SUN_DEVMAJOR) == 0)
- sscanf(dblock.dbuf.devmajor, "%llo", &lval1);
- if ((paxrec & PR_SUN_DEVMINOR) == 0)
- sscanf(dblock.dbuf.devminor, "%llo", &lval2);
- sp->st_rdev = makedev(lval1, lval2);
- if (tfile != NULL) {
- if (strchr(hbuf.name, '\n') == NULL) {
- int s;
- s = 3 * fprintf(tfile, "u %0*lo %s\n", TIMSIZ,
- (long)sp->st_mtime, hbuf.name);
- if (s > N)
- N = s;
- } else
- fprintf(stderr, "%s: warning: file name '%s' in "
- "archive contains a newline character "
- "and will always be added to archive\n",
- progname, hbuf.name);
- }
-}
-
-static void
-tgetnam(void)
-{
-again: if (dblock.dbuf.linkflag == 'L' && (gnuflag>0 ||
- strcmp(dblock.dbuf.name, "././@LongLink") == 0)) {
- tgetgnu(&hbuf.name, &hbuf.namesize);
- goto again;
- }
- if (dblock.dbuf.linkflag == 'K' && (gnuflag>0 ||
- strcmp(dblock.dbuf.name, "././@LongLink") == 0)) {
- tgetgnu(&hbuf.linkname, &hbuf.linksize);
- goto again;
- }
- if ((hbuf.name == NULL || hbuf.namesize < NAMSIZ+PFXSIZ+2) &&
- (paxrec & PR_PATH) == 0) {
- hbuf.namesize = NAMSIZ+PFXSIZ+2;
- hbuf.name = srealloc(hbuf.name, hbuf.namesize);
- hbuf.name[0] = '\0';
- }
- if ((hbuf.linkname == NULL || hbuf.linksize < NAMSIZ+1) &&
- (paxrec & PR_LINKPATH) == 0) {
- hbuf.linksize = NAMSIZ+1;
- hbuf.linkname = srealloc(hbuf.linkname, hbuf.linksize);
- hbuf.linkname[0] = '\0';
- }
- if (hbuf.name[0] == '\0' && (paxrec & PR_PATH) == 0)
- nameof(&dblock.dbuf, hbuf.name);
- if (hbuf.linkname[0] == '\0' && (paxrec & PR_LINKPATH) == 0)
- linkof(&dblock.dbuf, hbuf.linkname);
- hbuf.rname = hbuf.name;
- if (Aflag) {
- while (hbuf.rname[0] == '/')
- hbuf.rname++;
- if (hbuf.name[0] && hbuf.rname[0] == '\0')
- hbuf.rname = ".";
- }
- hbuf.rlinkname = hbuf.linkname;
- if (Aflag) {
- while (hbuf.rlinkname[0] == '/')
- hbuf.rlinkname++;
- if (hbuf.linkname[0] && hbuf.rlinkname[0] == '\0')
- hbuf.rlinkname = ".";
- }
-}
-
-static void
-tgetgnu(char **np, long *sp)
-{
- char buf[TBLOCK];
- long long blocks;
- long n, bytes;
-
- n = tgetval(dblock.dbuf.size, sizeof dblock.dbuf.size);
- if (*sp <= n)
- *np = srealloc(*np, *sp = n+1);
- blocks = n;
- blocks += TBLOCK-1;
- blocks /= TBLOCK;
- bytes = n;
- while (blocks-- > 0) {
- readtape(buf);
- memcpy(&(*np)[n-bytes], buf, bytes>TBLOCK?TBLOCK:bytes);
- bytes -= TBLOCK;
- }
- (*np)[n] = '\0';
- readtape((char *)&dblock);
-}
-
-static void
-tgetpax(struct stat *sp, long long *devmajor, long long *devminor)
-{
- char *keyword, *value;
- char buf[TBLOCK];
- char *block, *bp;
- long long n, blocks, bytes;
- enum paxrec pr;
-
- n = tgetval(dblock.dbuf.size, sizeof dblock.dbuf.size);
- bp = block = smalloc(n+1);
- blocks = n;
- blocks += TBLOCK-1;
- blocks /= TBLOCK;
- bytes = n;
- while (blocks-- > 0) {
- readtape(buf);
- memcpy(&block[n-bytes], buf, bytes>TBLOCK?TBLOCK:bytes);
- bytes -= TBLOCK;
- }
- block[n] = '\0';
- while (bp < &block[n]) {
- int c;
- pr = tgetrec(&bp, &keyword, &value);
- switch (pr) {
- case PR_ATIME:
- sp->st_atime = strtoll(value, NULL, 10);
- break;
- case PR_GID:
- sp->st_gid = strtoll(value, NULL, 10);
- break;
- case PR_LINKPATH:
- c = strlen(value);
- if (hbuf.linkname == NULL || hbuf.linksize < c+1) {
- hbuf.linksize = c+1;
- hbuf.linkname = srealloc(hbuf.linkname, c+1);
- }
- strcpy(hbuf.linkname, value);
- break;
- case PR_MTIME:
- sp->st_mtime = strtoll(value, NULL, 10);
- break;
- case PR_PATH:
- c = strlen(value);
- if (hbuf.name == NULL || hbuf.namesize < c+1) {
- hbuf.namesize = c+1;
- hbuf.name = srealloc(hbuf.name, c+1);
- }
- strcpy(hbuf.name, value);
- break;
- case PR_SIZE:
- sp->st_size = strtoll(value, NULL, 10);
- break;
- case PR_UID:
- sp->st_uid = strtoll(value, NULL, 10);
- break;
- case PR_SUN_DEVMAJOR:
- *devmajor = strtoll(value, NULL, 10);
- break;
- case PR_SUN_DEVMINOR:
- *devminor = strtoll(value, NULL, 10);
- break;
- }
- paxrec |= pr;
- }
- if (dblock.dbuf.linkflag == 'g') {
- globrec = paxrec & ~(PR_LINKPATH|PR_PATH|PR_SIZE);
- globst = *sp;
- } else if (dblock.dbuf.linkflag == 'X')
- Eflag = 1;
- readtape((char *)&dblock);
- free(block);
-}
-
-static enum paxrec
-tgetrec(char **bp, char **keyword, char **value)
-{
- char *x;
- long n = 0;
- enum paxrec pr;
-
- *keyword = "";
- *value = "";
- while (**bp && (n = strtol(*bp, &x, 10)) <= 0 && (*x!=' ' || *x!='\t'))
- do
- (*bp)++;
- while (**bp && **bp != '\n');
- if (*x == '\0' || **bp == '\0') {
- (*bp)++;
- return PR_NONE;
- }
- while (x < &(*bp)[n] && (*x == ' ' || *x == '\t'))
- x++;
- if (x == &(*bp)[n] || *x == '=')
- goto out;
- *keyword = x;
- while (x < &(*bp)[n] && *x != '=')
- x++;
- if (x == &(*bp)[n])
- goto out;
- *x = '\0';
- if (&x[1] < &(*bp)[n])
- *value = &x[1];
- (*bp)[n-1] = '\0';
-out: *bp = &(*bp)[n];
- if (strcmp(*keyword, "atime") == 0)
- pr = PR_ATIME;
- else if (strcmp(*keyword, "gid") == 0)
- pr = PR_GID;
- else if (strcmp(*keyword, "linkpath") == 0)
- pr = PR_LINKPATH;
- else if (strcmp(*keyword, "mtime") == 0)
- pr = PR_MTIME;
- else if (strcmp(*keyword, "path") == 0)
- pr = PR_PATH;
- else if (strcmp(*keyword, "size") == 0)
- pr = PR_SIZE;
- else if (strcmp(*keyword, "uid") == 0)
- pr = PR_UID;
- else if (strcmp(*keyword, "SUN.devmajor") == 0)
- pr = PR_SUN_DEVMAJOR;
- else if (strcmp(*keyword, "SUN.devminor") == 0)
- pr = PR_SUN_DEVMINOR;
- else
- pr = PR_NONE;
- return pr;
-}
-
-static long long
-tgetval(const char *s, int k)
-{
- long long n = 0;
- int i, h = 0;
-
- if (gnuflag>0 && s[0] & 0200) {
- for (i = k-1; i > 0; i--) {
- n += (s[i]&0377) << h;
- h += 8;
- }
- n += (s[0]&0177) << h;
- } else {
- i = 0;
- while (spacechar(s[i]&0377))
- i++;
- while (i < k && s[i] && !spacechar(s[i]&0377)) {
- n *= 8;
- n += s[i++]-'0';
- }
- }
- return n;
-}
-
-static void
-passtape(register struct stat *sp)
-{
- long long blocks;
- char buf[TBLOCK];
-
- switch (dblock.dbuf.linkflag) {
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- break;
- case '1':
- if (oldflag > 0 || gnuflag > 0)
- break;
- /*FALLTHRU*/
- default:
- blocks = sp->st_size;
- blocks += TBLOCK-1;
- blocks /= TBLOCK;
-
- while (blocks-- > 0) {
- if (((mtstat.st_mode&S_IFMT) == S_IFBLK ||
- (mtstat.st_mode&S_IFMT) == S_IFREG) &&
- recno >= nblock && blocks >= nblock) {
- long long lpos;
- lpos = (blocks/nblock)*nblock*TBLOCK;
- if ((volsize == 0 || rdtotal+lpos < volsize) &&
- lseek(mt, lpos, SEEK_CUR)
- != (off_t)-1) {
- blocks %= nblock;
- rdtotal += lpos;
- }
- }
- readtape(buf);
- }
- }
-}
-
-static void
-putfile(const char *longname, const char *shortname, int olddir, int vis_cnt)
-{
- struct stat stbuf;
- int infile = -1;
- char *copy = NULL, *cend;
- size_t sz, slen, ss;
- struct direc *dp;
- struct getdb *db;
- int i, j;
- int skip = 0;
- char *symblink = 0;
-
- paxrec = globrec;
- if ((hflag ? stat : lstat)(shortname, &stbuf) < 0) {
- fprintf(stderr, "%s: could not stat %s\n", progname, longname);
- edone(1);
- return;
- }
- if ((stbuf.st_mode&S_IFMT) == S_IFREG &&
- stbuf.st_dev == mtstat.st_dev &&
- stbuf.st_ino == mtstat.st_ino) {
- fprintf(stderr, "%s: %s same as archive file\n",
- progname, longname);
- return;
- }
- if ((stbuf.st_mode&S_IFMT) == S_IFREG &&
- stbuf.st_size > 077777777777LL) {
- if (gnuflag > 0 || oldflag > 0) {
- fprintf(stderr, "%s: %s too large (limit 8 GB)\n",
- progname, longname);
- return;
- }
- paxrec |= PR_SIZE;
- }
- if (sysv3 && eflag && (stbuf.st_mode&S_IFMT) == S_IFREG &&
- stbuf.st_size > volsize - wrtotal - 512) {
- fprintf(stderr, "%s: Single file cannot fit on volume\n",
- progname);
- done(3);
- }
- if ((stbuf.st_mode&S_IFMT) == S_IFREG ||
- (stbuf.st_mode&S_IFMT) == S_IFDIR) {
- infile = open(shortname, O_RDONLY);
- if (infile < 0) {
- fprintf(stderr, "%s: %s: cannot open file\n",
- progname, longname);
- edone(1);
- return;
- }
- }
-
- if (tfile != NULL && (i = checkupdate(longname, &stbuf)) != '\0') {
- if (infile >= 0 && (stbuf.st_mode & S_IFMT) == S_IFDIR &&
- i != 'X')
- skip = 1;
- else {
- if (i == 'X' && vflag)
- fprintf(stderr, "a %s%s excluded\n", longname,
- (stbuf.st_mode&S_IFMT) == S_IFDIR ?
- "/" : "");
- goto ret;
- }
- }
- if (!skip && checkw('r', shortname, &stbuf, -1) == 0)
- goto ret;
-
- if ((stbuf.st_mode & S_IFMT) == S_IFDIR && infile >= 0) {
- if (order == PREORDER)
- goto out;
- cont: if (hflag) {
- for (i = 0; i < vis_cnt; i++)
- if (stbuf.st_dev == vis_dev[i] &&
- stbuf.st_ino == vis_ino[i])
- goto fini;
- if (vis_cnt >= vis_max) {
- vis_max += 20;
- vis_dev = srealloc(vis_dev, sizeof *vis_dev *
- vis_max);
- vis_ino = srealloc(vis_ino, sizeof *vis_ino *
- vis_max);
- }
- vis_dev[vis_cnt] = stbuf.st_dev;
- vis_ino[vis_cnt] = stbuf.st_ino;
- vis_cnt++;
- }
- getpath(longname, ©, &cend, &sz, &slen);
- if (fchdir(infile) < 0) {
- fprintf(stderr, "can't change directories to %s\n",
- shortname);
- goto fini;
- }
- db = getdb_alloc(shortname, infile);
- while ((dp = getdir(db, &j)) != NULL && !term) {
- if (dp->d_ino == 0)
- continue;
- if (strcmp(".", dp->d_name) == 0 ||
- strcmp("..", dp->d_name) == 0)
- continue;
- setpath(dp->d_name, ©, &cend, slen, &sz, &ss);
- putfile(copy, dp->d_name, infile, vis_cnt);
- i++;
- }
- getdb_free(db);
- if (fchdir(olddir) < 0) {
- fprintf(stderr, "cannot change back?: %s\n",
- strerror(errno));
- done(1);
- }
- fini: free(copy);
- if (order == PREORDER)
- goto ret;
- }
-out:
- tomodes(longname, &stbuf);
-
- if (skip || mkname(&dblock.dbuf, longname) < 0)
- goto ret;
-
- if (stbuf.st_nlink > 1 && (stbuf.st_mode&S_IFMT) != S_IFDIR) {
- struct dslot *dp;
- struct islot *ip;
-
- dp = dfind(&devices, stbuf.st_dev);
- if ((ip = ifind(stbuf.st_ino, &dp->itree)) != NULL) {
- ip->count--;
- sprintf(dblock.dbuf.size, "%11.11o", 0);
- if (mklink(&dblock.dbuf, ip->pathname, longname) < 0)
- goto ret;
- dblock.dbuf.linkflag = '1';
- sprintf(dblock.dbuf.chksum, "%7.7o", checksum(0));
- if (paxrec != PR_NONE && oldflag <= 0 && gnuflag <= 0)
- wrpax(longname, ip->pathname, &stbuf);
- writetape( (char *) &dblock);
- if (vflag)
- fprintf(stderr, "a %s link to %s\n",
- longname, ip->pathname);
- goto ret;
- }
- else {
- int namelen = strlen(longname);
- ip = calloc(1, sizeof *ip);
- if (ip == 0 || (ip->pathname=malloc(namelen+1)) == 0) {
- if (freemem) {
- write(2, "Out of memory. "
- "Link information lost\n", 37);
- freemem = 0;
- edone(1);
- }
- } else {
- ip->nextp = ihead;
- ihead = ip;
- ip->inum = stbuf.st_ino;
- ip->count = stbuf.st_nlink - 1;
- strcpy(ip->pathname, longname);
- iput(ip, &dp->itree);
- }
- }
- }
-
- switch (stbuf.st_mode & S_IFMT) {
- default:
- def: fprintf(stderr, "%s: %s is not a file. Not dumped\n",
- progname, longname);
- edone(1);
- goto ret;
- case S_IFREG:
- dblock.dbuf.linkflag = '0';
- wrhdr(longname, NULL, &stbuf);
- putreg(longname, shortname, infile, &stbuf);
- goto ret;
- case S_IFLNK:
- if (putsym(longname, shortname, &symblink, stbuf.st_size) < 0)
- goto ret;
- dblock.dbuf.linkflag = '2';
- break;
- case S_IFCHR:
- if (oldflag > 0)
- goto def;
- dblock.dbuf.linkflag = '3';
- break;
- case S_IFBLK:
- if (oldflag > 0)
- goto def;
- dblock.dbuf.linkflag = '4';
- break;
- case S_IFDIR:
- if (oldflag > 0)
- goto nop;
- dblock.dbuf.linkflag = '5';
- break;
- case S_IFIFO:
- if (oldflag > 0)
- goto def;
- dblock.dbuf.linkflag = '6';
- break;
- }
- wrhdr(longname, symblink, &stbuf);
- free(symblink);
-nop: if (order == PREORDER && infile >= 0 && (stbuf.st_mode&S_IFMT)==S_IFDIR)
- goto cont;
-ret: if (infile >= 0)
- close(infile);
-}
-
-static void
-putreg(const char *longname, const char *shortname, int infile, struct stat *sp)
-{
- long long blocks;
- char buf[TBLOCK];
- int i;
-
- blocks = (sp->st_size + (TBLOCK-1)) / TBLOCK;
- midfile = 1;
- while ((i = read(infile, buf, TBLOCK)) > 0 && blocks > 0) {
- if (i < TBLOCK)
- memset(&buf[i], 0, TBLOCK - i);
- writetape(buf);
- blocks--;
- }
- close(infile);
- midfile = 0;
- if (blocks != 0 || i != 0) {
- fprintf(stderr, "%s: file changed size\n", longname);
- edone(1);
- }
- while (blocks-- > 0)
- putempty();
-}
-
-static int
-putsym(const char *longname, const char *shortname,
- char **symblink, size_t size)
-{
- size_t n;
- ssize_t len;
-
- n = size ? size : PATH_MAX;
- *symblink = smalloc(n+1);
- if ((len = readlink(shortname, *symblink, n)) < 0) {
- fprintf(stderr, "can't read symbolic link %s\n", longname);
- edone(1);
- return -1;
- }
- (*symblink)[len] = '\0';
- if (len >= 100) {
- if (oldflag <= 0 && gnuflag <= 0 && utf8(*symblink)) {
- paxrec |= PR_LINKPATH;
- strcpy(dblock.dbuf.linkname, sequence());
- return 0;
- }
- fprintf(stderr, "%s: %s: symbolic link too long\n",
- progname, longname);
- edone(1);
- return -1;
- }
- memcpy(dblock.dbuf.linkname, *symblink, len);
- if (len < NAMSIZ)
- dblock.dbuf.linkname[len] = '\0';
- return 0;
-}
-
-static void
-wrhdr(const char *longname, const char *symblink, struct stat *sp)
-{
- long long blocks;
-
- blocks = (sp->st_mode&S_IFMT) == S_IFREG ?
- (sp->st_size + (TBLOCK-1)) / TBLOCK : 0;
- if (vflag) {
- if (nflag)
- fprintf(stderr, "seek = %lldK\t",
- (wrtotal+recno*2+1023)/1024);
- fprintf(stderr, "a %s%s ", longname,
- (sp->st_mode&S_IFMT) == S_IFDIR ? "/" : "");
- if (symblink)
- fprintf(stderr, "symbolic link to %s\n", symblink);
- else if (nflag)
- fprintf(stderr, "%lldK\n",
- blocks&01?blocks|02:blocks>>1);
- else
- fprintf(stderr, "%lld tape blocks\n", blocks);
- }
- sprintf(dblock.dbuf.chksum, "%7.7o", checksum(0));
- if (paxrec != PR_NONE && oldflag <= 0 && gnuflag <= 0)
- wrpax(longname, symblink, sp);
- writetape( (char *) &dblock);
-}
-
-static void
-wrpax(const char *longname, const char *linkname, struct stat *sp)
-{
- char oblock[TBLOCK];
- char *pdata = NULL;
- long psize = 0, pcur = 0;
- long long blocks, i;
-
- memcpy(oblock, (char *)&dblock, TBLOCK);
- memset((char *)&dblock, 0, TBLOCK);
- if (paxrec & PR_ATIME)
- addrec(&pdata, &psize, &pcur, "atime", NULL, sp->st_atime);
- if (paxrec & PR_GID)
- addrec(&pdata, &psize, &pcur, "gid", NULL, sp->st_gid);
- if (paxrec & PR_LINKPATH)
- addrec(&pdata, &psize, &pcur, "linkpath", linkname, 0);
- if (paxrec & PR_MTIME)
- addrec(&pdata, &psize, &pcur, "mtime", NULL, sp->st_mtime);
- if (paxrec & PR_PATH)
- addrec(&pdata, &psize, &pcur, "path", longname, 0);
- if (paxrec & PR_SIZE)
- addrec(&pdata, &psize, &pcur, "size", NULL, sp->st_size);
- if (paxrec & PR_UID)
- addrec(&pdata, &psize, &pcur, "uid", NULL, sp->st_uid);
- if (paxrec & PR_SUN_DEVMAJOR)
- addrec(&pdata, &psize, &pcur, "SUN.devmajor", NULL,
- major(sp->st_rdev));
- if (paxrec & PR_SUN_DEVMINOR)
- addrec(&pdata, &psize, &pcur, "SUN.devminor", NULL,
- minor(sp->st_rdev));
- paxnam(&dblock.dbuf, longname);
- sprintf(dblock.dbuf.mode, "%7.7o", 0444);
- sprintf(dblock.dbuf.uid, "%7.7o", 0);
- sprintf(dblock.dbuf.gid, "%7.7o", 0);
- sprintf(dblock.dbuf.size, "%11.11lo", pcur);
- sprintf(dblock.dbuf.mtime, "%11.11o", 0);
- strcpy(dblock.dbuf.magic, "ustar");
- dblock.dbuf.version[0] = dblock.dbuf.version[1] = '0';
- strcpy(dblock.dbuf.uname, "root");
- strcpy(dblock.dbuf.gname, "root");
- dblock.dbuf.linkflag = Eflag ? 'X' : 'x';
- sprintf(dblock.dbuf.chksum, "%7.7o", checksum(0));
- writetape( (char *) &dblock);
- memset(&pdata[pcur], 0, psize - pcur);
- blocks = (pcur + (TBLOCK-1)) / TBLOCK;
- for (i = 0; i < blocks; i++)
- writetape(&pdata[i*TBLOCK]);
- memcpy((char *)&dblock, oblock, TBLOCK);
- free(pdata);
-}
-
-static void
-addrec(char **pdata, long *psize, long *pcur,
- const char *keyword, const char *sval, long long lval)
-{
- char dval[25], xval[25];
- long od, d, r;
-
- if (sval == 0) {
- sprintf(xval, "%lld", lval);
- sval = xval;
- }
- r = strlen(keyword) + strlen(sval) + 3;
- d = 0;
- do {
- od = d;
- sprintf(dval, "%ld", od + r);
- d = strlen(dval);
- } while (d != od);
- *psize += d + r + 1 + 512;
- *pdata = srealloc(*pdata, *psize);
- sprintf(&(*pdata)[*pcur], "%s %s=%s\n", dval, keyword, sval);
- *pcur += d + r;
-}
-
-static void
-paxnam(struct header *hp, const char *name)
-{
- char buf[257], *bp;
- const char *cp, *np;
- int bl = 0;
- static int pid;
-
- if (pid == 0)
- pid = getpid();
- for (np = name; *np; np++);
- while (np > name && *np != '/') {
- np--;
- bl++;
- }
- if ((np > name || *name == '/') && np-name <= 120)
- for (bp = buf, cp = name; cp < np; bp++, cp++)
- *bp = *cp;
- else {
- *buf = '.';
- bp = &buf[1];
- }
- snprintf(bp, sizeof buf - (bp - buf), "/PaxHeaders.%d/%s",
- pid, bl < 100 ? np>name?&np[1]:name : sequence());
- mkname(hp, buf);
-}
-
-static void
-doxtract(char *argv[])
-{
- struct stat stbuf;
- char *name;
- char **cp;
- int try;
-
- suprmsg();
- for (;;) {
- try = 0;
- tgetdir(&stbuf);
- if (endtape(0))
- break;
-
- name = hbuf.rname;
- if (*argv == 0)
- goto gotit;
-
- for (cp = argv; *cp; cp++)
- if (prefix(*cp, name)) {
- try = 1;
- goto gotit;
- }
- passtape(&stbuf);
- continue;
-
-gotit:
- if (checkw('x', name, &stbuf, dblock.dbuf.linkflag) == 0) {
- passtape(&stbuf);
- continue;
- }
-
- if (checkdir(name, &stbuf) == '/')
- goto dir;
-
- switch (dblock.dbuf.linkflag) {
- default:
- case '0':
- case '\0':
- if (xtrreg(name, &stbuf) < 0)
- continue;
- break;
- case '1':
- if (xtrlink(name, &stbuf, 0) == 0)
- passtape(&stbuf);
- else if (stbuf.st_size > 0)
- xtrreg(name, &stbuf);
- continue;
- case '2':
- xtrlink(name, &stbuf, 1);
- continue;
- case '3':
- if (xtrdev(name, &stbuf, S_IFCHR) < 0)
- continue;
- break;
- case '4':
- if (xtrdev(name, &stbuf, S_IFBLK) < 0)
- continue;
- break;
- case '5':
- dir: if (xtrdir(name, &stbuf) < 0)
- continue;
- break;
- case '6':
- if (xtrdev(name, &stbuf, S_IFIFO) < 0)
- continue;
- break;
- }
- if (pflag)
- chmod(name, stbuf.st_mode & cmask(&stbuf, 0));
- if (mflag == 0) {
- struct utimbuf timep;
-
- if (paxrec & PR_ATIME)
- timep.actime = stbuf.st_atime;
- else
- timep.actime = time(NULL);
- timep.modtime = stbuf.st_mtime;
- if (utime(name, &timep) < 0)
- fprintf(stderr, "can't set time on %s\n", name);
- }
- gotcha += try;
- }
- if (gotcha < files)
- fprintf(stderr, "%s: %ld file(s) not extracted\n",
- progname, files - gotcha);
-}
-
-static int
-xtrreg(const char *name, struct stat *sp)
-{
- long long blocks, bytes;
- char buf[TBLOCK];
- int ofile;
-
- remove(name);
- if ((ofile = creat(name, sp->st_mode & cmask(sp, 1))) < 0) {
- fprintf(stderr, "%s: %s - cannot create\n", progname, name);
- edone(1);
- passtape(sp);
- return -1;
- }
- tchown(chown, name, sp->st_uid, sp->st_gid);
- blocksof(name, sp, &blocks, &bytes);
- while (blocks-- > 0) {
- readtape(buf);
- if (bytes > TBLOCK) {
- if (write(ofile, buf, TBLOCK) < 0) {
- fprintf(stderr,
- "%s: %s: HELP - extract write error\n",
- progname, name);
- done(2);
- }
- } else
- if (write(ofile, buf, (int) bytes) < 0) {
- fprintf(stderr,
- "%s: %s: HELP - extract write error\n",
- progname, name);
- done(2);
- }
- bytes -= TBLOCK;
- }
- close(ofile);
- return 0;
-}
-
-static int
-xtrlink(const char *name, struct stat *sp, int symbolic)
-{
- struct stat nst, ost;
-
- if (lstat(name, &nst) == 0) {
- if ((nst.st_mode & S_IFMT) == S_IFDIR)
- rmdir(name);
- else if (!symbolic && lstat(hbuf.rlinkname, &ost) == 0 &&
- nst.st_dev == ost.st_dev &&
- nst.st_ino == ost.st_ino)
- /* An attempt to hardlink "name" to itself. This
- * happens if a file with more than link has been
- * stored in the archive more than once under the
- * same name. This is odd but the best we can do
- * is nothing at all in such a case. */
- goto good;
- else
- unlink(name);
- }
- if ((symbolic?symlink:link)(symbolic?hbuf.linkname:hbuf.rlinkname,
- name) < 0) {
- if (symbolic)
- fprintf(stderr, "%s: symbolic link failed\n", name);
- else
- fprintf(stderr, "%s: %s: cannot link\n",
- progname, name);
- edone(1);
- return -1;
- }
-good: if (vflag)
- fprintf(stderr, "%s %s %s\n", name,
- symbolic ? "symbolic link to" : "linked to",
- hbuf.linkname);
- if (symbolic)
- tchown(lchown, name, sp->st_uid, sp->st_gid);
- return 0;
-}
-
-static int
-xtrdev(const char *name, struct stat *sp, mode_t type)
-{
- remove(name);
- if (mknod(name, sp->st_mode&cmask(sp, 1) | type, sp->st_rdev) < 0) {
- fprintf(stderr, "Can't create special %s\n", name);
- edone(1);
- return -1;
- }
- tchown(chown, name, sp->st_uid, sp->st_gid);
- return 0;
-}
-
-static int
-xtrdir(const char *name, struct stat *sp)
-{
- remove(name);
- if (mkdir(name, sp->st_mode&cmask(sp, 1)|0700) < 0 && errno != EEXIST) {
- fprintf(stderr, "%s: %s: %s\n", progname, name,
- strerror(errno));
- edone(1);
- return -1;
- }
- tchown(chown, name, sp->st_uid, sp->st_gid);
- return 0;
-}
-
-static void
-blocksof(const char *name, struct stat *sp, long long *blocks, long long *bytes)
-{
- *blocks = ((*bytes = sp->st_size) + TBLOCK-1)/TBLOCK;
- if (vflag)
- fprintf(stderr, "x %s, %lld bytes, ""%lld%s\n",
- name, *bytes,
- nflag ? (*blocks&01?*blocks|02:*blocks)>>1 : *blocks,
- nflag ? "K" : " tape blocks");
-}
-
-static void
-tchown(int (*chfn)(const char *, uid_t, gid_t),
- const char *name, uid_t uid, gid_t gid)
-{
- if (oflag == 0) {
- if (chfn(name, uid, -1) < 0)
- fprintf(stderr, "%s: %s: owner not changed\n",
- progname, name);
- if (chfn(name, -1, gid) < 0)
- fprintf(stderr, "%s: %s: group not changed\n",
- progname, name);
- }
-}
-
-static void
-dotable(char *argv[])
-{
- struct stat stbuf;
- char **cp;
- char *name;
-
- for (;;) {
- tgetdir(&stbuf);
- if (endtape(0))
- break;
- name = hbuf.name;
- if (*argv == 0)
- goto yes;
- for (cp = argv; *cp; cp++)
- if (prefix(*cp, name)) {
- gotcha++;
- goto yes;
- }
- goto no;
- yes: if (vflag)
- longt(&stbuf, dblock.dbuf.linkflag);
- printf("%s", name);
- if (dblock.dbuf.linkflag == '1')
- printf(" linked to %s", hbuf.linkname);
- else if (dblock.dbuf.linkflag == '2')
- printf(" symbolic link to %s", hbuf.linkname);
- printf("\n");
- no: passtape(&stbuf);
- }
- if (gotcha < files)
- fprintf(stderr, "%s: %ld file(s) not found\n",
- progname, files - gotcha);
-}
-
-static void
-putempty(void)
-{
- char buf[TBLOCK];
-
- memset(buf, 0, sizeof buf);
- writetape(buf);
-}
-
-static void
-longt(register struct stat *st, int linkflag)
-{
- struct tm *tp;
- char buf[20];
-
- pmode(st, linkflag);
- printf("%3ld/%-3ld", (long)st->st_uid, (long)st->st_gid);
- printf(" %6lld", (long long)st->st_size);
- tp = localtime(&st->st_mtime);
- strftime(buf, sizeof buf, "%b %e %H:%M %Y", tp);
- printf(" %17.17s ", buf);
-}
-
-#define SUID 04000
-#define SGID 02010
-#define NFMT 02000
-#define ROWN 0400
-#define WOWN 0200
-#define XOWN 0100
-#define RGRP 040
-#define WGRP 020
-#define XGRP 010
-#define ROTH 04
-#define WOTH 02
-#define XOTH 01
-#define STXT 01000
-static int m1[] = { 1, ROWN, 'r', '-' };
-static int m2[] = { 1, WOWN, 'w', '-' };
-static int m3[] = { 2, SUID, 's', XOWN, 'x', '-' };
-static int m4[] = { 1, RGRP, 'r', '-' };
-static int m5[] = { 1, WGRP, 'w', '-' };
-static int m6[] = { 3, SGID, 's', NFMT, 'l', XGRP, 'x', '-' };
-static int m7[] = { 1, ROTH, 'r', '-' };
-static int m8[] = { 1, WOTH, 'w', '-' };
-static int m9[] = { 2, STXT, 't', XOTH, 'x', '-' };
-
-static int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9};
-
-static void
-pmode(register struct stat *st, int linkflag)
-{
- register int **mp;
- int c;
-
- switch (linkflag) {
- case -1:
- switch (st->st_mode & S_IFMT) {
- case S_IFLNK: c = 'l'; break;
- case S_IFCHR: c = 'c'; break;
- case S_IFBLK: c = 'b'; break;
- case S_IFDIR: c = 'd'; break;
- case S_IFIFO: c = 'p'; break;
- default: c = '-';
- } break;
- case '2': c = 'l'; break;
- case '3': c = 'c'; break;
- case '4': c = 'b'; break;
- case '5': c = 'd'; break;
- case '6': c = 'p'; break;
- default: c = '-';
- }
- printf("%c", c);
- for (mp = &m[0]; mp < &m[9];)
- tselect(*mp++, st);
-}
-
-static void
-tselect(int *pairp, struct stat *st)
-{
- register int n, *ap;
-
- ap = pairp;
- n = *ap++;
- while (--n>=0 && (ap++, (st->st_mode&ap[-1])!=ap[-1]))
- ap++;
- printf("%c", *ap);
-}
-
-static int
-checkdir(register char *name, struct stat *sp)
-{
- register char *cp;
-
- for (cp = name; *cp; cp++) {
- if (*cp == '/' && cp > name) {
- *cp = '\0';
- if (access(name, X_OK) < 0) {
- if (mkdir(name, 0777) < 0 && errno != EEXIST) {
- fprintf(stderr, "%s: %s: %s\n",
- progname, name,
- strerror(errno));
- edone(1);
- }
- tchown(chown, name, sp->st_uid, sp->st_gid);
- }
- *cp = '/';
- }
- }
- return cp > name ? cp[-1] : cp[0];
-}
-
-/*ARGUSED*/
-static void
-onsig(int signo)
-{
- sigset(signo, SIG_IGN);
- if (midfile) {
- fprintf(stderr, "%s: Interrupted in the middle of a file\n",
- progname);
- done(signo | 0200);
- }
- term = 1;
-}
-
-static void
-tomodes(const char *name, register struct stat *sp)
-{
- const char *cp;
- int mode;
-
- memset(&dblock, 0, sizeof dblock);
- mode = gnuflag<=0&&!Eflag?sp->st_mode&07777:sp->st_mode&(07777|S_IFMT);
- sprintf(dblock.dbuf.mode, "%7.7o", mode);
- sprintf(dblock.dbuf.uid, "%7.7lo", (long)(sp->st_uid <= 07777777 ?
- sp->st_uid : (paxrec |= PR_UID, 60001)));
- sprintf(dblock.dbuf.gid, "%7.7lo", (long)(sp->st_gid <= 07777777 ?
- sp->st_gid : (paxrec |= PR_GID, 60001)));
- sprintf(dblock.dbuf.size, "%11.11llo", (sp->st_mode&S_IFMT)==S_IFREG ?
- (long long)sp->st_size&077777777777LL : 0LL);
- sprintf(dblock.dbuf.mtime, "%11.11lo", (long)sp->st_mtime);
- if (oldflag <= 0) {
- strcpy(dblock.dbuf.magic, gnuflag>0 ? "ustar " : "ustar");
- if (gnuflag <= 0)
- dblock.dbuf.version[0] = dblock.dbuf.version[1] = '0';
- if ((cp = getuser(sp->st_uid)) != NULL)
- sprintf(dblock.dbuf.uname, "%.31s", cp);
- else
- fprintf(stderr,
- "%s: could not get passwd information for %s\n",
- progname, name);
- if ((cp = getgroup(sp->st_gid)) != NULL)
- sprintf(dblock.dbuf.gname, "%.31s", cp);
- else
- fprintf(stderr,
- "%s: could not get group information for %s\n",
- progname, name);
- if (Eflag && major(sp->st_rdev) > 07777777 &&
- ((sp->st_mode&S_IFMT) == S_IFBLK ||
- (sp->st_mode&S_IFMT) == S_IFCHR))
- paxrec |= PR_SUN_DEVMAJOR;
- sprintf(dblock.dbuf.devmajor, "%7.7o",
- (int)major(sp->st_rdev)&07777777);
- if (Eflag && minor(sp->st_rdev) > 07777777 &&
- ((sp->st_mode&S_IFMT) == S_IFBLK ||
- (sp->st_mode&S_IFMT) == S_IFCHR))
- paxrec |= PR_SUN_DEVMINOR;
- sprintf(dblock.dbuf.devminor, "%7.7o",
- (int)minor(sp->st_rdev)&07777777);
- }
-}
-
-static int
-checksum(int invert)
-{
- register uint32_t i;
- register char *cp;
-
- for (cp = dblock.dbuf.chksum;
- cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)];
- cp++)
- *cp = ' ';
- i = 0;
- for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
- i += oldflag>0^invert ? *(signed char *)cp : *cp & 0377;
- return(i);
-}
-
-static int
-checkw(int c, const char *name, struct stat *sp, int linkflag)
-{
- if (wflag) {
- printf("%c ", c);
- if (vflag)
- longt(sp, linkflag);
- printf("%s: ", name);
- fflush(stdout);
- if (response() == 'y'){
- return(1);
- }
- return(0);
- }
- return(1);
-}
-
-static int
-response(void)
-{
- char c, c2;
-
- if (read(0, &c, 1) == 1 && c != '\n')
- while (read(0, &c2, 1) == 1 && c2 != '\n');
- else c = 'n';
- return(c);
-}
-
-static int
-checkupdate(const char *arg, struct stat *sp)
-{
- long mtime; /* cf. LONG_MAX in readexcl() */
- off_t seekp;
- char c;
-
- rewind(tfile);
- for (;;) {
- if ((seekp = lookup(arg)) < 0)
- return(0);
- fseeko(tfile, seekp+1, SEEK_SET);
- fscanf(tfile, "%c %lo", &c, &mtime);
- if (c == 'u' && sp->st_mtime > mtime)
- return(0);
- else
- return(c);
- }
-}
-
-static void
-done(int n)
-{
- if (rflag && mt >= 0 && close(mt) < 0 && writerror == 0) {
- fprintf(stderr, "%s: tape write error\n", progname);
- if (n == 0)
- n = 2;
- }
- exit(n);
-}
-
-static int
-prefix(register const char *s1, register const char *s2)
-{
- while (*s1)
- if (*s1++ != *s2++)
- return(0);
- if (*s2)
- return(*s2 == '/');
- return(1);
-}
-
-static int njab;
-static off_t
-lookup(const char *s)
-{
- return bsrch(s, strlen(s), low, high);
-}
-
-static off_t
-bsrch(const char *s, int n, off_t l, off_t h)
-{
- register int i, j;
- char *b;
- off_t m, m1;
-
- b = alloca(N);
- njab = 0;
-
-loop:
- if(l >= h)
- return(-1L);
- m = l + (h-l)/2 - N/2;
- if(m < l)
- m = l;
- fseeko(tfile, m, SEEK_SET);
- fread(b, 1, N, tfile);
- njab++;
- for(i=0; i<N; i++) {
- if(b[i] == '\n')
- break;
- m++;
- }
- if(m >= h)
- return(-1L);
- m1 = m;
- j = i;
- for(i++; i<N; i++) {
- m1++;
- if(b[i] == '\n')
- break;
- }
- i = cmp(b+j, s, n);
- if(i < 0) {
- h = m;
- goto loop;
- }
- if(i > 0) {
- l = m1;
- goto loop;
- }
- return(m);
-}
-
-static int
-cmp(const char *b, const char *s, size_t n)
-{
- register int i;
-
- if(b[0] != '\n')
- abort();
- for(i=0; i<n; i++) {
- if((b[i+1+TIMSIZ+1+2]&0377) > (s[i]&0377))
- return(-1);
- if((b[i+1+TIMSIZ+1+2]&0377) < (s[i]&0377))
- return(1);
- }
- return(b[i+1+TIMSIZ+1+2] == '\n'? 0 : -1);
-}
-
-static int
-readtape(char *buffer)
-{
- static int rd;
- int i = -1, j;
-
-again: if (recno >= nblock || first == 0) {
- if (first == 0 && nblock == 1 && bflag == 0)
- j = NBLOCK;
- else
- j = nblock;
- if (volsize % TBLOCK*j) {
- fprintf(stderr, "%s: Volume size not a multiple "
- "of block size.\n", progname);
- done(1);
- }
- if ((rd = i = mtread(tbuf, TBLOCK*j)) < 0) {
- fprintf(stderr, "%s: tape read error\n", progname);
- done(3);
- }
- if (maybezip && checkzip(tbuf[0].dummy, i) == 1)
- goto again;
- if (first == 0 || i == 0) {
- if ((i % TBLOCK) != 0 || i == 0) {
- tbe: fprintf(stderr, "%s: tape blocksize error\n",
- progname);
- done(3);
- }
- i /= TBLOCK;
- if (i != nblock) {
- if ((mtstat.st_mode&S_IFMT) == S_IFCHR &&
- (i != 1 || bflag >= B_DEFN))
- fprintf(stderr, "%s: blocksize = %d\n",
- progname, i);
- nblock = i;
- }
- if (tapeblock == 0)
- tapeblock = i;
- }
- recno = 0;
- }
- first = 1;
- if ((rd -= TBLOCK) < 0)
- goto tbe;
- memcpy(buffer, &tbuf[recno++], TBLOCK);
- return(TBLOCK);
-}
-
-static int
-writetape(const char *buffer)
-{
- first = 1;
- if (recno >= nblock) {
- if (mtwrite(tbuf, TBLOCK*nblock) < 0) {
- fprintf(stderr, "%s: tape write error\n", progname);
- writerror++;
- done(2);
- }
- recno = 0;
- }
- memcpy(&tbuf[recno++], buffer, TBLOCK);
- if (recno >= nblock) {
- if (mtwrite(tbuf, TBLOCK*nblock) < 0) {
- fprintf(stderr, "%s: tape write error\n", progname);
- writerror++;
- done(2);
- }
- recno = 0;
- }
- return(TBLOCK);
-}
-
-static void
-tseek(int n, int rew)
-{
- int fault;
-#ifndef __G__
- if (tapeblock > 0 && rew) {
-#if defined (__linux__) || defined (__sun) || defined (__FreeBSD__) || \
- defined (__hpux) || defined (_AIX) || defined (__NetBSD__) || \
- defined (__OpenBSD__) || defined (__DragonFly__) || defined (__APPLE__)
- struct mtop mo;
- mo.mt_op = n > 0 ? MTFSR : MTBSR;
- mo.mt_count = (n > 0 ? n : -n) / tapeblock;
- fault = ioctl(mt, MTIOCTOP, &mo) < 0;
-#else /* SVR4.2MP */
- int t, a;
- t = n > 0 ? T_SBF : T_SBB;
- a = (n > 0 ? n : -n) / tapeblock;
- fault = ioctl(mt, t, a) < 0;
-#endif /* SVR4.2MP */
- } else
-#endif
- fault = lseek(mt, TBLOCK*n, SEEK_CUR) == (off_t)-1;
- if (fault && rew) {
- fprintf(stderr, "%s: device seek error\n", progname);
- done(4);
- }
-}
-
-static void
-backtape(int rew)
-{
- tseek(-nblock, rew);
- if (recno >= nblock) {
- recno = nblock - 1;
- if (mtread(tbuf, TBLOCK*nblock) < 0) {
- fprintf(stderr, "%s: tape read error after seek\n",
- progname);
- done(4);
- }
- tseek(-nblock, rew);
- } else if (rew)
- recno--;
-}
-
-static void
-flushtape(void)
-{
- if (mtwrite(tbuf, TBLOCK*nblock) < 0) {
- fprintf(stderr, "%s: tape write error\n", progname);
- writerror++;
- done(2);
- }
-}
-
-static void *
-srealloc(void *op, size_t size)
-{
- void *np;
-
- if ((np = realloc(op, size)) == NULL) {
- write(2, "no memory\n", 10);
- _exit(077);
- }
- return np;
-}
-
-static void *
-smalloc(size_t size)
-{
- return srealloc(NULL, size);
-}
-
-static void *
-scalloc(size_t count, size_t nelem)
-{
- void *np;
-
- if ((np = calloc(count, nelem)) == NULL) {
- write(2, "no memory\n", 10);
- _exit(077);
- }
- return np;
-}
-
-static void *
-bfalloc(size_t n)
-{
- static long pagesize;
- void *vp;
-
- if (pagesize == 0)
- if ((pagesize = sysconf(_SC_PAGESIZE)) < 0)
- pagesize = 4096;
- if ((vp = memalign(pagesize, n)) == NULL) {
- fprintf(stderr, "%s: cannot allocate physio buffer\n",
- progname);
- done(1);
- }
- return vp;
-}
-
-static char *
-nameof(struct header *hp, char *buf)
-{
- const char *cp;
- register char *bp = buf;
-
- if (gnuflag <= 0 && hp->prefix[0] != '\0') {
- cp = hp->prefix;
- while (cp < &hp->prefix[PFXSIZ] && *cp)
- *bp++ = *cp++;
- if (bp > buf)
- *bp++ = '/';
- }
- cp = hp->name;
- while (cp < &hp->name[NAMSIZ] && *cp)
- *bp++ = *cp++;
- *bp = '\0';
- return buf;
-}
-
-static int
-mkname(struct header *hp, const char *fn)
-{
- const char *cp, *cs = NULL;
-
- if (Aflag)
- while (*fn == '/')
- fn++;
- for (cp = fn; *cp; cp++) {
- if (*cp == '/' && cp[1] != '\0' && cp > fn &&
- cp - fn <= PFXSIZ &&
- gnuflag <= 0 && oldflag <= 0)
- cs = cp;
- }
- if (cp - (cs ? &cs[1] : fn) > NAMSIZ) {
- if (oldflag <= 0 && gnuflag <= 0 && utf8(fn)) {
- paxrec |= PR_PATH;
- strcpy(hp->name, sequence());
- return 0;
- }
- fprintf(stderr, "%s: file name too long\n", fn);
- edone(1);
- return -1;
- }
- if (cs && cp - fn > NAMSIZ) {
- memcpy(hp->prefix, fn, cs - fn);
- if (cs - fn < PFXSIZ)
- hp->prefix[cs - fn] = '\0';
- memcpy(hp->name, &cs[1], cp - &cs[1]);
- if (cp - &cs[1] < NAMSIZ)
- hp->name[cp - &cs[1]] = '\0';
- } else {
- memcpy(hp->name, fn, cp - fn);
- if (cp - fn < NAMSIZ)
- hp->name[cp - fn] = '\0';
- }
- return 0;
-}
-
-static char *
-linkof(struct header *hp, char *buf)
-{
- const char *cp;
- register char *bp = buf;
-
-
- cp = hp->linkname;
- while (cp < &hp->linkname[NAMSIZ] && *cp)
- *bp++ = *cp++;
- *bp = '\0';
- return buf;
-}
-
-static int
-mklink(struct header *hp, const char *fn, const char *refname)
-{
- const char *cp;
-
- if (Aflag)
- while (*fn == '/')
- fn++;
- for (cp = fn; *cp; cp++);
- if (cp - fn > NAMSIZ) {
- if (oldflag <= 0 && gnuflag <= 0 && utf8(fn)) {
- paxrec |= PR_LINKPATH;
- strcpy(hp->linkname, sequence());
- return 0;
- }
- fprintf(stderr, "%s: %s: linked to %s\n",
- progname, refname, fn);
- fprintf(stderr, "%s: %s: linked name too long\n",
- progname, fn);
- edone(1);
- return -1;
- }
- memcpy(hp->linkname, fn, cp - fn);
- if (cp - fn < NAMSIZ)
- hp->linkname[cp - fn] = '\0';
- return 0;
-}
-
-static void
-edone(int i)
-{
- if (eflag && sysv3 == 0)
- done(i);
-}
-
-static ssize_t
-mtwrite(const void *vdata, size_t sz)
-{
- register ssize_t wo, wt = 0;
- const char *data = vdata;
-
- if (volsize && wrtotal >= volsize) {
- newvolume();
- wrtotal = 0;
- }
- do {
- if ((wo = write(mt, data + wt, sz - wt)) < 0) {
- if (errno == EINTR)
- continue;
- else if (wt > 0) {
- wt += wo;
- break;
- } else
- return wo;
- }
- wt += wo;
- } while (wt < sz);
- wrtotal += sz;
- return wt;
-}
-
-static ssize_t
-mtread(void *vdata, size_t sz)
-{
- register ssize_t ro, rt = 0;
- char *data = vdata;
-
- if (volsize && rdtotal >= volsize) {
- newvolume();
- rdtotal = 0;
- }
- do {
- if ((ro = read(mt, data + rt, sz - rt)) <= 0) {
- if (ro < 0) {
- if (errno == EINTR)
- continue;
- }
- if (rt > 0) {
- rt += ro;
- break;
- }
- return ro;
- }
- rt += ro;
- } while (Bflag != 0 && rt < sz);
- rdtotal += sz;
- return rt;
-}
-
-static void
-newvolume(void)
-{
- static int ttyfd = -1;
- int curfd;
- char c;
-
- if (close(mt) < 0) {
- fprintf(stderr, "%s: close error on archive: %s\n", progname,
- strerror(errno));
- done(1);
- }
- if ((curfd = open(".", O_RDONLY)) < 0) {
- fprintf(stderr, "cannot open current directory: %s\n",
- strerror(errno));
- done(1);
- }
- goback(workdir);
- fprintf(stderr, "%s: please insert new volume, then press RETURN.\a",
- progname);
- if (ttyfd < 0 && isatty(0) || ttyfd == 0)
- ttyfd = 0;
- else
- ttyfd = open("/dev/tty", O_RDONLY);
- do
- if (read(ttyfd, &c, 1) != 1)
- done(0);
- while (c != '\n');
- if (ttyfd > 0)
- close(ttyfd);
- if ((mt = open(usefile, rflag ? O_RDWR : O_RDONLY)) < 0) {
- fprintf(stderr, "%s: cannot open %s\n", progname, usefile);
- done(1);
- }
- domtstat();
- if (rflag)
- odirect();
- goback(curfd);
- close(curfd);
-}
-
-static void
-goback(int fd)
-{
- if (fchdir(fd) < 0) {
- fprintf(stderr, "cannot change back?: %s\n", strerror(errno));
- done(1);
- }
-}
-
-static void
-getpath(const char *path, char **file, char **filend, size_t *sz, size_t *slen)
-{
- *sz = 14 + strlen(path) + 2;
- *file = smalloc(*sz);
- *filend = *file;
- if (path[0] == '/' && path[1] == '\0')
- *(*filend)++ = '/';
- else {
- const char *cp = path;
- while ((*(*filend)++ = *cp++) != '\0');
- (*filend)[-1] = '/';
- }
- *slen = *filend - *file;
-}
-
-static void
-setpath(const char *base, char **file, char **filend,
- size_t slen, size_t *sz, size_t *ss)
-{
- if (slen + (*ss = strlen(base)) >= *sz) {
- *sz += slen + *ss + 15;
- *file = srealloc(*file, *sz);
- *filend = &(*file)[slen];
- }
- strcpy(*filend, base);
-}
-
-static void
-defaults(void)
-{
- struct iblok *ip;
- char *line = NULL, *x, *y, *cp;
- size_t size = 0;
- struct magtape *mp;
-
- if ((ip = ib_open(TARDFL, 0)) == NULL)
- return;
- while (ib_getlin(ip, &line, &size, srealloc) != 0) {
- if (strncmp(line, "archive", 7) == 0) {
- if (line[8] == '=' && line[7] >= '0' && line[7] <= '9'){
- mp = &magtapes[line[7] - '0'];
- x = &line[9];
- } else if (line[7] == '=') {
- x = &line[8];
- mp = &magtapes[10];
- } else
- continue;
- for (y = x; *y && *y != ' ' && *y != '\t'; y++);
- mp->device = cp = smalloc(y - x + 1);
- while (x < y)
- *cp++ = *x++;
- *cp = '\0';
- mp->block = 1;
- mp->size = 0;
- mp->nflag = 0;
- if (*x) {
- mp->block = strtol(x, &y, 10);
- if (y > x && *(x=y)) {
- mp->size = strtoll(x, &y, 10) * 1024;
- if (y > x && *(x=y)) {
- while (*x && (*x == ' ' ||
- *x == '\t' ||
- *x == '\n'))
- x++;
- if (*x == 'n' || *x == 'N')
- mp->nflag = 1;
- else
- mp->nflag = 0;
- }
- }
- }
- } else if (strncmp(line, "order=", 6) == 0) {
- if (strcmp(&line[6], "post\n") == 0)
- order = POSTORDER;
- else if (strcmp(&line[6], "pre\n") == 0)
- order = PREORDER;
- }
- }
- ib_close(ip);
- if (line)
- free(line);
-}
-
-static void
-settape(int c)
-{
- struct magtape *mp;
-
- if (c >= '0' && c <= '9')
- mp = &magtapes[c - '0'];
- else {
- if (magtapes[10].device)
- mp = &magtapes[10];
- else
- mp = &magtapes[0];
- c = '0';
- }
- if (mp->device == NULL) {
- fprintf(stderr, "%s: missing or invalid 'archive%c=' entry "
- "in %s.\n", progname, c, TARDFL);
- return;
- }
- usefile = mp->device;
- if (bflag == 0 && mp->block > 0) {
- nblock = mp->block;
- bflag = B_DEFN;
- }
- if (kflag == 0)
- volsize = mp->size;
- if (nflag < 2)
- nflag = mp->nflag;
-}
-
-static void
-suprmsg(void)
-{
- if (Aflag && vflag)
- fprintf(stderr, "Suppressing absolute pathnames\n");
-}
-
-static void
-odirect(void)
-{
-#if defined (__linux__) && defined (O_DIRECT)
- /*
- * If we are operating on a floppy disk block device and know
- * its track size, use direct i/o. This has the advantage that
- * signals can be delivered after each write(); otherwise, the
- * kernel will buffer the entire data, close() will put us in
- * a non-interruptible blocking state and the user has to wait
- * ~40 seconds for return after he presses the interrupt key.
- *
- * This has no negative speed impact as long as the blocking
- * factor is set to a multiple of the track size of the floppy.
- * The only values still useful today (2003) seem to be 18 for
- * 3.5 inch high densitiy disks at 1440 kB and 15 for 5.25 inch
- * high density disks at 1200 kB, so we specify these in the
- * default file; consult fd(4) for other values, or give no
- * values at all and autodetect them in the code above.
- *
- * Addendum: Use direct i/o for all block devices if a block
- * size was specified or detected since the symptoms are
- * generally the same as for floppy disks (e. g. with USB
- * memory sticks). But don't use it when reading since it
- * just slows down operation then.
- */
- if ((mtstat.st_mode&S_IFMT) == S_IFBLK && bflag) {
- int flags;
- if ((flags = fcntl(mt, F_GETFL)) != -1)
- fcntl(mt, F_SETFL, flags | O_DIRECT);
- }
-#endif /* __linux__ && O_DIRECT */
-}
-
-static void
-domtstat(void)
-{
- static int twice;
-
- if (fstat(mt, &mtstat) < 0) {
- fprintf(stderr, "%s: cannot stat archive\n", progname);
- done(1);
- }
- if ((mtstat.st_mode&S_IFMT) == S_IFIFO ||
- (mtstat.st_mode&S_IFMT) == S_IFSOCK)
- Bflag = 1;
-#if defined (__linux__)
- if ((mtstat.st_mode&S_IFMT) == S_IFBLK) {
- struct floppy_struct fs;
- int blkbsz;
- if (ioctl(mt, FDGETPRM, &fs) == 0) {
- if (kflag == 0 && volsize == 0)
- volsize = fs.size * FD_SECTSIZE(&fs);
- if (bflag == 0 && nblock == 1 && twice == 0) {
- if ((nblock=fs.sect*FD_SECTSIZE(&fs)/512)==0 ||
- nblock > NBLOCK)
- nblock = 1;
- else
- bflag = B_AUTO;
- }
-#ifdef O_DIRECT
- if (bflag && (tflag || xflag)) {
- int flags;
- if ((flags = fcntl(mt, F_GETFL)) != -1)
- fcntl(mt, F_SETFL, flags | O_DIRECT);
- }
-#endif /* O_DIRECT */
-#ifdef BLKBSZGET
- } else if (ioctl(mt, BLKBSZGET, &blkbsz) == 0) {
- if (bflag == 0 && nblock == 1 && twice == 0 &&
- (blkbsz&0777) == 0) {
- nblock = blkbsz >> 9;
- bflag = B_AUTO;
- }
-#endif /* BLKBSZGET */
- }
-#ifndef __G__
- } else if ((mtstat.st_mode&S_IFMT) == S_IFCHR) {
- struct mtget mg;
- if (ioctl(mt, MTIOCGET, &mg) == 0)
- tapeblock = ((mg.mt_dsreg&MT_ST_BLKSIZE_MASK)
- >> MT_ST_BLKSIZE_SHIFT);
-#endif
- }
-#elif defined (__sun)
- if ((mtstat.st_mode&S_IFMT) == S_IFCHR) {
- struct mtdrivetype_request mr;
- static struct mtdrivetype md;
- mr.size = sizeof md;
- mr.mtdtp = &md;
- if (ioctl(mt, MTIOCGETDRIVETYPE, &mr) == 0)
- tapeblock = md.bsize;
- }
-#elif defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) \
- || defined (__DragonFly__) || defined (__APPLE__)
- if ((mtstat.st_mode&S_IFMT) == S_IFCHR) {
- struct mtget mg;
- if (ioctl(mt, MTIOCGET, &mg) == 0)
- tapeblock = mg.mt_blksiz;
- }
-#elif defined (__hpux) || defined (_AIX)
-#else /* SVR4.2MP */
- if ((mtstat.st_mode&S_IFMT) == S_IFCHR) {
- struct blklen bl;
- if (ioctl(mt, T_RDBLKLEN, &bl) == 0)
- /*
- * This ioctl is (apparently) not useful. It just
- * returns 1 as minimum and 16M-1 as maximum size
- * on DAT/DDS tape drives.
- */
- tapeblock = 0;
- }
-#endif /* SVR4.2MP */
- if (tapeblock > 0) {
- if (tapeblock % TBLOCK != 0) {
- fprintf(stderr, "%s: tape blocksize error\n",
- progname);
- done(3);
- }
- tapeblock /= TBLOCK;
- if (tapeblock > NBLOCK)
- NBLOCK = tapeblock;
-#if defined (__linux__) || defined (__sun) || defined (__FreeBSD__) || \
- defined (__NetBSD__) || defined (__OpenBSD__) || \
- defined (__DragonFly__) || defined (__APPLE__)
- if (bflag == 0 && cflag && twice == 0) {
- if (nblock == 1) {
- if ((nblock = tapeblock) > NBLOCK)
- nblock = 1;
- else
- bflag = B_AUTO;
- }
- }
-#endif /* __linux__ || __sun || __FreeBSD__ || __NetBSD__ || __OpenBSD__ ||
- __DragonFly__ || __APPLE__ */
- }
- if (twice == 0 && bflag == 0 && tapeblock < 0) {
- if ((nblock = mtstat.st_blksize >> 9) > NBLOCK)
- nblock = NBLOCK;
- else if (nblock <= 0)
- nblock = 1;
- else if ((mtstat.st_mode&S_IFMT) != S_IFCHR)
- bflag = B_AUTO;
- }
- twice = 1;
- if (nblock > NBLOCK)
- NBLOCK = nblock;
- tbuf = bfalloc(sizeof *tbuf * NBLOCK);
-}
-
-static int
-checkzip(const char *bp, int rd)
-{
- if (rd <= TBLOCK || (memcmp(&bp[257], "ustar", 5) &&
- memcmp(&bp[257], "\0\0\0\0\0", 5))) {
- if (bp[0] == 'B' && bp[1] == 'Z' && bp[2] == 'h')
- return redirect("bzip2", "-cd", rd);
- else if (bp[0] == 0xFD && bp[1] == '7' && bp[2] == 'z'
- && bp[3] == 'X' && bp[4] == 'Z' && bp[5] == 0x00)
- return redirect("xz", "-cd", rd);
- else if (bp[0] == '\37' && bp[1] == '\235')
- return redirect("zcat", NULL, rd);
- else if (bp[0] == '\37' && bp[1] == '\213')
- return redirect("gzip", "-cd", rd);
- }
- maybezip = 0;
- return -1;
-}
-
-static int
-redirect(const char *arg0, const char *arg1, int rd)
-{
- int pd[2];
-
- if (pipe(pd) < 0)
- return -1;
- switch (fork()) {
- case 0:
- if (tapeblock >= 0 || lseek(mt, -rd, SEEK_CUR) == (off_t)-1) {
- int xpd[2];
- if (pipe(xpd) == 0 && fork() == 0) {
- int wo, wt;
- close(xpd[0]);
- do {
- wo = wt = 0;
- do {
- if ((wo = write(xpd[1],
- tbuf + wt,
- rd - wt))
- <= 0) {
- if (errno == EINTR)
- continue;
- _exit(0);
- }
- wt += wo;
- } while (wt < rd);
- } while ((rd=mtread(tbuf, TBLOCK*nblock)) >= 0);
- if (rd < 0)
- fprintf(stderr, "%s: tape read error\n",
- progname);
- _exit(0);
- } else {
- close(xpd[1]);
- dup2(xpd[0], 0);
- close(xpd[0]);
- }
- } else
- dup2(mt, 0);
- close(mt);
- dup2(pd[1], 1);
- close(pd[0]);
- close(pd[1]);
- execlp(arg0, arg0, arg1, NULL);
- fprintf(stderr, "%s: could not exec %s: %s\n",
- progname, arg0, strerror(errno));
- _exit(0177);
- /*NOTREACHED*/
- default:
- Bflag = 1;
- tapeblock = -1;
- dup2(pd[0], mt);
- close(pd[0]);
- close(pd[1]);
- domtstat();
- break;
- case -1:
- return -1;
- }
- return 1;
-}
-
-#define CACHESIZE 16
-
-static const char *
-getuser(uid_t uid)
-{
- static struct {
- char *name;
- uid_t uid;
- } cache[CACHESIZE];
- static int last;
- int i;
- struct passwd *pwd;
- const char *name;
-
- for (i = 0; i < CACHESIZE && cache[i].name; i++)
- if (cache[i].uid == uid)
- goto found;
- if ((pwd = getpwuid(uid)) != NULL)
- name = pwd->pw_name;
- else
- name = "";
- if (i >= CACHESIZE) {
- if (last >= CACHESIZE)
- last = 0;
- i = last++;
- }
- if (cache[i].name)
- free(cache[i].name);
- cache[i].name = sstrdup(name);
- cache[i].uid = uid;
-found: return cache[i].name[0] ? cache[i].name : NULL;
-}
-
-static const char *
-getgroup(gid_t gid)
-{
- static struct {
- char *name;
- gid_t gid;
- } cache[CACHESIZE];
- static int last;
- int i;
- struct group *grp;
- const char *name;
-
- for (i = 0; i < CACHESIZE && cache[i].name; i++)
- if (cache[i].gid == gid)
- goto found;
- if ((grp = getgrgid(gid)) != NULL)
- name = grp->gr_name;
- else
- name = "";
- if (i >= CACHESIZE) {
- if (last >= CACHESIZE)
- last = 0;
- i = last++;
- }
- if (cache[i].name)
- free(cache[i].name);
- cache[i].name = sstrdup(name);
- cache[i].gid = gid;
-found: return cache[i].name[0] ? cache[i].name : NULL;
-}
-
-static char *
-sstrdup(const char *op)
-{
- char *np;
-
- np = smalloc(strlen(op) + 1);
- strcpy(np, op);
- return np;
-}
-
-static void
-fromfile(const char *fn)
-{
- struct iblok *ip;
- char *line = NULL;
- size_t size = 0, len;
-
- if ((ip = ib_open(fn, 0)) == NULL) {
- fprintf(stderr, "%s: %s: %s\n", progname, fn, strerror(errno));
- goback(workdir);
- } else {
- while ((len = ib_getlin(ip, &line, &size, srealloc)) != 0) {
- if (line[len-1] == '\n')
- line[--len] = '\0';
- doarg(line);
- goback(workdir);
- }
- ib_close(ip);
- if (line)
- free(line);
- }
-}
-
-static void
-readexcl(const char *fn)
-{
- FILE *fp;
- int c, slash, s;
-
- if ((fp = fopen(fn, "r")) == NULL) {
- fprintf(stderr, "%s: could not open %s: %s\n", progname, fn,
- strerror(errno));
- done(1);
- }
- do {
- if ((c = getc(fp)) != EOF && c != '\n') {
- slash = 0;
- s = fprintf(tfile, "X %0*lo %c", TIMSIZ, LONG_MAX, c);
- while ((c = getc(fp)) != EOF && c != '\n') {
- if (c == '/') {
- slash = 1;
- continue;
- } else if (slash == 1) {
- putc('/', tfile);
- s++;
- slash = 0;
- }
- putc(c, tfile);
- s++;
- }
- putc('\n', tfile);
- s++;
- s *= 3;
- if (s > N)
- N = s;
- }
- } while (c != EOF);
- fclose(fp);
-}
-
-static void
-creatfile(void)
-{
- char tname[PATH_MAX+1];
-
- if (tfile != NULL)
- return;
- settmp(tname, sizeof tname, "%s/tarXXXXXX");
- if ((tfile = fdopen(mkstemp(tname), "w")) == NULL) {
- fprintf(stderr, "%s: cannot create temporary file (%s)\n",
- progname, tname);
- done(1);
- }
- unlink(tname);
- fcntl(fileno(tfile), F_SETFD, FD_CLOEXEC);
- fprintf(tfile, "\177 %0*lo !!!!!/!/!/!/!/!/!/!\n", TIMSIZ, 0L);
-}
-
-static mode_t
-cmask(struct stat *sp, int creation)
-{
- mode_t mask = 07777;
-
- if (myuid != 0 || oflag || creation) {
- if (sp->st_uid != myuid || sp->st_gid != mygid) {
- mask &= ~(mode_t)S_ISUID;
- if ((sp->st_mode&S_IFMT)!=S_IFDIR && sp->st_mode&0010)
- mask &= ~(mode_t)S_ISGID;
- if ((sp->st_mode&S_IFMT)==S_IFDIR && sp->st_gid!=mygid)
- mask &= ~(mode_t)S_ISGID;
- }
- }
- return mask;
-}
-
-/*
- * Top-down splay function for inode tree.
- */
-static struct islot *
-isplay(ino_t ino, struct islot *x)
-{
- struct islot hdr;
- struct islot *leftmax, *rightmin;
- struct islot *y;
-
- hdr.left = hdr.right = inull;
- leftmax = rightmin = &hdr;
- inull->inum = ino;
- while (ino != x->inum) {
- if (ino < x->inum) {
- if (ino < x->left->inum) {
- y = x->left;
- x->left = y->right;
- y->right = x;
- x = y;
- }
- if (x->left == inull)
- break;
- rightmin->left = x;
- rightmin = x;
- x = x->left;
- } else {
- if (ino > x->right->inum) {
- y = x->right;
- x->right = y->left;
- y->left = x;
- x = y;
- }
- if (x->right == inull)
- break;
- leftmax->right = x;
- leftmax = x;
- x = x->right;
- }
- }
- leftmax->right = x->left;
- rightmin->left = x->right;
- x->left = hdr.right;
- x->right = hdr.left;
- inull->inum = !ino;
- return x;
-}
-
-/*
- * Find the inode number ino.
- */
-static struct islot *
-ifind(ino_t ino, struct islot **it)
-{
- if (*it == NULL)
- return NULL;
- *it = isplay(ino, *it);
- return (*it)->inum == ino ? *it : NULL;
-}
-
-/*
- * Put ik into the tree.
- */
-static void
-iput(struct islot *ik, struct islot **it)
-{
- if ((*it) == NULL) {
- ik->left = ik->right = inull;
- (*it) = ik;
- } else {
- /* ifind() is always called before */
- /*(*it) = isplay(ik->inum, (*it));*/
- if (ik->inum < (*it)->inum) {
- ik->left = (*it)->left;
- ik->right = (*it);
- (*it)->left = inull;
- (*it) = ik;
- } else if ((*it)->inum < ik->inum) {
- ik->right = (*it)->right;
- ik->left = (*it);
- (*it)->right = inull;
- (*it) = ik;
- }
- }
-}
-
-/*
- * Find the device dev or add it to the device/inode forest if not
- * already present.
- */
-static struct dslot *
-dfind(struct dslot **root, dev_t dev)
-{
- struct dslot *ds, *dp;
-
- for (ds = *root, dp = NULL; ds; dp = ds, ds = ds->nextp)
- if (ds->devnum == dev)
- break;
- if (ds == NULL) {
- ds = scalloc(1, sizeof *ds);
- ds->devnum = dev;
- if (*root == NULL)
- *root = ds;
- else
- dp->nextp = ds;
- }
- return ds;
-}
-
-static char *
-sequence(void)
-{
- static char buf[25];
- static long long d;
-
- sprintf(buf, "%10.10lld", ++d);
- return buf;
-}
-
-static void
-docomp(const char *name)
-{
- int pd[2];
- struct stat ost;
-
- if (tapeblock >= 0) {
- fprintf(stderr, "%s: Refusing to write compressed data "
- "to tapes.\n", progname);
- done(1);
- }
- if (pipe(pd) < 0) {
- fprintf(stderr, "%s: pipe() failed\n", progname);
- done(1);
- }
- switch (fork()) {
- case 0:
- dup2(mt, 1);
- close(mt);
- ftruncate(1, 0);
- dup2(pd[0], 0);
- close(pd[0]);
- close(pd[1]);
- execlp(name, name, "-c", NULL);
- fprintf(stderr, "%s: could not exec %s\n", progname, name);
- _exit(0177);
- /*NOTREACHED*/
- case -1:
- fprintf(stderr, "%s: could not fork(), try again later\n",
- progname);
- done(1);
- /*NOTREACHED*/
- default:
- dup2(pd[1], mt);
- close(pd[0]);
- close(pd[1]);
- }
- ost = mtstat;
- domtstat();
- mtstat.st_dev = ost.st_dev;
- mtstat.st_ino = ost.st_ino;
-}
-
-static int
-utf8(const char *cp)
-{
- int c, n;
-
- while (*cp) if ((c = *cp++ & 0377) & 0200) {
- if (c == (c & 037 | 0300))
- n = 1;
- else if (c == (c & 017 | 0340))
- n = 2;
- else if (c == (c & 07 | 0360))
- n = 3;
- else if (c == (c & 03 | 0370))
- n = 4;
- else if (c == (c & 01 | 0374))
- n = 5;
- else
- return 0;
- while (n--) {
- c = *cp++ & 0377;
- if (c != (c & 077 | 0200))
- return 0;
- }
- }
- return 1;
-}
-
-static void
-settmp(char *tbuf, size_t len, const char *template)
-{
- char *tmpdir;
-
- if ((tmpdir = getenv("TMPDIR")) == NULL)
- tmpdir = "/tmp";
- if (snprintf(tbuf, len, template, tmpdir) >= len)
- snprintf(tbuf, len, template, "/tmp");
-}
diff --git a/tar/tar.dfl b/tar/tar.dfl
@@ -1,9 +0,0 @@
-#
-# Sccsid @(#)tar.dfl 1.4 (gritter) 2/4/04
-
-archive=/dev/rmt/c0s0 20 0
-
-archive0=/dev/dsk/f0t 18 1440
-archive1=/dev/dsk/f1t 15 1200
-archive2=/dev/cdrom/c1t0d0 20 0
-archive3=/dev/cdrom/c1t0d1 20 0