Home | History | Annotate | Download | only in tar
      1     0    stevel /*
      2     0    stevel  * CDDL HEADER START
      3     0    stevel  *
      4     0    stevel  * The contents of this file are subject to the terms of the
      5  1676       jpk  * Common Development and Distribution License (the "License").
      6  1676       jpk  * You may not use this file except in compliance with the License.
      7     0    stevel  *
      8     0    stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9     0    stevel  * or http://www.opensolaris.org/os/licensing.
     10     0    stevel  * See the License for the specific language governing permissions
     11     0    stevel  * and limitations under the License.
     12     0    stevel  *
     13     0    stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14     0    stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15     0    stevel  * If applicable, add the following below this CDDL HEADER, with the
     16     0    stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17     0    stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18     0    stevel  *
     19     0    stevel  * CDDL HEADER END
     20     0    stevel  */
     21     0    stevel /*
     22  9694     Scott  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23     0    stevel  * Use is subject to license terms.
     24     0    stevel  */
     25     0    stevel 
     26     0    stevel /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
     27     0    stevel /*	  All Rights Reserved  	*/
     28     0    stevel 
     29     0    stevel /*	Copyright (c) 1987, 1988 Microsoft Corporation	*/
     30     0    stevel /*	  All Rights Reserved	*/
     31     0    stevel 
     32     0    stevel /*
     33     0    stevel  * Portions of this source code were derived from Berkeley 4.3 BSD
     34     0    stevel  * under license from the Regents of the University of California.
     35     0    stevel  */
     36     0    stevel 
     37     0    stevel #include <unistd.h>
     38     0    stevel #include <sys/types.h>
     39     0    stevel #include <sys/param.h>
     40     0    stevel #include <sys/stat.h>
     41     0    stevel #include <sys/mkdev.h>
     42     0    stevel #include <sys/wait.h>
     43     0    stevel #include <dirent.h>
     44     0    stevel #include <errno.h>
     45     0    stevel #include <stdio.h>
     46     0    stevel #include <signal.h>
     47     0    stevel #include <ctype.h>
     48     0    stevel #include <locale.h>
     49     0    stevel #include <nl_types.h>
     50     0    stevel #include <langinfo.h>
     51     0    stevel #include <pwd.h>
     52     0    stevel #include <grp.h>
     53     0    stevel #include <fcntl.h>
     54     0    stevel #include <string.h>
     55     0    stevel #include <malloc.h>
     56     0    stevel #include <time.h>
     57     0    stevel #include <utime.h>
     58     0    stevel #include <stdlib.h>
     59     0    stevel #include <stdarg.h>
     60     0    stevel #include <widec.h>
     61     0    stevel #include <sys/mtio.h>
     62     0    stevel #include <sys/acl.h>
     63     0    stevel #include <strings.h>
     64     0    stevel #include <deflt.h>
     65     0    stevel #include <limits.h>
     66     0    stevel #include <iconv.h>
     67     0    stevel #include <assert.h>
     68  5331       amw #include <libgen.h>
     69  5331       amw #include <libintl.h>
     70   789    ahrens #include <aclutils.h>
     71  5331       amw #include <libnvpair.h>
     72  5331       amw #include <archives.h>
     73  4774  as145665 
     74     0    stevel #if defined(__SunOS_5_6) || defined(__SunOS_5_7)
     75     0    stevel extern int defcntl();
     76     0    stevel #endif
     77  5331       amw #if defined(_PC_SATTR_ENABLED)
     78  5331       amw #include <attr.h>
     79  5331       amw #include <libcmdutils.h>
     80  5331       amw #endif
     81     0    stevel 
     82  1676       jpk /* Trusted Extensions */
     83  1676       jpk #include <zone.h>
     84  1676       jpk #include <tsol/label.h>
     85  1676       jpk #include <sys/tsol/label_macro.h>
     86  1676       jpk 
     87  5331       amw #include "getresponse.h"
     88     0    stevel /*
     89     0    stevel  * Source compatibility
     90     0    stevel  */
     91     0    stevel 
     92     0    stevel /*
     93     0    stevel  * These constants come from archives.h and sys/fcntl.h
     94     0    stevel  * and were introduced by the extended attributes project
     95     0    stevel  * in Solaris 9.
     96     0    stevel  */
     97     0    stevel #if !defined(O_XATTR)
     98     0    stevel #define	AT_SYMLINK_NOFOLLOW	0x1000
     99     0    stevel #define	AT_REMOVEDIR		0x1
    100     0    stevel #define	AT_FDCWD		0xffd19553
    101     0    stevel #define	_XATTR_HDRTYPE		'E'
    102     0    stevel static int attropen();
    103     0    stevel static int fstatat();
    104     0    stevel static int renameat();
    105     0    stevel static int unlinkat();
    106     0    stevel static int openat();
    107     0    stevel static int fchownat();
    108     0    stevel static int futimesat();
    109     0    stevel #endif
    110     0    stevel 
    111     0    stevel /*
    112     0    stevel  * Compiling with -D_XPG4_2 gets this but produces other problems, so
    113     0    stevel  * instead of including sys/time.h and compiling with -D_XPG4_2, I'm
    114     0    stevel  * explicitly doing the declaration here.
    115     0    stevel  */
    116     0    stevel int utimes(const char *path, const struct timeval timeval_ptr[]);
    117     0    stevel 
    118     0    stevel #ifndef MINSIZE
    119     0    stevel #define	MINSIZE 250
    120     0    stevel #endif
    121     0    stevel #define	DEF_FILE "/etc/default/tar"
    122     0    stevel 
    123     0    stevel #define	min(a, b)  ((a) < (b) ? (a) : (b))
    124     0    stevel #define	max(a, b)  ((a) > (b) ? (a) : (b))
    125     0    stevel 
    126     0    stevel /* -DDEBUG	ONLY for debugging */
    127     0    stevel #ifdef	DEBUG
    128     0    stevel #undef	DEBUG
    129     0    stevel #define	DEBUG(a, b, c)\
    130     0    stevel 	(void) fprintf(stderr, "DEBUG - "), (void) fprintf(stderr, a, b, c)
    131     0    stevel #endif
    132     0    stevel 
    133     0    stevel #define	TBLOCK	512	/* tape block size--should be universal */
    134     0    stevel 
    135     0    stevel #ifdef	BSIZE
    136     0    stevel #define	SYS_BLOCK BSIZE	/* from sys/param.h:  secondary block size */
    137     0    stevel #else	/* BSIZE */
    138     0    stevel #define	SYS_BLOCK 512	/* default if no BSIZE in param.h */
    139     0    stevel #endif	/* BSIZE */
    140     0    stevel 
    141     0    stevel #define	NBLOCK	20
    142     0    stevel #define	NAMSIZ	100
    143     0    stevel #define	PRESIZ	155
    144     0    stevel #define	MAXNAM	256
    145     0    stevel #define	MODEMASK 0777777	/* file creation mode mask */
    146     0    stevel #define	POSIXMODES 07777	/* mask for POSIX mode bits */
    147     0    stevel #define	MAXEXT	9	/* reasonable max # extents for a file */
    148     0    stevel #define	EXTMIN	50	/* min blks left on floppy to split a file */
    149     0    stevel 
    150     0    stevel /* max value dblock.dbuf.efsize can store */
    151     0    stevel #define	TAR_EFSIZE_MAX	 0777777777
    152     0    stevel 
    153     0    stevel /*
    154     0    stevel  * Symbols which specify the values at which the use of the 'E' function
    155     0    stevel  * modifier is required to properly store a file.
    156     0    stevel  *
    157     0    stevel  *     TAR_OFFSET_MAX    - the largest file size we can archive
    158     0    stevel  *     OCTAL7CHAR        - the limit for ustar gid, uid, dev
    159     0    stevel  */
    160     0    stevel 
    161     0    stevel #ifdef XHDR_DEBUG
    162     0    stevel /* tiny values which force the creation of extended header entries */
    163     0    stevel #define	TAR_OFFSET_MAX 9
    164     0    stevel #define	OCTAL7CHAR 2
    165     0    stevel #else
    166     0    stevel /* normal values */
    167   373   ceastha #define	TAR_OFFSET_MAX	077777777777ULL
    168     0    stevel #define	OCTAL7CHAR	07777777
    169     0    stevel #endif
    170     0    stevel 
    171     0    stevel #define	TBLOCKS(bytes)	(((bytes) + TBLOCK - 1) / TBLOCK)
    172     0    stevel #define	K(tblocks)	((tblocks+1)/2)	/* tblocks to Kbytes for printing */
    173     0    stevel 
    174     0    stevel #define	MAXLEV	(PATH_MAX / 2)
    175     0    stevel #define	LEV0	1
    176     0    stevel #define	SYMLINK_LEV0	0
    177     0    stevel 
    178     0    stevel #define	TRUE	1
    179     0    stevel #define	FALSE	0
    180     0    stevel 
    181     0    stevel #define	XATTR_FILE	1
    182     0    stevel #define	NORMAL_FILE	0
    183     0    stevel 
    184     0    stevel #define	PUT_AS_LINK	1
    185     0    stevel #define	PUT_NOTAS_LINK	0
    186     0    stevel 
    187  5331       amw #ifndef VIEW_READONLY
    188  5331       amw #define	VIEW_READONLY	"SUNWattr_ro"
    189  5331       amw #endif
    190  5331       amw 
    191  5331       amw #ifndef VIEW_READWRITE
    192  5331       amw #define	VIEW_READWRITE	"SUNWattr_rw"
    193  5331       amw #endif
    194  5331       amw 
    195     0    stevel #if _FILE_OFFSET_BITS == 64
    196     0    stevel #define	FMT_off_t "lld"
    197     0    stevel #define	FMT_off_t_o "llo"
    198     0    stevel #define	FMT_blkcnt_t "lld"
    199     0    stevel #else
    200     0    stevel #define	FMT_off_t "ld"
    201     0    stevel #define	FMT_off_t_o "lo"
    202     0    stevel #define	FMT_blkcnt_t "ld"
    203     0    stevel #endif
    204     0    stevel 
    205     0    stevel /* ACL support */
    206     0    stevel 
    207     0    stevel static
    208     0    stevel struct	sec_attr {
    209     0    stevel 	char	attr_type;
    210     0    stevel 	char	attr_len[7];
    211     0    stevel 	char	attr_info[1];
    212     0    stevel } *attr;
    213  5331       amw 
    214  5331       amw #if defined(O_XATTR)
    215  5331       amw typedef enum {
    216  5331       amw 	ATTR_OK,
    217  5331       amw 	ATTR_SKIP,
    218  5331       amw 	ATTR_CHDIR_ERR,
    219  5331       amw 	ATTR_OPEN_ERR,
    220  5331       amw 	ATTR_XATTR_ERR,
    221  5331       amw 	ATTR_SATTR_ERR
    222  5331       amw } attr_status_t;
    223  5331       amw #endif
    224  5331       amw 
    225  5331       amw #if defined(O_XATTR)
    226  5331       amw typedef enum {
    227  5331       amw 	ARC_CREATE,
    228  5331       amw 	ARC_RESTORE
    229  5331       amw } arc_action_t;
    230  5331       amw #endif
    231  5331       amw 
    232  5331       amw typedef struct attr_data {
    233  5331       amw 	char	*attr_parent;
    234  5331       amw 	char	*attr_path;
    235  5331       amw 	int	attr_parentfd;
    236  5331       amw 	int	attr_rw_sysattr;
    237  5331       amw } attr_data_t;
    238     0    stevel 
    239     0    stevel /*
    240     0    stevel  *
    241     0    stevel  * Tar has been changed to support extended attributes.
    242     0    stevel  *
    243     0    stevel  * As part of this change tar now uses the new *at() syscalls
    244     0    stevel  * such as openat, fchownat(), unlinkat()...
    245     0    stevel  *
    246     0    stevel  * This was done so that attributes can be handled with as few code changes
    247     0    stevel  * as possible.
    248     0    stevel  *
    249     0    stevel  * What this means is that tar now opens the directory that a file or directory
    250     0    stevel  * resides in and then performs *at() functions to manipulate the entry.
    251     0    stevel  *
    252     0    stevel  * For example a new file is now created like this:
    253     0    stevel  *
    254     0    stevel  * dfd = open(<some dir path>)
    255     0    stevel  * fd = openat(dfd, <name>,....);
    256     0    stevel  *
    257     0    stevel  * or in the case of an extended attribute
    258     0    stevel  *
    259     0    stevel  * dfd = attropen(<pathname>, ".", ....)
    260     0    stevel  *
    261     0    stevel  * Once we have a directory file descriptor all of the *at() functions can
    262     0    stevel  * be applied to it.
    263     0    stevel  *
    264     0    stevel  * unlinkat(dfd, <component name>,...)
    265     0    stevel  * fchownat(dfd, <component name>,..)
    266     0    stevel  *
    267     0    stevel  * This works for both normal namespace files and extended attribute file
    268     0    stevel  *
    269     0    stevel  */
    270     0    stevel 
    271     0    stevel /*
    272     0    stevel  *
    273     0    stevel  * Extended attribute Format
    274     0    stevel  *
    275     0    stevel  * Extended attributes are stored in two pieces.
    276     0    stevel  * 1. An attribute header which has information about
    277     0    stevel  *    what file the attribute is for and what the attribute
    278     0    stevel  *    is named.
    279     0    stevel  * 2. The attribute record itself.  Stored as a normal file type
    280     0    stevel  *    of entry.
    281     0    stevel  * Both the header and attribute record have special modes/typeflags
    282     0    stevel  * associated with them.
    283     0    stevel  *
    284     0    stevel  * The names of the header in the archive look like:
    285     0    stevel  * /dev/null/attr.hdr
    286     0    stevel  *
    287     0    stevel  * The name of the attribute looks like:
    288     0    stevel  * /dev/null/attr
    289     0    stevel  *
    290     0    stevel  * This is done so that an archiver that doesn't understand these formats
    291     0    stevel  * can just dispose of the attribute records.
    292     0    stevel  *
    293     0    stevel  * The format is composed of a fixed size header followed
    294     0    stevel  * by a variable sized xattr_buf. If the attribute is a hard link
    295     0    stevel  * to another attribute then another xattr_buf section is included
    296     0    stevel  * for the link.
    297     0    stevel  *
    298     0    stevel  * The xattr_buf is used to define the necessary "pathing" steps
    299     0    stevel  * to get to the extended attribute.  This is necessary to support
    300     0    stevel  * a fully recursive attribute model where an attribute may itself
    301     0    stevel  * have an attribute.
    302     0    stevel  *
    303     0    stevel  * The basic layout looks like this.
    304     0    stevel  *
    305     0    stevel  *     --------------------------------
    306     0    stevel  *     |                              |
    307     0    stevel  *     |         xattr_hdr            |
    308     0    stevel  *     |                              |
    309     0    stevel  *     --------------------------------
    310     0    stevel  *     --------------------------------
    311     0    stevel  *     |                              |
    312     0    stevel  *     |        xattr_buf             |
    313     0    stevel  *     |                              |
    314     0    stevel  *     --------------------------------
    315     0    stevel  *     --------------------------------
    316     0    stevel  *     |                              |
    317     0    stevel  *     |      (optional link info)    |
    318     0    stevel  *     |                              |
    319     0    stevel  *     --------------------------------
    320     0    stevel  *     --------------------------------
    321     0    stevel  *     |                              |
    322     0    stevel  *     |      attribute itself        |
    323     0    stevel  *     |      stored as normal tar    |
    324     0    stevel  *     |      or cpio data with       |
    325     0    stevel  *     |      special mode or         |
    326     0    stevel  *     |      typeflag                |
    327     0    stevel  *     |                              |
    328     0    stevel  *     --------------------------------
    329     0    stevel  *
    330     0    stevel  */
    331     0    stevel 
    332     0    stevel /*
    333     0    stevel  * xattrhead is a pointer to the xattr_hdr
    334     0    stevel  *
    335     0    stevel  * xattrp is a pointer to the xattr_buf structure
    336     0    stevel  * which contains the "pathing" steps to get to attributes
    337     0    stevel  *
    338     0    stevel  * xattr_linkp is a pointer to another xattr_buf structure that is
    339     0    stevel  * only used when an attribute is actually linked to another attribute
    340     0    stevel  *
    341     0    stevel  */
    342     0    stevel 
    343     0    stevel static struct xattr_hdr *xattrhead;
    344     0    stevel static struct xattr_buf *xattrp;
    345     0    stevel static struct xattr_buf *xattr_linkp;	/* pointer to link info, if any */
    346  5331       amw static char *xattrapath;		/* attribute name */
    347     0    stevel static char *xattr_linkaname;		/* attribute attribute is linked to */
    348     0    stevel static char Hiddendir;			/* are we processing hidden xattr dir */
    349     0    stevel static char xattrbadhead;
    350     0    stevel 
    351     0    stevel /* Was statically allocated tbuf[NBLOCK] */
    352     0    stevel static
    353     0    stevel union hblock {
    354     0    stevel 	char dummy[TBLOCK];
    355     0    stevel 	struct header {
    356     0    stevel 		char name[NAMSIZ];	/* If non-null prefix, path is	*/
    357     0    stevel 					/* <prefix>/<name>;  otherwise	*/
    358     0    stevel 					/* <name>			*/
    359     0    stevel 		char mode[8];
    360     0    stevel 		char uid[8];
    361     0    stevel 		char gid[8];
    362     0    stevel 		char size[12];		/* size of this extent if file split */
    363     0    stevel 		char mtime[12];
    364     0    stevel 		char chksum[8];
    365     0    stevel 		char typeflag;
    366     0    stevel 		char linkname[NAMSIZ];
    367     0    stevel 		char magic[6];
    368     0    stevel 		char version[2];
    369     0    stevel 		char uname[32];
    370     0    stevel 		char gname[32];
    371     0    stevel 		char devmajor[8];
    372     0    stevel 		char devminor[8];
    373     0    stevel 		char prefix[PRESIZ];	/* Together with "name", the path of */
    374     0    stevel 					/* the file:  <prefix>/<name>	*/
    375     0    stevel 		char extno;		/* extent #, null if not split */
    376     0    stevel 		char extotal;		/* total extents */
    377     0    stevel 		char efsize[10];	/* size of entire file */
    378     0    stevel 	} dbuf;
    379     0    stevel } dblock, *tbuf, xhdr_buf;
    380     0    stevel 
    381     0    stevel static
    382     0    stevel struct xtar_hdr {
    383     0    stevel 	uid_t		x_uid,		/* Uid of file */
    384     0    stevel 			x_gid;		/* Gid of file */
    385     0    stevel 	major_t		x_devmajor;	/* Device major node */
    386     0    stevel 	minor_t		x_devminor;	/* Device minor node */
    387     0    stevel 	off_t		x_filesz;	/* Length of file */
    388     0    stevel 	char		*x_uname,	/* Pointer to name of user */
    389     0    stevel 			*x_gname,	/* Pointer to gid of user */
    390     0    stevel 			*x_linkpath,	/* Path for a hard/symbolic link */
    391     0    stevel 			*x_path;	/* Path of file */
    392     0    stevel 	timestruc_t	x_mtime;	/* Seconds and nanoseconds */
    393     0    stevel } Xtarhdr;
    394     0    stevel 
    395     0    stevel static
    396     0    stevel struct gen_hdr {
    397     0    stevel 	ulong_t		g_mode;		/* Mode of file */
    398     0    stevel 	uid_t		g_uid,		/* Uid of file */
    399     0    stevel 			g_gid;		/* Gid of file */
    400     0    stevel 	off_t		g_filesz;	/* Length of file */
    401     0    stevel 	time_t		g_mtime;	/* Modification time */
    402     0    stevel 	uint_t		g_cksum;	/* Checksum of file */
    403     0    stevel 	ulong_t		g_devmajor,	/* File system of file */
    404     0    stevel 			g_devminor;	/* Major/minor of special files */
    405     0    stevel } Gen;
    406     0    stevel 
    407     0    stevel static
    408     0    stevel struct linkbuf {
    409     0    stevel 	ino_t	inum;
    410     0    stevel 	dev_t	devnum;
    411     0    stevel 	int	count;
    412     0    stevel 	char	pathname[MAXNAM+1];	/* added 1 for last NULL */
    413     0    stevel 	char 	attrname[MAXNAM+1];
    414     0    stevel 	struct	linkbuf *nextp;
    415     0    stevel } *ihead;
    416     0    stevel 
    417     0    stevel /* see comments before build_table() */
    418     0    stevel #define	TABLE_SIZE 512
    419  6525   ceastha typedef struct	file_list	{
    420     0    stevel 	char	*name;			/* Name of file to {in,ex}clude */
    421     0    stevel 	struct	file_list	*next;	/* Linked list */
    422  6525   ceastha } file_list_t;
    423  6525   ceastha static	file_list_t	*exclude_tbl[TABLE_SIZE],
    424  6525   ceastha 			*include_tbl[TABLE_SIZE];
    425     0    stevel 
    426  1676       jpk static int	append_secattr(char **, int *, int, char *, char);
    427     0    stevel static void	write_ancillary(union hblock *, char *, int, char);
    428     0    stevel 
    429  6525   ceastha static void add_file_to_table(file_list_t *table[], char *str);
    430     0    stevel static void assert_string(char *s, char *msg);
    431     0    stevel static int istape(int fd, int type);
    432     0    stevel static void backtape(void);
    433  6525   ceastha static void build_table(file_list_t *table[], char *file);
    434  5331       amw static int check_prefix(char **namep, char **dirp, char **compp);
    435     0    stevel static void closevol(void);
    436     0    stevel static void copy(void *dst, void *src);
    437     0    stevel static int convtoreg(off_t);
    438  3805    lovely static void delete_target(int fd, char *comp, char *namep);
    439     0    stevel static void doDirTimes(char *name, timestruc_t modTime);
    440     0    stevel static void done(int n);
    441     0    stevel static void dorep(char *argv[]);
    442     0    stevel #ifdef	_iBCS2
    443     0    stevel static void dotable(char *argv[], int cnt);
    444     0    stevel static void doxtract(char *argv[], int cnt);
    445     0    stevel #else
    446     0    stevel static void dotable(char *argv[]);
    447     0    stevel static void doxtract(char *argv[]);
    448     0    stevel #endif
    449     0    stevel static void fatal(char *format, ...);
    450     0    stevel static void vperror(int exit_status, char *fmt, ...);
    451     0    stevel static void flushtape(void);
    452     0    stevel static void getdir(void);
    453     0    stevel static void *getmem(size_t);
    454     0    stevel static void longt(struct stat *st, char aclchar);
    455  5482  as158974 static void load_info_from_xtarhdr(u_longlong_t flag, struct xtar_hdr *xhdrp);
    456     0    stevel static int makeDir(char *name);
    457     0    stevel static void mterr(char *operation, int i, int exitcode);
    458     0    stevel static void newvol(void);
    459     0    stevel static void passtape(void);
    460     0    stevel static void putempty(blkcnt_t n);
    461     0    stevel static int putfile(char *longname, char *shortname, char *parent,
    462  5331       amw     attr_data_t *attrinfo, int filetype, int lev, int symlink_lev);
    463     0    stevel static void readtape(char *buffer);
    464     0    stevel static void seekdisk(blkcnt_t blocks);
    465     0    stevel static void setPathTimes(int dirfd, char *path, timestruc_t modTime);
    466  5482  as158974 static void setbytes_to_skip(struct stat *st, int err);
    467     0    stevel static void splitfile(char *longname, int ifd, char *name,
    468     0    stevel 	char *prefix, int filetype);
    469     0    stevel static void tomodes(struct stat *sp);
    470     0    stevel static void usage(void);
    471  5331       amw static int xblocks(int issysattr, off_t bytes, int ofile);
    472  5331       amw static int xsfile(int issysattr, int ofd);
    473     0    stevel static void resugname(int dirfd, char *name, int symflag);
    474     0    stevel static int bcheck(char *bstr);
    475     0    stevel static int checkdir(char *name);
    476     0    stevel static int checksum(union hblock *dblockp);
    477     0    stevel #ifdef	EUC
    478     0    stevel static int checksum_signed(union hblock *dblockp);
    479     0    stevel #endif	/* EUC */
    480     0    stevel static int checkupdate(char *arg);
    481     0    stevel static int checkw(char c, char *name);
    482     0    stevel static int cmp(char *b, char *s, int n);
    483     0    stevel static int defset(char *arch);
    484     0    stevel static int endtape(void);
    485  6525   ceastha static int is_in_table(file_list_t *table[], char *str);
    486     0    stevel static int notsame(void);
    487     0    stevel static int is_prefix(char *s1, char *s2);
    488     0    stevel static int response(void);
    489     0    stevel static int build_dblock(const char *, const char *, const char,
    490     0    stevel 	const int filetype, const struct stat *, const dev_t, const char *);
    491     0    stevel static unsigned int hash(char *str);
    492     0    stevel 
    493     0    stevel #ifdef	_iBCS2
    494     0    stevel static void initarg(char *argv[], char *file);
    495     0    stevel static char *nextarg();
    496     0    stevel #endif
    497     0    stevel static blkcnt_t kcheck(char *kstr);
    498     0    stevel static off_t bsrch(char *s, int n, off_t l, off_t h);
    499     0    stevel static void onintr(int sig);
    500     0    stevel static void onquit(int sig);
    501     0    stevel static void onhup(int sig);
    502     0    stevel static uid_t getuidbyname(char *);
    503     0    stevel static gid_t getgidbyname(char *);
    504     0    stevel static char *getname(gid_t);
    505     0    stevel static char *getgroup(gid_t);
    506     0    stevel static int checkf(char *name, int mode, int howmuch);
    507     0    stevel static int writetbuf(char *buffer, int n);
    508  5331       amw static int wantit(char *argv[], char **namep, char **dirp, char **comp,
    509  5331       amw     attr_data_t **attrinfo);
    510  1676       jpk static void append_ext_attr(char *shortname, char **secinfo, int *len);
    511     0    stevel static int get_xdata(void);
    512     0    stevel static void gen_num(const char *keyword, const u_longlong_t number);
    513     0    stevel static void gen_date(const char *keyword, const timestruc_t time_value);
    514     0    stevel static void gen_string(const char *keyword, const char *value);
    515     0    stevel static void get_xtime(char *value, timestruc_t *xtime);
    516     0    stevel static int chk_path_build(char *name, char *longname, char *linkname,
    517     0    stevel     char *prefix, char type, int filetype);
    518     0    stevel static int gen_utf8_names(const char *filename);
    519     0    stevel static int utf8_local(char *option, char **Xhdr_ptrptr, char *target,
    520     0    stevel     const char *src, int max_val);
    521     0    stevel static int local_utf8(char **Xhdr_ptrptr, char *target, const char *src,
    522     0    stevel     iconv_t iconv_cd, int xhdrflg, int max_val);
    523     0    stevel static int c_utf8(char *target, const char *source);
    524  5331       amw static int getstat(int dirfd, char *longname, char *shortname,
    525  5331       amw     char *attrparent);
    526  5331       amw static void xattrs_put(char *, char *, char *, char *);
    527     0    stevel static void prepare_xattr(char **, char	*, char	*,
    528     0    stevel     char, struct linkbuf *, int *);
    529  5331       amw static int put_link(char *name, char *longname, char *component,
    530  5331       amw     char *longattrname, char *prefix, int filetype, char typeflag);
    531     0    stevel static int put_extra_attributes(char *longname, char *shortname,
    532  5331       amw     char *longattrname, char *prefix, int filetype, char typeflag);
    533  5331       amw static int put_xattr_hdr(char *longname, char *shortname, char *longattrname,
    534  5331       amw     char *prefix, int typeflag, int filetype, struct linkbuf *lp);
    535  5331       amw static int read_xattr_hdr(attr_data_t **attrinfo);
    536  1676       jpk 
    537  1676       jpk /* Trusted Extensions */
    538  1676       jpk #define	AUTO_ZONE	"/zone"
    539  1676       jpk 
    540  1676       jpk static void extract_attr(char **file_ptr, struct sec_attr *);
    541  1676       jpk static int check_ext_attr(char *filename);
    542  1676       jpk static void rebuild_comp_path(char *str, char **namep);
    543  1676       jpk static int rebuild_lk_comp_path(char *str, char **namep);
    544  1676       jpk 
    545     0    stevel static void get_parent(char *path, char *dir);
    546     0    stevel static char *get_component(char *path);
    547  5331       amw static int retry_open_attr(int pdirfd, int cwd, char *dirp, char *pattr,
    548  5331       amw     char *name, int oflag, mode_t mode);
    549     0    stevel static char *skipslashes(char *string, char *start);
    550     0    stevel static void chop_endslashes(char *path);
    551   789    ahrens 
    552     0    stevel static	struct stat stbuf;
    553     0    stevel 
    554  5331       amw static	char	*myname;
    555     0    stevel static	int	checkflag = 0;
    556     0    stevel #ifdef	_iBCS2
    557     0    stevel static	int	Fileflag;
    558     0    stevel char    *sysv3_env;
    559     0    stevel #endif
    560     0    stevel static	int	Xflag, Fflag, iflag, hflag, Bflag, Iflag;
    561     0    stevel static	int	rflag, xflag, vflag, tflag, mt, cflag, mflag, pflag;
    562     0    stevel static	int	uflag;
    563     0    stevel static	int	eflag, errflag, qflag;
    564     0    stevel static	int	oflag;
    565     0    stevel static	int	bflag, kflag, Aflag;
    566     0    stevel static 	int	Pflag;			/* POSIX conformant archive */
    567     0    stevel static	int	Eflag;			/* Allow files greater than 8GB */
    568     0    stevel static	int	atflag;			/* traverse extended attributes */
    569  5331       amw static	int	saflag;			/* traverse extended sys attributes */
    570     0    stevel static	int	Dflag;			/* Data change flag */
    571  1676       jpk /* Trusted Extensions */
    572  1676       jpk static	int	Tflag;			/* Trusted Extensions attr flags */
    573  1676       jpk static	int	dir_flag;		/* for attribute extract */
    574  1676       jpk static	int	mld_flag;		/* for attribute extract */
    575  1676       jpk static	char	*orig_namep;		/* original namep - unadorned */
    576  1676       jpk static	int	rpath_flag;		/* MLD real path is rebuilt */
    577  1676       jpk static	char	real_path[MAXPATHLEN];	/* MLD real path */
    578  1676       jpk static	int	lk_rpath_flag;		/* linked to real path is rebuilt */
    579  1676       jpk static	char	lk_real_path[MAXPATHLEN]; /* linked real path */
    580  1676       jpk static	bslabel_t	bs_label;	/* for attribute extract */
    581  1676       jpk static	bslabel_t	admin_low;
    582  1676       jpk static	bslabel_t	admin_high;
    583  1676       jpk static	int	ignored_aprivs = 0;
    584  1676       jpk static	int	ignored_fprivs = 0;
    585  1676       jpk static	int	ignored_fattrs = 0;
    586  1676       jpk 
    587     0    stevel static	int	term, chksum, wflag,
    588     0    stevel 		first = TRUE, defaults_used = FALSE, linkerrok;
    589     0    stevel static	blkcnt_t	recno;
    590     0    stevel static	int	freemem = 1;
    591     0    stevel static	int	nblock = NBLOCK;
    592     0    stevel static	int	Errflg = 0;
    593     0    stevel static	int	exitflag = 0;
    594     0    stevel 
    595     0    stevel static	dev_t	mt_dev;		/* device containing output file */
    596     0    stevel static	ino_t	mt_ino;		/* inode number of output file */
    597     0    stevel static	int	mt_devtype;	/* dev type of archive, from stat structure */
    598     0    stevel 
    599     0    stevel static	int update = 1;		/* for `open' call */
    600     0    stevel 
    601     0    stevel static	off_t	low;
    602     0    stevel static	off_t	high;
    603     0    stevel 
    604     0    stevel static	FILE	*tfile;
    605     0    stevel static	FILE	*vfile = stdout;
    606     0    stevel static	char	tname[] = "/tmp/tarXXXXXX";
    607     0    stevel static	char	archive[] = "archive0=";
    608     0    stevel static	char	*Xfile;
    609     0    stevel static	char	*usefile;
    610     0    stevel static	char	*Filefile;
    611     0    stevel 
    612     0    stevel static	int	mulvol;		/* multi-volume option selected */
    613     0    stevel static	blkcnt_t	blocklim; /* number of blocks to accept per volume */
    614     0    stevel static	blkcnt_t	tapepos; /* current block number to be written */
    615     0    stevel static	int	NotTape;	/* true if tape is a disk */
    616     0    stevel static	int	dumping;	/* true if writing a tape or other archive */
    617     0    stevel static	int	extno;		/* number of extent:  starts at 1 */
    618     0    stevel static	int	extotal;	/* total extents in this file */
    619     0    stevel static	off_t	extsize;	/* size of current extent during extraction */
    620     0    stevel static	ushort_t	Oumask = 0;	/* old umask value */
    621     0    stevel static 	int is_posix;	/* true if archive we're reading is POSIX-conformant */
    622     0    stevel static	const	char	*magic_type = "ustar";
    623     0    stevel static	size_t	xrec_size = 8 * PATH_MAX;	/* extended rec initial size */
    624     0    stevel static	char	*xrec_ptr;
    625     0    stevel static	off_t	xrec_offset = 0;
    626     0    stevel static	int	Xhdrflag;
    627     0    stevel static	int	charset_type = 0;
    628     0    stevel 
    629     0    stevel static	u_longlong_t	xhdr_flgs;	/* Bits set determine which items */
    630     0    stevel 					/*   need to be in extended header. */
    631     0    stevel #define	_X_DEVMAJOR	0x1
    632     0    stevel #define	_X_DEVMINOR	0x2
    633     0    stevel #define	_X_GID		0x4
    634     0    stevel #define	_X_GNAME	0x8
    635     0    stevel #define	_X_LINKPATH	0x10
    636     0    stevel #define	_X_PATH		0x20
    637     0    stevel #define	_X_SIZE		0x40
    638     0    stevel #define	_X_UID		0x80
    639     0    stevel #define	_X_UNAME	0x100
    640     0    stevel #define	_X_ATIME	0x200
    641     0    stevel #define	_X_CTIME	0x400
    642     0    stevel #define	_X_MTIME	0x800
    643  5482  as158974 #define	_X_XHDR		0x1000	/* Bit flag that determines whether 'X' */
    644  5482  as158974 				/* typeflag was followed by 'A' or non 'A' */
    645  5482  as158974 				/* typeflag. */
    646     0    stevel #define	_X_LAST		0x40000000
    647     0    stevel 
    648     0    stevel #define	PID_MAX_DIGITS		(10 * sizeof (pid_t) / 4)
    649     0    stevel #define	TIME_MAX_DIGITS		(10 * sizeof (time_t) / 4)
    650     0    stevel #define	LONG_MAX_DIGITS		(10 * sizeof (long) / 4)
    651     0    stevel #define	ULONGLONG_MAX_DIGITS	(10 * sizeof (u_longlong_t) / 4)
    652     0    stevel /*
    653     0    stevel  * UTF_8 encoding requires more space than the current codeset equivalent.
    654     0    stevel  * Currently a factor of 2-3 would suffice, but it is possible for a factor
    655     0    stevel  * of 6 to be needed in the future, so for saftey, we use that here.
    656     0    stevel  */
    657     0    stevel #define	UTF_8_FACTOR	6
    658     0    stevel 
    659     0    stevel static	u_longlong_t	xhdr_count = 0;
    660     0    stevel static char		xhdr_dirname[PRESIZ + 1];
    661     0    stevel static char		pidchars[PID_MAX_DIGITS + 1];
    662     0    stevel static char		*tchar = "";		/* null linkpath */
    663     0    stevel 
    664     0    stevel static	char	local_path[UTF_8_FACTOR * PATH_MAX + 1];
    665     0    stevel static	char	local_linkpath[UTF_8_FACTOR * PATH_MAX + 1];
    666     0    stevel static	char	local_gname[UTF_8_FACTOR * _POSIX_NAME_MAX + 1];
    667     0    stevel static	char	local_uname[UTF_8_FACTOR * _POSIX_NAME_MAX + 1];
    668     0    stevel 
    669     0    stevel /*
    670     0    stevel  * The following mechanism is provided to allow us to debug tar in complicated
    671     0    stevel  * situations, like when it is part of a pipe.  The idea is that you compile
    672     0    stevel  * with -DWAITAROUND defined, and then add the 'z' function modifier to the
    673     0    stevel  * target tar invocation, eg. "tar czf tarfile file".  If stderr is available,
    674     0    stevel  * it will tell you to which pid to attach the debugger; otherwise, use ps to
    675     0    stevel  * find it.  Attach to the process from the debugger, and, *PRESTO*, you are
    676     0    stevel  * there!
    677     0    stevel  *
    678     0    stevel  * Simply assign "waitaround = 0" once you attach to the process, and then
    679     0    stevel  * proceed from there as usual.
    680     0    stevel  */
    681     0    stevel 
    682     0    stevel #ifdef WAITAROUND
    683     0    stevel int waitaround = 0;		/* wait for rendezvous with the debugger */
    684     0    stevel #endif
    685     0    stevel 
    686     0    stevel 
    687     0    stevel int
    688     0    stevel main(int argc, char *argv[])
    689     0    stevel {
    690     0    stevel 	char		*cp;
    691     0    stevel 	char		*tmpdirp;
    692     0    stevel 	pid_t		thispid;
    693     0    stevel 
    694     0    stevel #ifdef	_iBCS2
    695     0    stevel 	int	tbl_cnt = 0;
    696     0    stevel 	sysv3_env = getenv("SYSV3");
    697     0    stevel #endif
    698     0    stevel 	(void) setlocale(LC_ALL, "");
    699     0    stevel #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
    700     0    stevel #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
    701     0    stevel #endif
    702     0    stevel 	(void) textdomain(TEXT_DOMAIN);
    703     0    stevel 	if (argc < 2)
    704     0    stevel 		usage();
    705     0    stevel 
    706     0    stevel 	tfile = NULL;
    707  5331       amw 	if ((myname = strdup(argv[0])) == NULL) {
    708  5331       amw 		(void) fprintf(stderr, gettext(
    709  5331       amw 		    "tar: cannot allocate program name\n"));
    710  5331       amw 		exit(1);
    711  5331       amw 	}
    712     0    stevel 
    713  4774  as145665 	if (init_yes() < 0) {
    714  4774  as145665 		(void) fprintf(stderr, gettext(ERR_MSG_INIT_YES),
    715  4774  as145665 		    strerror(errno));
    716  4774  as145665 		exit(2);
    717  4774  as145665 	}
    718  4774  as145665 
    719     0    stevel 	/*
    720     0    stevel 	 *  For XPG4 compatibility, we must be able to accept the "--"
    721     0    stevel 	 *  argument normally recognized by getopt; it is used to delimit
    722     0    stevel 	 *  the end opt the options section, and so can only appear in
    723     0    stevel 	 *  the position of the first argument.  We simply skip it.
    724     0    stevel 	 */
    725     0    stevel 
    726     0    stevel 	if (strcmp(argv[1], "--") == 0) {
    727     0    stevel 		argv++;
    728     0    stevel 		argc--;
    729     0    stevel 		if (argc < 3)
    730     0    stevel 			usage();
    731     0    stevel 	}
    732     0    stevel 
    733     0    stevel 	argv[argc] = NULL;
    734     0    stevel 	argv++;
    735     0    stevel 
    736     0    stevel 	/*
    737     0    stevel 	 * Set up default values.
    738     0    stevel 	 * Search the operand string looking for the first digit or an 'f'.
    739     0    stevel 	 * If you find a digit, use the 'archive#' entry in DEF_FILE.
    740     0    stevel 	 * If 'f' is given, bypass looking in DEF_FILE altogether.
    741     0    stevel 	 * If no digit or 'f' is given, still look in DEF_FILE but use '0'.
    742     0    stevel 	 */
    743     0    stevel 	if ((usefile = getenv("TAPE")) == (char *)NULL) {
    744     0    stevel 		for (cp = *argv; *cp; ++cp)
    745     0    stevel 			if (isdigit(*cp) || *cp == 'f')
    746     0    stevel 				break;
    747     0    stevel 		if (*cp != 'f') {
    748     0    stevel 			archive[7] = (*cp)? *cp: '0';
    749     0    stevel 			if (!(defaults_used = defset(archive))) {
    750     0    stevel 				usefile = NULL;
    751     0    stevel 				nblock = 1;
    752     0    stevel 				blocklim = 0;
    753     0    stevel 				NotTape = 0;
    754     0    stevel 			}
    755     0    stevel 		}
    756     0    stevel 	}
    757     0    stevel 
    758     0    stevel 	for (cp = *argv++; *cp; cp++)
    759     0    stevel 		switch (*cp) {
    760     0    stevel #ifdef WAITAROUND
    761     0    stevel 		case 'z':
    762     0    stevel 			/* rendezvous with the debugger */
    763     0    stevel 			waitaround = 1;
    764     0    stevel 			break;
    765     0    stevel #endif
    766     0    stevel 		case 'f':
    767     0    stevel 			assert_string(*argv, gettext(
    768     0    stevel 			    "tar: tarfile must be specified with 'f' "
    769     0    stevel 			    "function modifier\n"));
    770     0    stevel 			usefile = *argv++;
    771     0    stevel 			break;
    772     0    stevel 		case 'F':
    773     0    stevel #ifdef	_iBCS2
    774     0    stevel 			if (sysv3_env) {
    775     0    stevel 				assert_string(*argv, gettext(
    776  1266   ceastha 				    "tar: 'F' requires a file name\n"));
    777     0    stevel 				Filefile = *argv++;
    778     0    stevel 				Fileflag++;
    779     0    stevel 			} else
    780     0    stevel #endif	/*  _iBCS2 */
    781     0    stevel 				Fflag++;
    782     0    stevel 			break;
    783     0    stevel 		case 'c':
    784     0    stevel 			cflag++;
    785     0    stevel 			rflag++;
    786     0    stevel 			update = 1;
    787     0    stevel 			break;
    788     0    stevel #if defined(O_XATTR)
    789     0    stevel 		case '@':
    790     0    stevel 			atflag++;
    791     0    stevel 			break;
    792  5331       amw #endif	/* O_XATTR */
    793  5331       amw #if defined(_PC_SATTR_ENABLED)
    794  5331       amw 		case '/':
    795  5331       amw 			saflag++;
    796  5331       amw 			break;
    797  5331       amw #endif	/* _PC_SATTR_ENABLED */
    798     0    stevel 		case 'u':
    799     0    stevel 			uflag++;	/* moved code after signals caught */
    800     0    stevel 			rflag++;
    801     0    stevel 			update = 2;
    802     0    stevel 			break;
    803     0    stevel 		case 'r':
    804     0    stevel 			rflag++;
    805     0    stevel 			update = 2;
    806     0    stevel 			break;
    807     0    stevel 		case 'v':
    808     0    stevel 			vflag++;
    809     0    stevel 			break;
    810     0    stevel 		case 'w':
    811     0    stevel 			wflag++;
    812     0    stevel 			break;
    813     0    stevel 		case 'x':
    814     0    stevel 			xflag++;
    815     0    stevel 			break;
    816     0    stevel 		case 'X':
    817     0    stevel 			assert_string(*argv, gettext(
    818     0    stevel 			    "tar: exclude file must be specified with 'X' "
    819     0    stevel 			    "function modifier\n"));
    820     0    stevel 			Xflag = 1;
    821     0    stevel 			Xfile = *argv++;
    822     0    stevel 			build_table(exclude_tbl, Xfile);
    823     0    stevel 			break;
    824     0    stevel 		case 't':
    825     0    stevel 			tflag++;
    826     0    stevel 			break;
    827     0    stevel 		case 'm':
    828     0    stevel 			mflag++;
    829     0    stevel 			break;
    830     0    stevel 		case 'p':
    831     0    stevel 			pflag++;
    832     0    stevel 			break;
    833     0    stevel 		case 'D':
    834     0    stevel 			Dflag++;
    835     0    stevel 			break;
    836     0    stevel 		case '-':
    837     0    stevel 			/* ignore this silently */
    838     0    stevel 			break;
    839     0    stevel 		case '0':	/* numeric entries used only for defaults */
    840     0    stevel 		case '1':
    841     0    stevel 		case '2':
    842     0    stevel 		case '3':
    843     0    stevel 		case '4':
    844     0    stevel 		case '5':
    845     0    stevel 		case '6':
    846     0    stevel 		case '7':
    847     0    stevel 			break;
    848     0    stevel 		case 'b':
    849     0    stevel 			assert_string(*argv, gettext(
    850     0    stevel 			    "tar: blocking factor must be specified "
    851     0    stevel 			    "with 'b' function modifier\n"));
    852     0    stevel 			bflag++;
    853     0    stevel 			nblock = bcheck(*argv++);
    854     0    stevel 			break;
    855     0    stevel 		case 'q':
    856     0    stevel 			qflag++;
    857     0    stevel 			break;
    858     0    stevel 		case 'k':
    859     0    stevel 			assert_string(*argv, gettext(
    860     0    stevel 			    "tar: size value must be specified with 'k' "
    861     0    stevel 			    "function modifier\n"));
    862     0    stevel 			kflag++;
    863     0    stevel 			blocklim = kcheck(*argv++);
    864     0    stevel 			break;
    865     0    stevel 		case 'n':		/* not a magtape (instead of 'k') */
    866     0    stevel 			NotTape++;	/* assume non-magtape */
    867     0    stevel 			break;
    868     0    stevel 		case 'l':
    869     0    stevel 			linkerrok++;
    870     0    stevel 			break;
    871     0    stevel 		case 'e':
    872     0    stevel #ifdef	_iBCS2
    873     0    stevel 			/* If sysv3 IS set, don't be as verbose */
    874     0    stevel 			if (!sysv3_env)
    875     0    stevel #endif	/* _iBCS2 */
    876     0    stevel 				errflag++;
    877     0    stevel 			eflag++;
    878     0    stevel 			break;
    879     0    stevel 		case 'o':
    880     0    stevel 			oflag++;
    881     0    stevel 			break;
    882     0    stevel 		case 'h':
    883     0    stevel 			hflag++;
    884     0    stevel 			break;
    885     0    stevel 		case 'i':
    886     0    stevel 			iflag++;
    887     0    stevel 			break;
    888     0    stevel 		case 'B':
    889     0    stevel 			Bflag++;
    890     0    stevel 			break;
    891     0    stevel 		case 'P':
    892     0    stevel 			Pflag++;
    893     0    stevel 			break;
    894     0    stevel 		case 'E':
    895     0    stevel 			Eflag++;
    896     0    stevel 			Pflag++;	/* Only POSIX archive made */
    897     0    stevel 			break;
    898  1676       jpk 		case 'T':
    899  1676       jpk 			Tflag++;	/* Handle Trusted Extensions attrs */
    900  1676       jpk 			pflag++;	/* also set flag for ACL */
    901  1676       jpk 			break;
    902     0    stevel 		default:
    903     0    stevel 			(void) fprintf(stderr, gettext(
    904     0    stevel 			"tar: %c: unknown function modifier\n"), *cp);
    905     0    stevel 			usage();
    906     0    stevel 		}
    907     0    stevel 
    908     0    stevel #ifdef	_iBCS2
    909     0    stevel 	if (Xflag && Fileflag) {
    910     0    stevel 		(void) fprintf(stderr, gettext(
    911     0    stevel 		"tar: specify only one of X or F.\n"));
    912     0    stevel 		usage();
    913     0    stevel 	}
    914     0    stevel #endif	/*  _iBCS2 */
    915     0    stevel 
    916     0    stevel 	if (!rflag && !xflag && !tflag)
    917     0    stevel 		usage();
    918     0    stevel 	if ((rflag && xflag) || (xflag && tflag) || (rflag && tflag)) {
    919     0    stevel 		(void) fprintf(stderr, gettext(
    920     0    stevel 		"tar: specify only one of [ctxru].\n"));
    921  1676       jpk 		usage();
    922  1676       jpk 	}
    923  1676       jpk 	/* Trusted Extensions attribute handling */
    924  1676       jpk 	if (Tflag && ((getzoneid() != GLOBAL_ZONEID) ||
    925  1676       jpk 	    !is_system_labeled())) {
    926  1676       jpk 		(void) fprintf(stderr, gettext(
    927  1676       jpk 		"tar: the 'T' option is only available with "
    928  1676       jpk 		    "Trusted Extensions\nand must be run from "
    929  1676       jpk 		    "the global zone.\n"));
    930     0    stevel 		usage();
    931     0    stevel 	}
    932     0    stevel 	if (cflag && *argv == NULL && Filefile == NULL)
    933     0    stevel 		fatal(gettext("Missing filenames"));
    934     0    stevel 	if (usefile == NULL)
    935     0    stevel 		fatal(gettext("device argument required"));
    936     0    stevel 
    937     0    stevel 	/* alloc a buffer of the right size */
    938     0    stevel 	if ((tbuf = (union hblock *)
    939  1266   ceastha 	    calloc(sizeof (union hblock) * nblock, sizeof (char))) ==
    940  1266   ceastha 	    (union hblock *)NULL) {
    941     0    stevel 		(void) fprintf(stderr, gettext(
    942     0    stevel 		"tar: cannot allocate physio buffer\n"));
    943     0    stevel 		exit(1);
    944     0    stevel 	}
    945     0    stevel 
    946     0    stevel 	if ((xrec_ptr = malloc(xrec_size)) == NULL) {
    947     0    stevel 		(void) fprintf(stderr, gettext(
    948     0    stevel 		    "tar: cannot allocate extended header buffer\n"));
    949     0    stevel 		exit(1);
    950     0    stevel 	}
    951     0    stevel 
    952     0    stevel #ifdef WAITAROUND
    953     0    stevel 	if (waitaround) {
    954     0    stevel 		(void) fprintf(stderr, gettext("Rendezvous with tar on pid"
    955     0    stevel 		    " %d\n"), getpid());
    956     0    stevel 
    957     0    stevel 		while (waitaround) {
    958     0    stevel 			(void) sleep(10);
    959     0    stevel 		}
    960     0    stevel 	}
    961     0    stevel #endif
    962     0    stevel 
    963     0    stevel 	thispid = getpid();
    964     0    stevel 	(void) sprintf(pidchars, "%ld", thispid);
    965     0    stevel 	thispid = strlen(pidchars);
    966     0    stevel 
    967     0    stevel 	if ((tmpdirp = getenv("TMPDIR")) == (char *)NULL)
    968     0    stevel 		(void) strcpy(xhdr_dirname, "/tmp");
    969     0    stevel 	else {
    970     0    stevel 		/*
    971     0    stevel 		 * Make sure that dir is no longer than what can
    972     0    stevel 		 * fit in the prefix part of the header.
    973     0    stevel 		 */
    974     0    stevel 		if (strlen(tmpdirp) > (size_t)(PRESIZ - thispid - 12)) {
    975     0    stevel 			(void) strcpy(xhdr_dirname, "/tmp");
    976     0    stevel 			if ((vflag > 0) && (Eflag > 0))
    977     0    stevel 				(void) fprintf(stderr, gettext(
    978     0    stevel 				    "Ignoring TMPDIR\n"));
    979     0    stevel 		} else
    980     0    stevel 			(void) strcpy(xhdr_dirname, tmpdirp);
    981     0    stevel 	}
    982     0    stevel 	(void) strcat(xhdr_dirname, "/PaxHeaders.");
    983     0    stevel 	(void) strcat(xhdr_dirname, pidchars);
    984     0    stevel 
    985     0    stevel 	if (rflag) {
    986     0    stevel 		if (cflag && tfile != NULL)
    987     0    stevel 			usage();
    988     0    stevel 		if (signal(SIGINT, SIG_IGN) != SIG_IGN)
    989     0    stevel 			(void) signal(SIGINT, onintr);
    990     0    stevel 		if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
    991     0    stevel 			(void) signal(SIGHUP, onhup);
    992     0    stevel 		if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
    993     0    stevel 			(void) signal(SIGQUIT, onquit);
    994     0    stevel 		if (uflag) {
    995     0    stevel 			int tnum;
    996     0    stevel 			if ((tnum = mkstemp(tname)) == -1)
    997     0    stevel 				vperror(1, "%s", tname);
    998     0    stevel 			if ((tfile = fdopen(tnum, "w")) == NULL)
    999     0    stevel 				vperror(1, "%s", tname);
   1000     0    stevel 		}
   1001     0    stevel 		if (strcmp(usefile, "-") == 0) {
   1002     0    stevel 			if (cflag == 0)
   1003     0    stevel 				fatal(gettext(
   1004     0    stevel 				"can only create standard output archives."));
   1005     0    stevel 			vfile = stderr;
   1006     0    stevel 			mt = dup(1);
   1007     0    stevel 			++bflag;
   1008     0    stevel 		} else {
   1009     0    stevel 			if (cflag)
   1010     0    stevel 				mt = open(usefile,
   1011     0    stevel 				    O_RDWR|O_CREAT|O_TRUNC, 0666);
   1012     0    stevel 			else
   1013     0    stevel 				mt = open(usefile, O_RDWR);
   1014     0    stevel 
   1015     0    stevel 			if (mt < 0) {
   1016     0    stevel 				if (cflag == 0 || (mt =  creat(usefile, 0666))
   1017  1266   ceastha 				    < 0)
   1018     0    stevel 				vperror(1, "%s", usefile);
   1019     0    stevel 			}
   1020     0    stevel 		}
   1021     0    stevel 		/* Get inode and device number of output file */
   1022     0    stevel 		(void) fstat(mt, &stbuf);
   1023     0    stevel 		mt_ino = stbuf.st_ino;
   1024     0    stevel 		mt_dev = stbuf.st_dev;
   1025     0    stevel 		mt_devtype = stbuf.st_mode & S_IFMT;
   1026     0    stevel 		NotTape = !istape(mt, mt_devtype);
   1027     0    stevel 
   1028     0    stevel 		if (rflag && !cflag && (mt_devtype == S_IFIFO))
   1029     0    stevel 			fatal(gettext("cannot append to pipe or FIFO."));
   1030     0    stevel 
   1031     0    stevel 		if (Aflag && vflag)
   1032     0    stevel 			(void) printf(
   1033     0    stevel 			gettext("Suppressing absolute pathnames\n"));
   1034     0    stevel 		dorep(argv);
   1035     0    stevel 	} else if (xflag || tflag) {
   1036     0    stevel 		/*
   1037     0    stevel 		 * for each argument, check to see if there is a "-I file" pair.
   1038     0    stevel 		 * if so, move the 3rd argument into "-I"'s place, build_table()
   1039     0    stevel 		 * using "file"'s name and increment argc one (the second
   1040     0    stevel 		 * increment appears in the for loop) which removes the two
   1041     0    stevel 		 * args "-I" and "file" from the argument vector.
   1042     0    stevel 		 */
   1043     0    stevel 		for (argc = 0; argv[argc]; argc++) {
   1044     0    stevel 			if (strcmp(argv[argc], "-I") == 0) {
   1045     0    stevel 				if (!argv[argc+1]) {
   1046     0    stevel 					(void) fprintf(stderr, gettext(
   1047     0    stevel 					"tar: missing argument for -I flag\n"));
   1048     0    stevel 					done(2);
   1049     0    stevel 				} else {
   1050     0    stevel 					Iflag = 1;
   1051     0    stevel 					argv[argc] = argv[argc+2];
   1052     0    stevel 					build_table(include_tbl, argv[++argc]);
   1053     0    stevel #ifdef	_iBCS2
   1054     0    stevel 					if (Fileflag) {
   1055     0    stevel 						(void) fprintf(stderr, gettext(
   1056     0    stevel 						"tar: only one of I or F.\n"));
   1057     0    stevel 						usage();
   1058     0    stevel 					}
   1059     0    stevel #endif	/*  _iBCS2 */
   1060     0    stevel 
   1061     0    stevel 				}
   1062     0    stevel 			}
   1063     0    stevel 		}
   1064     0    stevel 		if (strcmp(usefile, "-") == 0) {
   1065     0    stevel 			mt = dup(0);
   1066     0    stevel 			++bflag;
   1067     0    stevel 			/* try to recover from short reads when reading stdin */
   1068     0    stevel 			++Bflag;
   1069     0    stevel 		} else if ((mt = open(usefile, 0)) < 0)
   1070     0    stevel 			vperror(1, "%s", usefile);
   1071     0    stevel 
   1072     0    stevel 		if (xflag) {
   1073     0    stevel 			if (Aflag && vflag)
   1074  1266   ceastha 				(void) printf(gettext(
   1075  1266   ceastha 				    "Suppressing absolute pathnames.\n"));
   1076     0    stevel 
   1077     0    stevel #ifdef	_iBCS2
   1078     0    stevel 			doxtract(argv, tbl_cnt);
   1079     0    stevel #else
   1080     0    stevel 			doxtract(argv);
   1081     0    stevel #endif
   1082     0    stevel 		} else if (tflag)
   1083     0    stevel 
   1084     0    stevel #ifdef	_iBCS2
   1085     0    stevel 			dotable(argv, tbl_cnt);
   1086     0    stevel #else
   1087     0    stevel 			dotable(argv);
   1088     0    stevel #endif
   1089     0    stevel 	}
   1090     0    stevel 	else
   1091     0    stevel 		usage();
   1092     0    stevel 
   1093     0    stevel 	done(Errflg);
   1094     0    stevel 
   1095     0    stevel 	/* Not reached:  keep compiler quiet */
   1096     0    stevel 	return (1);
   1097     0    stevel }
   1098     0    stevel 
   1099     0    stevel static void
   1100     0    stevel usage(void)
   1101     0    stevel {
   1102     0    stevel 
   1103     0    stevel #ifdef	_iBCS2
   1104     0    stevel 	if (sysv3_env) {
   1105     0    stevel 		(void) fprintf(stderr, gettext(
   1106     0    stevel #if defined(O_XATTR)
   1107  5331       amw #if defined(_PC_SATTR_ENABLED)
   1108  5331       amw 		"Usage: tar {c|r|t|u|x}[BDeEhilmnopPqTvw@/[0-7]][bfFk][X...] "
   1109  5331       amw #else
   1110  1676       jpk 		"Usage: tar {c|r|t|u|x}[BDeEhilmnopPqTvw@[0-7]][bfFk][X...] "
   1111  5331       amw #endif	/* _PC_SATTR_ENABLED */
   1112  1676       jpk #else
   1113  1676       jpk 		"Usage: tar {c|r|t|u|x}[BDeEhilmnopPqTvw[0-7]][bfFk][X...] "
   1114  5331       amw #endif	/* O_XATTR */
   1115     0    stevel 		"[blocksize] [tarfile] [filename] [size] [exclude-file...] "
   1116     0    stevel 		"{file | -I include-file | -C directory file}...\n"));
   1117     0    stevel 	} else
   1118     0    stevel #endif	/* _iBCS2 */
   1119     0    stevel 	{
   1120     0    stevel 		(void) fprintf(stderr, gettext(
   1121     0    stevel #if defined(O_XATTR)
   1122  5331       amw #if defined(_PC_SATTR_ENABLED)
   1123  5331       amw 		"Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqTvw@/[0-7]][bfk][X...] "
   1124  5331       amw #else
   1125  1676       jpk 		"Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqTvw@[0-7]][bfk][X...] "
   1126  5331       amw #endif	/* _PC_SATTR_ENABLED */
   1127  1676       jpk #else
   1128  1676       jpk 		"Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqTvw[0-7]][bfk][X...] "
   1129  5331       amw #endif	/* O_XATTR */
   1130     0    stevel 		"[blocksize] [tarfile] [size] [exclude-file...] "
   1131     0    stevel 		"{file | -I include-file | -C directory file}...\n"));
   1132     0    stevel 	}
   1133     0    stevel 	done(1);
   1134     0    stevel }
   1135     0    stevel 
   1136     0    stevel /*
   1137     0    stevel  * dorep - do "replacements"
   1138     0    stevel  *
   1139     0    stevel  *	Dorep is responsible for creating ('c'),  appending ('r')
   1140     0    stevel  *	and updating ('u');
   1141     0    stevel  */
   1142     0    stevel 
   1143     0    stevel static void
   1144     0    stevel dorep(char *argv[])
   1145     0    stevel {
   1146     0    stevel 	char *cp, *cp2, *p;
   1147     0    stevel 	char wdir[PATH_MAX+2], tempdir[PATH_MAX+2], *parent;
   1148     0    stevel 	char file[PATH_MAX*2], origdir[PATH_MAX+1];
   1149     0    stevel 	FILE *fp = (FILE *)NULL;
   1150     0    stevel 	FILE *ff = (FILE *)NULL;
   1151     0    stevel 	int archtype;
   1152  5482  as158974 	int ret;
   1153     0    stevel 
   1154     0    stevel 
   1155     0    stevel 	if (!cflag) {
   1156     0    stevel 		xhdr_flgs = 0;
   1157     0    stevel 		getdir();			/* read header for next file */
   1158     0    stevel 		if (Xhdrflag > 0) {
   1159     0    stevel 			if (!Eflag)
   1160     0    stevel 				fatal(gettext("Archive contains extended"
   1161     0    stevel 				    " header.  -E flag required.\n"));
   1162  5482  as158974 			ret = get_xdata();	/* Get extended header items */
   1163     0    stevel 						/*   and regular header */
   1164     0    stevel 		} else {
   1165     0    stevel 			if (Eflag)
   1166     0    stevel 				fatal(gettext("Archive contains no extended"
   1167     0    stevel 				    " header.  -E flag not allowed.\n"));
   1168     0    stevel 		}
   1169     0    stevel 		while (!endtape()) {		/* changed from a do while */
   1170  5482  as158974 			setbytes_to_skip(&stbuf, ret);
   1171     0    stevel 			passtape();		/* skip the file data */
   1172     0    stevel 			if (term)
   1173     0    stevel 				done(Errflg);	/* received signal to stop */
   1174     0    stevel 			xhdr_flgs = 0;
   1175     0    stevel 			getdir();
   1176     0    stevel 			if (Xhdrflag > 0)
   1177  5482  as158974 				ret = get_xdata();
   1178  5482  as158974 		}
   1179  5482  as158974 		if (ret == 0) {
   1180  5482  as158974 			if ((dblock.dbuf.typeflag != 'A') &&
   1181  5482  as158974 			    (xhdr_flgs != 0)) {
   1182  5482  as158974 				load_info_from_xtarhdr(xhdr_flgs,
   1183  5482  as158974 				    &Xtarhdr);
   1184  5482  as158974 				xhdr_flgs |= _X_XHDR;
   1185  5482  as158974 			}
   1186     0    stevel 		}
   1187     0    stevel 		backtape();			/* was called by endtape */
   1188     0    stevel 		if (tfile != NULL) {
   1189     0    stevel 			char buf[200];
   1190     0    stevel 
   1191     0    stevel 			(void) sprintf(buf, "sort +0 -1 +1nr %s -o %s; awk '$1 "
   1192     0    stevel 			    "!= prev {print; prev=$1}' %s >%sX;mv %sX %s",
   1193  1266   ceastha 			    tname, tname, tname, tname, tname, tname);
   1194     0    stevel 			(void) fflush(tfile);
   1195     0    stevel 			(void) system(buf);
   1196     0    stevel 			(void) freopen(tname, "r", tfile);
   1197     0    stevel 			(void) fstat(fileno(tfile), &stbuf);
   1198     0    stevel 			high = stbuf.st_size;
   1199     0    stevel 		}
   1200     0    stevel 	}
   1201     0    stevel 
   1202     0    stevel 	dumping = 1;
   1203     0    stevel 	if (mulvol) {	/* SP-1 */
   1204     0    stevel 		if (nblock && (blocklim%nblock) != 0)
   1205     0    stevel 			fatal(gettext(
   1206     0    stevel 			"Volume size not a multiple of block size."));
   1207     0    stevel 		blocklim -= 2;			/* for trailer records */
   1208     0    stevel 		if (vflag)
   1209     0    stevel 			(void) fprintf(vfile, gettext("Volume ends at %"
   1210     0    stevel 			    FMT_blkcnt_t "K, blocking factor = %dK\n"),
   1211     0    stevel 			    K((blocklim - 1)), K(nblock));
   1212     0    stevel 	}
   1213     0    stevel 
   1214     0    stevel #ifdef	_iBCS2
   1215     0    stevel 	if (Fileflag) {
   1216     0    stevel 		if (Filefile != NULL) {
   1217     0    stevel 			if ((ff = fopen(Filefile, "r")) == NULL)
   1218     0    stevel 				vperror(0, "%s", Filefile);
   1219     0    stevel 		} else {
   1220     0    stevel 			(void) fprintf(stderr, gettext(
   1221     0    stevel 			    "tar: F requires a file name.\n"));
   1222     0    stevel 			usage();
   1223     0    stevel 		}
   1224     0    stevel 	}
   1225     0    stevel #endif	/*  _iBCS2 */
   1226     0    stevel 
   1227     0    stevel 	/*
   1228     0    stevel 	 * Save the original directory before it gets
   1229     0    stevel 	 * changed.
   1230     0    stevel 	 */
   1231     0    stevel 	if (getcwd(origdir, (PATH_MAX+1)) == NULL) {
   1232     0    stevel 		vperror(0, gettext("A parent directory cannot be read"));
   1233     0    stevel 		exit(1);
   1234     0    stevel 	}
   1235     0    stevel 
   1236     0    stevel 	(void) strcpy(wdir, origdir);
   1237     0    stevel 
   1238     0    stevel 	while ((*argv || fp || ff) && !term) {
   1239     0    stevel 		if (fp || (strcmp(*argv, "-I") == 0)) {
   1240     0    stevel #ifdef	_iBCS2
   1241     0    stevel 			if (Fileflag) {
   1242     0    stevel 				(void) fprintf(stderr, gettext(
   1243     0    stevel 				"tar: only one of I or F.\n"));
   1244     0    stevel 				usage();
   1245     0    stevel 			}
   1246     0    stevel #endif	/*  _iBCS2 */
   1247     0    stevel 			if (fp == NULL) {
   1248     0    stevel 				if (*++argv == NULL)
   1249     0    stevel 					fatal(gettext(
   1250     0    stevel 					    "missing file name for -I flag."));
   1251     0    stevel 				else if ((fp = fopen(*argv++, "r")) == NULL)
   1252     0    stevel 					vperror(0, "%s", argv[-1]);
   1253     0    stevel 				continue;
   1254     0    stevel 			} else if ((fgets(file, PATH_MAX-1, fp)) == NULL) {
   1255     0    stevel 				(void) fclose(fp);
   1256     0    stevel 				fp = NULL;
   1257     0    stevel 				continue;
   1258     0    stevel 			} else {
   1259     0    stevel 				cp = cp2 = file;
   1260     0    stevel 				if ((p = strchr(cp2, '\n')))
   1261     0    stevel 					*p = 0;
   1262     0    stevel 			}
   1263     0    stevel 		} else if ((strcmp(*argv, "-C") == 0) && argv[1]) {
   1264     0    stevel #ifdef	_iBCS2
   1265     0    stevel 			if (Fileflag) {
   1266     0    stevel 				(void) fprintf(stderr, gettext(
   1267     0    stevel 				"tar: only one of F or C\n"));
   1268     0    stevel 				usage();
   1269     0    stevel 			}
   1270     0    stevel #endif	/*  _iBCS2 */
   1271     0    stevel 
   1272     0    stevel 			if (chdir(*++argv) < 0)
   1273     0    stevel 				vperror(0, gettext(
   1274  5331       amw 				    "can't change directories to %s"), *argv);
   1275     0    stevel 			else
   1276     0    stevel 				(void) getcwd(wdir, (sizeof (wdir)));
   1277     0    stevel 			argv++;
   1278     0    stevel 			continue;
   1279     0    stevel #ifdef	_iBCS2
   1280     0    stevel 		} else if (Fileflag && (ff != NULL)) {
   1281     0    stevel 			if ((fgets(file, PATH_MAX-1, ff)) == NULL) {
   1282     0    stevel 				(void) fclose(ff);
   1283     0    stevel 				ff = NULL;
   1284     0    stevel 				continue;
   1285     0    stevel 			} else {
   1286     0    stevel 				cp = cp2 = file;
   1287     0    stevel 				if (p = strchr(cp2, '\n'))
   1288     0    stevel 					*p = 0;
   1289     0    stevel 			}
   1290     0    stevel #endif	/*  _iBCS2 */
   1291     0    stevel 		} else
   1292     0    stevel 			cp = cp2 = strcpy(file, *argv++);
   1293     0    stevel 
   1294     0    stevel 		/*
   1295     0    stevel 		 * point cp2 to the last '/' in file, but not
   1296     0    stevel 		 * to a trailing '/'
   1297     0    stevel 		 */
   1298     0    stevel 		for (; *cp; cp++) {
   1299     0    stevel 			if (*cp == '/') {
   1300     0    stevel 				while (*(cp+1) == '/') {
   1301     0    stevel 					++cp;
   1302     0    stevel 				}
   1303     0    stevel 				if (*(cp+1) != '\0') {
   1304     0    stevel 					/* not trailing slash */
   1305     0    stevel 					cp2 = cp;
   1306     0    stevel 				}
   1307     0    stevel 			}
   1308     0    stevel 		}
   1309     0    stevel 		if (cp2 != file) {
   1310     0    stevel 			*cp2 = '\0';
   1311     0    stevel 			if (chdir(file) < 0) {
   1312     0    stevel 				vperror(0, gettext(
   1313  5331       amw 				    "can't change directories to %s"), file);
   1314     0    stevel 				continue;
   1315     0    stevel 			}
   1316     0    stevel 			*cp2 = '/';
   1317     0    stevel 			cp2++;
   1318     0    stevel 		}
   1319     0    stevel 
   1320     0    stevel 		parent = getcwd(tempdir, (sizeof (tempdir)));
   1321  5331       amw 
   1322  5331       amw 		archtype = putfile(file, cp2, parent, NULL, NORMAL_FILE,
   1323     0    stevel 		    LEV0, SYMLINK_LEV0);
   1324     0    stevel 
   1325     0    stevel #if defined(O_XATTR)
   1326     0    stevel 		if (!exitflag) {
   1327  5331       amw 			if ((atflag || saflag) &&
   1328  5331       amw 			    (archtype == PUT_NOTAS_LINK)) {
   1329  5331       amw 				xattrs_put(file, cp2, parent, NULL);
   1330     0    stevel 			}
   1331     0    stevel 		}
   1332     0    stevel #endif
   1333     0    stevel 
   1334     0    stevel 		if (chdir(origdir) < 0)
   1335     0    stevel 			vperror(0, gettext("cannot change back?: %s"), origdir);
   1336     0    stevel 
   1337     0    stevel 		if (exitflag) {
   1338     0    stevel 			/*
   1339     0    stevel 			 * If e function modifier has been specified
   1340     0    stevel 			 * write the files (that are listed before the
   1341     0    stevel 			 * file causing the error) to tape.  exitflag is
   1342     0    stevel 			 * used because only some of the error conditions
   1343     0    stevel 			 * in putfile() recognize the e function modifier.
   1344     0    stevel 			 */
   1345     0    stevel 			break;
   1346     0    stevel 		}
   1347     0    stevel 	}
   1348     0    stevel 
   1349     0    stevel 	putempty((blkcnt_t)2);
   1350     0    stevel 	flushtape();
   1351     0    stevel 	closevol();	/* SP-1 */
   1352     0    stevel 	if (linkerrok == 1)
   1353     0    stevel 		for (; ihead != NULL; ihead = ihead->nextp) {
   1354     0    stevel 			if (ihead->count == 0)
   1355     0    stevel 				continue;
   1356     0    stevel 			(void) fprintf(stderr, gettext(
   1357     0    stevel 			"tar: missing links to %s\n"), ihead->pathname);
   1358     0    stevel 			if (errflag)
   1359     0    stevel 				done(1);
   1360     0    stevel 			else
   1361     0    stevel 				Errflg = 1;
   1362     0    stevel 		}
   1363     0    stevel }
   1364     0    stevel 
   1365     0    stevel 
   1366     0    stevel /*
   1367     0    stevel  * endtape - check for tape at end
   1368     0    stevel  *
   1369     0    stevel  *	endtape checks the entry in dblock.dbuf to see if its the
   1370     0    stevel  *	special EOT entry.  Endtape is usually called after getdir().
   1371     0    stevel  *
   1372     0    stevel  *	endtape used to call backtape; it no longer does, he who
   1373     0    stevel  *	wants it backed up must call backtape himself
   1374     0    stevel  *	RETURNS:	0 if not EOT, tape position unaffected
   1375     0    stevel  *			1 if	 EOT, tape position unaffected
   1376     0    stevel  */
   1377     0    stevel 
   1378     0    stevel static int
   1379     0    stevel endtape(void)
   1380     0    stevel {
   1381     0    stevel 	if (dblock.dbuf.name[0] == '\0') {	/* null header = EOT */
   1382     0    stevel 		return (1);
   1383     0    stevel 	} else
   1384     0    stevel 		return (0);
   1385     0    stevel }
   1386     0    stevel 
   1387     0    stevel /*
   1388     0    stevel  *	getdir - get directory entry from tar tape
   1389     0    stevel  *
   1390     0    stevel  *	getdir reads the next tarblock off the tape and cracks
   1391     0    stevel  *	it as a directory. The checksum must match properly.
   1392     0    stevel  *
   1393     0    stevel  *	If tfile is non-null getdir writes the file name and mod date
   1394     0    stevel  *	to tfile.
   1395     0    stevel  */
   1396     0    stevel 
   1397     0    stevel static void
   1398     0    stevel getdir(void)
   1399     0    stevel {
   1400     0    stevel 	struct stat *sp;
   1401     0    stevel #ifdef EUC
   1402     0    stevel 	static int warn_chksum_sign = 0;
   1403     0    stevel #endif /* EUC */
   1404     0    stevel 
   1405     0    stevel top:
   1406     0    stevel 	readtape((char *)&dblock);
   1407     0    stevel 	if (dblock.dbuf.name[0] == '\0')
   1408     0    stevel 		return;
   1409     0    stevel 	sp = &stbuf;
   1410     0    stevel 	(void) sscanf(dblock.dbuf.mode, "%8lo", &Gen.g_mode);
   1411     0    stevel 	(void) sscanf(dblock.dbuf.uid, "%8lo", (ulong_t *)&Gen.g_uid);
   1412     0    stevel 	(void) sscanf(dblock.dbuf.gid, "%8lo", (ulong_t *)&Gen.g_gid);
   1413     0    stevel 	(void) sscanf(dblock.dbuf.size, "%12" FMT_off_t_o, &Gen.g_filesz);
   1414     0    stevel 	(void) sscanf(dblock.dbuf.mtime, "%12lo", (ulong_t *)&Gen.g_mtime);
   1415     0    stevel 	(void) sscanf(dblock.dbuf.chksum, "%8o", &Gen.g_cksum);
   1416     0    stevel 	(void) sscanf(dblock.dbuf.devmajor, "%8lo", &Gen.g_devmajor);
   1417     0    stevel 	(void) sscanf(dblock.dbuf.devminor, "%8lo", &Gen.g_devminor);
   1418     0    stevel 
   1419     0    stevel 	is_posix = (strcmp(dblock.dbuf.magic, magic_type) == 0);
   1420     0    stevel 
   1421     0    stevel 	sp->st_mode = Gen.g_mode;
   1422     0    stevel 	if (is_posix && (sp->st_mode & S_IFMT) == 0)
   1423     0    stevel 		switch (dblock.dbuf.typeflag) {
   1424     0    stevel 		case '0': case 0: case _XATTR_HDRTYPE:
   1425     0    stevel 			sp->st_mode |= S_IFREG;
   1426     0    stevel 			break;
   1427     0    stevel 		case '1':	/* hard link */
   1428     0    stevel 			break;
   1429     0    stevel 		case '2':
   1430     0    stevel 			sp->st_mode |= S_IFLNK;
   1431     0    stevel 			break;
   1432     0    stevel 		case '3':
   1433     0    stevel 			sp->st_mode |= S_IFCHR;
   1434     0    stevel 			break;
   1435     0    stevel 		case '4':
   1436     0    stevel 			sp->st_mode |= S_IFBLK;
   1437     0    stevel 			break;
   1438     0    stevel 		case '5':
   1439     0    stevel 			sp->st_mode |= S_IFDIR;
   1440     0    stevel 			break;
   1441     0    stevel 		case '6':
   1442     0    stevel 			sp->st_mode |= S_IFIFO;
   1443     0    stevel 			break;
   1444     0    stevel 		default:
   1445     0    stevel 			if (convtoreg(Gen.g_filesz))
   1446     0    stevel 				sp->st_mode |= S_IFREG;
   1447     0    stevel 			break;
   1448     0    stevel 		}
   1449     0    stevel 
   1450     0    stevel 	if (dblock.dbuf.typeflag == 'X')
   1451     0    stevel 		Xhdrflag = 1;	/* Currently processing extended header */
   1452     0    stevel 	else
   1453     0    stevel 		Xhdrflag = 0;
   1454     0    stevel 
   1455     0    stevel 	sp->st_uid = Gen.g_uid;
   1456     0    stevel 	sp->st_gid = Gen.g_gid;
   1457     0    stevel 	sp->st_size = Gen.g_filesz;
   1458     0    stevel 	sp->st_mtime = Gen.g_mtime;
   1459     0    stevel 	chksum = Gen.g_cksum;
   1460     0    stevel 
   1461     0    stevel 	if (dblock.dbuf.extno != '\0') {	/* split file? */
   1462     0    stevel 		extno = dblock.dbuf.extno;
   1463     0    stevel 		extsize = Gen.g_filesz;
   1464     0    stevel 		extotal = dblock.dbuf.extotal;
   1465     0    stevel 	} else {
   1466     0    stevel 		extno = 0;	/* tell others file not split */
   1467     0    stevel 		extsize = 0;
   1468     0    stevel 		extotal = 0;
   1469     0    stevel 	}
   1470     0    stevel 
   1471     0    stevel #ifdef	EUC
   1472     0    stevel 	if (chksum != checksum(&dblock)) {
   1473     0    stevel 		if (chksum != checksum_signed(&dblock)) {
   1474     0    stevel 			(void) fprintf(stderr, gettext(
   1475     0    stevel 			    "tar: directory checksum error\n"));
   1476     0    stevel 			if (iflag)
   1477     0    stevel 				goto top;
   1478     0    stevel 			done(2);
   1479     0    stevel 		} else {
   1480     0    stevel 			if (! warn_chksum_sign) {
   1481     0    stevel 				warn_chksum_sign = 1;
   1482     0    stevel 				(void) fprintf(stderr, gettext(
   1483     0    stevel 			"tar: warning: tar file made with signed checksum\n"));
   1484     0    stevel 			}
   1485     0    stevel 		}
   1486     0    stevel 	}
   1487     0    stevel #else
   1488     0    stevel 	if (chksum != checksum(&dblock)) {
   1489     0    stevel 		(void) fprintf(stderr, gettext(
   1490     0    stevel 		"tar: directory checksum error\n"));
   1491     0    stevel 		if (iflag)
   1492     0    stevel 			goto top;
   1493     0    stevel 		done(2);
   1494     0    stevel 	}
   1495     0    stevel #endif	/* EUC */
   1496     0    stevel 	if (tfile != NULL && Xhdrflag == 0) {
   1497     0    stevel 		/*
   1498     0    stevel 		 * If an extended header is present, then time is available
   1499     0    stevel 		 * in nanoseconds in the extended header data, so set it.
   1500     0    stevel 		 * Otherwise, give an invalid value so that checkupdate will
   1501     0    stevel 		 * not test beyond seconds.
   1502     0    stevel 		 */
   1503     0    stevel 		if ((xhdr_flgs & _X_MTIME))
   1504     0    stevel 			sp->st_mtim.tv_nsec = Xtarhdr.x_mtime.tv_nsec;
   1505     0    stevel 		else
   1506     0    stevel 			sp->st_mtim.tv_nsec = -1;
   1507     0    stevel 
   1508     0    stevel 		if (xhdr_flgs & _X_PATH)
   1509     0    stevel 			(void) fprintf(tfile, "%s %10ld.%9.9ld\n",
   1510     0    stevel 			    Xtarhdr.x_path, sp->st_mtim.tv_sec,
   1511     0    stevel 			    sp->st_mtim.tv_nsec);
   1512     0    stevel 		else
   1513     0    stevel 			(void) fprintf(tfile, "%.*s %10ld.%9.9ld\n",
   1514     0    stevel 			    NAMSIZ, dblock.dbuf.name, sp->st_mtim.tv_sec,
   1515     0    stevel 			    sp->st_mtim.tv_nsec);
   1516     0    stevel 	}
   1517     0    stevel 
   1518     0    stevel #if defined(O_XATTR)
   1519     0    stevel 	Hiddendir = 0;
   1520     0    stevel 	if (xattrp && dblock.dbuf.typeflag == _XATTR_HDRTYPE) {
   1521     0    stevel 		if (xattrbadhead) {
   1522     0    stevel 			free(xattrhead);
   1523     0    stevel 			xattrp = NULL;
   1524     0    stevel 			xattr_linkp = NULL;
   1525     0    stevel 			xattrhead = NULL;
   1526     0    stevel 		} else {
   1527  5331       amw 			char	*aname = basename(xattrapath);
   1528  5331       amw 			size_t	xindex  = aname - xattrapath;
   1529  5331       amw 
   1530  5331       amw 			if (xattrapath[xindex] == '.' &&
   1531  5331       amw 			    xattrapath[xindex + 1] == '\0' &&
   1532     0    stevel 			    xattrp->h_typeflag == '5') {
   1533     0    stevel 				Hiddendir = 1;
   1534     0    stevel 				sp->st_mode =
   1535  1231     marks 				    (S_IFDIR | (sp->st_mode & POSIXMODES));
   1536     0    stevel 			}
   1537     0    stevel 			dblock.dbuf.typeflag = xattrp->h_typeflag;
   1538     0    stevel 		}
   1539     0    stevel 	}
   1540     0    stevel #endif
   1541     0    stevel }
   1542     0    stevel 
   1543     0    stevel 
   1544     0    stevel /*
   1545     0    stevel  *	passtape - skip over a file on the tape
   1546     0    stevel  *
   1547     0    stevel  *	passtape skips over the next data file on the tape.
   1548     0    stevel  *	The tape directory entry must be in dblock.dbuf. This
   1549     0    stevel  *	routine just eats the number of blocks computed from the
   1550     0    stevel  *	directory size entry; the tape must be (logically) positioned
   1551     0    stevel  *	right after thee directory info.
   1552     0    stevel  */
   1553     0    stevel 
   1554     0    stevel static void
   1555     0    stevel passtape(void)
   1556     0    stevel {
   1557     0    stevel 	blkcnt_t blocks;
   1558     0    stevel 	char buf[TBLOCK];
   1559     0    stevel 
   1560     0    stevel 	/*
   1561     0    stevel 	 * Types link(1), sym-link(2), char special(3), blk special(4),
   1562     0    stevel 	 *  directory(5), and FIFO(6) do not have data blocks associated
   1563     0    stevel 	 *  with them so just skip reading the data block.
   1564     0    stevel 	 */
   1565     0    stevel 	if (dblock.dbuf.typeflag == '1' || dblock.dbuf.typeflag == '2' ||
   1566  1266   ceastha 	    dblock.dbuf.typeflag == '3' || dblock.dbuf.typeflag == '4' ||
   1567  1266   ceastha 	    dblock.dbuf.typeflag == '5' || dblock.dbuf.typeflag == '6')
   1568     0    stevel 		return;
   1569     0    stevel 	blocks = TBLOCKS(stbuf.st_size);
   1570     0    stevel 
   1571     0    stevel 	/* if operating on disk, seek instead of reading */
   1572     0    stevel 	if (NotTape)
   1573     0    stevel 		seekdisk(blocks);
   1574     0    stevel 	else
   1575     0    stevel 		while (blocks-- > 0)
   1576     0    stevel 			readtape(buf);
   1577     0    stevel }
   1578     0    stevel 
   1579  5331       amw #if defined(O_XATTR)
   1580  5331       amw static int
   1581  5331       amw is_sysattr(char *name)
   1582  5331       amw {
   1583  5331       amw 	return ((strcmp(name, VIEW_READONLY) == 0) ||
   1584  5331       amw 	    (strcmp(name, VIEW_READWRITE) == 0));
   1585  5331       amw }
   1586  5331       amw #endif
   1587  5331       amw 
   1588  5331       amw #if defined(O_XATTR)
   1589  5331       amw /*
   1590  5331       amw  * Verify the attribute, attrname, is an attribute we want to restore.
   1591  5331       amw  * Never restore read-only system attribute files.  Only restore read-write
   1592  5331       amw  * system attributes files when -/ was specified, and only traverse into
   1593  5331       amw  * the 2nd level attribute directory containing only system attributes if
   1594  5331       amw  * -@ was specified.  This keeps us from archiving
   1595  5331       amw  *	<attribute name>/<read-write system attribute file>
   1596  5331       amw  * when -/ was specified without -@.
   1597  5331       amw  *
   1598  5331       amw  * attrname	- attribute file name
   1599  5331       amw  * attrparent	- attribute's parent name within the base file's attribute
   1600  5331       amw  *		directory hierarchy
   1601  5331       amw  */
   1602  5331       amw static attr_status_t
   1603  5331       amw verify_attr(char *attrname, char *attrparent, int arc_rwsysattr,
   1604  5331       amw     int *rw_sysattr)
   1605  5331       amw {
   1606  5331       amw #if defined(_PC_SATTR_ENABLED)
   1607  5331       amw 	int	attr_supported;
   1608  5331       amw 
   1609  5331       amw 	/* Never restore read-only system attribute files */
   1610  5331       amw 	if ((attr_supported = sysattr_type(attrname)) == _RO_SATTR) {
   1611  5331       amw 		*rw_sysattr = 0;
   1612  5331       amw 		return (ATTR_SKIP);
   1613  5331       amw 	} else {
   1614  5331       amw 		*rw_sysattr = (attr_supported == _RW_SATTR);
   1615  5331       amw 	}
   1616  5331       amw #else
   1617  5331       amw 	/*
   1618  5331       amw 	 * Only need to check if this attribute is an extended system
   1619  5331       amw 	 * attribute.
   1620  5331       amw 	 */
   1621  5331       amw 	if (*rw_sysattr = is_sysattr(attrname)) {
   1622  5331       amw 		return (ATTR_SKIP);
   1623  5331       amw 	} else {
   1624  5331       amw 		return (ATTR_OK);
   1625  5331       amw 	}
   1626  5331       amw #endif	/* _PC_SATTR_ENABLED */
   1627  5331       amw 
   1628  5331       amw 	/*
   1629  5331       amw 	 * If the extended system attribute file is specified with the
   1630  5331       amw 	 * arc_rwsysattr flag, as being transient (default extended
   1631  5331       amw 	 * attributes), then don't archive it.
   1632  5331       amw 	 */
   1633  5331       amw 	if (*rw_sysattr && !arc_rwsysattr) {
   1634  5331       amw 		return (ATTR_SKIP);
   1635  5331       amw 	}
   1636  5331       amw 
   1637  5331       amw 	/*
   1638  5331       amw 	 * Only restore read-write system attribute files
   1639  5331       amw 	 * when -/ was specified.  Only restore extended
   1640  5331       amw 	 * attributes when -@ was specified.
   1641  5331       amw 	 */
   1642  5331       amw 	if (atflag) {
   1643  5331       amw 		if (!saflag) {
   1644  5331       amw 			/*
   1645  5331       amw 			 * Only archive/restore the hidden directory "." if
   1646  5331       amw 			 * we're processing the top level hidden attribute
   1647  5331       amw 			 * directory.  We don't want to process the
   1648  5331       amw 			 * hidden attribute directory of the attribute
   1649  5331       amw 			 * directory that contains only extended system
   1650  5331       amw 			 * attributes.
   1651  5331       amw 			 */
   1652  5331       amw 			if (*rw_sysattr || (Hiddendir &&
   1653  5331       amw 			    (attrparent != NULL))) {
   1654  5331       amw 				return (ATTR_SKIP);
   1655  5331       amw 			}
   1656  5331       amw 		}
   1657  5331       amw 	} else if (saflag) {
   1658  5331       amw 		/*
   1659  5331       amw 		 * Only archive/restore read-write extended system attribute
   1660  5331       amw 		 * files of the base file.
   1661  5331       amw 		 */
   1662  5331       amw 		if (!*rw_sysattr || (attrparent != NULL)) {
   1663  5331       amw 			return (ATTR_SKIP);
   1664  5331       amw 		}
   1665  5331       amw 	} else {
   1666  5331       amw 		return (ATTR_SKIP);
   1667  5331       amw 	}
   1668  5331       amw 
   1669  5331       amw 	return (ATTR_OK);
   1670  5331       amw }
   1671  5331       amw #endif
   1672  5331       amw 
   1673  6525   ceastha static void
   1674  6525   ceastha free_children(file_list_t *children)
   1675  6525   ceastha {
   1676  6525   ceastha 	file_list_t	*child = children;
   1677  6525   ceastha 	file_list_t	*cptr;
   1678  6525   ceastha 
   1679  6525   ceastha 	while (child != NULL) {
   1680  6525   ceastha 		cptr = child->next;
   1681  6525   ceastha 		if (child->name != NULL) {
   1682  6525   ceastha 			free(child->name);
   1683  6525   ceastha 		}
   1684  6525   ceastha 		child = cptr;
   1685  6525   ceastha 	}
   1686  6525   ceastha }
   1687  6525   ceastha 
   1688  5331       amw static int
   1689  5331       amw putfile(char *longname, char *shortname, char *parent, attr_data_t *attrinfo,
   1690     0    stevel     int filetype, int lev, int symlink_lev)
   1691     0    stevel {
   1692     0    stevel 	int infile = -1;	/* deliberately invalid */
   1693     0    stevel 	blkcnt_t blocks;
   1694     0    stevel 	char buf[PATH_MAX + 2];	/* Add trailing slash and null */
   1695     0    stevel 	char *bigbuf;
   1696     0    stevel 	int	maxread;
   1697     0    stevel 	int	hint;		/* amount to write to get "in sync" */
   1698     0    stevel 	char filetmp[PATH_MAX + 1];
   1699     0    stevel 	char *cp;
   1700     0    stevel 	char *name;
   1701  5331       amw 	char *attrparent = NULL;
   1702  5331       amw 	char *longattrname = NULL;
   1703  6525   ceastha 	file_list_t	*child = NULL;
   1704  6525   ceastha 	file_list_t	*child_end = NULL;
   1705  6525   ceastha 	file_list_t	*cptr;
   1706     0    stevel 	struct dirent *dp;
   1707     0    stevel 	DIR *dirp;
   1708     0    stevel 	int i;
   1709     0    stevel 	int split;
   1710     0    stevel 	int dirfd = -1;
   1711     0    stevel 	int rc = PUT_NOTAS_LINK;
   1712     0    stevel 	int archtype = 0;
   1713  5331       amw 	int rw_sysattr = 0;
   1714     0    stevel 	char newparent[PATH_MAX + MAXNAMLEN + 1];
   1715     0    stevel 	char *prefix = "";
   1716     0    stevel 	char *tmpbuf;
   1717     0    stevel 	char goodbuf[PRESIZ + 2];
   1718     0    stevel 	char junkbuf[MAXNAM+1];
   1719     0    stevel 	char *lastslash;
   1720     0    stevel 	int j;
   1721     0    stevel 	struct stat sbuf;
   1722     0    stevel 	int readlink_max;
   1723     0    stevel 
   1724     0    stevel 	(void) memset(goodbuf, '\0', sizeof (goodbuf));
   1725     0    stevel 	(void) memset(junkbuf, '\0', sizeof (junkbuf));
   1726     0    stevel 
   1727     0    stevel 	xhdr_flgs = 0;
   1728     0    stevel 
   1729     0    stevel 	if (filetype == XATTR_FILE) {
   1730  5331       amw 		attrparent = attrinfo->attr_parent;
   1731  5331       amw 		longattrname = attrinfo->attr_path;
   1732  5331       amw 		dirfd = attrinfo->attr_parentfd;
   1733  5750   ceastha 		rw_sysattr = attrinfo->attr_rw_sysattr;
   1734     0    stevel 	} else {
   1735     0    stevel 		dirfd = open(".", O_RDONLY);
   1736     0    stevel 	}
   1737     0    stevel 
   1738     0    stevel 	if (dirfd == -1) {
   1739     0    stevel 		(void) fprintf(stderr, gettext(
   1740  5331       amw 		    "tar: unable to open%sdirectory %s%s%s%s\n"),
   1741     0    stevel 		    (filetype == XATTR_FILE) ? gettext(" attribute ") : " ",
   1742  5331       amw 		    (attrparent == NULL) ? "" : gettext("of attribute "),
   1743  5331       amw 		    (attrparent == NULL) ? "" : attrparent,
   1744  5331       amw 		    (attrparent == NULL) ? "" : gettext(" of "),
   1745     0    stevel 		    (filetype == XATTR_FILE) ? longname : parent);
   1746     0    stevel 		goto out;
   1747     0    stevel 	}
   1748     0    stevel 
   1749     0    stevel 	if (lev > MAXLEV) {
   1750     0    stevel 		(void) fprintf(stderr,
   1751     0    stevel 		    gettext("tar: directory nesting too deep, %s not dumped\n"),
   1752     0    stevel 		    longname);
   1753     0    stevel 		goto out;
   1754     0    stevel 	}
   1755     0    stevel 
   1756  5331       amw 	if (getstat(dirfd, longname, shortname, attrparent))
   1757     0    stevel 		goto out;
   1758     0    stevel 
   1759     0    stevel 	if (hflag) {
   1760     0    stevel 		/*
   1761     0    stevel 		 * Catch nesting where a file is a symlink to its directory.
   1762     0    stevel 		 */
   1763     0    stevel 		j = fstatat(dirfd, shortname, &sbuf, AT_SYMLINK_NOFOLLOW);
   1764     0    stevel 		if (S_ISLNK(sbuf.st_mode)) {
   1765     0    stevel 			if (symlink_lev++ >= MAXSYMLINKS) {
   1766     0    stevel 				(void) fprintf(stderr, gettext(
   1767     0    stevel 				    "tar: %s: Number of symbolic links "
   1768     0    stevel 				    "encountered during path name traversal "
   1769     0    stevel 				    "exceeds MAXSYMLINKS\n"), longname);
   1770     0    stevel 				Errflg = 1;
   1771     0    stevel 				goto out;
   1772     0    stevel 			}
   1773     0    stevel 		}
   1774     0    stevel 	}
   1775     0    stevel 
   1776     0    stevel 	/*
   1777     0    stevel 	 * Check if the input file is the same as the tar file we
   1778     0    stevel 	 * are creating
   1779     0    stevel 	 */
   1780     0    stevel 	if ((mt_ino == stbuf.st_ino) && (mt_dev == stbuf.st_dev)) {
   1781     0    stevel 		(void) fprintf(stderr, gettext(
   1782  5331       amw 		    "tar: %s%s%s%s%s same as archive file\n"),
   1783  5331       amw 		    rw_sysattr ? gettext("system ") : "",
   1784  5331       amw 		    (longattrname == NULL) ? "" : gettext("attribute "),
   1785  5331       amw 		    (longattrname == NULL) ? "" : longattrname,
   1786  5331       amw 		    (longattrname == NULL) ? "" : gettext(" of "),
   1787  5331       amw 		    longname);
   1788     0    stevel 		Errflg = 1;
   1789     0    stevel 		goto out;
   1790     0    stevel 	}
   1791     0    stevel 	/*
   1792     0    stevel 	 * Check size limit - we can't archive files that
   1793     0    stevel 	 * exceed TAR_OFFSET_MAX bytes because of header
   1794     0    stevel 	 * limitations. Exclude file types that set
   1795     0    stevel 	 * st_size to zero below because they take no
   1796     0    stevel 	 * archive space to represent contents.
   1797     0    stevel 	 */
   1798     0    stevel 	if ((stbuf.st_size > (off_t)TAR_OFFSET_MAX) &&
   1799     0    stevel 	    !S_ISDIR(stbuf.st_mode) &&
   1800     0    stevel 	    !S_ISCHR(stbuf.st_mode) &&
   1801     0    stevel 	    !S_ISBLK(stbuf.st_mode) &&
   1802     0    stevel 	    (Eflag == 0)) {
   1803     0    stevel 		(void) fprintf(stderr, gettext(
   1804  5331       amw 		    "tar: %s%s%s%s%s too large to archive.  "
   1805  5331       amw 		    "Use E function modifier.\n"),
   1806  5331       amw 		    rw_sysattr ? gettext("system ") : "",
   1807  5331       amw 		    (longattrname == NULL) ? "" : gettext("attribute "),
   1808  5331       amw 		    (longattrname == NULL) ? "" : longattrname,
   1809  5331       amw 		    (longattrname == NULL) ? "" : gettext(" of "),
   1810  5331       amw 		    longname);
   1811     0    stevel 		if (errflag)
   1812     0    stevel 			exitflag = 1;
   1813     0    stevel 		Errflg = 1;
   1814     0    stevel 		goto out;
   1815     0    stevel 	}
   1816     0    stevel 
   1817     0    stevel 	if (tfile != NULL && checkupdate(longname) == 0) {
   1818     0    stevel 		goto out;
   1819     0    stevel 	}
   1820     0    stevel 	if (checkw('r', longname) == 0) {
   1821     0    stevel 		goto out;
   1822     0    stevel 	}
   1823     0    stevel 
   1824     0    stevel 	if (Fflag && checkf(shortname, stbuf.st_mode, Fflag) == 0)
   1825     0    stevel 		goto out;
   1826     0    stevel 
   1827     0    stevel 	if (Xflag) {
   1828     0    stevel 		if (is_in_table(exclude_tbl, longname)) {
   1829     0    stevel 			if (vflag) {
   1830     0    stevel 				(void) fprintf(vfile, gettext(
   1831     0    stevel 				    "a %s excluded\n"), longname);
   1832     0    stevel 			}
   1833     0    stevel 			goto out;
   1834     0    stevel 		}
   1835     0    stevel 	}
   1836     0    stevel 
   1837     0    stevel 	/*
   1838     0    stevel 	 * If the length of the fullname is greater than MAXNAM,
   1839     0    stevel 	 * print out a message and return (unless extended headers are used,
   1840     0    stevel 	 * in which case fullname is limited to PATH_MAX).
   1841     0    stevel 	 */
   1842     0    stevel 
   1843     0    stevel 	if ((((split = (int)strlen(longname)) > MAXNAM) && (Eflag == 0)) ||
   1844     0    stevel 	    (split > PATH_MAX)) {
   1845     0    stevel 		(void) fprintf(stderr, gettext(
   1846     0    stevel 		    "tar: %s: file name too long\n"), longname);
   1847     0    stevel 		if (errflag)
   1848     0    stevel 			exitflag = 1;
   1849     0    stevel 		Errflg = 1;
   1850     0    stevel 		goto out;
   1851     0    stevel 	}
   1852     0    stevel 
   1853     0    stevel 	/*
   1854     0    stevel 	 * We split the fullname into prefix and name components if any one
   1855     0    stevel 	 * of three conditions holds:
   1856     0    stevel 	 *	-- the length of the fullname exceeds NAMSIZ,
   1857     0    stevel 	 *	-- the length of the fullname equals NAMSIZ, and the shortname
   1858     0    stevel 	 *	   is less than NAMSIZ, (splitting in this case preserves
   1859     0    stevel 	 *	   compatibility with 5.6 and 5.5.1 tar), or
   1860     0    stevel 	 * 	-- the length of the fullname equals NAMSIZ, the file is a
   1861     0    stevel 	 *	   directory and we are not in POSIX-conformant mode (where
   1862     0    stevel 	 *	   trailing slashes are removed from directories).
   1863     0    stevel 	 */
   1864     0    stevel 	if ((split > NAMSIZ) ||
   1865     0    stevel 	    (split == NAMSIZ && strlen(shortname) < NAMSIZ) ||
   1866   871    casper 	    (split == NAMSIZ && S_ISDIR(stbuf.st_mode) && !Pflag)) {
   1867     0    stevel 		/*
   1868     0    stevel 		 * Since path is limited to PRESIZ characters, look for the
   1869     0    stevel 		 * last slash within PRESIZ + 1 characters only.
   1870     0    stevel 		 */
   1871     0    stevel 		(void) strncpy(&goodbuf[0], longname, min(split, PRESIZ + 1));
   1872     0    stevel 		tmpbuf = goodbuf;
   1873     0    stevel 		lastslash = strrchr(tmpbuf, '/');
   1874     0    stevel 		if (lastslash == NULL) {
   1875     0    stevel 			i = split;		/* Length of name */
   1876     0    stevel 			j = 0;			/* Length of prefix */
   1877     0    stevel 			goodbuf[0] = '\0';
   1878     0    stevel 		} else {
   1879     0    stevel 			*lastslash = '\0';	/* Terminate the prefix */
   1880     0    stevel 			j = strlen(tmpbuf);
   1881     0    stevel 			i = split - j - 1;
   1882     0    stevel 		}
   1883     0    stevel 		/*
   1884     0    stevel 		 * If the filename is greater than NAMSIZ we can't
   1885     0    stevel 		 * archive the file unless we are using extended headers.
   1886     0    stevel 		 */
   1887   871    casper 		if ((i > NAMSIZ) || (i == NAMSIZ && S_ISDIR(stbuf.st_mode) &&
   1888     0    stevel 		    !Pflag)) {
   1889     0    stevel 			/* Determine which (filename or path) is too long. */
   1890     0    stevel 			lastslash = strrchr(longname, '/');
   1891     0    stevel 			if (lastslash != NULL)
   1892     0    stevel 				i = strlen(lastslash + 1);
   1893     0    stevel 			if (Eflag > 0) {
   1894     0    stevel 				xhdr_flgs |= _X_PATH;
   1895     0    stevel 				Xtarhdr.x_path = longname;
   1896     0    stevel 				if (i <= NAMSIZ)
   1897     0    stevel 					(void) strcpy(junkbuf, lastslash + 1);
   1898     0    stevel 				else
   1899     0    stevel 					(void) sprintf(junkbuf, "%llu",
   1900     0    stevel 					    xhdr_count + 1);
   1901     0    stevel 				if (split - i - 1 > PRESIZ)
   1902     0    stevel 					(void) strcpy(goodbuf, xhdr_dirname);
   1903     0    stevel 			} else {
   1904     0    stevel 				if ((i > NAMSIZ) || (i == NAMSIZ &&
   1905   871    casper 				    S_ISDIR(stbuf.st_mode) && !Pflag))
   1906     0    stevel 					(void) fprintf(stderr, gettext(
   1907     0    stevel 					    "tar: %s: filename is greater than "
   1908     0    stevel 					    "%d\n"), lastslash == NULL ?
   1909     0    stevel 					    longname : lastslash + 1, NAMSIZ);
   1910     0    stevel 				else
   1911     0    stevel 					(void) fprintf(stderr, gettext(
   1912     0    stevel 					    "tar: %s: prefix is greater than %d"
   1913     0    stevel 					    "\n"), longname, PRESIZ);
   1914     0    stevel 				if (errflag)
   1915     0    stevel 					exitflag = 1;
   1916     0    stevel 				Errflg = 1;
   1917     0    stevel 				goto out;
   1918     0    stevel 			}
   1919     0    stevel 		} else
   1920     0    stevel 			(void) strncpy(&junkbuf[0], longname + j + 1,
   1921     0    stevel 			    strlen(longname + j + 1));
   1922     0    stevel 		name = junkbuf;
   1923     0    stevel 		prefix = goodbuf;
   1924     0    stevel 	} else {
   1925     0    stevel 		name = longname;
   1926     0    stevel 	}
   1927     0    stevel 	if (Aflag) {
   1928     0    stevel 		if ((prefix != NULL) && (*prefix != '\0'))
   1929     0    stevel 			while (*prefix == '/')
   1930     0    stevel 				++prefix;
   1931     0    stevel 		else
   1932     0    stevel 			while (*name == '/')
   1933     0    stevel 				++name;
   1934     0    stevel 	}
   1935     0    stevel 
   1936     0    stevel 	switch (stbuf.st_mode & S_IFMT) {
   1937     0    stevel 	case S_IFDIR:
   1938     0    stevel 		stbuf.st_size = (off_t)0;
   1939     0    stevel 		blocks = TBLOCKS(stbuf.st_size);
   1940     0    stevel 
   1941     0    stevel 		if (filetype != XATTR_FILE && Hiddendir == 0) {
   1942     0    stevel 			i = 0;
   1943     0    stevel 			cp = buf;
   1944     0    stevel 			while ((*cp++ = longname[i++]))
   1945     0    stevel 				;
   1946     0    stevel 			*--cp = '/';
   1947     0    stevel 			*++cp = 0;
   1948     0    stevel 		}
   1949     0    stevel 		if (!oflag) {
   1950     0    stevel 			tomodes(&stbuf);
   1951     0    stevel 			if (build_dblock(name, tchar, '5', filetype,
   1952     0    stevel 			    &stbuf, stbuf.st_dev, prefix) != 0) {
   1953     0    stevel 				goto out;
   1954     0    stevel 			}
   1955     0    stevel 			if (!Pflag) {
   1956     0    stevel 				/*
   1957     0    stevel 				 * Old archives require a slash at the end
   1958     0    stevel 				 * of a directory name.
   1959     0    stevel 				 *
   1960     0    stevel 				 * XXX
   1961     0    stevel 				 * If directory name is too long, will
   1962     0    stevel 				 * slash overfill field?
   1963     0    stevel 				 */
   1964     0    stevel 				if (strlen(name) > (unsigned)NAMSIZ-1) {
   1965     0    stevel 					(void) fprintf(stderr, gettext(
   1966     0    stevel 					    "tar: %s: filename is greater "
   1967     0    stevel 					    "than %d\n"), name, NAMSIZ);
   1968     0    stevel 					if (errflag)
   1969     0    stevel 						exitflag = 1;
   1970     0    stevel 					Errflg = 1;
   1971     0    stevel 					goto out;
   1972     0    stevel 				} else {
   1973     0    stevel 					if (strlen(name) == (NAMSIZ - 1)) {
   1974     0    stevel 						(void) memcpy(dblock.dbuf.name,
   1975     0    stevel 						    name, NAMSIZ);
   1976     0    stevel 						dblock.dbuf.name[NAMSIZ-1]
   1977     0    stevel 						    = '/';
   1978     0    stevel 					} else
   1979     0    stevel 						(void) sprintf(dblock.dbuf.name,
   1980     0    stevel 						    "%s/", name);
   1981     0    stevel 
   1982     0    stevel 					/*
   1983     0    stevel 					 * need to recalculate checksum
   1984     0    stevel 					 * because the name changed.
   1985     0    stevel 					 */
   1986     0    stevel 					(void) sprintf(dblock.dbuf.chksum,
   1987     0    stevel 					    "%07o", checksum(&dblock));
   1988     0    stevel 				}
   1989     0    stevel 			}
   1990     0    stevel 
   1991  5331       amw 			if (put_extra_attributes(longname, shortname,
   1992  5331       amw 			    longattrname, prefix, filetype, '5') != 0)
   1993     0    stevel 				goto out;
   1994     0    stevel 
   1995     0    stevel #if defined(O_XATTR)
   1996     0    stevel 			/*
   1997     0    stevel 			 * Reset header typeflag when archiving directory, since
   1998     0    stevel 			 * build_dblock changed it on us.
   1999     0    stevel 			 */
   2000     0    stevel 			if (filetype == XATTR_FILE) {
   2001     0    stevel 				dblock.dbuf.typeflag = _XATTR_HDRTYPE;
   2002     0    stevel 			} else {
   2003     0    stevel 				dblock.dbuf.typeflag = '5';
   2004     0    stevel 			}
   2005     0    stevel #else
   2006     0    stevel 			dblock.dbuf.typeflag = '5';
   2007     0    stevel #endif
   2008     0    stevel 
   2009     0    stevel 			(void) sprintf(dblock.dbuf.chksum, "%07o",
   2010     0    stevel 			    checksum(&dblock));
   2011     0    stevel 
   2012     0    stevel 			(void) writetbuf((char *)&dblock, 1);
   2013     0    stevel 		}
   2014     0    stevel 		if (vflag) {
   2015     0    stevel #ifdef DEBUG
   2016     0    stevel 			if (NotTape)
   2017     0    stevel 				DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
   2018     0    stevel 				    0);
   2019     0    stevel #endif
   2020     0    stevel 			if (filetype == XATTR_FILE && Hiddendir) {
   2021  5331       amw 				(void) fprintf(vfile, "a %s attribute %s ",
   2022  5331       amw 				    longname, longattrname);
   2023     0    stevel 
   2024     0    stevel 			} else {
   2025     0    stevel 				(void) fprintf(vfile, "a %s/ ", longname);
   2026     0    stevel 			}
   2027     0    stevel 			if (NotTape)
   2028     0    stevel 				(void) fprintf(vfile, "%" FMT_blkcnt_t "K\n",
   2029     0    stevel 				    K(blocks));
   2030     0    stevel 			else
   2031     0    stevel 				(void) fprintf(vfile, gettext("%" FMT_blkcnt_t
   2032     0    stevel 				    " tape blocks\n"), blocks);
   2033     0    stevel 		}
   2034     0    stevel 
   2035     0    stevel 		/*
   2036     0    stevel 		 * If hidden dir then break now since xattrs_put() will do
   2037     0    stevel 		 * the iterating of the directory.
   2038     0    stevel 		 *
   2039  5331       amw 		 * At the moment, there can only be system attributes on
   2040  5331       amw 		 * attributes.  There can be no attributes on attributes or
   2041  5331       amw 		 * directories within the attributes hidden directory hierarchy.
   2042     0    stevel 		 */
   2043     0    stevel 		if (filetype == XATTR_FILE)
   2044     0    stevel 			break;
   2045     0    stevel 
   2046     0    stevel 		if (*shortname != '/')
   2047     0    stevel 			(void) sprintf(newparent, "%s/%s", parent, shortname);
   2048     0    stevel 		else
   2049     0    stevel 			(void) sprintf(newparent, "%s", shortname);
   2050     0    stevel 
   2051     0    stevel 		if (chdir(shortname) < 0) {
   2052     0    stevel 			vperror(0, "%s", newparent);
   2053     0    stevel 			goto out;
   2054     0    stevel 		}
   2055     0    stevel 
   2056     0    stevel 		if ((dirp = opendir(".")) == NULL) {
   2057     0    stevel 			vperror(0, gettext(
   2058  5331       amw 			    "can't open directory %s"), longname);
   2059     0    stevel 			if (chdir(parent) < 0)
   2060     0    stevel 				vperror(0, gettext("cannot change back?: %s"),
   2061     0    stevel 				    parent);
   2062     0    stevel 			goto out;
   2063     0    stevel 		}
   2064     0    stevel 
   2065  6525   ceastha 		/*
   2066  6525   ceastha 		 * Create a list of files (children) in this directory to avoid
   2067  6525   ceastha 		 * having to perform telldir()/seekdir().
   2068  6525   ceastha 		 */
   2069     0    stevel 		while ((dp = readdir(dirp)) != NULL && !term) {
   2070     0    stevel 			if ((strcmp(".", dp->d_name) == 0) ||
   2071     0    stevel 			    (strcmp("..", dp->d_name) == 0))
   2072     0    stevel 				continue;
   2073  6525   ceastha 			if (((cptr = (file_list_t *)calloc(sizeof (char),
   2074  6525   ceastha 			    sizeof (file_list_t))) == NULL) ||
   2075  6525   ceastha 			    ((cptr->name = strdup(dp->d_name)) == NULL)) {
   2076  6525   ceastha 				vperror(1, gettext(
   2077  6525   ceastha 				    "Insufficient memory for directory "
   2078  6525   ceastha 				    "list entry %s/%s\n"),
   2079  6525   ceastha 				    newparent, dp->d_name);
   2080  6525   ceastha 			}
   2081  6525   ceastha 
   2082  6525   ceastha 			/* Add the file to the list */
   2083  6525   ceastha 			if (child == NULL) {
   2084  6525   ceastha 				child = cptr;
   2085  6525   ceastha 			} else {
   2086  6525   ceastha 				child_end->next = cptr;
   2087  6525   ceastha 			}
   2088  6525   ceastha 			child_end = cptr;
   2089  6525   ceastha 		}
   2090  6525   ceastha 		(void) closedir(dirp);
   2091  6525   ceastha 
   2092  6525   ceastha 		/*
   2093  6525   ceastha 		 * Archive each of the files in the current directory.
   2094  6525   ceastha 		 * If a file is a directory, putfile() is called
   2095  6525   ceastha 		 * recursively to archive the file hierarchy of the
   2096  6525   ceastha 		 * directory before archiving the next file in the
   2097  6525   ceastha 		 * current directory.
   2098  6525   ceastha 		 */
   2099  6525   ceastha 		while ((child != NULL) && !term) {
   2100  6525   ceastha 			(void) strcpy(cp, child->name);
   2101  5331       amw 			archtype = putfile(buf, cp, newparent, NULL,
   2102     0    stevel 			    NORMAL_FILE, lev + 1, symlink_lev);
   2103     0    stevel 
   2104     0    stevel 			if (!exitflag) {
   2105  5331       amw 				if ((atflag || saflag) &&
   2106  5331       amw 				    (archtype == PUT_NOTAS_LINK)) {
   2107  5331       amw 					xattrs_put(buf, cp, newparent, NULL);
   2108     0    stevel 				}
   2109     0    stevel 			}
   2110     0    stevel 			if (exitflag)
   2111     0    stevel 				break;
   2112     0    stevel 
   2113  6525   ceastha 			/* Free each child as we are done processing it. */
   2114  6525   ceastha 			cptr = child;
   2115  6525   ceastha 			child = child->next;
   2116  6525   ceastha 			free(cptr->name);
   2117  6525   ceastha 			free(cptr);
   2118  6525   ceastha 		}
   2119  6525   ceastha 		if ((child != NULL) && !term) {
   2120  6525   ceastha 			free_children(child);
   2121  6525   ceastha 		}
   2122     0    stevel 
   2123     0    stevel 		if (chdir(parent) < 0) {
   2124     0    stevel 			vperror(0, gettext("cannot change back?: %s"), parent);
   2125     0    stevel 		}
   2126     0    stevel 
   2127     0    stevel 		break;
   2128     0    stevel 
   2129     0    stevel 	case S_IFLNK:
   2130     0    stevel 		readlink_max = NAMSIZ;
   2131     0    stevel 		if (stbuf.st_size > NAMSIZ) {
   2132     0    stevel 			if (Eflag > 0) {
   2133     0    stevel 				xhdr_flgs |= _X_LINKPATH;
   2134     0    stevel 				readlink_max = PATH_MAX;
   2135     0    stevel 			} else {
   2136     0    stevel 				(void) fprintf(stderr, gettext(
   2137     0    stevel 				    "tar: %s: symbolic link too long\n"),
   2138     0    stevel 				    longname);
   2139     0    stevel 				if (errflag)
   2140     0    stevel 					exitflag = 1;
   2141     0    stevel 				Errflg = 1;
   2142     0    stevel 				goto out;
   2143     0    stevel 			}
   2144     0    stevel 		}
   2145     0    stevel 		/*
   2146     0    stevel 		 * Sym-links need header size of zero since you
   2147     0    stevel 		 * don't store any data for this type.
   2148     0    stevel 		 */
   2149     0    stevel 		stbuf.st_size = (off_t)0;
   2150     0    stevel 		tomodes(&stbuf);
   2151     0    stevel 		i = readlink(shortname, filetmp, readlink_max);
   2152     0    stevel 		if (i < 0) {
   2153     0    stevel 			vperror(0, gettext(
   2154     0    stevel 			    "can't read symbolic link %s"), longname);
   2155     0    stevel 			goto out;
   2156     0    stevel 		} else {
   2157     0    stevel 			filetmp[i] = 0;
   2158     0    stevel 		}
   2159     0    stevel 		if (vflag)
   2160     0    stevel 			(void) fprintf(vfile, gettext(
   2161     0    stevel 			    "a %s symbolic link to %s\n"),
   2162     0    stevel 			    longname, filetmp);
   2163     0    stevel 		if (xhdr_flgs & _X_LINKPATH) {
   2164     0    stevel 			Xtarhdr.x_linkpath = filetmp;
   2165     0    stevel 			if (build_dblock(name, tchar, '2', filetype, &stbuf,
   2166     0    stevel 			    stbuf.st_dev, prefix) != 0)
   2167     0    stevel 				goto out;
   2168     0    stevel 		} else
   2169     0    stevel 			if (build_dblock(name, filetmp, '2', filetype, &stbuf,
   2170     0    stevel 			    stbuf.st_dev, prefix) != 0)
   2171     0    stevel 				goto out;
   2172     0    stevel 		(void) writetbuf((char *)&dblock, 1);
   2173     0    stevel 		/*
   2174     0    stevel 		 * No acls for symlinks: mode is always 777
   2175     0    stevel 		 * dont call write ancillary
   2176     0    stevel 		 */
   2177     0    stevel 		rc = PUT_AS_LINK;
   2178     0    stevel 		break;
   2179     0    stevel 	case S_IFREG:
   2180     0    stevel 		if ((infile = openat(dirfd, shortname, 0)) < 0) {
   2181  5331       amw 			vperror(0, "unable to open %s%s%s%s", longname,
   2182  5331       amw 			    rw_sysattr ? gettext(" system") : "",
   2183     0    stevel 			    (filetype == XATTR_FILE) ?
   2184     0    stevel 			    gettext(" attribute ") : "",
   2185  5331       amw 			    (filetype == XATTR_FILE) ? (longattrname == NULL) ?
   2186  5331       amw 			    shortname : longattrname : "");
   2187     0    stevel 			goto out;
   2188     0    stevel 		}
   2189     0    stevel 
   2190     0    stevel 		blocks = TBLOCKS(stbuf.st_size);
   2191     0    stevel 
   2192  5331       amw 		if (put_link(name, longname, shortname, longattrname,
   2193     0    stevel 		    prefix, filetype, '1') == 0) {
   2194     0    stevel 			(void) close(infile);
   2195     0    stevel 			rc = PUT_AS_LINK;
   2196     0    stevel 			goto out;
   2197     0    stevel 		}
   2198     0    stevel 
   2199     0    stevel 		tomodes(&stbuf);
   2200     0    stevel 
   2201     0    stevel 		/* correctly handle end of volume */
   2202     0    stevel 		while (mulvol && tapepos + blocks + 1 > blocklim) {
   2203     0    stevel 			/* file won't fit */
   2204     0    stevel 			if (eflag) {
   2205     0    stevel 				if (blocks <= blocklim) {
   2206     0    stevel 					newvol();
   2207     0    stevel 					break;
   2208     0    stevel 				}
   2209     0    stevel 				(void) fprintf(stderr, gettext(
   2210     0    stevel 				    "tar: Single file cannot fit on volume\n"));
   2211     0    stevel 				done(3);
   2212     0    stevel 			}
   2213     0    stevel 			/* split if floppy has some room and file is large */
   2214     0    stevel 			if (((blocklim - tapepos) >= EXTMIN) &&
   2215     0    stevel 			    ((blocks + 1) >= blocklim/10)) {
   2216     0    stevel 				splitfile(longname, infile,
   2217     0    stevel 				    name, prefix, filetype);
   2218     0    stevel 				(void) close(dirfd);
   2219     0    stevel 				(void) close(infile);
   2220     0    stevel 				goto out;
   2221     0    stevel 			}
   2222     0    stevel 			newvol();	/* not worth it--just get new volume */
   2223     0    stevel 		}
   2224     0    stevel #ifdef DEBUG
   2225     0    stevel 		DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,
   2226     0    stevel 		    blocks);
   2227     0    stevel #endif
   2228     0    stevel 		if (build_dblock(name, tchar, '0', filetype,
   2229     0    stevel 		    &stbuf, stbuf.st_dev, prefix) != 0) {
   2230     0    stevel 			goto out;
   2231     0    stevel 		}
   2232     0    stevel 		if (vflag) {
   2233     0    stevel #ifdef DEBUG
   2234     0    stevel 			if (NotTape)
   2235     0    stevel 				DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
   2236     0    stevel 				    0);
   2237     0    stevel #endif
   2238  5331       amw 			(void) fprintf(vfile, "a %s%s%s%s ", longname,
   2239  5331       amw 			    rw_sysattr ? gettext(" system") : "",
   2240  5331       amw 			    (filetype == XATTR_FILE) ? gettext(
   2241  5331       amw 			    " attribute ") : "",
   2242     0    stevel 			    (filetype == XATTR_FILE) ?
   2243  5331       amw 			    longattrname : "");
   2244     0    stevel 			if (NotTape)
   2245     0    stevel 				(void) fprintf(vfile, "%" FMT_blkcnt_t "K\n",
   2246     0    stevel 				    K(blocks));
   2247     0    stevel 			else
   2248     0    stevel 				(void) fprintf(vfile,
   2249     0    stevel 				    gettext("%" FMT_blkcnt_t " tape blocks\n"),
   2250     0    stevel 				    blocks);
   2251     0    stevel 		}
   2252     0    stevel 
   2253  5331       amw 		if (put_extra_attributes(longname, shortname, longattrname,
   2254  5331       amw 		    prefix, filetype, '0') != 0)
   2255     0    stevel 			goto out;
   2256     0    stevel 
   2257     0    stevel 		/*
   2258     0    stevel 		 * No need to reset typeflag for extended attribute here, since
   2259     0    stevel 		 * put_extra_attributes already set it and we haven't called
   2260     0    stevel 		 * build_dblock().
   2261     0    stevel 		 */
   2262     0    stevel 		(void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock));
   2263     0    stevel 		hint = writetbuf((char *)&dblock, 1);
   2264  1266   ceastha 		maxread = max(min(stbuf.st_blksize, stbuf.st_size),
   2265  1266   ceastha 		    (nblock * TBLOCK));
   2266     0    stevel 		if ((bigbuf = calloc((unsigned)maxread, sizeof (char))) == 0) {
   2267     0    stevel 			maxread = TBLOCK;
   2268     0    stevel 			bigbuf = buf;
   2269     0    stevel 		}
   2270     0    stevel 
   2271     0    stevel 		while (((i = (int)
   2272     0    stevel 		    read(infile, bigbuf, min((hint*TBLOCK), maxread))) > 0) &&
   2273     0    stevel 		    blocks) {
   2274     0    stevel 			blkcnt_t nblks;
   2275     0    stevel 
   2276     0    stevel 			nblks = ((i-1)/TBLOCK)+1;
   2277     0    stevel 			if (nblks > blocks)
   2278     0    stevel 				nblks = blocks;
   2279     0    stevel 			hint = writetbuf(bigbuf, nblks);
   2280     0    stevel 			blocks -= nblks;
   2281     0    stevel 		}
   2282     0    stevel 		(void) close(infile);
   2283     0    stevel 		if (bigbuf != buf)
   2284     0    stevel 			free(bigbuf);
   2285     0    stevel 		if (i < 0)
   2286     0    stevel 			vperror(0, gettext("Read error on %s"), longname);
   2287     0    stevel 		else if (blocks != 0 || i != 0) {
   2288     0    stevel 			(void) fprintf(stderr, gettext(
   2289     0    stevel 			"tar: %s: file changed size\n"), longname);
   2290     0    stevel 			if (errflag) {
   2291     0    stevel 				exitflag = 1;
   2292     0    stevel 				Errflg = 1;
   2293     0    stevel 			} else if (!Dflag) {
   2294     0    stevel 				Errflg = 1;
   2295     0    stevel 			}
   2296     0    stevel 		}
   2297     0    stevel 		putempty(blocks);
   2298     0    stevel 		break;
   2299     0    stevel 	case S_IFIFO:
   2300     0    stevel 		blocks = TBLOCKS(stbuf.st_size);
   2301     0    stevel 		stbuf.st_size = (off_t)0;
   2302     0    stevel 
   2303  5331       amw 		if (put_link(name, longname, shortname, longattrname,
   2304     0    stevel 		    prefix, filetype, '6') == 0) {
   2305     0    stevel 			rc = PUT_AS_LINK;
   2306     0    stevel 			goto out;
   2307     0    stevel 		}
   2308     0    stevel 		tomodes(&stbuf);
   2309     0    stevel 
   2310     0    stevel 		while (mulvol && tapepos + blocks + 1 > blocklim) {
   2311     0    stevel 			if (eflag) {
   2312     0    stevel 				if (blocks <= blocklim) {
   2313     0    stevel 					newvol();
   2314     0    stevel 					break;
   2315     0    stevel 				}
   2316     0    stevel 				(void) fprintf(stderr, gettext(
   2317     0    stevel 				    "tar: Single file cannot fit on volume\n"));
   2318     0    stevel 				done(3);
   2319     0    stevel 			}
   2320     0    stevel 
   2321     0    stevel 			if (((blocklim - tapepos) >= EXTMIN) &&
   2322     0    stevel 			    ((blocks + 1) >= blocklim/10)) {
   2323     0    stevel 				splitfile(longname, infile, name,
   2324     0    stevel 				    prefix, filetype);
   2325     0    stevel 				(void) close(dirfd);
   2326     0    stevel 				(void) close(infile);
   2327     0    stevel 				goto out;
   2328     0    stevel 			}
   2329     0    stevel 			newvol();
   2330     0    stevel 		}
   2331     0    stevel #ifdef DEBUG
   2332     0    stevel 		DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,
   2333     0    stevel 		    blocks);
   2334     0    stevel #endif
   2335     0    stevel 		if (vflag) {
   2336     0    stevel #ifdef DEBUG
   2337     0    stevel 			if (NotTape)
   2338     0    stevel 				DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
   2339     0    stevel 				    0);
   2340     0    stevel #endif
   2341     0    stevel 			if (NotTape)
   2342     0    stevel 				(void) fprintf(vfile, gettext("a %s %"
   2343     0    stevel 				    FMT_blkcnt_t "K\n "), longname, K(blocks));
   2344     0    stevel 			else
   2345     0    stevel 				(void) fprintf(vfile, gettext(
   2346     0    stevel 				    "a %s %" FMT_blkcnt_t " tape blocks\n"),
   2347     0    stevel 				    longname, blocks);
   2348     0    stevel 		}
   2349     0    stevel 		if (build_dblock(name, tchar, '6', filetype,
   2350     0    stevel 		    &stbuf, stbuf.st_dev, prefix) != 0)
   2351     0    stevel 			goto out;
   2352     0    stevel 
   2353  5331       amw 		if (put_extra_attributes(longname, shortname, longattrname,
   2354  5331       amw 		    prefix, filetype, '6') != 0)
   2355     0    stevel 			goto out;
   2356     0    stevel 
   2357     0    stevel 		(void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock));
   2358     0    stevel 		dblock.dbuf.typeflag = '6';
   2359     0    stevel 
   2360     0    stevel 		(void) writetbuf((char *)&dblock, 1);
   2361     0    stevel 		break;
   2362     0    stevel 	case S_IFCHR:
   2363     0    stevel 		stbuf.st_size = (off_t)0;
   2364     0    stevel 		blocks = TBLOCKS(stbuf.st_size);
   2365  5331       amw 		if (put_link(name, longname, shortname, longattrname,
   2366  5331       amw 		    prefix, filetype, '3') == 0) {
   2367     0    stevel 			rc = PUT_AS_LINK;
   2368     0    stevel 			goto out;
   2369     0    stevel 		}
   2370     0    stevel 		tomodes(&stbuf);
   2371     0    stevel 
   2372     0    stevel 		while (mulvol && tapepos + blocks + 1 > blocklim) {
   2373     0    stevel 			if (eflag) {
   2374     0    stevel 				if (blocks <= blocklim) {
   2375     0    stevel 					newvol();
   2376     0    stevel 					break;
   2377     0    stevel 				}
   2378     0    stevel 				(void) fprintf(stderr, gettext(
   2379     0    stevel 				    "tar: Single file cannot fit on volume\n"));
   2380     0    stevel 				done(3);
   2381     0    stevel 			}
   2382     0    stevel 
   2383     0    stevel 			if (((blocklim - tapepos) >= EXTMIN) &&
   2384     0    stevel 			    ((blocks + 1) >= blocklim/10)) {
   2385     0    stevel 				splitfile(longname, infile, name,
   2386     0    stevel 				    prefix, filetype);
   2387     0    stevel 				(void) close(dirfd);
   2388     0    stevel 				goto out;
   2389     0    stevel 			}
   2390     0    stevel 			newvol();
   2391     0    stevel 		}
   2392     0    stevel #ifdef DEBUG
   2393     0    stevel 		DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,
   2394     0    stevel 		    blocks);
   2395     0    stevel #endif
   2396     0    stevel 		if (vflag) {
   2397     0    stevel #ifdef DEBUG
   2398     0    stevel 			if (NotTape)
   2399     0    stevel 				DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
   2400     0    stevel 				    0);
   2401     0    stevel #endif
   2402     0    stevel 			if (NotTape)
   2403     0    stevel 				(void) fprintf(vfile, gettext("a %s %"
   2404     0    stevel 				    FMT_blkcnt_t "K\n"), longname, K(blocks));
   2405     0    stevel 			else
   2406     0    stevel 				(void) fprintf(vfile, gettext("a %s %"
   2407     0    stevel 				    FMT_blkcnt_t " tape blocks\n"), longname,
   2408     0    stevel 				    blocks);
   2409     0    stevel 		}
   2410     0    stevel 		if (build_dblock(name, tchar, '3',
   2411     0    stevel 		    filetype, &stbuf, stbuf.st_rdev, prefix) != 0)
   2412     0    stevel 			goto out;
   2413     0    stevel 
   2414  5331       amw 		if (put_extra_attributes(longname, shortname, longattrname,
   2415     0    stevel 		    prefix, filetype, '3') != 0)
   2416     0    stevel 			goto out;
   2417     0    stevel 
   2418     0    stevel 		(void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock));
   2419     0    stevel 		dblock.dbuf.typeflag = '3';
   2420     0    stevel 
   2421     0    stevel 		(void) writetbuf((char *)&dblock, 1);
   2422     0    stevel 		break;
   2423     0    stevel 	case S_IFBLK:
   2424     0    stevel 		stbuf.st_size = (off_t)0;
   2425     0    stevel 		blocks = TBLOCKS(stbuf.st_size);
   2426  5331       amw 		if (put_link(name, longname, shortname, longattrname,
   2427  5331       amw 		    prefix, filetype, '4') == 0) {
   2428     0    stevel 			rc = PUT_AS_LINK;
   2429     0    stevel 			goto out;
   2430     0    stevel 		}
   2431     0    stevel 		tomodes(&stbuf);
   2432     0    stevel 
   2433     0    stevel 		while (mulvol && tapepos + blocks + 1 > blocklim) {
   2434     0    stevel 			if (eflag) {
   2435     0    stevel 				if (blocks <= blocklim) {
   2436     0    stevel 					newvol();
   2437     0    stevel 					break;
   2438     0    stevel 				}
   2439     0    stevel 				(void) fprintf(stderr, gettext(
   2440     0    stevel 				    "tar: Single file cannot fit on volume\n"));
   2441     0    stevel 				done(3);
   2442     0    stevel 			}
   2443     0    stevel 
   2444     0    stevel 			if (((blocklim - tapepos) >= EXTMIN) &&
   2445     0    stevel 			    ((blocks + 1) >= blocklim/10)) {
   2446     0    stevel 				splitfile(longname, infile,
   2447     0    stevel 				    name, prefix, filetype);
   2448     0    stevel 				(void) close(dirfd);
   2449     0    stevel 				goto out;
   2450     0    stevel 			}
   2451     0    stevel 			newvol();
   2452     0    stevel 		}
   2453     0    stevel #ifdef DEBUG
   2454     0    stevel 		DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,
   2455     0    stevel 		    blocks);
   2456     0    stevel #endif
   2457     0    stevel 		if (vflag) {
   2458     0    stevel #ifdef DEBUG
   2459     0    stevel 			if (NotTape)
   2460     0    stevel 				DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
   2461     0    stevel 				    0);
   2462     0    stevel #endif
   2463     0    stevel 			(void) fprintf(vfile, "a %s ", longname);
   2464     0    stevel 			if (NotTape)
   2465     0    stevel 				(void) fprintf(vfile, "%" FMT_blkcnt_t "K\n",
   2466     0    stevel 				    K(blocks));
   2467     0    stevel 			else
   2468     0    stevel 				(void) fprintf(vfile, gettext("%"
   2469     0    stevel 				    FMT_blkcnt_t " tape blocks\n"), blocks);
   2470     0    stevel 		}
   2471     0    stevel 		if (build_dblock(name, tchar, '4',
   2472     0    stevel 		    filetype, &stbuf, stbuf.st_rdev, prefix) != 0)
   2473     0    stevel 			goto out;
   2474     0    stevel 
   2475  5331       amw 		if (put_extra_attributes(longname, shortname, longattrname,
   2476     0    stevel 		    prefix, filetype, '4') != 0)
   2477     0    stevel 			goto out;
   2478     0    stevel 
   2479     0    stevel 		(void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock));
   2480     0    stevel 		dblock.dbuf.typeflag = '4';
   2481     0    stevel 
   2482     0    stevel 		(void) writetbuf((char *)&dblock, 1);
   2483     0    stevel 		break;
   2484     0    stevel 	default:
   2485     0    stevel 		(void) fprintf(stderr, gettext(
   2486     0    stevel 		    "tar: %s is not a file. Not dumped\n"), longname);
   2487     0    stevel 		if (errflag)
   2488     0    stevel 			exitflag = 1;
   2489     0    stevel 		Errflg = 1;
   2490     0    stevel 		goto out;
   2491     0    stevel 	}
   2492     0    stevel 
   2493     0    stevel out:
   2494  5331       amw 	if ((dirfd != -1) && (filetype != XATTR_FILE)) {
   2495     0    stevel 		(void) close(dirfd);
   2496     0    stevel 	}
   2497     0    stevel 	return (rc);
   2498     0    stevel }
   2499     0    stevel 
   2500     0    stevel 
   2501     0    stevel /*
   2502     0    stevel  *	splitfile	dump a large file across volumes
   2503     0    stevel  *
   2504     0    stevel  *	splitfile(longname, fd);
   2505     0    stevel  *		char *longname;		full name of file
   2506     0    stevel  *		int ifd;		input file descriptor
   2507     0    stevel  *
   2508     0    stevel  *	NOTE:  only called by putfile() to dump a large file.
   2509     0    stevel  */
   2510     0    stevel 
   2511     0    stevel static void
   2512     0    stevel splitfile(char *longname, int ifd, char *name, char *prefix, int filetype)
   2513     0    stevel {
   2514     0    stevel 	blkcnt_t blocks;
   2515     0    stevel 	off_t bytes, s;
   2516     0    stevel 	char buf[TBLOCK];
   2517     0    stevel 	int i, extents;
   2518     0    stevel 
   2519     0    stevel 	blocks = TBLOCKS(stbuf.st_size);	/* blocks file needs */
   2520     0    stevel 
   2521     0    stevel 	/*
   2522     0    stevel 	 * # extents =
   2523     0    stevel 	 *	size of file after using up rest of this floppy
   2524     0    stevel 	 *		blocks - (blocklim - tapepos) + 1	(for header)
   2525     0    stevel 	 *	plus roundup value before divide by blocklim-1
   2526     0    stevel 	 *		+ (blocklim - 1) - 1
   2527     0    stevel 	 *	all divided by blocklim-1 (one block for each header).
   2528     0    stevel 	 * this gives
   2529     0    stevel 	 *	(blocks - blocklim + tapepos + 1 + blocklim - 2)/(blocklim-1)
   2530     0    stevel 	 * which reduces to the expression used.
   2531     0    stevel 	 * one is added to account for this first extent.
   2532     0    stevel 	 *
   2533     0    stevel 	 * When one is dealing with extremely large archives, one may want
   2534     0    stevel 	 * to allow for a large number of extents.  This code should be
   2535     0    stevel 	 * revisited to determine if extents should be changed to something
   2536     0    stevel 	 * larger than an int.
   2537     0    stevel 	 */
   2538     0    stevel 	extents = (int)((blocks + tapepos - 1ULL)/(blocklim - 1ULL) + 1);
   2539     0    stevel 
   2540     0    stevel 	if (extents < 2 || extents > MAXEXT) {	/* let's be reasonable */
   2541     0    stevel 		(void) fprintf(stderr, gettext(
   2542     0    stevel 		    "tar: %s needs unusual number of volumes to split\n"
   2543     0    stevel 		    "tar: %s not dumped\n"), longname, longname);
   2544     0    stevel 		return;
   2545     0    stevel 	}
   2546     0    stevel 	if (build_dblock(name, tchar, '0', filetype,
   2547     0    stevel 	    &stbuf, stbuf.st_dev, prefix) != 0)
   2548     0    stevel 		return;
   2549     0    stevel 
   2550     0    stevel 	dblock.dbuf.extotal = extents;
   2551     0    stevel 	bytes = stbuf.st_size;
   2552     0    stevel 
   2553     0    stevel 	/*
   2554     0    stevel 	 * The value contained in dblock.dbuf.efsize was formerly used when the
   2555     0    stevel 	 * v flag was specified in conjunction with the t flag. Although it is
   2556     0    stevel 	 * no longer used, older versions of tar will expect the former
   2557     0    stevel 	 * behaviour, so we must continue to write it to the archive.
   2558     0    stevel 	 *
   2559     0    stevel 	 * Since dblock.dbuf.efsize is 10 chars in size, the maximum value it
   2560     0    stevel 	 * can store is TAR_EFSIZE_MAX. If bytes exceeds that value, simply
   2561     0    stevel 	 * store 0.
   2562     0    stevel 	 */
   2563     0    stevel 	if (bytes <= TAR_EFSIZE_MAX)
   2564     0    stevel 		(void) sprintf(dblock.dbuf.efsize, "%9" FMT_off_t_o, bytes);
   2565     0    stevel 	else
   2566     0    stevel 		(void) sprintf(dblock.dbuf.efsize, "%9" FMT_off_t_o, (off_t)0);
   2567     0    stevel 
   2568     0    stevel 	(void) fprintf(stderr, gettext(
   2569     0    stevel 	    "tar: large file %s needs %d extents.\n"
   2570     0    stevel 	    "tar: current device seek position = %" FMT_blkcnt_t "K\n"),
   2571     0    stevel 	    longname, extents, K(tapepos));
   2572     0    stevel 
   2573     0    stevel 	s = (off_t)(blocklim - tapepos - 1) * TBLOCK;
   2574     0    stevel 	for (i = 1; i <= extents; i++) {
   2575     0    stevel 		if (i > 1) {
   2576     0    stevel 			newvol();
   2577     0    stevel 			if (i == extents)
   2578     0    stevel 				s = bytes;	/* last ext. gets true bytes */
   2579     0    stevel 			else
   2580     0    stevel 				s = (off_t)(blocklim - 1)*TBLOCK; /* all */
   2581     0    stevel 		}
   2582     0    stevel 		bytes -= s;
   2583     0    stevel 		blocks = TBLOCKS(s);
   2584     0    stevel 
   2585     0    stevel 		(void) sprintf(dblock.dbuf.size, "%011" FMT_off_t_o, s);
   2586     0    stevel 		dblock.dbuf.extno = i;
   2587     0    stevel 		(void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock));
   2588     0    stevel 		(void) writetbuf((char *)&dblock, 1);
   2589     0    stevel 
   2590     0    stevel 		if (vflag)
   2591     0    stevel 			(void) fprintf(vfile,
   2592     0    stevel 			    "+++ a %s %" FMT_blkcnt_t "K [extent #%d of %d]\n",
   2593     0    stevel 			    longname, K(blocks), i, extents);
   2594     0    stevel 		while (blocks && read(ifd, buf, TBLOCK) > 0) {
   2595     0    stevel 			blocks--;
   2596     0    stevel 			(void) writetbuf(buf, 1);
   2597     0    stevel 		}
   2598     0    stevel 		if (blocks != 0) {
   2599     0    stevel 			(void) fprintf(stderr, gettext(
   2600     0    stevel 			    "tar: %s: file changed size\n"), longname);
   2601     0    stevel 			(void) fprintf(stderr, gettext(
   2602     0    stevel 			    "tar: aborting split file %s\n"), longname);
   2603     0    stevel 			(void) close(ifd);
   2604     0    stevel 			return;
   2605     0    stevel 		}
   2606     0    stevel 	}
   2607     0    stevel 	(void) close(ifd);
   2608     0    stevel 	if (vflag)
   2609     0    stevel 		(void) fprintf(vfile, gettext("a %s %" FMT_off_t "K (in %d "
   2610     0    stevel 		    "extents)\n"), longname, K(TBLOCKS(stbuf.st_size)),
   2611     0    stevel 		    extents);
   2612     0    stevel }
   2613     0    stevel 
   2614     0    stevel /*
   2615     0    stevel  *	convtoreg - determines whether the file should be converted to a
   2616     0    stevel  *	            regular file when extracted
   2617     0    stevel  *
   2618     0    stevel  *	Returns 1 when file size > 0 and typeflag is not recognized
   2619     0    stevel  * 	Otherwise returns 0
   2620     0    stevel  */
   2621     0    stevel static int
   2622     0    stevel convtoreg(off_t size)
   2623     0    stevel {
   2624     0    stevel 	if ((size > 0) && (dblock.dbuf.typeflag != '0') &&
   2625     0    stevel 	    (dblock.dbuf.typeflag != NULL) && (dblock.dbuf.typeflag != '1') &&
   2626     0    stevel 	    (dblock.dbuf.typeflag != '2') && (dblock.dbuf.typeflag != '3') &&
   2627     0    stevel 	    (dblock.dbuf.typeflag != '4') && (dblock.dbuf.typeflag != '5') &&
   2628     0    stevel 	    (dblock.dbuf.typeflag != '6') && (dblock.dbuf.typeflag != 'A') &&
   2629     0    stevel 	    (dblock.dbuf.typeflag != _XATTR_HDRTYPE) &&
   2630     0    stevel 	    (dblock.dbuf.typeflag != 'X')) {
   2631     0    stevel 		return (1);
   2632     0    stevel 	}
   2633     0    stevel 	return (0);
   2634     0    stevel }
   2635     0    stevel 
   2636  5331       amw #if defined(O_XATTR)
   2637  5331       amw static int
   2638  5331       amw save_cwd(void)
   2639  5331       amw {
   2640  5331       amw 	return (open(".", O_RDONLY));
   2641  5331       amw }
   2642  5331       amw #endif
   2643  5331       amw 
   2644  5331       amw #if defined(O_XATTR)
   2645  5331       amw static void
   2646  5331       amw rest_cwd(int *cwd)
   2647  5331       amw {
   2648  5331       amw 	if (*cwd != -1) {
   2649  5331       amw 		if (fchdir(*cwd) < 0) {
   2650  5331       amw 			vperror(0, gettext(
   2651  5331       amw 			    "Cannot fchdir to attribute directory"));
   2652  5331       amw 			exit(1);
   2653  5331       amw 		}
   2654  5331       amw 		(void) close(*cwd);
   2655  5331       amw 		*cwd = -1;
   2656  5331       amw 	}
   2657  5331       amw }
   2658  5331       amw #endif
   2659  5331       amw 
   2660  5331       amw /*
   2661  5331       amw  * Verify the underlying file system supports the attribute type.
   2662  5331       amw  * Only archive extended attribute files when '-@' was specified.
   2663  5331       amw  * Only archive system extended attribute files if '-/' was specified.
   2664  5331       amw  */
   2665  5331       amw #if defined(O_XATTR)
   2666  5331       amw static attr_status_t
   2667  5750   ceastha verify_attr_support(char *filename, int attrflg, arc_action_t actflag,
   2668  5750   ceastha     int *ext_attrflg)
   2669  5750   ceastha {
   2670  5750   ceastha 	/*
   2671  5750   ceastha 	 * Verify extended attributes are supported/exist.  We only
   2672  5750   ceastha 	 * need to check if we are processing a base file, not an
   2673  5750   ceastha 	 * extended attribute.
   2674  5750   ceastha 	 */
   2675  5750   ceastha 	if (attrflg) {
   2676  5750   ceastha 		*ext_attrflg = (pathconf(filename, (actflag == ARC_CREATE) ?
   2677  5750   ceastha 		    _PC_XATTR_EXISTS : _PC_XATTR_ENABLED) == 1);
   2678  5750   ceastha 	}
   2679  5750   ceastha 
   2680  5331       amw 	if (atflag) {
   2681  5750   ceastha 		if (!*ext_attrflg) {
   2682  5331       amw #if defined(_PC_SATTR_ENABLED)
   2683  5331       amw 			if (saflag) {
   2684  5331       amw 				/* Verify system attributes are supported */
   2685  5331       amw 				if (sysattr_support(filename,
   2686  5331       amw 				    (actflag == ARC_CREATE) ? _PC_SATTR_EXISTS :
   2687  5331       amw 				    _PC_SATTR_ENABLED) != 1) {
   2688  5331       amw 					return (ATTR_SATTR_ERR);
   2689  5331       amw 				}
   2690  5331       amw 			} else
   2691  5331       amw 				return (ATTR_XATTR_ERR);
   2692  5331       amw #else
   2693  5331       amw 				return (ATTR_XATTR_ERR);
   2694  5331       amw #endif	/* _PC_SATTR_ENABLED */
   2695  5331       amw 		}
   2696  5331       amw 
   2697  5331       amw #if defined(_PC_SATTR_ENABLED)
   2698  5331       amw 	} else if (saflag) {
   2699  5331       amw 		/* Verify system attributes are supported */
   2700  5331       amw 		if (sysattr_support(filename, (actflag == ARC_CREATE) ?
   2701  5331       amw 		    _PC_SATTR_EXISTS : _PC_SATTR_ENABLED) != 1) {
   2702  5331       amw 			return (ATTR_SATTR_ERR);
   2703  5331       amw 		}
   2704  5331       amw #endif	/* _PC_SATTR_ENABLED */
   2705  5331       amw 	} else {
   2706  5331       amw 		return (ATTR_SKIP);
   2707  5331       amw 	}
   2708  5331       amw 
   2709  5331       amw 	return (ATTR_OK);
   2710  5331       amw }
   2711  5331       amw #endif
   2712  5331       amw 
   2713  5331       amw #if defined(O_XATTR)
   2714  5331       amw /*
   2715  5331       amw  * Recursively open attribute directories until the attribute directory
   2716  5331       amw  * containing the specified attribute, attrname, is opened.
   2717  5331       amw  *
   2718  5331       amw  * Currently, only 2 directory levels of attributes are supported, (i.e.,
   2719  5331       amw  * extended system attributes on extended attributes).  The following are
   2720  5331       amw  * the possible input combinations:
   2721  5331       amw  *	1.  Open the attribute directory of the base file (don't change
   2722  5331       amw  *	    into it).
   2723  5331       amw  *		attrinfo->parent = NULL
   2724  5331       amw  *		attrname = '.'
   2725  5331       amw  *	2.  Open the attribute directory of the base file and change into it.
   2726  5331       amw  *		attrinfo->parent = NULL
   2727  5331       amw  *		attrname = <attr> | <sys_attr>
   2728  5331       amw  *	3.  Open the attribute directory of the base file, change into it,
   2729  5331       amw  *	    then recursively call open_attr_dir() to open the attribute's
   2730  5331       amw  *	    parent directory (don't change into it).
   2731  5331       amw  *		attrinfo->parent = <attr>
   2732  5331       amw  *		attrname = '.'
   2733  5331       amw  *	4.  Open the attribute directory of the base file, change into it,
   2734  5331       amw  *	    then recursively call open_attr_dir() to open the attribute's
   2735  5331       amw  *	    parent directory and change into it.
   2736  5331       amw  *		attrinfo->parent = <attr>
   2737  5331       amw  *		attrname = <attr> | <sys_attr>
   2738  5331       amw  *
   2739  5331       amw  * An attribute directory will be opened only if the underlying file system
   2740  5331       amw  * supports the attribute type, and if the command line specifications (atflag
   2741  5331       amw  * and saflag) enable the processing of the attribute type.
   2742  5331       amw  *
   2743  5331       amw  * On succesful return, attrinfo->parentfd will be the file descriptor of the
   2744  5331       amw  * opened attribute directory.  In addition, if the attribute is a read-write
   2745  5331       amw  * extended system attribute, attrinfo->rw_sysattr will be set to 1, otherwise
   2746  5331       amw  * it will be set to 0.
   2747  5331       amw  *
   2748  5331       amw  * Possible return values:
   2749  5331       amw  * 	ATTR_OK		Successfully opened and, if needed, changed into the
   2750  5331       amw  *			attribute directory containing attrname.
   2751  5331       amw  *	ATTR_SKIP	The command line specifications don't enable the
   2752  5331       amw  *			processing of the attribute type.
   2753  5331       amw  * 	ATTR_CHDIR_ERR	An error occurred while trying to change into an
   2754  5331       amw  *			attribute directory.
   2755  5331       amw  * 	ATTR_OPEN_ERR	An error occurred while trying to open an
   2756  5331       amw  *			attribute directory.
   2757  5331       amw  *	ATTR_XATTR_ERR	The underlying file system doesn't support extended
   2758  5331       amw  *			attributes.
   2759  5331       amw  *	ATTR_SATTR_ERR	The underlying file system doesn't support extended
   2760  5331       amw  *			system attributes.
   2761  5331       amw  */
   2762  5331       amw static int
   2763  5331       amw open_attr_dir(char *attrname, char *dirp, int cwd, attr_data_t *attrinfo)
   2764  5331       amw {
   2765  5331       amw 	attr_status_t	rc;
   2766  5331       amw 	int		firsttime = (attrinfo->attr_parentfd == -1);
   2767  5331       amw 	int		saveerrno;
   2768  5750   ceastha 	int		ext_attr;
   2769  5331       amw 
   2770  5331       amw 	/*
   2771  5331       amw 	 * open_attr_dir() was recursively called (input combination number 4),
   2772  5331       amw 	 * close the previously opened file descriptor as we've already changed
   2773  5331       amw 	 * into it.
   2774  5331       amw 	 */
   2775  5331       amw 	if (!firsttime) {
   2776  5331       amw 		(void) close(attrinfo->attr_parentfd);
   2777  5331       amw 		attrinfo->attr_parentfd = -1;
   2778  5331       amw 	}
   2779  5331       amw 
   2780  5331       amw 	/*
   2781  5331       amw 	 * Verify that the underlying file system supports the restoration
   2782  5331       amw 	 * of the attribute.
   2783  5331       amw 	 */
   2784  5750   ceastha 	if ((rc = verify_attr_support(dirp, firsttime, ARC_RESTORE,
   2785  5750   ceastha 	    &ext_attr)) != ATTR_OK) {
   2786  5331       amw 		return (rc);
   2787  5331       amw 	}
   2788  5331       amw 
   2789  5331       amw 	/* Open the base file's attribute directory */
   2790  5331       amw 	if ((attrinfo->attr_parentfd = attropen(dirp, ".", O_RDONLY)) == -1) {
   2791  5331       amw 		/*
   2792  5331       amw 		 * Save the errno from the attropen so it can be reported
   2793  5331       amw 		 * if the retry of the attropen fails.
   2794  5331       amw 		 */
   2795  5331       amw 		saveerrno = errno;
   2796  5331       amw 		if ((attrinfo->attr_parentfd = retry_open_attr(-1, cwd, dirp,
   2797  5331       amw 		    NULL, ".", O_RDONLY, 0)) == -1) {
   2798  5331       amw 			/*
   2799  5331       amw 			 * Reset typeflag back to real value so passtape
   2800  5331       amw 			 * will skip ahead correctly.
   2801  5331       amw 			 */
   2802  5331       amw 			dblock.dbuf.typeflag = _XATTR_HDRTYPE;
   2803  5331       amw 			(void) close(attrinfo->attr_parentfd);
   2804  5331       amw 			attrinfo->attr_parentfd = -1;
   2805  5331       amw 			errno = saveerrno;
   2806  5331       amw 			return (ATTR_OPEN_ERR);
   2807  5331       amw 		}
   2808  5331       amw 	}
   2809  5331       amw 
   2810  5331       amw 	/*
   2811  5331       amw 	 * Change into the parent attribute's directory unless we are
   2812  5331       amw 	 * processing the hidden attribute directory of the base file itself.
   2813  5331       amw 	 */
   2814  5331       amw 	if ((Hiddendir == 0) || (firsttime && attrinfo->attr_parent != NULL)) {
   2815  5331       amw 		if (fchdir(attrinfo->attr_parentfd) != 0) {
   2816  5331       amw 			saveerrno = errno;
   2817  5331       amw 			(void) close(attrinfo->attr_parentfd);
   2818  5331       amw 			attrinfo->attr_parentfd = -1;
   2819  5331       amw 			errno = saveerrno;
   2820  5331       amw 			return (ATTR_CHDIR_ERR);
   2821  5331       amw 		}
   2822  5331       amw 	}
   2823  5331       amw 
   2824  5331       amw 	/* Determine if the attribute should be processed */
   2825  5331       amw 	if ((rc = verify_attr(attrname, attrinfo->attr_parent, 1,
   2826  5331       amw 	    &attrinfo->attr_rw_sysattr)) != ATTR_OK) {
   2827  5331       amw 		saveerrno = errno;
   2828  5331       amw 		(void) close(attrinfo->attr_parentfd);
   2829  5331       amw 		attrinfo->attr_parentfd = -1;
   2830  5331       amw 		errno = saveerrno;
   2831  5331       amw 		return (rc);
   2832  5331       amw 	}
   2833  5331       amw 
   2834  5331       amw 	/*
   2835  5331       amw 	 * If the attribute is an extended attribute, or extended system
   2836  5331       amw 	 * attribute, of an attribute (i.e., <attr>/<sys_attr>), then
   2837  5331       amw 	 * recursively call open_attr_dir() to open the attribute directory
   2838  5331       amw 	 * of the parent attribute.
   2839  5331       amw 	 */
   2840  5331       amw 	if (firsttime && (attrinfo->attr_parent != NULL)) {
   2841  5331       amw 		return (open_attr_dir(attrname, attrinfo->attr_parent,
   2842  5331       amw 		    attrinfo->attr_parentfd, attrinfo));
   2843  5331       amw 	}
   2844  5331       amw 
   2845  5331       amw 	return (ATTR_OK);
   2846  5331       amw }
   2847  5331       amw #endif
   2848  5331       amw 
   2849     0    stevel static void
   2850     0    stevel #ifdef	_iBCS2
   2851     0    stevel doxtract(char *argv[], int tbl_cnt)
   2852     0    stevel #else
   2853     0    stevel doxtract(char *argv[])
   2854     0    stevel #endif
   2855     0    stevel {
   2856     0    stevel 	struct	stat	xtractbuf;	/* stat on file after extracting */
   2857     0    stevel 	blkcnt_t blocks;
   2858     0    stevel 	off_t bytes;
   2859     0    stevel 	int ofile;
   2860     0    stevel 	int newfile;			/* Does the file already exist  */
   2861     0    stevel 	int xcnt = 0;			/* count # files extracted */
   2862     0    stevel 	int fcnt = 0;			/* count # files in argv list */
   2863     0    stevel 	int dir;
   2864     0    stevel 	int dirfd = -1;
   2865  5331       amw 	int cwd = -1;
   2866  5750   ceastha 	int rw_sysattr;
   2867  5331       amw 	int saveerrno;
   2868     0    stevel 	uid_t Uid;
   2869     0    stevel 	char *namep, *dirp, *comp, *linkp; /* for removing absolute paths */
   2870     0    stevel 	char dirname[PATH_MAX+1];
   2871     0    stevel 	char templink[PATH_MAX+1];	/* temp link with terminating NULL */
   2872     0    stevel 	int once = 1;
   2873     0    stevel 	int error;
   2874     0    stevel 	int symflag;
   2875     0    stevel 	int want;
   2876  5331       amw 	attr_data_t *attrinfo = NULL;	/* attribute info */
   2877   789    ahrens 	acl_t	*aclp = NULL;	/* acl info */
   2878  1676       jpk 	char dot[] = ".";		/* dirp for using realpath */
   2879     0    stevel 	timestruc_t	time_zero;	/* used for call to doDirTimes */
   2880     0    stevel 	int		dircreate;
   2881     0    stevel 	int convflag;
   2882     0    stevel 	time_zero.tv_sec = 0;
   2883     0    stevel 	time_zero.tv_nsec = 0;
   2884  1676       jpk 
   2885  1676       jpk 	/* reset Trusted Extensions variables */
   2886  1676       jpk 	rpath_flag = 0;
   2887  1676       jpk 	lk_rpath_flag = 0;
   2888  1676       jpk 	dir_flag = 0;
   2889  1676       jpk 	mld_flag = 0;
   2890  1676       jpk 	bslundef(&bs_label);
   2891  1676       jpk 	bsllow(&admin_low);
   2892  1676       jpk 	bslhigh(&admin_high);
   2893  1676       jpk 	orig_namep = 0;
   2894     0    stevel 
   2895     0    stevel 	dumping = 0;	/* for newvol(), et al:  we are not writing */
   2896     0    stevel 
   2897     0    stevel 	/*
   2898     0    stevel 	 * Count the number of files that are to be extracted
   2899     0    stevel 	 */
   2900     0    stevel 	Uid = getuid();
   2901     0    stevel 
   2902     0    stevel #ifdef	_iBCS2
   2903     0    stevel 	initarg(argv, Filefile);
   2904     0    stevel 	while (nextarg() != NULL)
   2905     0    stevel 		++fcnt;
   2906     0    stevel 	fcnt += tbl_cnt;
   2907     0    stevel #endif	/*  _iBCS2 */
   2908     0    stevel 
   2909     0    stevel 	for (;;) {
   2910     0    stevel 		convflag = 0;
   2911     0    stevel 		symflag = 0;
   2912     0    stevel 		dir = 0;
   2913  5750   ceastha 		Hiddendir = 0;
   2914  5750   ceastha 		rw_sysattr = 0;
   2915     0    stevel 		ofile = -1;
   2916     0    stevel 
   2917  5331       amw 		if (dirfd != -1) {
   2918  5331       amw 			(void) close(dirfd);
   2919  5331       amw 			dirfd = -1;
   2920  5331       amw 		}
   2921  5331       amw 		if (ofile != -1) {
   2922  5331       amw 			if (close(ofile) != 0)
   2923  5331       amw 				vperror(2, gettext("close error"));
   2924  5331       amw 		}
   2925  5331       amw 
   2926  5331       amw #if defined(O_XATTR)
   2927  5331       amw 		if (cwd != -1) {
   2928  5331       amw 			rest_cwd(&cwd);
   2929  5331       amw 		}
   2930  5331       amw #endif
   2931  5331       amw 
   2932     0    stevel 		/* namep is set by wantit to point to the full name */
   2933  5331       amw 		if ((want = wantit(argv, &namep, &dirp, &comp,
   2934  5331       amw 		    &attrinfo)) == 0) {
   2935  5331       amw #if defined(O_XATTR)
   2936  5331       amw 			if (xattrp != NULL) {
   2937     0    stevel 				free(xattrhead);
   2938     0    stevel 				xattrp = NULL;
   2939     0    stevel 				xattr_linkp = NULL;
   2940     0    stevel 				xattrhead = NULL;
   2941     0    stevel 			}
   2942     0    stevel #endif
   2943     0    stevel 			continue;
   2944     0    stevel 		}
   2945     0    stevel 		if (want == -1)
   2946     0    stevel 			break;
   2947  1676       jpk 
   2948  1676       jpk /* Trusted Extensions */
   2949  1676       jpk 		/*
   2950  1676       jpk 		 * During tar extract (x):
   2951  1676       jpk 		 * If the pathname of the restored file has been
   2952  1676       jpk 		 * reconstructed from the ancillary file,
   2953  1676       jpk 		 * use it to process the normal file.
   2954  1676       jpk 		 */
   2955  1676       jpk 		if (mld_flag) {		/* Skip over .MLD. directory */
   2956  1676       jpk 			mld_flag = 0;
   2957  1676       jpk 			passtape();
   2958  1676       jpk 			continue;
   2959  1676       jpk 		}
   2960  1676       jpk 		orig_namep = namep;	/* save original */
   2961  1676       jpk 		if (rpath_flag) {
   2962  1676       jpk 			namep = real_path;	/* use zone path */
   2963  1676       jpk 			comp = real_path;	/* use zone path */
   2964  1676       jpk 			dirp = dot;		/* work from the top */
   2965  1676       jpk 			rpath_flag = 0;		/* reset */
   2966  1676       jpk 		}
   2967     0    stevel 
   2968     0    stevel 		if (dirfd != -1)
   2969     0    stevel 			(void) close(dirfd);
   2970     0    stevel 
   2971     0    stevel 		(void) strcpy(&dirname[0], namep);
   2972     0    stevel 		dircreate = checkdir(&dirname[0]);
   2973     0    stevel 
   2974     0    stevel #if defined(O_XATTR)
   2975  5331       amw 		if (xattrp != NULL) {
   2976  5331       amw 			int	rc;
   2977  5331       amw 
   2978  5331       amw 			if (((cwd = save_cwd()) == -1) ||
   2979  5331       amw 			    ((rc = open_attr_dir(comp, dirp, cwd,
   2980  5331       amw 			    attrinfo)) != ATTR_OK)) {
   2981  5331       amw 				if (cwd == -1) {
   2982  5331       amw 					vperror(0, gettext(
   2983  5331       amw 					    "unable to save current working "
   2984  5331       amw 					    "directory while processing "
   2985  5331       amw 					    "attribute %s of %s"),
   2986  5331       amw 					    dirp, attrinfo->attr_path);
   2987  5331       amw 				} else if (rc != ATTR_SKIP) {
   2988  1231     marks 					(void) fprintf(vfile,
   2989  1231     marks 					    gettext("tar: cannot open "
   2990  5331       amw 					    "%sattribute %s of file %s: %s\n"),
   2991  5331       amw 					    attrinfo->attr_rw_sysattr ? gettext(
   2992  5331       amw 					    "system ") : "",
   2993  5331       amw 					    comp, dirp, strerror(errno));
   2994  5331       amw 				}
   2995  5331       amw 				free(xattrhead);
   2996  5331       amw 				xattrp = NULL;
   2997  5331       amw 				xattr_linkp = NULL;
   2998  5331       amw 				xattrhead = NULL;
   2999  5331       amw 
   3000     0    stevel 				passtape();
   3001     0    stevel 				continue;
   3002  5331       amw 			} else {
   3003  5331       amw 				dirfd = attrinfo->attr_parentfd;
   3004  5331       amw 				rw_sysattr = attrinfo->attr_rw_sysattr;
   3005  5331       amw 			}
   3006  5331       amw 		} else {
   3007  5331       amw 			dirfd = open(dirp, O_RDONLY);
   3008  5331       amw 		}
   3009  5331       amw #else
   3010  5331       amw 		dirfd = open(dirp, O_RDONLY);
   3011  5331       amw #endif
   3012  5331       amw 		if (dirfd == -1) {
   3013  5331       amw 			(void) fprintf(vfile, gettext(
   3014  5331       amw 			    "tar: cannot open %s: %s\n"),
   3015  5331       amw 			    dirp, strerror(errno));
   3016  5331       amw 			passtape();
   3017  5331       amw 			continue;
   3018     0    stevel 		}
   3019     0    stevel 
   3020     0    stevel 		if (xhdr_flgs & _X_LINKPATH)
   3021     0    stevel 			(void) strcpy(templink, Xtarhdr.x_linkpath);
   3022     0    stevel 		else {
   3023     0    stevel #if defined(O_XATTR)
   3024     0    stevel 			if (xattrp && dblock.dbuf.typeflag == '1') {
   3025     0    stevel 				(void) sprintf(templink, "%.*s", NAMSIZ,
   3026     0    stevel 				    xattrp->h_names);
   3027     0    stevel 			} else {
   3028     0    stevel 				(void) sprintf(templink, "%.*s", NAMSIZ,
   3029     0    stevel 				    dblock.dbuf.linkname);
   3030     0    stevel 			}
   3031     0    stevel #else
   3032     0    stevel 			(void) sprintf(templink, "%.*s", NAMSIZ,
   3033     0    stevel 			    dblock.dbuf.linkname);
   3034     0    stevel #endif
   3035     0    stevel 		}
   3036     0    stevel 
   3037     0    stevel 		if (Fflag) {
   3038     0    stevel 			char *s;
   3039     0    stevel 
   3040     0    stevel 			if ((s = strrchr(namep, '/')) == 0)
   3041     0    stevel 				s = namep;
   3042     0    stevel 
   3043     0    stevel 			else
   3044     0    stevel 				s++;
   3045     0    stevel 			if (checkf(s, stbuf.st_mode, Fflag) == 0) {
   3046     0    stevel 				passtape();
   3047     0    stevel 				continue;
   3048     0    stevel 			}
   3049     0    stevel 		}
   3050     0    stevel 
   3051     0    stevel 		if (checkw('x', namep) == 0) {
   3052     0    stevel 			passtape();
   3053     0    stevel 			continue;
   3054     0    stevel 		}
   3055     0    stevel 		if (once) {
   3056     0    stevel 			if (strcmp(dblock.dbuf.magic, magic_type) == 0) {
   3057     0    stevel 				if (geteuid() == (uid_t)0) {
   3058     0    stevel 					checkflag = 1;
   3059     0    stevel 					pflag = 1;
   3060     0    stevel 				} else {
   3061     0    stevel 					/* get file creation mask */
   3062     0    stevel 					Oumask = umask(0);
   3063     0    stevel 					(void) umask(Oumask);
   3064     0    stevel 				}
   3065     0    stevel 				once = 0;
   3066     0    stevel 			} else {
   3067     0    stevel 				if (geteuid() == (uid_t)0) {
   3068     0    stevel 					pflag = 1;
   3069     0    stevel 					checkflag = 2;
   3070     0    stevel 				}
   3071     0    stevel 				if (!pflag) {
   3072     0    stevel 					/* get file creation mask */
   3073     0    stevel 					Oumask = umask(0);
   3074     0    stevel 					(void) umask(Oumask);
   3075     0    stevel 				}
   3076     0    stevel 				once = 0;
   3077     0    stevel 			}
   3078     0    stevel 		}
   3079     0    stevel 
   3080     0    stevel #if defined(O_XATTR)
   3081     0    stevel 		/*
   3082     0    stevel 		 * Handle extraction of hidden attr dir.
   3083     0    stevel 		 * Dir is automatically created, we only
   3084     0    stevel 		 * need to update mode and perm's.
   3085     0    stevel 		 */
   3086  5331       amw 		if ((xattrp != NULL) && Hiddendir == 1) {
   3087  5331       amw 			bytes = stbuf.st_size;
   3088  5331       amw 			blocks = TBLOCKS(bytes);
   3089  5331       amw 			if (vflag) {
   3090  5331       amw 				(void) fprintf(vfile,
   3091  5331       amw 				    "x %s%s%s, %" FMT_off_t " bytes, ", namep,
   3092  5331       amw 				    gettext(" attribute "),
   3093  5331       amw 				    xattrapath, bytes);
   3094  5331       amw 				if (NotTape)
   3095  5331       amw 					(void) fprintf(vfile,
   3096  5331       amw 					    "%" FMT_blkcnt_t "K\n", K(blocks));
   3097  5331       amw 				else
   3098  5331       amw 					(void) fprintf(vfile, gettext("%"
   3099  5331       amw 					    FMT_blkcnt_t " tape blocks\n"),
   3100  5331       amw 					    blocks);
   3101  5331       amw 			}
   3102  5331       amw 
   3103  5331       amw 			/*
   3104  5331       amw 			 * Set the permissions and mode of the attribute
   3105  5331       amw 			 * unless the attribute is a system attribute (can't
   3106  5331       amw 			 * successfully do this) or the hidden attribute
   3107  5331       amw 			 * directory (".") of an attribute (when the attribute
   3108  5331       amw 			 * is restored, the hidden attribute directory of an
   3109  5331       amw 			 * attribute is transient).  Note:  when the permissions
   3110  5331       amw 			 * and mode are set for the hidden attribute directory
   3111  5331       amw 			 * of a file on a system supporting extended system
   3112  5331       amw 			 * attributes, even though it returns successfully, it
   3113  5331       amw 			 * will not have any affect since the attribute
   3114  5331       amw 			 * directory is transient.
   3115  5331       amw 			 */
   3116  5331       amw 			if (attrinfo->attr_parent == NULL) {
   3117  5331       amw 				if (fchownat(dirfd, ".", stbuf.st_uid,
   3118  5331       amw 				    stbuf.st_gid, 0) != 0) {
   3119  5331       amw 					vperror(0, gettext(
   3120  5331       amw 					    "%s%s%s: failed to set ownership "
   3121  5331       amw 					    "of attribute directory"), namep,
   3122  5331       amw 					    gettext(" attribute "), xattrapath);
   3123  5331       amw 				}
   3124  5331       amw 
   3125  5331       amw 				if (fchmod(dirfd, stbuf.st_mode) != 0) {
   3126  5331       amw 					vperror(0, gettext(
   3127  5331       amw 					    "%s%s%s: failed to set permissions "
   3128  5331       amw 					    "of attribute directory"), namep,
   3129  5331       amw 					    gettext(" attribute "), xattrapath);
   3130  5331       amw 				}
   3131     0    stevel 			}
   3132     0    stevel 			goto filedone;
   3133     0    stevel 		}
   3134     0    stevel #endif
   3135     0    stevel 
   3136     0    stevel 		if (dircreate && (!is_posix || dblock.dbuf.typeflag == '5')) {
   3137     0    stevel 			dir = 1;
   3138     0    stevel 			if (vflag) {
   3139     0    stevel 				(void) fprintf(vfile, "x %s, 0 bytes, ",
   3140     0    stevel 				    &dirname[0]);
   3141     0    stevel 				if (NotTape)
   3142     0    stevel 					(void) fprintf(vfile, "0K\n");
   3143     0    stevel 				else
   3144     0    stevel 					(void) fprintf(vfile, gettext("%"
   3145     0    stevel 					    FMT_blkcnt_t " tape blocks\n"),
   3146     0    stevel 					    (blkcnt_t)0);
   3147     0    stevel 			}
   3148     0    stevel 			goto filedone;
   3149     0    stevel 		}
   3150     0    stevel 
   3151     0    stevel 		if (dblock.dbuf.typeflag == '6') {	/* FIFO */
   3152     0    stevel 			if (rmdir(namep) < 0) {
   3153     0    stevel 				if (errno == ENOTDIR)
   3154     0    stevel 					(void) unlink(namep);
   3155     0    stevel 			}
   3156     0    stevel 			linkp = templink;
   3157     0    stevel 			if (*linkp !=  NULL) {
   3158     0    stevel 				if (Aflag && *linkp == '/')
   3159     0    stevel 					linkp++;
   3160     0    stevel 				if (link(linkp, namep) < 0) {
   3161     0    stevel 					(void) fprintf(stderr, gettext(
   3162     0    stevel 					    "tar: %s: cannot link\n"), namep);
   3163     0    stevel 					continue;
   3164     0    stevel 				}
   3165     0    stevel 				if (vflag)
   3166     0    stevel 					(void) fprintf(vfile, gettext(
   3167  5331       amw 					    "x %s linked to %s\n"), namep,
   3168  5331       amw 					    linkp);
   3169     0    stevel 				xcnt++;	 /* increment # files extracted */
   3170     0    stevel 				continue;
   3171     0    stevel 			}
   3172     0    stevel 			if (mknod(namep, (int)(Gen.g_mode|S_IFIFO),
   3173     0    stevel 			    (int)Gen.g_devmajor) < 0) {
   3174     0    stevel 				vperror(0, gettext("%s: mknod failed"), namep);
   3175     0    stevel 				continue;
   3176     0    stevel 			}
   3177     0    stevel 			bytes = stbuf.st_size;
   3178     0    stevel 			blocks = TBLOCKS(bytes);
   3179     0    stevel 			if (vflag) {
   3180     0    stevel 				(void) fprintf(vfile, "x %s, %" FMT_off_t
   3181     0    stevel 				    " bytes, ", namep, bytes);
   3182     0    stevel 				if (NotTape)
   3183     0    stevel 					(void) fprintf(vfile, "%" FMT_blkcnt_t
   3184     0    stevel 					    "K\n", K(blocks));
   3185     0    stevel 				else
   3186     0    stevel 					(void) fprintf(vfile, gettext("%"
   3187     0