Home | History | Annotate | Download | only in tar
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
     27 /*	  All Rights Reserved  	*/
     28 
     29 /*	Copyright (c) 1987, 1988 Microsoft Corporation	*/
     30 /*	  All Rights Reserved	*/
     31 
     32 /*
     33  * Portions of this source code were derived from Berkeley 4.3 BSD
     34  * under license from the Regents of the University of California.
     35  */
     36 
     37 #include <unistd.h>
     38 #include <sys/types.h>
     39 #include <sys/param.h>
     40 #include <sys/stat.h>
     41 #include <sys/mkdev.h>
     42 #include <sys/wait.h>
     43 #include <dirent.h>
     44 #include <errno.h>
     45 #include <stdio.h>
     46 #include <signal.h>
     47 #include <ctype.h>
     48 #include <locale.h>
     49 #include <nl_types.h>
     50 #include <langinfo.h>
     51 #include <pwd.h>
     52 #include <grp.h>
     53 #include <fcntl.h>
     54 #include <string.h>
     55 #include <malloc.h>
     56 #include <time.h>
     57 #include <utime.h>
     58 #include <stdlib.h>
     59 #include <stdarg.h>
     60 #include <widec.h>
     61 #include <sys/mtio.h>
     62 #include <sys/acl.h>
     63 #include <strings.h>
     64 #include <deflt.h>
     65 #include <limits.h>
     66 #include <iconv.h>
     67 #include <assert.h>
     68 #include <libgen.h>
     69 #include <libintl.h>
     70 #include <aclutils.h>
     71 #include <libnvpair.h>
     72 #include <archives.h>
     73 
     74 #if defined(__SunOS_5_6) || defined(__SunOS_5_7)
     75 extern int defcntl();
     76 #endif
     77 #if defined(_PC_SATTR_ENABLED)
     78 #include <attr.h>
     79 #include <libcmdutils.h>
     80 #endif
     81 
     82 /* Trusted Extensions */
     83 #include <zone.h>
     84 #include <tsol/label.h>
     85 #include <sys/tsol/label_macro.h>
     86 
     87 #include "getresponse.h"
     88 /*
     89  * Source compatibility
     90  */
     91 
     92 /*
     93  * These constants come from archives.h and sys/fcntl.h
     94  * and were introduced by the extended attributes project
     95  * in Solaris 9.
     96  */
     97 #if !defined(O_XATTR)
     98 #define	AT_SYMLINK_NOFOLLOW	0x1000
     99 #define	AT_REMOVEDIR		0x1
    100 #define	AT_FDCWD		0xffd19553
    101 #define	_XATTR_HDRTYPE		'E'
    102 static int attropen();
    103 static int fstatat();
    104 static int renameat();
    105 static int unlinkat();
    106 static int openat();
    107 static int fchownat();
    108 static int futimesat();
    109 #endif
    110 
    111 /*
    112  * Compiling with -D_XPG4_2 gets this but produces other problems, so
    113  * instead of including sys/time.h and compiling with -D_XPG4_2, I'm
    114  * explicitly doing the declaration here.
    115  */
    116 int utimes(const char *path, const struct timeval timeval_ptr[]);
    117 
    118 #ifndef MINSIZE
    119 #define	MINSIZE 250
    120 #endif
    121 #define	DEF_FILE "/etc/default/tar"
    122 
    123 #define	min(a, b)  ((a) < (b) ? (a) : (b))
    124 #define	max(a, b)  ((a) > (b) ? (a) : (b))
    125 
    126 /* -DDEBUG	ONLY for debugging */
    127 #ifdef	DEBUG
    128 #undef	DEBUG
    129 #define	DEBUG(a, b, c)\
    130 	(void) fprintf(stderr, "DEBUG - "), (void) fprintf(stderr, a, b, c)
    131 #endif
    132 
    133 #define	TBLOCK	512	/* tape block size--should be universal */
    134 
    135 #ifdef	BSIZE
    136 #define	SYS_BLOCK BSIZE	/* from sys/param.h:  secondary block size */
    137 #else	/* BSIZE */
    138 #define	SYS_BLOCK 512	/* default if no BSIZE in param.h */
    139 #endif	/* BSIZE */
    140 
    141 #define	NBLOCK	20
    142 #define	NAMSIZ	100
    143 #define	PRESIZ	155
    144 #define	MAXNAM	256
    145 #define	MODEMASK 0777777	/* file creation mode mask */
    146 #define	POSIXMODES 07777	/* mask for POSIX mode bits */
    147 #define	MAXEXT	9	/* reasonable max # extents for a file */
    148 #define	EXTMIN	50	/* min blks left on floppy to split a file */
    149 
    150 /* max value dblock.dbuf.efsize can store */
    151 #define	TAR_EFSIZE_MAX	 0777777777
    152 
    153 /*
    154  * Symbols which specify the values at which the use of the 'E' function
    155  * modifier is required to properly store a file.
    156  *
    157  *     TAR_OFFSET_MAX    - the largest file size we can archive
    158  *     OCTAL7CHAR        - the limit for ustar gid, uid, dev
    159  */
    160 
    161 #ifdef XHDR_DEBUG
    162 /* tiny values which force the creation of extended header entries */
    163 #define	TAR_OFFSET_MAX 9
    164 #define	OCTAL7CHAR 2
    165 #else
    166 /* normal values */
    167 #define	TAR_OFFSET_MAX	077777777777ULL
    168 #define	OCTAL7CHAR	07777777
    169 #endif
    170 
    171 #define	TBLOCKS(bytes)	(((bytes) + TBLOCK - 1) / TBLOCK)
    172 #define	K(tblocks)	((tblocks+1)/2)	/* tblocks to Kbytes for printing */
    173 
    174 #define	MAXLEV	(PATH_MAX / 2)
    175 #define	LEV0	1
    176 #define	SYMLINK_LEV0	0
    177 
    178 #define	TRUE	1
    179 #define	FALSE	0
    180 
    181 #define	XATTR_FILE	1
    182 #define	NORMAL_FILE	0
    183 
    184 #define	PUT_AS_LINK	1
    185 #define	PUT_NOTAS_LINK	0
    186 
    187 #ifndef VIEW_READONLY
    188 #define	VIEW_READONLY	"SUNWattr_ro"
    189 #endif
    190 
    191 #ifndef VIEW_READWRITE
    192 #define	VIEW_READWRITE	"SUNWattr_rw"
    193 #endif
    194 
    195 #if _FILE_OFFSET_BITS == 64
    196 #define	FMT_off_t "lld"
    197 #define	FMT_off_t_o "llo"
    198 #define	FMT_blkcnt_t "lld"
    199 #else
    200 #define	FMT_off_t "ld"
    201 #define	FMT_off_t_o "lo"
    202 #define	FMT_blkcnt_t "ld"
    203 #endif
    204 
    205 /* ACL support */
    206 
    207 static
    208 struct	sec_attr {
    209 	char	attr_type;
    210 	char	attr_len[7];
    211 	char	attr_info[1];
    212 } *attr;
    213 
    214 #if defined(O_XATTR)
    215 typedef enum {
    216 	ATTR_OK,
    217 	ATTR_SKIP,
    218 	ATTR_CHDIR_ERR,
    219 	ATTR_OPEN_ERR,
    220 	ATTR_XATTR_ERR,
    221 	ATTR_SATTR_ERR
    222 } attr_status_t;
    223 #endif
    224 
    225 #if defined(O_XATTR)
    226 typedef enum {
    227 	ARC_CREATE,
    228 	ARC_RESTORE
    229 } arc_action_t;
    230 #endif
    231 
    232 typedef struct attr_data {
    233 	char	*attr_parent;
    234 	char	*attr_path;
    235 	int	attr_parentfd;
    236 	int	attr_rw_sysattr;
    237 } attr_data_t;
    238 
    239 /*
    240  *
    241  * Tar has been changed to support extended attributes.
    242  *
    243  * As part of this change tar now uses the new *at() syscalls
    244  * such as openat, fchownat(), unlinkat()...
    245  *
    246  * This was done so that attributes can be handled with as few code changes
    247  * as possible.
    248  *
    249  * What this means is that tar now opens the directory that a file or directory
    250  * resides in and then performs *at() functions to manipulate the entry.
    251  *
    252  * For example a new file is now created like this:
    253  *
    254  * dfd = open(<some dir path>)
    255  * fd = openat(dfd, <name>,....);
    256  *
    257  * or in the case of an extended attribute
    258  *
    259  * dfd = attropen(<pathname>, ".", ....)
    260  *
    261  * Once we have a directory file descriptor all of the *at() functions can
    262  * be applied to it.
    263  *
    264  * unlinkat(dfd, <component name>,...)
    265  * fchownat(dfd, <component name>,..)
    266  *
    267  * This works for both normal namespace files and extended attribute file
    268  *
    269  */
    270 
    271 /*
    272  *
    273  * Extended attribute Format
    274  *
    275  * Extended attributes are stored in two pieces.
    276  * 1. An attribute header which has information about
    277  *    what file the attribute is for and what the attribute
    278  *    is named.
    279  * 2. The attribute record itself.  Stored as a normal file type
    280  *    of entry.
    281  * Both the header and attribute record have special modes/typeflags
    282  * associated with them.
    283  *
    284  * The names of the header in the archive look like:
    285  * /dev/null/attr.hdr
    286  *
    287  * The name of the attribute looks like:
    288  * /dev/null/attr
    289  *
    290  * This is done so that an archiver that doesn't understand these formats
    291  * can just dispose of the attribute records.
    292  *
    293  * The format is composed of a fixed size header followed
    294  * by a variable sized xattr_buf. If the attribute is a hard link
    295  * to another attribute then another xattr_buf section is included
    296  * for the link.
    297  *
    298  * The xattr_buf is used to define the necessary "pathing" steps
    299  * to get to the extended attribute.  This is necessary to support
    300  * a fully recursive attribute model where an attribute may itself
    301  * have an attribute.
    302  *
    303  * The basic layout looks like this.
    304  *
    305  *     --------------------------------
    306  *     |                              |
    307  *     |         xattr_hdr            |
    308  *     |                              |
    309  *     --------------------------------
    310  *     --------------------------------
    311  *     |                              |
    312  *     |        xattr_buf             |
    313  *     |                              |
    314  *     --------------------------------
    315  *     --------------------------------
    316  *     |                              |
    317  *     |      (optional link info)    |
    318  *     |                              |
    319  *     --------------------------------
    320  *     --------------------------------
    321  *     |                              |
    322  *     |      attribute itself        |
    323  *     |      stored as normal tar    |
    324  *     |      or cpio data with       |
    325  *     |      special mode or         |
    326  *     |      typeflag                |
    327  *     |                              |
    328  *     --------------------------------
    329  *
    330  */
    331 
    332 /*
    333  * xattrhead is a pointer to the xattr_hdr
    334  *
    335  * xattrp is a pointer to the xattr_buf structure
    336  * which contains the "pathing" steps to get to attributes
    337  *
    338  * xattr_linkp is a pointer to another xattr_buf structure that is
    339  * only used when an attribute is actually linked to another attribute
    340  *
    341  */
    342 
    343 static struct xattr_hdr *xattrhead;
    344 static struct xattr_buf *xattrp;
    345 static struct xattr_buf *xattr_linkp;	/* pointer to link info, if any */
    346 static char *xattrapath;		/* attribute name */
    347 static char *xattr_linkaname;		/* attribute attribute is linked to */
    348 static char Hiddendir;			/* are we processing hidden xattr dir */
    349 static char xattrbadhead;
    350 
    351 /* Was statically allocated tbuf[NBLOCK] */
    352 static
    353 union hblock {
    354 	char dummy[TBLOCK];
    355 	struct header {
    356 		char name[NAMSIZ];	/* If non-null prefix, path is	*/
    357 					/* <prefix>/<name>;  otherwise	*/
    358 					/* <name>			*/
    359 		char mode[8];
    360 		char uid[8];
    361 		char gid[8];
    362 		char size[12];		/* size of this extent if file split */
    363 		char mtime[12];
    364 		char chksum[8];
    365 		char typeflag;
    366 		char linkname[NAMSIZ];
    367 		char magic[6];
    368 		char version[2];
    369 		char uname[32];
    370 		char gname[32];
    371 		char devmajor[8];
    372 		char devminor[8];
    373 		char prefix[PRESIZ];	/* Together with "name", the path of */
    374 					/* the file:  <prefix>/<name>	*/
    375 		char extno;		/* extent #, null if not split */
    376 		char extotal;		/* total extents */
    377 		char efsize[10];	/* size of entire file */
    378 	} dbuf;
    379 } dblock, *tbuf, xhdr_buf;
    380 
    381 static
    382 struct xtar_hdr {
    383 	uid_t		x_uid,		/* Uid of file */
    384 			x_gid;		/* Gid of file */
    385 	major_t		x_devmajor;	/* Device major node */
    386 	minor_t		x_devminor;	/* Device minor node */
    387 	off_t		x_filesz;	/* Length of file */
    388 	char		*x_uname,	/* Pointer to name of user */
    389 			*x_gname,	/* Pointer to gid of user */
    390 			*x_linkpath,	/* Path for a hard/symbolic link */
    391 			*x_path;	/* Path of file */
    392 	timestruc_t	x_mtime;	/* Seconds and nanoseconds */
    393 } Xtarhdr;
    394 
    395 static
    396 struct gen_hdr {
    397 	ulong_t		g_mode;		/* Mode of file */
    398 	uid_t		g_uid,		/* Uid of file */
    399 			g_gid;		/* Gid of file */
    400 	off_t		g_filesz;	/* Length of file */
    401 	time_t		g_mtime;	/* Modification time */
    402 	uint_t		g_cksum;	/* Checksum of file */
    403 	ulong_t		g_devmajor,	/* File system of file */
    404 			g_devminor;	/* Major/minor of special files */
    405 } Gen;
    406 
    407 static
    408 struct linkbuf {
    409 	ino_t	inum;
    410 	dev_t	devnum;
    411 	int	count;
    412 	char	pathname[MAXNAM+1];	/* added 1 for last NULL */
    413 	char 	attrname[MAXNAM+1];
    414 	struct	linkbuf *nextp;
    415 } *ihead;
    416 
    417 /* see comments before build_table() */
    418 #define	TABLE_SIZE 512
    419 typedef struct	file_list	{
    420 	char	*name;			/* Name of file to {in,ex}clude */
    421 	struct	file_list	*next;	/* Linked list */
    422 } file_list_t;
    423 static	file_list_t	*exclude_tbl[TABLE_SIZE],
    424 			*include_tbl[TABLE_SIZE];
    425 
    426 static int	append_secattr(char **, int *, int, char *, char);
    427 static void	write_ancillary(union hblock *, char *, int, char);
    428 
    429 static void add_file_to_table(file_list_t *table[], char *str);
    430 static void assert_string(char *s, char *msg);
    431 static int istape(int fd, int type);
    432 static void backtape(void);
    433 static void build_table(file_list_t *table[], char *file);
    434 static int check_prefix(char **namep, char **dirp, char **compp);
    435 static void closevol(void);
    436 static void copy(void *dst, void *src);
    437 static int convtoreg(off_t);
    438 static void delete_target(int fd, char *comp, char *namep);
    439 static void doDirTimes(char *name, timestruc_t modTime);
    440 static void done(int n);
    441 static void dorep(char *argv[]);
    442 #ifdef	_iBCS2
    443 static void dotable(char *argv[], int cnt);
    444 static void doxtract(char *argv[], int cnt);
    445 #else
    446 static void dotable(char *argv[]);
    447 static void doxtract(char *argv[]);
    448 #endif
    449 static void fatal(char *format, ...);
    450 static void vperror(int exit_status, char *fmt, ...);
    451 static void flushtape(void);
    452 static void getdir(void);
    453 static void *getmem(size_t);
    454 static void longt(struct stat *st, char aclchar);
    455 static void load_info_from_xtarhdr(u_longlong_t flag, struct xtar_hdr *xhdrp);
    456 static int makeDir(char *name);
    457 static void mterr(char *operation, int i, int exitcode);
    458 static void newvol(void);
    459 static void passtape(void);
    460 static void putempty(blkcnt_t n);
    461 static int putfile(char *longname, char *shortname, char *parent,
    462     attr_data_t *attrinfo, int filetype, int lev, int symlink_lev);
    463 static void readtape(char *buffer);
    464 static void seekdisk(blkcnt_t blocks);
    465 static void setPathTimes(int dirfd, char *path, timestruc_t modTime);
    466 static void setbytes_to_skip(struct stat *st, int err);
    467 static void splitfile(char *longname, int ifd, char *name,
    468 	char *prefix, int filetype);
    469 static void tomodes(struct stat *sp);
    470 static void usage(void);
    471 static int xblocks(int issysattr, off_t bytes, int ofile);
    472 static int xsfile(int issysattr, int ofd);
    473 static void resugname(int dirfd, char *name, int symflag);
    474 static int bcheck(char *bstr);
    475 static int checkdir(char *name);
    476 static int checksum(union hblock *dblockp);
    477 #ifdef	EUC
    478 static int checksum_signed(union hblock *dblockp);
    479 #endif	/* EUC */
    480 static int checkupdate(char *arg);
    481 static int checkw(char c, char *name);
    482 static int cmp(char *b, char *s, int n);
    483 static int defset(char *arch);
    484 static int endtape(void);
    485 static int is_in_table(file_list_t *table[], char *str);
    486 static int notsame(void);
    487 static int is_prefix(char *s1, char *s2);
    488 static int response(void);
    489 static int build_dblock(const char *, const char *, const char,
    490 	const int filetype, const struct stat *, const dev_t, const char *);
    491 static unsigned int hash(char *str);
    492 
    493 #ifdef	_iBCS2
    494 static void initarg(char *argv[], char *file);
    495 static char *nextarg();
    496 #endif
    497 static blkcnt_t kcheck(char *kstr);
    498 static off_t bsrch(char *s, int n, off_t l, off_t h);
    499 static void onintr(int sig);
    500 static void onquit(int sig);
    501 static void onhup(int sig);
    502 static uid_t getuidbyname(char *);
    503 static gid_t getgidbyname(char *);
    504 static char *getname(gid_t);
    505 static char *getgroup(gid_t);
    506 static int checkf(char *name, int mode, int howmuch);
    507 static int writetbuf(char *buffer, int n);
    508 static int wantit(char *argv[], char **namep, char **dirp, char **comp,
    509     attr_data_t **attrinfo);
    510 static void append_ext_attr(char *shortname, char **secinfo, int *len);
    511 static int get_xdata(void);
    512 static void gen_num(const char *keyword, const u_longlong_t number);
    513 static void gen_date(const char *keyword, const timestruc_t time_value);
    514 static void gen_string(const char *keyword, const char *value);
    515 static void get_xtime(char *value, timestruc_t *xtime);
    516 static int chk_path_build(char *name, char *longname, char *linkname,
    517     char *prefix, char type, int filetype);
    518 static int gen_utf8_names(const char *filename);
    519 static int utf8_local(char *option, char **Xhdr_ptrptr, char *target,
    520     const char *src, int max_val);
    521 static int local_utf8(char **Xhdr_ptrptr, char *target, const char *src,
    522     iconv_t iconv_cd, int xhdrflg, int max_val);
    523 static int c_utf8(char *target, const char *source);
    524 static int getstat(int dirfd, char *longname, char *shortname,
    525     char *attrparent);
    526 static void xattrs_put(char *, char *, char *, char *);
    527 static void prepare_xattr(char **, char	*, char	*,
    528     char, struct linkbuf *, int *);
    529 static int put_link(char *name, char *longname, char *component,
    530     char *longattrname, char *prefix, int filetype, char typeflag);
    531 static int put_extra_attributes(char *longname, char *shortname,
    532     char *longattrname, char *prefix, int filetype, char typeflag);
    533 static int put_xattr_hdr(char *longname, char *shortname, char *longattrname,
    534     char *prefix, int typeflag, int filetype, struct linkbuf *lp);
    535 static int read_xattr_hdr(attr_data_t **attrinfo);
    536 
    537 /* Trusted Extensions */
    538 #define	AUTO_ZONE	"/zone"
    539 
    540 static void extract_attr(char **file_ptr, struct sec_attr *);
    541 static int check_ext_attr(char *filename);
    542 static void rebuild_comp_path(char *str, char **namep);
    543 static int rebuild_lk_comp_path(char *str, char **namep);
    544 
    545 static void get_parent(char *path, char *dir);
    546 static char *get_component(char *path);
    547 static int retry_open_attr(int pdirfd, int cwd, char *dirp, char *pattr,
    548     char *name, int oflag, mode_t mode);
    549 static char *skipslashes(char *string, char *start);
    550 static void chop_endslashes(char *path);
    551 
    552 static	struct stat stbuf;
    553 
    554 static	char	*myname;
    555 static	int	checkflag = 0;
    556 #ifdef	_iBCS2
    557 static	int	Fileflag;
    558 char    *sysv3_env;
    559 #endif
    560 static	int	Xflag, Fflag, iflag, hflag, Bflag, Iflag;
    561 static	int	rflag, xflag, vflag, tflag, mt, cflag, mflag, pflag;
    562 static	int	uflag;
    563 static	int	eflag, errflag, qflag;
    564 static	int	oflag;
    565 static	int	bflag, kflag, Aflag;
    566 static 	int	Pflag;			/* POSIX conformant archive */
    567 static	int	Eflag;			/* Allow files greater than 8GB */
    568 static	int	atflag;			/* traverse extended attributes */
    569 static	int	saflag;			/* traverse extended sys attributes */
    570 static	int	Dflag;			/* Data change flag */
    571 /* Trusted Extensions */
    572 static	int	Tflag;			/* Trusted Extensions attr flags */
    573 static	int	dir_flag;		/* for attribute extract */
    574 static	int	mld_flag;		/* for attribute extract */
    575 static	char	*orig_namep;		/* original namep - unadorned */
    576 static	int	rpath_flag;		/* MLD real path is rebuilt */
    577 static	char	real_path[MAXPATHLEN];	/* MLD real path */
    578 static	int	lk_rpath_flag;		/* linked to real path is rebuilt */
    579 static	char	lk_real_path[MAXPATHLEN]; /* linked real path */
    580 static	bslabel_t	bs_label;	/* for attribute extract */
    581 static	bslabel_t	admin_low;
    582 static	bslabel_t	admin_high;
    583 static	int	ignored_aprivs = 0;
    584 static	int	ignored_fprivs = 0;
    585 static	int	ignored_fattrs = 0;
    586 
    587 static	int	term, chksum, wflag,
    588 		first = TRUE, defaults_used = FALSE, linkerrok;
    589 static	blkcnt_t	recno;
    590 static	int	freemem = 1;
    591 static	int	nblock = NBLOCK;
    592 static	int	Errflg = 0;
    593 static	int	exitflag = 0;
    594 
    595 static	dev_t	mt_dev;		/* device containing output file */
    596 static	ino_t	mt_ino;		/* inode number of output file */
    597 static	int	mt_devtype;	/* dev type of archive, from stat structure */
    598 
    599 static	int update = 1;		/* for `open' call */
    600 
    601 static	off_t	low;
    602 static	off_t	high;
    603 
    604 static	FILE	*tfile;
    605 static	FILE	*vfile = stdout;
    606 static	char	tname[] = "/tmp/tarXXXXXX";
    607 static	char	archive[] = "archive0=";
    608 static	char	*Xfile;
    609 static	char	*usefile;
    610 static	char	*Filefile;
    611 
    612 static	int	mulvol;		/* multi-volume option selected */
    613 static	blkcnt_t	blocklim; /* number of blocks to accept per volume */
    614 static	blkcnt_t	tapepos; /* current block number to be written */
    615 static	int	NotTape;	/* true if tape is a disk */
    616 static	int	dumping;	/* true if writing a tape or other archive */
    617 static	int	extno;		/* number of extent:  starts at 1 */
    618 static	int	extotal;	/* total extents in this file */
    619 static	off_t	extsize;	/* size of current extent during extraction */
    620 static	ushort_t	Oumask = 0;	/* old umask value */
    621 static 	int is_posix;	/* true if archive we're reading is POSIX-conformant */
    622 static	const	char	*magic_type = "ustar";
    623 static	size_t	xrec_size = 8 * PATH_MAX;	/* extended rec initial size */
    624 static	char	*xrec_ptr;
    625 static	off_t	xrec_offset = 0;
    626 static	int	Xhdrflag;
    627 static	int	charset_type = 0;
    628 
    629 static	u_longlong_t	xhdr_flgs;	/* Bits set determine which items */
    630 					/*   need to be in extended header. */
    631 #define	_X_DEVMAJOR	0x1
    632 #define	_X_DEVMINOR	0x2
    633 #define	_X_GID		0x4
    634 #define	_X_GNAME	0x8
    635 #define	_X_LINKPATH	0x10
    636 #define	_X_PATH		0x20
    637 #define	_X_SIZE		0x40
    638 #define	_X_UID		0x80
    639 #define	_X_UNAME	0x100
    640 #define	_X_ATIME	0x200
    641 #define	_X_CTIME	0x400
    642 #define	_X_MTIME	0x800
    643 #define	_X_XHDR		0x1000	/* Bit flag that determines whether 'X' */
    644 				/* typeflag was followed by 'A' or non 'A' */
    645 				/* typeflag. */
    646 #define	_X_LAST		0x40000000
    647 
    648 #define	PID_MAX_DIGITS		(10 * sizeof (pid_t) / 4)
    649 #define	TIME_MAX_DIGITS		(10 * sizeof (time_t) / 4)
    650 #define	LONG_MAX_DIGITS		(10 * sizeof (long) / 4)
    651 #define	ULONGLONG_MAX_DIGITS	(10 * sizeof (u_longlong_t) / 4)
    652 /*
    653  * UTF_8 encoding requires more space than the current codeset equivalent.
    654  * Currently a factor of 2-3 would suffice, but it is possible for a factor
    655  * of 6 to be needed in the future, so for saftey, we use that here.
    656  */
    657 #define	UTF_8_FACTOR	6
    658 
    659 static	u_longlong_t	xhdr_count = 0;
    660 static char		xhdr_dirname[PRESIZ + 1];
    661 static char		pidchars[PID_MAX_DIGITS + 1];
    662 static char		*tchar = "";		/* null linkpath */
    663 
    664 static	char	local_path[UTF_8_FACTOR * PATH_MAX + 1];
    665 static	char	local_linkpath[UTF_8_FACTOR * PATH_MAX + 1];
    666 static	char	local_gname[UTF_8_FACTOR * _POSIX_NAME_MAX + 1];
    667 static	char	local_uname[UTF_8_FACTOR * _POSIX_NAME_MAX + 1];
    668 
    669 /*
    670  * The following mechanism is provided to allow us to debug tar in complicated
    671  * situations, like when it is part of a pipe.  The idea is that you compile
    672  * with -DWAITAROUND defined, and then add the 'z' function modifier to the
    673  * target tar invocation, eg. "tar czf tarfile file".  If stderr is available,
    674  * it will tell you to which pid to attach the debugger; otherwise, use ps to
    675  * find it.  Attach to the process from the debugger, and, *PRESTO*, you are
    676  * there!
    677  *
    678  * Simply assign "waitaround = 0" once you attach to the process, and then
    679  * proceed from there as usual.
    680  */
    681 
    682 #ifdef WAITAROUND
    683 int waitaround = 0;		/* wait for rendezvous with the debugger */
    684 #endif
    685 
    686 
    687 int
    688 main(int argc, char *argv[])
    689 {
    690 	char		*cp;
    691 	char		*tmpdirp;
    692 	pid_t		thispid;
    693 
    694 #ifdef	_iBCS2
    695 	int	tbl_cnt = 0;
    696 	sysv3_env = getenv("SYSV3");
    697 #endif
    698 	(void) setlocale(LC_ALL, "");
    699 #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
    700 #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
    701 #endif
    702 	(void) textdomain(TEXT_DOMAIN);
    703 	if (argc < 2)
    704 		usage();
    705 
    706 	tfile = NULL;
    707 	if ((myname = strdup(argv[0])) == NULL) {
    708 		(void) fprintf(stderr, gettext(
    709 		    "tar: cannot allocate program name\n"));
    710 		exit(1);
    711 	}
    712 
    713 	if (init_yes() < 0) {
    714 		(void) fprintf(stderr, gettext(ERR_MSG_INIT_YES),
    715 		    strerror(errno));
    716 		exit(2);
    717 	}
    718 
    719 	/*
    720 	 *  For XPG4 compatibility, we must be able to accept the "--"
    721 	 *  argument normally recognized by getopt; it is used to delimit
    722 	 *  the end opt the options section, and so can only appear in
    723 	 *  the position of the first argument.  We simply skip it.
    724 	 */
    725 
    726 	if (strcmp(argv[1], "--") == 0) {
    727 		argv++;
    728 		argc--;
    729 		if (argc < 3)
    730 			usage();
    731 	}
    732 
    733 	argv[argc] = NULL;
    734 	argv++;
    735 
    736 	/*
    737 	 * Set up default values.
    738 	 * Search the operand string looking for the first digit or an 'f'.
    739 	 * If you find a digit, use the 'archive#' entry in DEF_FILE.
    740 	 * If 'f' is given, bypass looking in DEF_FILE altogether.
    741 	 * If no digit or 'f' is given, still look in DEF_FILE but use '0'.
    742 	 */
    743 	if ((usefile = getenv("TAPE")) == (char *)NULL) {
    744 		for (cp = *argv; *cp; ++cp)
    745 			if (isdigit(*cp) || *cp == 'f')
    746 				break;
    747 		if (*cp != 'f') {
    748 			archive[7] = (*cp)? *cp: '0';
    749 			if (!(defaults_used = defset(archive))) {
    750 				usefile = NULL;
    751 				nblock = 1;
    752 				blocklim = 0;
    753 				NotTape = 0;
    754 			}
    755 		}
    756 	}
    757 
    758 	for (cp = *argv++; *cp; cp++)
    759 		switch (*cp) {
    760 #ifdef WAITAROUND
    761 		case 'z':
    762 			/* rendezvous with the debugger */
    763 			waitaround = 1;
    764 			break;
    765 #endif
    766 		case 'f':
    767 			assert_string(*argv, gettext(
    768 			    "tar: tarfile must be specified with 'f' "
    769 			    "function modifier\n"));
    770 			usefile = *argv++;
    771 			break;
    772 		case 'F':
    773 #ifdef	_iBCS2
    774 			if (sysv3_env) {
    775 				assert_string(*argv, gettext(
    776 				    "tar: 'F' requires a file name\n"));
    777 				Filefile = *argv++;
    778 				Fileflag++;
    779 			} else
    780 #endif	/*  _iBCS2 */
    781 				Fflag++;
    782 			break;
    783 		case 'c':
    784 			cflag++;
    785 			rflag++;
    786 			update = 1;
    787 			break;
    788 #if defined(O_XATTR)
    789 		case '@':
    790 			atflag++;
    791 			break;
    792 #endif	/* O_XATTR */
    793 #if defined(_PC_SATTR_ENABLED)
    794 		case '/':
    795 			saflag++;
    796 			break;
    797 #endif	/* _PC_SATTR_ENABLED */
    798 		case 'u':
    799 			uflag++;	/* moved code after signals caught */
    800 			rflag++;
    801 			update = 2;
    802 			break;
    803 		case 'r':
    804 			rflag++;
    805 			update = 2;
    806 			break;
    807 		case 'v':
    808 			vflag++;
    809 			break;
    810 		case 'w':
    811 			wflag++;
    812 			break;
    813 		case 'x':
    814 			xflag++;
    815 			break;
    816 		case 'X':
    817 			assert_string(*argv, gettext(
    818 			    "tar: exclude file must be specified with 'X' "
    819 			    "function modifier\n"));
    820 			Xflag = 1;
    821 			Xfile = *argv++;
    822 			build_table(exclude_tbl, Xfile);
    823 			break;
    824 		case 't':
    825 			tflag++;
    826 			break;
    827 		case 'm':
    828 			mflag++;
    829 			break;
    830 		case 'p':
    831 			pflag++;
    832 			break;
    833 		case 'D':
    834 			Dflag++;
    835 			break;
    836 		case '-':
    837 			/* ignore this silently */
    838 			break;
    839 		case '0':	/* numeric entries used only for defaults */
    840 		case '1':
    841 		case '2':
    842 		case '3':
    843 		case '4':
    844 		case '5':
    845 		case '6':
    846 		case '7':
    847 			break;
    848 		case 'b':
    849 			assert_string(*argv, gettext(
    850 			    "tar: blocking factor must be specified "
    851 			    "with 'b' function modifier\n"));
    852 			bflag++;
    853 			nblock = bcheck(*argv++);
    854 			break;
    855 		case 'q':
    856 			qflag++;
    857 			break;
    858 		case 'k':
    859 			assert_string(*argv, gettext(
    860 			    "tar: size value must be specified with 'k' "
    861 			    "function modifier\n"));
    862 			kflag++;
    863 			blocklim = kcheck(*argv++);
    864 			break;
    865 		case 'n':		/* not a magtape (instead of 'k') */
    866 			NotTape++;	/* assume non-magtape */
    867 			break;
    868 		case 'l':
    869 			linkerrok++;
    870 			break;
    871 		case 'e':
    872 #ifdef	_iBCS2
    873 			/* If sysv3 IS set, don't be as verbose */
    874 			if (!sysv3_env)
    875 #endif	/* _iBCS2 */
    876 				errflag++;
    877 			eflag++;
    878 			break;
    879 		case 'o':
    880 			oflag++;
    881 			break;
    882 		case 'h':
    883 			hflag++;
    884 			break;
    885 		case 'i':
    886 			iflag++;
    887 			break;
    888 		case 'B':
    889 			Bflag++;
    890 			break;
    891 		case 'P':
    892 			Pflag++;
    893 			break;
    894 		case 'E':
    895 			Eflag++;
    896 			Pflag++;	/* Only POSIX archive made */
    897 			break;
    898 		case 'T':
    899 			Tflag++;	/* Handle Trusted Extensions attrs */
    900 			pflag++;	/* also set flag for ACL */
    901 			break;
    902 		default:
    903 			(void) fprintf(stderr, gettext(
    904 			"tar: %c: unknown function modifier\n"), *cp);
    905 			usage();
    906 		}
    907 
    908 #ifdef	_iBCS2
    909 	if (Xflag && Fileflag) {
    910 		(void) fprintf(stderr, gettext(
    911 		"tar: specify only one of X or F.\n"));
    912 		usage();
    913 	}
    914 #endif	/*  _iBCS2 */
    915 
    916 	if (!rflag && !xflag && !tflag)
    917 		usage();
    918 	if ((rflag && xflag) || (xflag && tflag) || (rflag && tflag)) {
    919 		(void) fprintf(stderr, gettext(
    920 		"tar: specify only one of [ctxru].\n"));
    921 		usage();
    922 	}
    923 	/* Trusted Extensions attribute handling */
    924 	if (Tflag && ((getzoneid() != GLOBAL_ZONEID) ||
    925 	    !is_system_labeled())) {
    926 		(void) fprintf(stderr, gettext(
    927 		"tar: the 'T' option is only available with "
    928 		    "Trusted Extensions\nand must be run from "
    929 		    "the global zone.\n"));
    930 		usage();
    931 	}
    932 	if (cflag && *argv == NULL && Filefile == NULL)
    933 		fatal(gettext("Missing filenames"));
    934 	if (usefile == NULL)
    935 		fatal(gettext("device argument required"));
    936 
    937 	/* alloc a buffer of the right size */
    938 	if ((tbuf = (union hblock *)
    939 	    calloc(sizeof (union hblock) * nblock, sizeof (char))) ==
    940 	    (union hblock *)NULL) {
    941 		(void) fprintf(stderr, gettext(
    942 		"tar: cannot allocate physio buffer\n"));
    943 		exit(1);
    944 	}
    945 
    946 	if ((xrec_ptr = malloc(xrec_size)) == NULL) {
    947 		(void) fprintf(stderr, gettext(
    948 		    "tar: cannot allocate extended header buffer\n"));
    949 		exit(1);
    950 	}
    951 
    952 #ifdef WAITAROUND
    953 	if (waitaround) {
    954 		(void) fprintf(stderr, gettext("Rendezvous with tar on pid"
    955 		    " %d\n"), getpid());
    956 
    957 		while (waitaround) {
    958 			(void) sleep(10);
    959 		}
    960 	}
    961 #endif
    962 
    963 	thispid = getpid();
    964 	(void) sprintf(pidchars, "%ld", thispid);
    965 	thispid = strlen(pidchars);
    966 
    967 	if ((tmpdirp = getenv("TMPDIR")) == (char *)NULL)
    968 		(void) strcpy(xhdr_dirname, "/tmp");
    969 	else {
    970 		/*
    971 		 * Make sure that dir is no longer than what can
    972 		 * fit in the prefix part of the header.
    973 		 */
    974 		if (strlen(tmpdirp) > (size_t)(PRESIZ - thispid - 12)) {
    975 			(void) strcpy(xhdr_dirname, "/tmp");
    976 			if ((vflag > 0) && (Eflag > 0))
    977 				(void) fprintf(stderr, gettext(
    978 				    "Ignoring TMPDIR\n"));
    979 		} else
    980 			(void) strcpy(xhdr_dirname, tmpdirp);
    981 	}
    982 	(void) strcat(xhdr_dirname, "/PaxHeaders.");
    983 	(void) strcat(xhdr_dirname, pidchars);
    984 
    985 	if (rflag) {
    986 		if (cflag && tfile != NULL)
    987 			usage();
    988 		if (signal(SIGINT, SIG_IGN) != SIG_IGN)
    989 			(void) signal(SIGINT, onintr);
    990 		if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
    991 			(void) signal(SIGHUP, onhup);
    992 		if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
    993 			(void) signal(SIGQUIT, onquit);
    994 		if (uflag) {
    995 			int tnum;
    996 			if ((tnum = mkstemp(tname)) == -1)
    997 				vperror(1, "%s", tname);
    998 			if ((tfile = fdopen(tnum, "w")) == NULL)
    999 				vperror(1, "%s", tname);
   1000 		}
   1001 		if (strcmp(usefile, "-") == 0) {
   1002 			if (cflag == 0)
   1003 				fatal(gettext(
   1004 				"can only create standard output archives."));
   1005 			vfile = stderr;
   1006 			mt = dup(1);
   1007 			++bflag;
   1008 		} else {
   1009 			if (cflag)
   1010 				mt = open(usefile,
   1011 				    O_RDWR|O_CREAT|O_TRUNC, 0666);
   1012 			else
   1013 				mt = open(usefile, O_RDWR);
   1014 
   1015 			if (mt < 0) {
   1016 				if (cflag == 0 || (mt =  creat(usefile, 0666))
   1017 				    < 0)
   1018 				vperror(1, "%s", usefile);
   1019 			}
   1020 		}
   1021 		/* Get inode and device number of output file */
   1022 		(void) fstat(mt, &stbuf);
   1023 		mt_ino = stbuf.st_ino;
   1024 		mt_dev = stbuf.st_dev;
   1025 		mt_devtype = stbuf.st_mode & S_IFMT;
   1026 		NotTape = !istape(mt, mt_devtype);
   1027 
   1028 		if (rflag && !cflag && (mt_devtype == S_IFIFO))
   1029 			fatal(gettext("cannot append to pipe or FIFO."));
   1030 
   1031 		if (Aflag && vflag)
   1032 			(void) printf(
   1033 			gettext("Suppressing absolute pathnames\n"));
   1034 		dorep(argv);
   1035 	} else if (xflag || tflag) {
   1036 		/*
   1037 		 * for each argument, check to see if there is a "-I file" pair.
   1038 		 * if so, move the 3rd argument into "-I"'s place, build_table()
   1039 		 * using "file"'s name and increment argc one (the second
   1040 		 * increment appears in the for loop) which removes the two
   1041 		 * args "-I" and "file" from the argument vector.
   1042 		 */
   1043 		for (argc = 0; argv[argc]; argc++) {
   1044 			if (strcmp(argv[argc], "-I") == 0) {
   1045 				if (!argv[argc+1]) {
   1046 					(void) fprintf(stderr, gettext(
   1047 					"tar: missing argument for -I flag\n"));
   1048 					done(2);
   1049 				} else {
   1050 					Iflag = 1;
   1051 					argv[argc] = argv[argc+2];
   1052 					build_table(include_tbl, argv[++argc]);
   1053 #ifdef	_iBCS2
   1054 					if (Fileflag) {
   1055 						(void) fprintf(stderr, gettext(
   1056 						"tar: only one of I or F.\n"));
   1057 						usage();
   1058 					}
   1059 #endif	/*  _iBCS2 */
   1060 
   1061 				}
   1062 			}
   1063 		}
   1064 		if (strcmp(usefile, "-") == 0) {
   1065 			mt = dup(0);
   1066 			++bflag;
   1067 			/* try to recover from short reads when reading stdin */
   1068 			++Bflag;
   1069 		} else if ((mt = open(usefile, 0)) < 0)
   1070 			vperror(1, "%s", usefile);
   1071 
   1072 		if (xflag) {
   1073 			if (Aflag && vflag)
   1074 				(void) printf(gettext(
   1075 				    "Suppressing absolute pathnames.\n"));
   1076 
   1077 #ifdef	_iBCS2
   1078 			doxtract(argv, tbl_cnt);
   1079 #else
   1080 			doxtract(argv);
   1081 #endif
   1082 		} else if (tflag)
   1083 
   1084 #ifdef	_iBCS2
   1085 			dotable(argv, tbl_cnt);
   1086 #else
   1087 			dotable(argv);
   1088 #endif
   1089 	}
   1090 	else
   1091 		usage();
   1092 
   1093 	done(Errflg);
   1094 
   1095 	/* Not reached:  keep compiler quiet */
   1096 	return (1);
   1097 }
   1098 
   1099 static void
   1100 usage(void)
   1101 {
   1102 
   1103 #ifdef	_iBCS2
   1104 	if (sysv3_env) {
   1105 		(void) fprintf(stderr, gettext(
   1106 #if defined(O_XATTR)
   1107 #if defined(_PC_SATTR_ENABLED)
   1108 		"Usage: tar {c|r|t|u|x}[BDeEhilmnopPqTvw@/[0-7]][bfFk][X...] "
   1109 #else
   1110 		"Usage: tar {c|r|t|u|x}[BDeEhilmnopPqTvw@[0-7]][bfFk][X...] "
   1111 #endif	/* _PC_SATTR_ENABLED */
   1112 #else
   1113 		"Usage: tar {c|r|t|u|x}[BDeEhilmnopPqTvw[0-7]][bfFk][X...] "
   1114 #endif	/* O_XATTR */
   1115 		"[blocksize] [tarfile] [filename] [size] [exclude-file...] "
   1116 		"{file | -I include-file | -C directory file}...\n"));
   1117 	} else
   1118 #endif	/* _iBCS2 */
   1119 	{
   1120 		(void) fprintf(stderr, gettext(
   1121 #if defined(O_XATTR)
   1122 #if defined(_PC_SATTR_ENABLED)
   1123 		"Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqTvw@/[0-7]][bfk][X...] "
   1124 #else
   1125 		"Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqTvw@[0-7]][bfk][X...] "
   1126 #endif	/* _PC_SATTR_ENABLED */
   1127 #else
   1128 		"Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqTvw[0-7]][bfk][X...] "
   1129 #endif	/* O_XATTR */
   1130 		"[blocksize] [tarfile] [size] [exclude-file...] "
   1131 		"{file | -I include-file | -C directory file}...\n"));
   1132 	}
   1133 	done(1);
   1134 }
   1135 
   1136 /*
   1137  * dorep - do "replacements"
   1138  *
   1139  *	Dorep is responsible for creating ('c'),  appending ('r')
   1140  *	and updating ('u');
   1141  */
   1142 
   1143 static void
   1144 dorep(char *argv[])
   1145 {
   1146 	char *cp, *cp2, *p;
   1147 	char wdir[PATH_MAX+2], tempdir[PATH_MAX+2], *parent;
   1148 	char file[PATH_MAX*2], origdir[PATH_MAX+1];
   1149 	FILE *fp = (FILE *)NULL;
   1150 	FILE *ff = (FILE *)NULL;
   1151 	int archtype;
   1152 	int ret;
   1153 
   1154 
   1155 	if (!cflag) {
   1156 		xhdr_flgs = 0;
   1157 		getdir();			/* read header for next file */
   1158 		if (Xhdrflag > 0) {
   1159 			if (!Eflag)
   1160 				fatal(gettext("Archive contains extended"
   1161 				    " header.  -E flag required.\n"));
   1162 			ret = get_xdata();	/* Get extended header items */
   1163 						/*   and regular header */
   1164 		} else {
   1165 			if (Eflag)
   1166 				fatal(gettext("Archive contains no extended"
   1167 				    " header.  -E flag not allowed.\n"));
   1168 		}
   1169 		while (!endtape()) {		/* changed from a do while */
   1170 			setbytes_to_skip(&stbuf, ret);
   1171 			passtape();		/* skip the file data */
   1172 			if (term)
   1173 				done(Errflg);	/* received signal to stop */
   1174 			xhdr_flgs = 0;
   1175 			getdir();
   1176 			if (Xhdrflag > 0)
   1177 				ret = get_xdata();
   1178 		}
   1179 		if (ret == 0) {
   1180 			if ((dblock.dbuf.typeflag != 'A') &&
   1181 			    (xhdr_flgs != 0)) {
   1182 				load_info_from_xtarhdr(xhdr_flgs,
   1183 				    &Xtarhdr);
   1184 				xhdr_flgs |= _X_XHDR;
   1185 			}
   1186 		}
   1187 		backtape();			/* was called by endtape */
   1188 		if (tfile != NULL) {
   1189 			char buf[200];
   1190 
   1191 			(void) sprintf(buf, "sort +0 -1 +1nr %s -o %s; awk '$1 "
   1192 			    "!= prev {print; prev=$1}' %s >%sX;mv %sX %s",
   1193 			    tname, tname, tname, tname, tname, tname);
   1194 			(void) fflush(tfile);
   1195 			(void) system(buf);
   1196 			(void) freopen(tname, "r", tfile);
   1197 			(void) fstat(fileno(tfile), &stbuf);
   1198 			high = stbuf.st_size;
   1199 		}
   1200 	}
   1201 
   1202 	dumping = 1;
   1203 	if (mulvol) {	/* SP-1 */
   1204 		if (nblock && (blocklim%nblock) != 0)
   1205 			fatal(gettext(
   1206 			"Volume size not a multiple of block size."));
   1207 		blocklim -= 2;			/* for trailer records */
   1208 		if (vflag)
   1209 			(void) fprintf(vfile, gettext("Volume ends at %"
   1210 			    FMT_blkcnt_t "K, blocking factor = %dK\n"),
   1211 			    K((blocklim - 1)), K(nblock));
   1212 	}
   1213 
   1214 #ifdef	_iBCS2
   1215 	if (Fileflag) {
   1216 		if (Filefile != NULL) {
   1217 			if ((ff = fopen(Filefile, "r")) == NULL)
   1218 				vperror(0, "%s", Filefile);
   1219 		} else {
   1220 			(void) fprintf(stderr, gettext(
   1221 			    "tar: F requires a file name.\n"));
   1222 			usage();
   1223 		}
   1224 	}
   1225 #endif	/*  _iBCS2 */
   1226 
   1227 	/*
   1228 	 * Save the original directory before it gets
   1229 	 * changed.
   1230 	 */
   1231 	if (getcwd(origdir, (PATH_MAX+1)) == NULL) {
   1232 		vperror(0, gettext("A parent directory cannot be read"));
   1233 		exit(1);
   1234 	}
   1235 
   1236 	(void) strcpy(wdir, origdir);
   1237 
   1238 	while ((*argv || fp || ff) && !term) {
   1239 		if (fp || (strcmp(*argv, "-I") == 0)) {
   1240 #ifdef	_iBCS2
   1241 			if (Fileflag) {
   1242 				(void) fprintf(stderr, gettext(
   1243 				"tar: only one of I or F.\n"));
   1244 				usage();
   1245 			}
   1246 #endif	/*  _iBCS2 */
   1247 			if (fp == NULL) {
   1248 				if (*++argv == NULL)
   1249 					fatal(gettext(
   1250 					    "missing file name for -I flag."));
   1251 				else if ((fp = fopen(*argv++, "r")) == NULL)
   1252 					vperror(0, "%s", argv[-1]);
   1253 				continue;
   1254 			} else if ((fgets(file, PATH_MAX-1, fp)) == NULL) {
   1255 				(void) fclose(fp);
   1256 				fp = NULL;
   1257 				continue;
   1258 			} else {
   1259 				cp = cp2 = file;
   1260 				if ((p = strchr(cp2, '\n')))
   1261 					*p = 0;
   1262 			}
   1263 		} else if ((strcmp(*argv, "-C") == 0) && argv[1]) {
   1264 #ifdef	_iBCS2
   1265 			if (Fileflag) {
   1266 				(void) fprintf(stderr, gettext(
   1267 				"tar: only one of F or C\n"));
   1268 				usage();
   1269 			}
   1270 #endif	/*  _iBCS2 */
   1271 
   1272 			if (chdir(*++argv) < 0)
   1273 				vperror(0, gettext(
   1274 				    "can't change directories to %s"), *argv);
   1275 			else
   1276 				(void) getcwd(wdir, (sizeof (wdir)));
   1277 			argv++;
   1278 			continue;
   1279 #ifdef	_iBCS2
   1280 		} else if (Fileflag && (ff != NULL)) {
   1281 			if ((fgets(file, PATH_MAX-1, ff)) == NULL) {
   1282 				(void) fclose(ff);
   1283 				ff = NULL;
   1284 				continue;
   1285 			} else {
   1286 				cp = cp2 = file;
   1287 				if (p = strchr(cp2, '\n'))
   1288 					*p = 0;
   1289 			}
   1290 #endif	/*  _iBCS2 */
   1291 		} else
   1292 			cp = cp2 = strcpy(file, *argv++);
   1293 
   1294 		/*
   1295 		 * point cp2 to the last '/' in file, but not
   1296 		 * to a trailing '/'
   1297 		 */
   1298 		for (; *cp; cp++) {
   1299 			if (*cp == '/') {
   1300 				while (*(cp+1) == '/') {
   1301 					++cp;
   1302 				}
   1303 				if (*(cp+1) != '\0') {
   1304 					/* not trailing slash */
   1305 					cp2 = cp;
   1306 				}
   1307 			}
   1308 		}
   1309 		if (cp2 != file) {
   1310 			*cp2 = '\0';
   1311 			if (chdir(file) < 0) {
   1312 				vperror(0, gettext(
   1313 				    "can't change directories to %s"), file);
   1314 				continue;
   1315 			}
   1316 			*cp2 = '/';
   1317 			cp2++;
   1318 		}
   1319 
   1320 		parent = getcwd(tempdir, (sizeof (tempdir)));
   1321 
   1322 		archtype = putfile(file, cp2, parent, NULL, NORMAL_FILE,
   1323 		    LEV0, SYMLINK_LEV0);
   1324 
   1325 #if defined(O_XATTR)
   1326 		if (!exitflag) {
   1327 			if ((atflag || saflag) &&
   1328 			    (archtype == PUT_NOTAS_LINK)) {
   1329 				xattrs_put(file, cp2, parent, NULL);
   1330 			}
   1331 		}
   1332 #endif
   1333 
   1334 		if (chdir(origdir) < 0)
   1335 			vperror(0, gettext("cannot change back?: %s"), origdir);
   1336 
   1337 		if (exitflag) {
   1338 			/*
   1339 			 * If e function modifier has been specified
   1340 			 * write the files (that are listed before the
   1341 			 * file causing the error) to tape.  exitflag is
   1342 			 * used because only some of the error conditions
   1343 			 * in putfile() recognize the e function modifier.
   1344 			 */
   1345 			break;
   1346 		}
   1347 	}
   1348 
   1349 	putempty((blkcnt_t)2);
   1350 	flushtape();
   1351 	closevol();	/* SP-1 */
   1352 	if (linkerrok == 1)
   1353 		for (; ihead != NULL; ihead = ihead->nextp) {
   1354 			if (ihead->count == 0)
   1355 				continue;
   1356 			(void) fprintf(stderr, gettext(
   1357 			"tar: missing links to %s\n"), ihead->pathname);
   1358 			if (errflag)
   1359 				done(1);
   1360 			else
   1361 				Errflg = 1;
   1362 		}
   1363 }
   1364 
   1365 
   1366 /*
   1367  * endtape - check for tape at end
   1368  *
   1369  *	endtape checks the entry in dblock.dbuf to see if its the
   1370  *	special EOT entry.  Endtape is usually called after getdir().
   1371  *
   1372  *	endtape used to call backtape; it no longer does, he who
   1373  *	wants it backed up must call backtape himself
   1374  *	RETURNS:	0 if not EOT, tape position unaffected
   1375  *			1 if	 EOT, tape position unaffected
   1376  */
   1377 
   1378 static int
   1379 endtape(void)
   1380 {
   1381 	if (dblock.dbuf.name[0] == '\0') {	/* null header = EOT */
   1382 		return (1);
   1383 	} else
   1384 		return (0);
   1385 }
   1386 
   1387 /*
   1388  *	getdir - get directory entry from tar tape
   1389  *
   1390  *	getdir reads the next tarblock off the tape and cracks
   1391  *	it as a directory. The checksum must match properly.
   1392  *
   1393  *	If tfile is non-null getdir writes the file name and mod date
   1394  *	to tfile.
   1395  */
   1396 
   1397 static void
   1398 getdir(void)
   1399 {
   1400 	struct stat *sp;
   1401 #ifdef EUC
   1402 	static int warn_chksum_sign = 0;
   1403 #endif /* EUC */
   1404 
   1405 top:
   1406 	readtape((char *)&dblock);
   1407 	if (dblock.dbuf.name[0] == '\0')
   1408 		return;
   1409 	sp = &stbuf;
   1410 	(void) sscanf(dblock.dbuf.mode, "%8lo", &Gen.g_mode);
   1411 	(void) sscanf(dblock.dbuf.uid, "%8lo", (ulong_t *)&Gen.g_uid);
   1412 	(void) sscanf(dblock.dbuf.gid, "%8lo", (ulong_t *)&Gen.g_gid);
   1413 	(void) sscanf(dblock.dbuf.size, "%12" FMT_off_t_o, &Gen.g_filesz);
   1414 	(void) sscanf(dblock.dbuf.mtime, "%12lo", (ulong_t *)&Gen.g_mtime);
   1415 	(void) sscanf(dblock.dbuf.chksum, "%8o", &Gen.g_cksum);
   1416 	(void) sscanf(dblock.dbuf.devmajor, "%8lo", &Gen.g_devmajor);
   1417 	(void) sscanf(dblock.dbuf.devminor, "%8lo", &Gen.g_devminor);
   1418 
   1419 	is_posix = (strcmp(dblock.dbuf.magic, magic_type) == 0);
   1420 
   1421 	sp->st_mode = Gen.g_mode;
   1422 	if (is_posix && (sp->st_mode & S_IFMT) == 0)
   1423 		switch (dblock.dbuf.typeflag) {
   1424 		case '0': case 0: case _XATTR_HDRTYPE:
   1425 			sp->st_mode |= S_IFREG;
   1426 			break;
   1427 		case '1':	/* hard link */
   1428 			break;
   1429 		case '2':
   1430 			sp->st_mode |= S_IFLNK;
   1431 			break;
   1432 		case '3':
   1433 			sp->st_mode |= S_IFCHR;
   1434 			break;
   1435 		case '4':
   1436 			sp->st_mode |= S_IFBLK;
   1437 			break;
   1438 		case '5':
   1439 			sp->st_mode |= S_IFDIR;
   1440 			break;
   1441 		case '6':
   1442 			sp->st_mode |= S_IFIFO;
   1443 			break;
   1444 		default:
   1445 			if (convtoreg(Gen.g_filesz))
   1446 				sp->st_mode |= S_IFREG;
   1447 			break;
   1448 		}
   1449 
   1450 	if (dblock.dbuf.typeflag == 'X')
   1451 		Xhdrflag = 1;	/* Currently processing extended header */
   1452 	else
   1453 		Xhdrflag = 0;
   1454 
   1455 	sp->st_uid = Gen.g_uid;
   1456 	sp->st_gid = Gen.g_gid;
   1457 	sp->st_size = Gen.g_filesz;
   1458 	sp->st_mtime = Gen.g_mtime;
   1459 	chksum = Gen.g_cksum;
   1460 
   1461 	if (dblock.dbuf.extno != '\0') {	/* split file? */
   1462 		extno = dblock.dbuf.extno;
   1463 		extsize = Gen.g_filesz;
   1464 		extotal = dblock.dbuf.extotal;
   1465 	} else {
   1466 		extno = 0;	/* tell others file not split */
   1467 		extsize = 0;
   1468 		extotal = 0;
   1469 	}
   1470 
   1471 #ifdef	EUC
   1472 	if (chksum != checksum(&dblock)) {
   1473 		if (chksum != checksum_signed(&dblock)) {
   1474 			(void) fprintf(stderr, gettext(
   1475 			    "tar: directory checksum error\n"));
   1476 			if (iflag)
   1477 				goto top;
   1478 			done(2);
   1479 		} else {
   1480 			if (! warn_chksum_sign) {
   1481 				warn_chksum_sign = 1;
   1482 				(void) fprintf(stderr, gettext(
   1483 			"tar: warning: tar file made with signed checksum\n"));
   1484 			}
   1485 		}
   1486 	}
   1487 #else
   1488 	if (chksum != checksum(&dblock)) {
   1489 		(void) fprintf(stderr, gettext(
   1490 		"tar: directory checksum error\n"));
   1491 		if (iflag)
   1492 			goto top;
   1493 		done(2);
   1494 	}
   1495 #endif	/* EUC */
   1496 	if (tfile != NULL && Xhdrflag == 0) {
   1497 		/*
   1498 		 * If an extended header is present, then time is available
   1499 		 * in nanoseconds in the extended header data, so set it.
   1500 		 * Otherwise, give an invalid value so that checkupdate will
   1501 		 * not test beyond seconds.
   1502 		 */
   1503 		if ((xhdr_flgs & _X_MTIME))
   1504 			sp->st_mtim.tv_nsec = Xtarhdr.x_mtime.tv_nsec;
   1505 		else
   1506 			sp->st_mtim.tv_nsec = -1;
   1507 
   1508 		if (xhdr_flgs & _X_PATH)
   1509 			(void) fprintf(tfile, "%s %10ld.%9.9ld\n",
   1510 			    Xtarhdr.x_path, sp->st_mtim.tv_sec,
   1511 			    sp->st_mtim.tv_nsec);
   1512 		else
   1513 			(void) fprintf(tfile, "%.*s %10ld.%9.9ld\n",
   1514 			    NAMSIZ, dblock.dbuf.name, sp->st_mtim.tv_sec,
   1515 			    sp->st_mtim.tv_nsec);
   1516 	}
   1517 
   1518 #if defined(O_XATTR)
   1519 	Hiddendir = 0;
   1520 	if (xattrp && dblock.dbuf.typeflag == _XATTR_HDRTYPE) {
   1521 		if (xattrbadhead) {
   1522 			free(xattrhead);
   1523 			xattrp = NULL;
   1524 			xattr_linkp = NULL;
   1525 			xattrhead = NULL;
   1526 		} else {
   1527 			char	*aname = basename(xattrapath);
   1528 			size_t	xindex  = aname - xattrapath;
   1529 
   1530 			if (xattrapath[xindex] == '.' &&
   1531 			    xattrapath[xindex + 1] == '\0' &&
   1532 			    xattrp->h_typeflag == '5') {
   1533 				Hiddendir = 1;
   1534 				sp->st_mode =
   1535 				    (S_IFDIR | (sp->st_mode & POSIXMODES));
   1536 			}
   1537 			dblock.dbuf.typeflag = xattrp->h_typeflag;
   1538 		}
   1539 	}
   1540 #endif
   1541 }
   1542 
   1543 
   1544 /*
   1545  *	passtape - skip over a file on the tape
   1546  *
   1547  *	passtape skips over the next data file on the tape.
   1548  *	The tape directory entry must be in dblock.dbuf. This
   1549  *	routine just eats the number of blocks computed from the
   1550  *	directory size entry; the tape must be (logically) positioned
   1551  *	right after thee directory info.
   1552  */
   1553 
   1554 static void
   1555 passtape(void)
   1556 {
   1557 	blkcnt_t blocks;
   1558 	char buf[TBLOCK];
   1559 
   1560 	/*
   1561 	 * Types link(1), sym-link(2), char special(3), blk special(4),
   1562 	 *  directory(5), and FIFO(6) do not have data blocks associated
   1563 	 *  with them so just skip reading the data block.
   1564 	 */
   1565 	if (dblock.dbuf.typeflag == '1' || dblock.dbuf.typeflag == '2' ||
   1566 	    dblock.dbuf.typeflag == '3' || dblock.dbuf.typeflag == '4' ||
   1567 	    dblock.dbuf.typeflag == '5' || dblock.dbuf.typeflag == '6')
   1568 		return;
   1569 	blocks = TBLOCKS(stbuf.st_size);
   1570 
   1571 	/* if operating on disk, seek instead of reading */
   1572 	if (NotTape)
   1573 		seekdisk(blocks);
   1574 	else
   1575 		while (blocks-- > 0)
   1576 			readtape(buf);
   1577 }
   1578 
   1579 #if defined(O_XATTR)
   1580 static int
   1581 is_sysattr(char *name)
   1582 {
   1583 	return ((strcmp(name, VIEW_READONLY) == 0) ||
   1584 	    (strcmp(name, VIEW_READWRITE) == 0));
   1585 }
   1586 #endif
   1587 
   1588 #if defined(O_XATTR)
   1589 /*
   1590  * Verify the attribute, attrname, is an attribute we want to restore.
   1591  * Never restore read-only system attribute files.  Only restore read-write
   1592  * system attributes files when -/ was specified, and only traverse into
   1593  * the 2nd level attribute directory containing only system attributes if
   1594  * -@ was specified.  This keeps us from archiving
   1595  *	<attribute name>/<read-write system attribute file>
   1596  * when -/ was specified without -@.
   1597  *
   1598  * attrname	- attribute file name
   1599  * attrparent	- attribute's parent name within the base file's attribute
   1600  *		directory hierarchy
   1601  */
   1602 static attr_status_t
   1603 verify_attr(char *attrname, char *attrparent, int arc_rwsysattr,
   1604     int *rw_sysattr)
   1605 {
   1606 #if defined(_PC_SATTR_ENABLED)
   1607 	int	attr_supported;
   1608 
   1609 	/* Never restore read-only system attribute files */
   1610 	if ((attr_supported = sysattr_type(attrname)) == _RO_SATTR) {
   1611 		*rw_sysattr = 0;
   1612 		return (ATTR_SKIP);
   1613 	} else {
   1614 		*rw_sysattr = (attr_supported == _RW_SATTR);
   1615 	}
   1616 #else
   1617 	/*
   1618 	 * Only need to check if this attribute is an extended system
   1619 	 * attribute.
   1620 	 */
   1621 	if (*rw_sysattr = is_sysattr(attrname)) {
   1622 		return (ATTR_SKIP);
   1623 	} else {
   1624 		return (ATTR_OK);
   1625 	}
   1626 #endif	/* _PC_SATTR_ENABLED */
   1627 
   1628 	/*
   1629 	 * If the extended system attribute file is specified with the
   1630 	 * arc_rwsysattr flag, as being transient (default extended
   1631 	 * attributes), then don't archive it.
   1632 	 */
   1633 	if (*rw_sysattr && !arc_rwsysattr) {
   1634 		return (ATTR_SKIP);
   1635 	}
   1636 
   1637 	/*
   1638 	 * Only restore read-write system attribute files
   1639 	 * when -/ was specified.  Only restore extended
   1640 	 * attributes when -@ was specified.
   1641 	 */
   1642 	if (atflag) {
   1643 		if (!saflag) {
   1644 			/*
   1645 			 * Only archive/restore the hidden directory "." if
   1646 			 * we're processing the top level hidden attribute
   1647 			 * directory.  We don't want to process the
   1648 			 * hidden attribute directory of the attribute
   1649 			 * directory that contains only extended system
   1650 			 * attributes.
   1651 			 */
   1652 			if (*rw_sysattr || (Hiddendir &&
   1653 			    (attrparent != NULL))) {
   1654 				return (ATTR_SKIP);
   1655 			}
   1656 		}
   1657 	} else if (saflag) {
   1658 		/*
   1659 		 * Only archive/restore read-write extended system attribute
   1660 		 * files of the base file.
   1661 		 */
   1662 		if (!*rw_sysattr || (attrparent != NULL)) {
   1663 			return (ATTR_SKIP);
   1664 		}
   1665 	} else {
   1666 		return (ATTR_SKIP);
   1667 	}
   1668 
   1669 	return (ATTR_OK);
   1670 }
   1671 #endif
   1672 
   1673 static void
   1674 free_children(file_list_t *children)
   1675 {
   1676 	file_list_t	*child = children;
   1677 	file_list_t	*cptr;
   1678 
   1679 	while (child != NULL) {
   1680 		cptr = child->next;
   1681 		if (child->name != NULL) {
   1682 			free(child->name);
   1683 		}
   1684 		child = cptr;
   1685 	}
   1686 }
   1687 
   1688 static int
   1689 putfile(char *longname, char *shortname, char *parent, attr_data_t *attrinfo,
   1690     int filetype, int lev, int symlink_lev)
   1691 {
   1692 	int infile = -1;	/* deliberately invalid */
   1693 	blkcnt_t blocks;
   1694 	char buf[PATH_MAX + 2];	/* Add trailing slash and null */
   1695 	char *bigbuf;
   1696 	int	maxread;
   1697 	int	hint;		/* amount to write to get "in sync" */
   1698 	char filetmp[PATH_MAX + 1];
   1699 	char *cp;
   1700 	char *name;
   1701 	char *attrparent = NULL;
   1702 	char *longattrname = NULL;
   1703 	file_list_t	*child = NULL;
   1704 	file_list_t	*child_end = NULL;
   1705 	file_list_t	*cptr;
   1706 	struct dirent *dp;
   1707 	DIR *dirp;
   1708 	int i;
   1709 	int split;
   1710 	int dirfd = -1;
   1711 	int rc = PUT_NOTAS_LINK;
   1712 	int archtype = 0;
   1713 	int rw_sysattr = 0;
   1714 	char newparent[PATH_MAX + MAXNAMLEN + 1];
   1715 	char *prefix = "";
   1716 	char *tmpbuf;
   1717 	char goodbuf[PRESIZ + 2];
   1718 	char junkbuf[MAXNAM+1];
   1719 	char *lastslash;
   1720 	int j;
   1721 	struct stat sbuf;
   1722 	int readlink_max;
   1723 
   1724 	(void) memset(goodbuf, '\0', sizeof (goodbuf));
   1725 	(void) memset(junkbuf, '\0', sizeof (junkbuf));
   1726 
   1727 	xhdr_flgs = 0;
   1728 
   1729 	if (filetype == XATTR_FILE) {
   1730 		attrparent = attrinfo->attr_parent;
   1731 		longattrname = attrinfo->attr_path;
   1732 		dirfd = attrinfo->attr_parentfd;
   1733 		rw_sysattr = attrinfo->attr_rw_sysattr;
   1734 	} else {
   1735 		dirfd = open(".", O_RDONLY);
   1736 	}
   1737 
   1738 	if (dirfd == -1) {
   1739 		(void) fprintf(stderr, gettext(
   1740 		    "tar: unable to open%sdirectory %s%s%s%s\n"),
   1741 		    (filetype == XATTR_FILE) ? gettext(" attribute ") : " ",
   1742 		    (attrparent == NULL) ? "" : gettext("of attribute "),
   1743 		    (attrparent == NULL) ? "" : attrparent,
   1744 		    (attrparent == NULL) ? "" : gettext(" of "),
   1745 		    (filetype == XATTR_FILE) ? longname : parent);
   1746 		goto out;
   1747 	}
   1748 
   1749 	if (lev > MAXLEV) {
   1750 		(void) fprintf(stderr,
   1751 		    gettext("tar: directory nesting too deep, %s not dumped\n"),
   1752 		    longname);
   1753 		goto out;
   1754 	}
   1755 
   1756 	if (getstat(dirfd, longname, shortname, attrparent))
   1757 		goto out;
   1758 
   1759 	if (hflag) {
   1760 		/*
   1761 		 * Catch nesting where a file is a symlink to its directory.
   1762 		 */
   1763 		j = fstatat(dirfd, shortname, &sbuf, AT_SYMLINK_NOFOLLOW);
   1764 		if (S_ISLNK(sbuf.st_mode)) {
   1765 			if (symlink_lev++ >= MAXSYMLINKS) {
   1766 				(void) fprintf(stderr, gettext(
   1767 				    "tar: %s: Number of symbolic links "
   1768 				    "encountered during path name traversal "
   1769 				    "exceeds MAXSYMLINKS\n"), longname);
   1770 				Errflg = 1;
   1771 				goto out;
   1772 			}
   1773 		}
   1774 	}
   1775 
   1776 	/*
   1777 	 * Check if the input file is the same as the tar file we
   1778 	 * are creating
   1779 	 */
   1780 	if ((mt_ino == stbuf.st_ino) && (mt_dev == stbuf.st_dev)) {
   1781 		(void) fprintf(stderr, gettext(
   1782 		    "tar: %s%s%s%s%s same as archive file\n"),
   1783 		    rw_sysattr ? gettext("system ") : "",
   1784 		    (longattrname == NULL) ? "" : gettext("attribute "),
   1785 		    (longattrname == NULL) ? "" : longattrname,
   1786 		    (longattrname == NULL) ? "" : gettext(" of "),
   1787 		    longname);
   1788 		Errflg = 1;
   1789 		goto out;
   1790 	}
   1791 	/*
   1792 	 * Check size limit - we can't archive files that
   1793 	 * exceed TAR_OFFSET_MAX bytes because of header
   1794 	 * limitations. Exclude file types that set
   1795 	 * st_size to zero below because they take no
   1796 	 * archive space to represent contents.
   1797 	 */
   1798 	if ((stbuf.st_size > (off_t)TAR_OFFSET_MAX) &&
   1799 	    !S_ISDIR(stbuf.st_mode) &&
   1800 	    !S_ISCHR(stbuf.st_mode) &&
   1801 	    !S_ISBLK(stbuf.st_mode) &&
   1802 	    (Eflag == 0)) {
   1803 		(void) fprintf(stderr, gettext(
   1804 		    "tar: %s%s%s%s%s too large to archive.  "
   1805 		    "Use E function modifier.\n"),
   1806 		    rw_sysattr ? gettext("system ") : "",
   1807 		    (longattrname == NULL) ? "" : gettext("attribute "),
   1808 		    (longattrname == NULL) ? "" : longattrname,
   1809 		    (longattrname == NULL) ? "" : gettext(" of "),
   1810 		    longname);
   1811 		if (errflag)
   1812 			exitflag = 1;
   1813 		Errflg = 1;
   1814 		goto out;
   1815 	}
   1816 
   1817 	if (tfile != NULL && checkupdate(longname) == 0) {
   1818 		goto out;
   1819 	}
   1820 	if (checkw('r', longname) == 0) {
   1821 		goto out;
   1822 	}
   1823 
   1824 	if (Fflag && checkf(shortname, stbuf.st_mode, Fflag) == 0)
   1825 		goto out;
   1826 
   1827 	if (Xflag) {
   1828 		if (is_in_table(exclude_tbl, longname)) {
   1829 			if (vflag) {
   1830 				(void) fprintf(vfile, gettext(
   1831 				    "a %s excluded\n"), longname);
   1832 			}
   1833 			goto out;
   1834 		}
   1835 	}
   1836 
   1837 	/*
   1838 	 * If the length of the fullname is greater than MAXNAM,
   1839 	 * print out a message and return (unless extended headers are used,
   1840 	 * in which case fullname is limited to PATH_MAX).
   1841 	 */
   1842 
   1843 	if ((((split = (int)strlen(longname)) > MAXNAM) && (Eflag == 0)) ||
   1844 	    (split > PATH_MAX)) {
   1845 		(void) fprintf(stderr, gettext(
   1846 		    "tar: %s: file name too long\n"), longname);
   1847 		if (errflag)
   1848 			exitflag = 1;
   1849 		Errflg = 1;
   1850 		goto out;
   1851 	}
   1852 
   1853 	/*
   1854 	 * We split the fullname into prefix and name components if any one
   1855 	 * of three conditions holds:
   1856 	 *	-- the length of the fullname exceeds NAMSIZ,
   1857 	 *	-- the length of the fullname equals NAMSIZ, and the shortname
   1858 	 *	   is less than NAMSIZ, (splitting in this case preserves
   1859 	 *	   compatibility with 5.6 and 5.5.1 tar), or
   1860 	 * 	-- the length of the fullname equals NAMSIZ, the file is a
   1861 	 *	   directory and we are not in POSIX-conformant mode (where
   1862 	 *	   trailing slashes are removed from directories).
   1863 	 */
   1864 	if ((split > NAMSIZ) ||
   1865 	    (split == NAMSIZ && strlen(shortname) < NAMSIZ) ||
   1866 	    (split == NAMSIZ && S_ISDIR(stbuf.st_mode) && !Pflag)) {
   1867 		/*
   1868 		 * Since path is limited to PRESIZ characters, look for the
   1869 		 * last slash within PRESIZ + 1 characters only.
   1870 		 */
   1871 		(void) strncpy(&goodbuf[0], longname, min(split, PRESIZ + 1));
   1872 		tmpbuf = goodbuf;
   1873 		lastslash = strrchr(tmpbuf, '/');
   1874 		if (lastslash == NULL) {
   1875 			i = split;		/* Length of name */
   1876 			j = 0;			/* Length of prefix */
   1877 			goodbuf[0] = '\0';
   1878 		} else {
   1879 			*lastslash = '\0';	/* Terminate the prefix */
   1880 			j = strlen(tmpbuf);
   1881 			i = split - j - 1;
   1882 		}
   1883 		/*
   1884 		 * If the filename is greater than NAMSIZ we can't
   1885 		 * archive the file unless we are using extended headers.
   1886 		 */
   1887 		if ((i > NAMSIZ) || (i == NAMSIZ && S_ISDIR(stbuf.st_mode) &&
   1888 		    !Pflag)) {
   1889 			/* Determine which (filename or path) is too long. */
   1890 			lastslash = strrchr(longname, '/');
   1891 			if (lastslash != NULL)
   1892 				i = strlen(lastslash + 1);
   1893 			if (Eflag > 0) {
   1894 				xhdr_flgs |= _X_PATH;
   1895 				Xtarhdr.x_path = longname;
   1896 				if (i <= NAMSIZ)
   1897 					(void) strcpy(junkbuf, lastslash + 1);
   1898 				else
   1899 					(void) sprintf(junkbuf, "%llu",
   1900 					    xhdr_count + 1);
   1901 				if (split - i - 1 > PRESIZ)
   1902 					(void) strcpy(goodbuf, xhdr_dirname);
   1903 			} else {
   1904 				if ((i > NAMSIZ) || (i == NAMSIZ &&
   1905 				    S_ISDIR(stbuf.st_mode) && !Pflag))
   1906 					(void) fprintf(stderr, gettext(
   1907 					    "tar: %s: filename is greater than "
   1908 					    "%d\n"), lastslash == NULL ?
   1909 					    longname : lastslash + 1, NAMSIZ);
   1910 				else
   1911 					(void) fprintf(stderr, gettext(
   1912 					    "tar: %s: prefix is greater than %d"
   1913 					    "\n"), longname, PRESIZ);
   1914 				if (errflag)
   1915 					exitflag = 1;
   1916 				Errflg = 1;
   1917 				goto out;
   1918 			}
   1919 		} else
   1920 			(void) strncpy(&junkbuf[0], longname + j + 1,
   1921 			    strlen(longname + j + 1));
   1922 		name = junkbuf;
   1923 		prefix = goodbuf;
   1924 	} else {
   1925 		name = longname;
   1926 	}
   1927 	if (Aflag) {
   1928 		if ((prefix != NULL) && (*prefix != '\0'))
   1929 			while (*prefix == '/')
   1930 				++prefix;
   1931 		else
   1932 			while (*name == '/')
   1933 				++name;
   1934 	}
   1935 
   1936 	switch (stbuf.st_mode & S_IFMT) {
   1937 	case S_IFDIR:
   1938 		stbuf.st_size = (off_t)0;
   1939 		blocks = TBLOCKS(stbuf.st_size);
   1940 
   1941 		if (filetype != XATTR_FILE && Hiddendir == 0) {
   1942 			i = 0;
   1943 			cp = buf;
   1944 			while ((*cp++ = longname[i++]))
   1945 				;
   1946 			*--cp = '/';
   1947 			*++cp = 0;
   1948 		}
   1949 		if (!oflag) {
   1950 			tomodes(&stbuf);
   1951 			if (build_dblock(name, tchar, '5', filetype,
   1952 			    &stbuf, stbuf.st_dev, prefix) != 0) {
   1953 				goto out;
   1954 			}
   1955 			if (!Pflag) {
   1956 				/*
   1957 				 * Old archives require a slash at the end
   1958 				 * of a directory name.
   1959 				 *
   1960 				 * XXX
   1961 				 * If directory name is too long, will
   1962 				 * slash overfill field?
   1963 				 */
   1964 				if (strlen(name) > (unsigned)NAMSIZ-1) {
   1965 					(void) fprintf(stderr, gettext(
   1966 					    "tar: %s: filename is greater "
   1967 					    "than %d\n"), name, NAMSIZ);
   1968 					if (errflag)
   1969 						exitflag = 1;
   1970 					Errflg = 1;
   1971 					goto out;
   1972 				} else {
   1973 					if (strlen(name) == (NAMSIZ - 1)) {
   1974 						(void) memcpy(dblock.dbuf.name,
   1975 						    name, NAMSIZ);
   1976 						dblock.dbuf.name[NAMSIZ-1]
   1977 						    = '/';
   1978 					} else
   1979 						(void) sprintf(dblock.dbuf.name,
   1980 						    "%s/", name);
   1981 
   1982 					/*
   1983 					 * need to recalculate checksum
   1984 					 * because the name changed.
   1985 					 */
   1986 					(void) sprintf(dblock.dbuf.chksum,
   1987 					    "%07o", checksum(&dblock));
   1988 				}
   1989 			}
   1990 
   1991 			if (put_extra_attributes(longname, shortname,
   1992 			    longattrname, prefix, filetype, '5') != 0)
   1993 				goto out;
   1994 
   1995 #if defined(O_XATTR)
   1996 			/*
   1997 			 * Reset header typeflag when archiving directory, since
   1998 			 * build_dblock changed it on us.
   1999 			 */
   2000 			if (filetype == XATTR_FILE) {
   2001 				dblock.dbuf.typeflag = _XATTR_HDRTYPE;
   2002 			} else {
   2003 				dblock.dbuf.typeflag = '5';
   2004 			}
   2005 #else
   2006 			dblock.dbuf.typeflag = '5';
   2007 #endif
   2008 
   2009 			(void) sprintf(dblock.dbuf.chksum, "%07o",
   2010 			    checksum(&dblock));
   2011 
   2012 			(void) writetbuf((char *)&dblock, 1);
   2013 		}
   2014 		if (vflag) {
   2015 #ifdef DEBUG
   2016 			if (NotTape)
   2017 				DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
   2018 				    0);
   2019 #endif
   2020 			if (filetype == XATTR_FILE && Hiddendir) {
   2021 				(void) fprintf(vfile, "a %s attribute %s ",
   2022 				    longname, longattrname);
   2023 
   2024 			} else {
   2025 				(void) fprintf(vfile, "a %s/ ", longname);
   2026 			}
   2027 			if (NotTape)
   2028 				(void) fprintf(vfile, "%" FMT_blkcnt_t "K\n",
   2029 				    K(blocks));
   2030 			else
   2031 				(void) fprintf(vfile, gettext("%" FMT_blkcnt_t
   2032 				    " tape blocks\n"), blocks);
   2033 		}
   2034 
   2035 		/*
   2036 		 * If hidden dir then break now since xattrs_put() will do
   2037 		 * the iterating of the directory.
   2038 		 *
   2039 		 * At the moment, there can only be system attributes on
   2040 		 * attributes.  There can be no attributes on attributes or
   2041 		 * directories within the attributes hidden directory hierarchy.
   2042 		 */
   2043 		if (filetype == XATTR_FILE)
   2044 			break;
   2045 
   2046 		if (*shortname != '/')
   2047 			(void) sprintf(newparent, "%s/%s", parent, shortname);
   2048 		else
   2049 			(void) sprintf(newparent, "%s", shortname);
   2050 
   2051 		if (chdir(shortname) < 0) {
   2052 			vperror(0, "%s", newparent);
   2053 			goto out;
   2054 		}
   2055 
   2056 		if ((dirp = opendir(".")) == NULL) {
   2057 			vperror(0, gettext(
   2058 			    "can't open directory %s"), longname);
   2059 			if (chdir(parent) < 0)
   2060 				vperror(0, gettext("cannot change back?: %s"),
   2061 				    parent);
   2062 			goto out;
   2063 		}
   2064 
   2065 		/*
   2066 		 * Create a list of files (children) in this directory to avoid
   2067 		 * having to perform telldir()/seekdir().
   2068 		 */
   2069 		while ((dp = readdir(dirp)) != NULL && !term) {
   2070 			if ((strcmp(".", dp->d_name) == 0) ||
   2071 			    (strcmp("..", dp->d_name) == 0))
   2072 				continue;
   2073 			if (((cptr = (file_list_t *)calloc(sizeof (char),
   2074 			    sizeof (file_list_t))) == NULL) ||
   2075 			    ((cptr->name = strdup(dp->d_name)) == NULL)) {
   2076 				vperror(1, gettext(
   2077 				    "Insufficient memory for directory "
   2078 				    "list entry %s/%s\n"),
   2079 				    newparent, dp->d_name);
   2080 			}
   2081 
   2082 			/* Add the file to the list */
   2083 			if (child == NULL) {
   2084 				child = cptr;
   2085 			} else {
   2086 				child_end->next = cptr;
   2087 			}
   2088 			child_end = cptr;
   2089 		}
   2090 		(void) closedir(dirp);
   2091 
   2092 		/*
   2093 		 * Archive each of the files in the current directory.
   2094 		 * If a file is a directory, putfile() is called
   2095 		 * recursively to archive the file hierarchy of the
   2096 		 * directory before archiving the next file in the
   2097 		 * current directory.
   2098 		 */
   2099 		while ((child != NULL) && !term) {
   2100 			(void) strcpy(cp, child->name);
   2101 			archtype = putfile(buf, cp, newparent, NULL,
   2102 			    NORMAL_FILE, lev + 1, symlink_lev);
   2103 
   2104 			if (!exitflag) {
   2105 				if ((atflag || saflag) &&
   2106 				    (archtype == PUT_NOTAS_LINK)) {
   2107 					xattrs_put(buf, cp, newparent, NULL);
   2108 				}
   2109 			}
   2110 			if (exitflag)
   2111 				break;
   2112 
   2113 			/* Free each child as we are done processing it. */
   2114 			cptr = child;
   2115 			child = child->next;
   2116 			free(cptr->name);
   2117 			free(cptr);
   2118 		}
   2119 		if ((child != NULL) && !term) {
   2120 			free_children(child);
   2121 		}
   2122 
   2123 		if (chdir(parent) < 0) {
   2124 			vperror(0, gettext("cannot change back?: %s"), parent);
   2125 		}
   2126 
   2127 		break;
   2128 
   2129 	case S_IFLNK:
   2130 		readlink_max = NAMSIZ;
   2131 		if (stbuf.st_size > NAMSIZ) {
   2132 			if (Eflag > 0) {
   2133 				xhdr_flgs |= _X_LINKPATH;
   2134 				readlink_max = PATH_MAX;
   2135 			} else {
   2136 				(void) fprintf(stderr, gettext(
   2137 				    "tar: %s: symbolic link too long\n"),
   2138 				    longname);
   2139 				if (errflag)
   2140 					exitflag = 1;
   2141 				Errflg = 1;
   2142 				goto out;
   2143 			}
   2144 		}
   2145 		/*
   2146 		 * Sym-links need header size of zero since you
   2147 		 * don't store any data for this type.
   2148 		 */
   2149 		stbuf.st_size = (off_t)0;
   2150 		tomodes(&stbuf);
   2151 		i = readlink(shortname, filetmp, readlink_max);
   2152 		if (i < 0) {
   2153 			vperror(0, gettext(
   2154 			    "can't read symbolic link %s"), longname);
   2155 			goto out;
   2156 		} else {
   2157 			filetmp[i] = 0;
   2158 		}
   2159 		if (vflag)
   2160 			(void) fprintf(vfile, gettext(
   2161 			    "a %s symbolic link to %s\n"),
   2162 			    longname, filetmp);
   2163 		if (xhdr_flgs & _X_LINKPATH) {
   2164 			Xtarhdr.x_linkpath = filetmp;
   2165 			if (build_dblock(name, tchar, '2', filetype, &stbuf,
   2166 			    stbuf.st_dev, prefix) != 0)
   2167 				goto out;
   2168 		} else
   2169 			if (build_dblock(name, filetmp, '2', filetype, &stbuf,
   2170 			    stbuf.st_dev, prefix) != 0)
   2171 				goto out;
   2172 		(void) writetbuf((char *)&dblock, 1);
   2173 		/*
   2174 		 * No acls for symlinks: mode is always 777
   2175 		 * dont call write ancillary
   2176 		 */
   2177 		rc = PUT_AS_LINK;
   2178 		break;
   2179 	case S_IFREG:
   2180 		if ((infile = openat(dirfd, shortname, 0)) < 0) {
   2181 			vperror(0, "unable to open %s%s%s%s", longname,
   2182 			    rw_sysattr ? gettext(" system") : "",
   2183 			    (filetype == XATTR_FILE) ?
   2184 			    gettext(" attribute ") : "",
   2185 			    (filetype == XATTR_FILE) ? (longattrname == NULL) ?
   2186 			    shortname : longattrname : "");
   2187 			goto out;
   2188 		}
   2189 
   2190 		blocks = TBLOCKS(stbuf.st_size);
   2191 
   2192 		if (put_link(name, longname, shortname, longattrname,
   2193 		    prefix, filetype, '1') == 0) {
   2194 			(void) close(infile);
   2195 			rc = PUT_AS_LINK;
   2196 			goto out;
   2197 		}
   2198 
   2199 		tomodes(&stbuf);
   2200 
   2201 		/* correctly handle end of volume */
   2202 		while (mulvol && tapepos + blocks + 1 > blocklim) {
   2203 			/* file won't fit */
   2204 			if (eflag) {
   2205 				if (blocks <= blocklim) {
   2206 					newvol();
   2207 					break;
   2208 				}
   2209 				(void) fprintf(stderr, gettext(
   2210 				    "tar: Single file cannot fit on volume\n"));
   2211 				done(3);
   2212 			}
   2213 			/* split if floppy has some room and file is large */
   2214 			if (((blocklim - tapepos) >= EXTMIN) &&
   2215 			    ((blocks + 1) >= blocklim/10)) {
   2216 				splitfile(longname, infile,
   2217 				    name, prefix, filetype);
   2218 				(void) close(dirfd);
   2219 				(void) close(infile);
   2220 				goto out;
   2221 			}
   2222 			newvol();	/* not worth it--just get new volume */
   2223 		}
   2224 #ifdef DEBUG
   2225 		DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,
   2226 		    blocks);
   2227 #endif
   2228 		if (build_dblock(name, tchar, '0', filetype,
   2229 		    &stbuf, stbuf.st_dev, prefix) != 0) {
   2230 			goto out;
   2231 		}
   2232 		if (vflag) {
   2233 #ifdef DEBUG
   2234 			if (NotTape)
   2235 				DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
   2236 				    0);
   2237 #endif
   2238 			(void) fprintf(vfile, "a %s%s%s%s ", longname,
   2239 			    rw_sysattr ? gettext(" system") : "",
   2240 			    (filetype == XATTR_FILE) ? gettext(
   2241 			    " attribute ") : "",
   2242 			    (filetype == XATTR_FILE) ?
   2243 			    longattrname : "");
   2244 			if (NotTape)
   2245 				(void) fprintf(vfile, "%" FMT_blkcnt_t "K\n",
   2246 				    K(blocks));
   2247 			else
   2248 				(void) fprintf(vfile,
   2249 				    gettext("%" FMT_blkcnt_t " tape blocks\n"),
   2250 				    blocks);
   2251 		}
   2252 
   2253 		if (put_extra_attributes(longname, shortname, longattrname,
   2254 		    prefix, filetype, '0') != 0)
   2255 			goto out;
   2256 
   2257 		/*
   2258 		 * No need to reset typeflag for extended attribute here, since
   2259 		 * put_extra_attributes already set it and we haven't called
   2260 		 * build_dblock().
   2261 		 */
   2262 		(void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock));
   2263 		hint = writetbuf((char *)&dblock, 1);
   2264 		maxread = max(min(stbuf.st_blksize, stbuf.st_size),
   2265 		    (nblock * TBLOCK));
   2266 		if ((bigbuf = calloc((unsigned)maxread, sizeof (char))) == 0) {
   2267 			maxread = TBLOCK;
   2268 			bigbuf = buf;
   2269 		}
   2270 
   2271 		while (((i = (int)
   2272 		    read(infile, bigbuf, min((hint*TBLOCK), maxread))) > 0) &&
   2273 		    blocks) {
   2274 			blkcnt_t nblks;
   2275 
   2276 			nblks = ((i-1)/TBLOCK)+1;
   2277 			if (nblks > blocks)
   2278 				nblks = blocks;
   2279 			hint = writetbuf(bigbuf, nblks);
   2280 			blocks -= nblks;
   2281 		}
   2282 		(void) close(infile);
   2283 		if (bigbuf != buf)
   2284 			free(bigbuf);
   2285 		if (i < 0)
   2286 			vperror(0, gettext("Read error on %s"), longname);
   2287 		else if (blocks != 0 || i != 0) {
   2288 			(void) fprintf(stderr, gettext(
   2289 			"tar: %s: file changed size\n"), longname);
   2290 			if (errflag) {
   2291 				exitflag = 1;
   2292 				Errflg = 1;
   2293 			} else if (!Dflag) {
   2294 				Errflg = 1;
   2295 			}
   2296 		}
   2297 		putempty(blocks);
   2298 		break;
   2299 	case S_IFIFO:
   2300 		blocks = TBLOCKS(stbuf.st_size);
   2301 		stbuf.st_size = (off_t)0;
   2302 
   2303 		if (put_link(name, longname, shortname, longattrname,
   2304 		    prefix, filetype, '6') == 0) {
   2305 			rc = PUT_AS_LINK;
   2306 			goto out;
   2307 		}
   2308 		tomodes(&stbuf);
   2309 
   2310 		while (mulvol && tapepos + blocks + 1 > blocklim) {
   2311 			if (eflag) {
   2312 				if (blocks <= blocklim) {
   2313 					newvol();
   2314 					break;
   2315 				}
   2316 				(void) fprintf(stderr, gettext(
   2317 				    "tar: Single file cannot fit on volume\n"));
   2318 				done(3);
   2319 			}
   2320 
   2321 			if (((blocklim - tapepos) >= EXTMIN) &&
   2322 			    ((blocks + 1) >= blocklim/10)) {
   2323 				splitfile(longname, infile, name,
   2324 				    prefix, filetype);
   2325 				(void) close(dirfd);
   2326 				(void) close(infile);
   2327 				goto out;
   2328 			}
   2329 			newvol();
   2330 		}
   2331 #ifdef DEBUG
   2332 		DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,
   2333 		    blocks);
   2334 #endif
   2335 		if (vflag) {
   2336 #ifdef DEBUG
   2337 			if (NotTape)
   2338 				DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
   2339 				    0);
   2340 #endif
   2341 			if (NotTape)
   2342 				(void) fprintf(vfile, gettext("a %s %"
   2343 				    FMT_blkcnt_t "K\n "), longname, K(blocks));
   2344 			else
   2345 				(void) fprintf(vfile, gettext(
   2346 				    "a %s %" FMT_blkcnt_t " tape blocks\n"),
   2347 				    longname, blocks);
   2348 		}
   2349 		if (build_dblock(name, tchar, '6', filetype,
   2350 		    &stbuf, stbuf.st_dev, prefix) != 0)
   2351 			goto out;
   2352 
   2353 		if (put_extra_attributes(longname, shortname, longattrname,
   2354 		    prefix, filetype, '6') != 0)
   2355 			goto out;
   2356 
   2357 		(void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock));
   2358 		dblock.dbuf.typeflag = '6';
   2359 
   2360 		(void) writetbuf((char *)&dblock, 1);
   2361 		break;
   2362 	case S_IFCHR:
   2363 		stbuf.st_size = (off_t)0;
   2364 		blocks = TBLOCKS(stbuf.st_size);
   2365 		if (put_link(name, longname, shortname, longattrname,
   2366 		    prefix, filetype, '3') == 0) {
   2367 			rc = PUT_AS_LINK;
   2368 			goto out;
   2369 		}
   2370 		tomodes(&stbuf);
   2371 
   2372 		while (mulvol && tapepos + blocks + 1 > blocklim) {
   2373 			if (eflag) {
   2374 				if (blocks <= blocklim) {
   2375 					newvol();
   2376 					break;
   2377 				}
   2378 				(void) fprintf(stderr, gettext(
   2379 				    "tar: Single file cannot fit on volume\n"));
   2380 				done(3);
   2381 			}
   2382 
   2383 			if (((blocklim - tapepos) >= EXTMIN) &&
   2384 			    ((blocks + 1) >= blocklim/10)) {
   2385 				splitfile(longname, infile, name,
   2386 				    prefix, filetype);
   2387 				(void) close(dirfd);
   2388 				goto out;
   2389 			}
   2390 			newvol();
   2391 		}
   2392 #ifdef DEBUG
   2393 		DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,
   2394 		    blocks);
   2395 #endif
   2396 		if (vflag) {
   2397 #ifdef DEBUG
   2398 			if (NotTape)
   2399 				DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
   2400 				    0);
   2401 #endif
   2402 			if (NotTape)
   2403 				(void) fprintf(vfile, gettext("a %s %"
   2404 				    FMT_blkcnt_t "K\n"), longname, K(blocks));
   2405 			else
   2406 				(void) fprintf(vfile, gettext("a %s %"
   2407 				    FMT_blkcnt_t " tape blocks\n"), longname,
   2408 				    blocks);
   2409 		}
   2410 		if (build_dblock(name, tchar, '3',
   2411 		    filetype, &stbuf, stbuf.st_rdev, prefix) != 0)
   2412 			goto out;
   2413 
   2414 		if (put_extra_attributes(longname, shortname, longattrname,
   2415 		    prefix, filetype, '3') != 0)
   2416 			goto out;
   2417 
   2418 		(void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock));
   2419 		dblock.dbuf.typeflag = '3';
   2420 
   2421 		(void) writetbuf((char *)&dblock, 1);
   2422 		break;
   2423 	case S_IFBLK:
   2424 		stbuf.st_size = (off_t)0;
   2425 		blocks = TBLOCKS(stbuf.st_size);
   2426 		if (put_link(name, longname, shortname, longattrname,
   2427 		    prefix, filetype, '4') == 0) {
   2428 			rc = PUT_AS_LINK;
   2429 			goto out;
   2430 		}
   2431 		tomodes(&stbuf);
   2432 
   2433 		while (mulvol && tapepos + blocks + 1 > blocklim) {
   2434 			if (eflag) {
   2435 				if (blocks <= blocklim) {
   2436 					newvol();
   2437 					break;
   2438 				}
   2439 				(void) fprintf(stderr, gettext(
   2440 				    "tar: Single file cannot fit on volume\n"));
   2441 				done(3);
   2442 			}
   2443 
   2444 			if (((blocklim - tapepos) >= EXTMIN) &&
   2445 			    ((blocks + 1) >= blocklim/10)) {
   2446 				splitfile(longname, infile,
   2447 				    name, prefix, filetype);
   2448 				(void) close(dirfd);
   2449 				goto out;
   2450 			}
   2451 			newvol();
   2452 		}
   2453 #ifdef DEBUG
   2454 		DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,
   2455 		    blocks);
   2456 #endif
   2457 		if (vflag) {
   2458 #ifdef DEBUG
   2459 			if (NotTape)
   2460 				DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
   2461 				    0);
   2462 #endif
   2463 			(void) fprintf(vfile, "a %s ", longname);
   2464 			if (NotTape)
   2465 				(void) fprintf(vfile, "%" FMT_blkcnt_t "K\n",
   2466 				    K(blocks));
   2467 			else
   2468 				(void) fprintf(vfile, gettext("%"
   2469 				    FMT_blkcnt_t " tape blocks\n"), blocks);
   2470 		}
   2471 		if (build_dblock(name, tchar, '4',
   2472 		    filetype, &stbuf, stbuf.st_rdev, prefix) != 0)
   2473 			goto out;
   2474 
   2475 		if (put_extra_attributes(longname, shortname, longattrname,
   2476 		    prefix, filetype, '4') != 0)
   2477 			goto out;
   2478 
   2479 		(void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock));
   2480 		dblock.dbuf.typeflag = '4';
   2481 
   2482 		(void) writetbuf((char *)&dblock, 1);
   2483 		break;
   2484 	default:
   2485 		(void) fprintf(stderr, gettext(
   2486 		    "tar: %s is not a file. Not dumped\n"), longname);
   2487 		if (errflag)
   2488 			exitflag = 1;
   2489 		Errflg = 1;
   2490 		goto out;
   2491 	}
   2492 
   2493 out:
   2494 	if ((dirfd != -1) && (filetype != XATTR_FILE)) {
   2495 		(void) close(dirfd);
   2496 	}
   2497 	return (rc);
   2498 }
   2499 
   2500 
   2501 /*
   2502  *	splitfile	dump a large file across volumes
   2503  *
   2504  *	splitfile(longname, fd);
   2505  *		char *longname;		full name of file
   2506  *		int ifd;		input file descriptor
   2507  *
   2508  *	NOTE:  only called by putfile() to dump a large file.
   2509  */
   2510 
   2511 static void
   2512 splitfile(char *longname, int ifd, char *name, char *prefix, int filetype)
   2513 {
   2514 	blkcnt_t blocks;
   2515 	off_t bytes, s;
   2516 	char buf[TBLOCK];
   2517 	int i, extents;
   2518 
   2519 	blocks = TBLOCKS(stbuf.st_size);	/* blocks file needs */
   2520 
   2521 	/*
   2522 	 * # extents =
   2523 	 *	size of file after using up rest of this floppy
   2524 	 *		blocks - (blocklim - tapepos) + 1	(for header)
   2525 	 *	plus roundup value before divide by blocklim-1
   2526 	 *		+ (blocklim - 1) - 1
   2527 	 *	all divided by blocklim-1 (one block for each header).
   2528 	 * this gives
   2529 	 *	(blocks - blocklim + tapepos + 1 + blocklim - 2)/(blocklim-1)
   2530 	 * which reduces to the expression used.
   2531 	 * one is added to account for this first extent.
   2532 	 *
   2533 	 * When one is dealing with extremely large archives, one may want
   2534 	 * to allow for a large number of extents.  This code should be
   2535 	 * revisited to determine if extents should be changed to something
   2536 	 * larger than an int.
   2537 	 */
   2538 	extents = (int)((blocks + tapepos - 1ULL)/(blocklim - 1ULL) + 1);
   2539 
   2540 	if (extents < 2 || extents > MAXEXT) {	/* let's be reasonable */
   2541 		(void) fprintf(stderr, gettext(
   2542 		    "tar: %s needs unusual number of volumes to split\n"
   2543 		    "tar: %s not dumped\n"), longname, longname);
   2544 		return;
   2545 	}
   2546 	if (build_dblock(name, tchar, '0', filetype,
   2547 	    &stbuf, stbuf.st_dev, prefix) != 0)
   2548 		return;
   2549 
   2550 	dblock.dbuf.extotal = extents;
   2551 	bytes = stbuf.st_size;
   2552 
   2553 	/*
   2554 	 * The value contained in dblock.dbuf.efsize was formerly used when the
   2555 	 * v flag was specified in conjunction with the t flag. Although it is
   2556 	 * no longer used, older versions of tar will expect the former
   2557 	 * behaviour, so we must continue to write it to the archive.
   2558 	 *
   2559 	 * Since dblock.dbuf.efsize is 10 chars in size, the maximum value it
   2560 	 * can store is TAR_EFSIZE_MAX. If bytes exceeds that value, simply
   2561 	 * store 0.
   2562 	 */
   2563 	if (bytes <= TAR_EFSIZE_MAX)
   2564 		(void) sprintf(dblock.dbuf.efsize, "%9" FMT_off_t_o, bytes);
   2565 	else
   2566 		(void) sprintf(dblock.dbuf.efsize, "%9" FMT_off_t_o, (off_t)0);
   2567 
   2568 	(void) fprintf(stderr, gettext(
   2569 	    "tar: large file %s needs %d extents.\n"
   2570 	    "tar: current device seek position = %" FMT_blkcnt_t "K\n"),
   2571 	    longname, extents, K(tapepos));
   2572 
   2573 	s = (off_t)(blocklim - tapepos - 1) * TBLOCK;
   2574 	for (i = 1; i <= extents; i++) {
   2575 		if (i > 1) {
   2576 			newvol();
   2577 			if (i == extents)
   2578 				s = bytes;	/* last ext. gets true bytes */
   2579 			else
   2580 				s = (off_t)(blocklim - 1)*TBLOCK; /* all */
   2581 		}
   2582 		bytes -= s;
   2583 		blocks = TBLOCKS(s);
   2584 
   2585 		(void) sprintf(dblock.dbuf.size, "%011" FMT_off_t_o, s);
   2586 		dblock.dbuf.extno = i;
   2587 		(void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock));
   2588 		(void) writetbuf((char *)&dblock, 1);
   2589 
   2590 		if (vflag)
   2591 			(void) fprintf(vfile,
   2592 			    "+++ a %s %" FMT_blkcnt_t "K [extent #%d of %d]\n",
   2593 			    longname, K(blocks), i, extents);
   2594 		while (blocks && read(ifd, buf, TBLOCK) > 0) {
   2595 			blocks--;
   2596 			(void) writetbuf(buf, 1);
   2597 		}
   2598 		if (blocks != 0) {
   2599 			(void) fprintf(stderr, gettext(
   2600 			    "tar: %s: file changed size\n"), longname);
   2601 			(void) fprintf(stderr, gettext(
   2602 			    "tar: aborting split file %s\n"), longname);
   2603 			(void) close(ifd);
   2604 			return;
   2605 		}
   2606 	}
   2607 	(void) close(ifd);
   2608 	if (vflag)
   2609 		(void) fprintf(vfile, gettext("a %s %" FMT_off_t "K (in %d "
   2610 		    "extents)\n"), longname, K(TBLOCKS(stbuf.st_size)),
   2611 		    extents);
   2612 }
   2613 
   2614 /*
   2615  *	convtoreg - determines whether the file should be converted to a
   2616  *	            regular file when extracted
   2617  *
   2618  *	Returns 1 when file size > 0 and typeflag is not recognized
   2619  * 	Otherwise returns 0
   2620  */
   2621 static int
   2622 convtoreg(off_t size)
   2623 {
   2624 	if ((size > 0) && (dblock.dbuf.typeflag != '0') &&
   2625 	    (dblock.dbuf.typeflag != NULL) && (dblock.dbuf.typeflag != '1') &&
   2626 	    (dblock.dbuf.typeflag != '2') && (dblock.dbuf.typeflag != '3') &&
   2627 	    (dblock.dbuf.typeflag != '4') && (dblock.dbuf.typeflag != '5') &&
   2628 	    (dblock.dbuf.typeflag != '6') && (dblock.dbuf.typeflag != 'A') &&
   2629 	    (dblock.dbuf.typeflag != _XATTR_HDRTYPE) &&
   2630 	    (dblock.dbuf.typeflag != 'X')) {
   2631 		return (1);
   2632 	}
   2633 	return (0);
   2634 }
   2635 
   2636 #if defined(O_XATTR)
   2637 static int
   2638 save_cwd(void)
   2639 {
   2640 	return (open(".", O_RDONLY));
   2641 }
   2642 #endif
   2643 
   2644 #if defined(O_XATTR)
   2645 static void
   2646 rest_cwd(int *cwd)
   2647 {
   2648 	if (*cwd != -1) {
   2649 		if (fchdir(*cwd) < 0) {
   2650 			vperror(0, gettext(
   2651 			    "Cannot fchdir to attribute directory"));
   2652 			exit(1);
   2653 		}
   2654 		(void) close(*cwd);
   2655 		*cwd = -1;
   2656 	}
   2657 }
   2658 #endif
   2659 
   2660 /*
   2661  * Verify the underlying file system supports the attribute type.
   2662  * Only archive extended attribute files when '-@' was specified.
   2663  * Only archive system extended attribute files if '-/' was specified.
   2664  */
   2665 #if defined(O_XATTR)
   2666 static attr_status_t
   2667 verify_attr_support(char *filename, int attrflg, arc_action_t actflag,
   2668     int *ext_attrflg)
   2669 {
   2670 	/*
   2671 	 * Verify extended attributes are supported/exist.  We only
   2672 	 * need to check if we are processing a base file, not an
   2673 	 * extended attribute.
   2674 	 */
   2675 	if (attrflg) {
   2676 		*ext_attrflg = (pathconf(filename, (actflag == ARC_CREATE) ?
   2677 		    _PC_XATTR_EXISTS : _PC_XATTR_ENABLED) == 1);
   2678 	}
   2679 
   2680 	if (atflag) {
   2681 		if (!*ext_attrflg) {
   2682 #if defined(_PC_SATTR_ENABLED)
   2683 			if (saflag) {
   2684 				/* Verify system attributes are supported */
   2685 				if (sysattr_support(filename,
   2686 				    (actflag == ARC_CREATE) ? _PC_SATTR_EXISTS :
   2687 				    _PC_SATTR_ENABLED) != 1) {
   2688 					return (ATTR_SATTR_ERR);
   2689 				}
   2690 			} else
   2691 				return (ATTR_XATTR_ERR);
   2692 #else
   2693 				return (ATTR_XATTR_ERR);
   2694 #endif	/* _PC_SATTR_ENABLED */
   2695 		}
   2696 
   2697 #if defined(_PC_SATTR_ENABLED)
   2698 	} else if (saflag) {
   2699 		/* Verify system attributes are supported */
   2700 		if (sysattr_support(filename, (actflag == ARC_CREATE) ?
   2701 		    _PC_SATTR_EXISTS : _PC_SATTR_ENABLED) != 1) {
   2702 			return (ATTR_SATTR_ERR);
   2703 		}
   2704 #endif	/* _PC_SATTR_ENABLED */
   2705 	} else {
   2706 		return (ATTR_SKIP);
   2707 	}
   2708 
   2709 	return (ATTR_OK);
   2710 }
   2711 #endif
   2712 
   2713 #if defined(O_XATTR)
   2714 /*
   2715  * Recursively open attribute directories until the attribute directory
   2716  * containing the specified attribute, attrname, is opened.
   2717  *
   2718  * Currently, only 2 directory levels of attributes are supported, (i.e.,
   2719  * extended system attributes on extended attributes).  The following are
   2720  * the possible input combinations:
   2721  *	1.  Open the attribute directory of the base file (don't change
   2722  *	    into it).
   2723  *		attrinfo->parent = NULL
   2724  *		attrname = '.'
   2725  *	2.  Open the attribute directory of the base file and change into it.
   2726  *		attrinfo->parent = NULL
   2727  *		attrname = <attr> | <sys_attr>
   2728  *	3.  Open the attribute directory of the base file, change into it,
   2729  *	    then recursively call open_attr_dir() to open the attribute's
   2730  *	    parent directory (don't change into it).
   2731  *		attrinfo->parent = <attr>
   2732  *		attrname = '.'
   2733  *	4.  Open the attribute directory of the base file, change into it,
   2734  *	    then recursively call open_attr_dir() to open the attribute's
   2735  *	    parent directory and change into it.
   2736  *		attrinfo->parent = <attr>
   2737  *		attrname = <attr> | <sys_attr>
   2738  *
   2739  * An attribute directory will be opened only if the underlying file system
   2740  * supports the attribute type, and if the command line specifications (atflag
   2741  * and saflag) enable the processing of the attribute type.
   2742  *
   2743  * On succesful return, attrinfo->parentfd will be the file descriptor of the
   2744  * opened attribute directory.  In addition, if the attribute is a read-write
   2745  * extended system attribute, attrinfo->rw_sysattr will be set to 1, otherwise
   2746  * it will be set to 0.
   2747  *
   2748  * Possible return values:
   2749  * 	ATTR_OK		Successfully opened and, if needed, changed into the
   2750  *			attribute directory containing attrname.
   2751  *	ATTR_SKIP	The command line specifications don't enable the
   2752  *			processing of the attribute type.
   2753  * 	ATTR_CHDIR_ERR	An error occurred while trying to change into an
   2754  *			attribute directory.
   2755  * 	ATTR_OPEN_ERR	An error occurred while trying to open an
   2756  *			attribute directory.
   2757  *	ATTR_XATTR_ERR	The underlying file system doesn't support extended
   2758  *			attributes.
   2759  *	ATTR_SATTR_ERR	The underlying file system doesn't support extended
   2760  *			system attributes.
   2761  */
   2762 static int
   2763 open_attr_dir(char *attrname, char *dirp, int cwd, attr_data_t *attrinfo)
   2764 {
   2765 	attr_status_t	rc;
   2766 	int		firsttime = (attrinfo->attr_parentfd == -1);
   2767 	int		saveerrno;
   2768 	int		ext_attr;
   2769 
   2770 	/*
   2771 	 * open_attr_dir() was recursively called (input combination number 4),
   2772 	 * close the previously opened file descriptor as we've already changed
   2773 	 * into it.
   2774 	 */
   2775 	if (!firsttime) {
   2776 		(void) close(attrinfo->attr_parentfd);
   2777 		attrinfo->attr_parentfd = -1;
   2778 	}
   2779 
   2780 	/*
   2781 	 * Verify that the underlying file system supports the restoration
   2782 	 * of the attribute.
   2783 	 */
   2784 	if ((rc = verify_attr_support(dirp, firsttime, ARC_RESTORE,
   2785 	    &ext_attr)) != ATTR_OK) {
   2786 		return (rc);
   2787 	}
   2788 
   2789 	/* Open the base file's attribute directory */
   2790 	if ((attrinfo->attr_parentfd = attropen(dirp, ".", O_RDONLY)) == -1) {
   2791 		/*
   2792 		 * Save the errno from the attropen so it can be reported
   2793 		 * if the retry of the attropen fails.
   2794 		 */
   2795 		saveerrno = errno;
   2796 		if ((attrinfo->attr_parentfd = retry_open_attr(-1, cwd, dirp,
   2797 		    NULL, ".", O_RDONLY, 0)) == -1) {
   2798 			/*
   2799 			 * Reset typeflag back to real value so passtape
   2800 			 * will skip ahead correctly.
   2801 			 */
   2802 			dblock.dbuf.typeflag = _XATTR_HDRTYPE;
   2803 			(void) close(attrinfo->attr_parentfd);
   2804 			attrinfo->attr_parentfd = -1;
   2805 			errno = saveerrno;
   2806 			return (ATTR_OPEN_ERR);
   2807 		}
   2808 	}
   2809 
   2810 	/*
   2811 	 * Change into the parent attribute's directory unless we are
   2812 	 * processing the hidden attribute directory of the base file itself.
   2813 	 */
   2814 	if ((Hiddendir == 0) || (firsttime && attrinfo->attr_parent != NULL)) {
   2815 		if (fchdir(attrinfo->attr_parentfd) != 0) {
   2816 			saveerrno = errno;
   2817 			(void) close(attrinfo->attr_parentfd);
   2818 			attrinfo->attr_parentfd = -1;
   2819 			errno = saveerrno;
   2820 			return (ATTR_CHDIR_ERR);
   2821 		}
   2822 	}
   2823 
   2824 	/* Determine if the attribute should be processed */
   2825 	if ((rc = verify_attr(attrname, attrinfo->attr_parent, 1,
   2826 	    &attrinfo->attr_rw_sysattr)) != ATTR_OK) {
   2827 		saveerrno = errno;
   2828 		(void) close(attrinfo->attr_parentfd);
   2829 		attrinfo->attr_parentfd = -1;
   2830 		errno = saveerrno;
   2831 		return (rc);
   2832 	}
   2833 
   2834 	/*
   2835 	 * If the attribute is an extended attribute, or extended system
   2836 	 * attribute, of an attribute (i.e., <attr>/<sys_attr>), then
   2837 	 * recursively call open_attr_dir() to open the attribute directory
   2838 	 * of the parent attribute.
   2839 	 */
   2840 	if (firsttime && (attrinfo->attr_parent != NULL)) {
   2841 		return (open_attr_dir(attrname, attrinfo->attr_parent,
   2842 		    attrinfo->attr_parentfd, attrinfo));
   2843 	}
   2844 
   2845 	return (ATTR_OK);
   2846 }
   2847 #endif
   2848 
   2849 static void
   2850 #ifdef	_iBCS2
   2851 doxtract(char *argv[], int tbl_cnt)
   2852 #else
   2853 doxtract(char *argv[])
   2854 #endif
   2855 {
   2856 	struct	stat	xtractbuf;	/* stat on file after extracting */
   2857 	blkcnt_t blocks;
   2858 	off_t bytes;
   2859 	int ofile;
   2860 	int newfile;			/* Does the file already exist  */
   2861 	int xcnt = 0;			/* count # files extracted */
   2862 	int fcnt = 0;			/* count # files in argv list */
   2863 	int dir;
   2864 	int dirfd = -1;
   2865 	int cwd = -1;
   2866 	int rw_sysattr;
   2867 	int saveerrno;
   2868 	uid_t Uid;
   2869 	char *namep, *dirp, *comp, *linkp; /* for removing absolute paths */
   2870 	char dirname[PATH_MAX+1];
   2871 	char templink[PATH_MAX+1];	/* temp link with terminating NULL */
   2872 	int once = 1;
   2873 	int error;
   2874 	int symflag;
   2875 	int want;
   2876 	attr_data_t *attrinfo = NULL;	/* attribute info */
   2877 	acl_t	*aclp = NULL;	/* acl info */
   2878 	char dot[] = ".";		/* dirp for using realpath */
   2879 	timestruc_t	time_zero;	/* used for call to doDirTimes */
   2880 	int		dircreate;
   2881 	int convflag;
   2882 	time_zero.tv_sec = 0;
   2883 	time_zero.tv_nsec = 0;
   2884 
   2885 	/* reset Trusted Extensions variables */
   2886 	rpath_flag = 0;
   2887 	lk_rpath_flag = 0;
   2888 	dir_flag = 0;
   2889 	mld_flag = 0;
   2890 	bslundef(&bs_label);
   2891 	bsllow(&admin_low);
   2892 	bslhigh(&admin_high);
   2893 	orig_namep = 0;
   2894 
   2895 	dumping = 0;	/* for newvol(), et al:  we are not writing */
   2896 
   2897 	/*
   2898 	 * Count the number of files that are to be extracted
   2899 	 */
   2900 	Uid = getuid();
   2901 
   2902 #ifdef	_iBCS2
   2903 	initarg(argv, Filefile);
   2904 	while (nextarg() != NULL)
   2905 		++fcnt;
   2906 	fcnt += tbl_cnt;
   2907 #endif	/*  _iBCS2 */
   2908 
   2909 	for (;;) {
   2910 		convflag = 0;
   2911 		symflag = 0;
   2912 		dir = 0;
   2913 		Hiddendir = 0;
   2914 		rw_sysattr = 0;
   2915 		ofile = -1;
   2916 
   2917 		if (dirfd != -1) {
   2918 			(void) close(dirfd);
   2919 			dirfd = -1;
   2920 		}
   2921 		if (ofile != -1) {
   2922 			if (close(ofile) != 0)
   2923 				vperror(2, gettext("close error"));
   2924 		}
   2925 
   2926 #if defined(O_XATTR)
   2927 		if (cwd != -1) {
   2928 			rest_cwd(&cwd);
   2929 		}
   2930 #endif
   2931 
   2932 		/* namep is set by wantit to point to the full name */
   2933 		if ((want = wantit(argv, &namep, &dirp, &comp,
   2934 		    &attrinfo)) == 0) {
   2935 #if defined(O_XATTR)
   2936 			if (xattrp != NULL) {
   2937 				free(xattrhead);
   2938 				xattrp = NULL;
   2939 				xattr_linkp = NULL;
   2940 				xattrhead = NULL;
   2941 			}
   2942 #endif
   2943 			continue;
   2944 		}
   2945 		if (want == -1)
   2946 			break;
   2947 
   2948 /* Trusted Extensions */
   2949 		/*
   2950 		 * During tar extract (x):
   2951 		 * If the pathname of the restored file has been
   2952 		 * reconstructed from the ancillary file,
   2953 		 * use it to process the normal file.
   2954 		 */
   2955 		if (mld_flag) {		/* Skip over .MLD. directory */
   2956 			mld_flag = 0;
   2957 			passtape();
   2958 			continue;
   2959 		}
   2960 		orig_namep = namep;	/* save original */
   2961 		if (rpath_flag) {
   2962 			namep = real_path;	/* use zone path */
   2963 			comp = real_path;	/* use zone path */
   2964 			dirp = dot;		/* work from the top */
   2965 			rpath_flag = 0;		/* reset */
   2966 		}
   2967 
   2968 		if (dirfd != -1)
   2969 			(void) close(dirfd);
   2970 
   2971 		(void) strcpy(&dirname[0], namep);
   2972 		dircreate = checkdir(&dirname[0]);
   2973 
   2974 #if defined(O_XATTR)
   2975 		if (xattrp != NULL) {
   2976 			int	rc;
   2977 
   2978 			if (((cwd = save_cwd()) == -1) ||
   2979 			    ((rc = open_attr_dir(comp, dirp, cwd,
   2980 			    attrinfo)) != ATTR_OK)) {
   2981 				if (cwd == -1) {
   2982 					vperror(0, gettext(
   2983 					    "unable to save current working "
   2984 					    "directory while processing "
   2985 					    "attribute %s of %s"),
   2986 					    dirp, attrinfo->attr_path);
   2987 				} else if (rc != ATTR_SKIP) {
   2988 					(void) fprintf(vfile,
   2989 					    gettext("tar: cannot open "
   2990 					    "%sattribute %s of file %s: %s\n"),
   2991 					    attrinfo->attr_rw_sysattr ? gettext(
   2992 					    "system ") : "",
   2993 					    comp, dirp, strerror(errno));
   2994 				}
   2995 				free(xattrhead);
   2996 				xattrp = NULL;
   2997 				xattr_linkp = NULL;
   2998 				xattrhead = NULL;
   2999 
   3000 				passtape();
   3001 				continue;
   3002 			} else {
   3003 				dirfd = attrinfo->attr_parentfd;
   3004 				rw_sysattr = attrinfo->attr_rw_sysattr;
   3005 			}
   3006 		} else {
   3007 			dirfd = open(dirp, O_RDONLY);
   3008 		}
   3009 #else
   3010 		dirfd = open(dirp, O_RDONLY);
   3011 #endif
   3012 		if (dirfd == -1) {
   3013 			(void) fprintf(vfile, gettext(
   3014 			    "tar: cannot open %s: %s\n"),
   3015 			    dirp, strerror(errno));
   3016 			passtape();
   3017 			continue;
   3018 		}
   3019 
   3020 		if (xhdr_flgs & _X_LINKPATH)
   3021 			(void) strcpy(templink, Xtarhdr.x_linkpath);
   3022 		else {
   3023 #if defined(O_XATTR)
   3024 			if (xattrp && dblock.dbuf.typeflag == '1') {
   3025 				(void) sprintf(templink, "%.*s", NAMSIZ,
   3026 				    xattrp->h_names);
   3027 			} else {
   3028 				(void) sprintf(templink, "%.*s", NAMSIZ,
   3029 				    dblock.dbuf.linkname);
   3030 			}
   3031 #else
   3032 			(void) sprintf(templink, "%.*s", NAMSIZ,
   3033 			    dblock.dbuf.linkname);
   3034 #endif
   3035 		}
   3036 
   3037 		if (Fflag) {
   3038 			char *s;
   3039 
   3040 			if ((s = strrchr(namep, '/')) == 0)
   3041 				s = namep;
   3042 
   3043 			else
   3044 				s++;
   3045 			if (checkf(s, stbuf.st_mode, Fflag) == 0) {
   3046 				passtape();
   3047 				continue;
   3048 			}
   3049 		}
   3050 
   3051 		if (checkw('x', namep) == 0) {
   3052 			passtape();
   3053 			continue;
   3054 		}
   3055 		if (once) {
   3056 			if (strcmp(dblock.dbuf.magic, magic_type) == 0) {
   3057 				if (geteuid() == (uid_t)0) {
   3058 					checkflag = 1;
   3059 					pflag = 1;
   3060 				} else {
   3061 					/* get file creation mask */
   3062 					Oumask = umask(0);
   3063 					(void) umask(Oumask);
   3064 				}
   3065 				once = 0;
   3066 			} else {
   3067 				if (geteuid() == (uid_t)0) {
   3068 					pflag = 1;
   3069 					checkflag = 2;
   3070 				}
   3071 				if (!pflag) {
   3072 					/* get file creation mask */
   3073 					Oumask = umask(0);
   3074 					(void) umask(Oumask);
   3075 				}
   3076 				once = 0;
   3077 			}
   3078 		}
   3079 
   3080 #if defined(O_XATTR)
   3081 		/*
   3082 		 * Handle extraction of hidden attr dir.
   3083 		 * Dir is automatically created, we only
   3084 		 * need to update mode and perm's.
   3085 		 */
   3086 		if ((xattrp != NULL) && Hiddendir == 1) {
   3087 			bytes = stbuf.st_size;
   3088 			blocks = TBLOCKS(bytes);
   3089 			if (vflag) {
   3090 				(void) fprintf(vfile,
   3091 				    "x %s%s%s, %" FMT_off_t " bytes, ", namep,
   3092 				    gettext(" attribute "),
   3093 				    xattrapath, bytes);
   3094 				if (NotTape)
   3095 					(void) fprintf(vfile,
   3096 					    "%" FMT_blkcnt_t "K\n", K(blocks));
   3097 				else
   3098 					(void) fprintf(vfile, gettext("%"
   3099 					    FMT_blkcnt_t " tape blocks\n"),
   3100 					    blocks);
   3101 			}
   3102 
   3103 			/*
   3104 			 * Set the permissions and mode of the attribute
   3105 			 * unless the attribute is a system attribute (can't
   3106 			 * successfully do this) or the hidden attribute
   3107 			 * directory (".") of an attribute (when the attribute
   3108 			 * is restored, the hidden attribute directory of an
   3109 			 * attribute is transient).  Note:  when the permissions
   3110 			 * and mode are set for the hidden attribute directory
   3111 			 * of a file on a system supporting extended system
   3112 			 * attributes, even though it returns successfully, it
   3113 			 * will not have any affect since the attribute
   3114 			 * directory is transient.
   3115 			 */
   3116 			if (attrinfo->attr_parent == NULL) {
   3117 				if (fchownat(dirfd, ".", stbuf.st_uid,
   3118 				    stbuf.st_gid, 0) != 0) {
   3119 					vperror(0, gettext(
   3120 					    "%s%s%s: failed to set ownership "
   3121 					    "of attribute directory"), namep,
   3122 					    gettext(" attribute "), xattrapath);
   3123 				}
   3124 
   3125 				if (fchmod(dirfd, stbuf.st_mode) != 0) {
   3126 					vperror(0, gettext(
   3127 					    "%s%s%s: failed to set permissions "
   3128 					    "of attribute directory"), namep,
   3129 					    gettext(" attribute "), xattrapath);
   3130 				}
   3131 			}
   3132 			goto filedone;
   3133 		}
   3134 #endif
   3135 
   3136 		if (dircreate && (!is_posix || dblock.dbuf.typeflag == '5')) {
   3137 			dir = 1;
   3138 			if (vflag) {
   3139 				(void) fprintf(vfile, "x %s, 0 bytes, ",
   3140 				    &dirname[0]);
   3141 				if (NotTape)
   3142 					(void) fprintf(vfile, "0K\n");
   3143 				else
   3144 					(void) fprintf(vfile, gettext("%"
   3145 					    FMT_blkcnt_t " tape blocks\n"),
   3146 					    (blkcnt_t)0);
   3147 			}
   3148 			goto filedone;
   3149 		}
   3150 
   3151 		if (dblock.dbuf.typeflag == '6') {	/* FIFO */
   3152 			if (rmdir(namep) < 0) {
   3153 				if (errno == ENOTDIR)
   3154 					(void) unlink(namep);
   3155 			}
   3156 			linkp = templink;
   3157 			if (*linkp !=  NULL) {
   3158 				if (Aflag && *linkp == '/')
   3159 					linkp++;
   3160 				if (link(linkp, namep) < 0) {
   3161 					(void) fprintf(stderr, gettext(
   3162 					    "tar: %s: cannot link\n"), namep);
   3163 					continue;
   3164 				}
   3165 				if (vflag)
   3166 					(void) fprintf(vfile, gettext(
   3167 					    "x %s linked to %s\n"), namep,
   3168 					    linkp);
   3169 				xcnt++;	 /* increment # files extracted */
   3170 				continue;
   3171 			}
   3172 			if (mknod(namep, (int)(Gen.g_mode|S_IFIFO),
   3173 			    (int)Gen.g_devmajor) < 0) {
   3174 				vperror(0, gettext("%s: mknod failed"), namep);
   3175 				continue;
   3176 			}
   3177 			bytes = stbuf.st_size;
   3178 			blocks = TBLOCKS(bytes);
   3179 			if (vflag) {
   3180 				(void) fprintf(vfile, "x %s, %" FMT_off_t
   3181 				    " bytes, ", namep, bytes);
   3182 				if (NotTape)
   3183 					(void) fprintf(vfile, "%" FMT_blkcnt_t
   3184 					    "K\n", K(blocks));
   3185 				else
   3186 					(void) fprintf(vfile, gettext("%"
   3187 					    FMT_blkcnt_t " tape blocks\n"),
   3188 					    blocks);
   3189 			}
   3190 			goto filedone;
   3191 		}
   3192 		if (dblock.dbuf.typeflag == '3' && !Uid) { /* CHAR SPECIAL */
   3193 			if (rmdir(namep) < 0) {
   3194 				if (errno == ENOTDIR)
   3195 					(void) unlink(namep);
   3196 			}
   3197 			linkp = templink;
   3198 			if (*linkp != NULL) {
   3199 				if (Aflag && *linkp == '/')
   3200 					linkp++;
   3201 				if (link(linkp, namep) < 0) {
   3202 					(void) fprintf(stderr, gettext(
   3203 					    "tar: %s: cannot link\n"), namep);
   3204 					continue;
   3205 				}
   3206 				if (vflag)
   3207 					(void) fprintf(vfile, gettext(
   3208 					    "x %s linked to %s\n"), namep,
   3209 					    linkp);
   3210 				xcnt++;	 /* increment # files extracted */
   3211 				continue;
   3212 			}
   3213 			if (mknod(namep, (int)(Gen.g_mode|S_IFCHR),
   3214 			    (int)makedev(Gen.g_devmajor, Gen.g_devminor)) < 0) {
   3215 				vperror(0, gettext(
   3216 				    "%s: mknod failed"), namep);
   3217 				continue;
   3218 			}
   3219 			bytes = stbuf.st_size;
   3220 			blocks = TBLOCKS(bytes);
   3221 			if (vflag) {
   3222 				(void) fprintf(vfile, "x %s, %" FMT_off_t
   3223 				    " bytes, ", namep, bytes);
   3224 				if (NotTape)
   3225 					(void) fprintf(vfile, "%" FMT_blkcnt_t
   3226 					    "K\n", K(blocks));
   3227 				else
   3228 					(void) fprintf(vfile, gettext("%"
   3229 					    FMT_blkcnt_t " tape blocks\n"),
   3230 					    blocks);
   3231 			}
   3232 			goto filedone;
   3233 		} else if (dblock.dbuf.typeflag == '3' && Uid) {
   3234 			(void) fprintf(stderr, gettext(
   3235 			    "Can't create special %s\n"), namep);
   3236 			continue;
   3237 		}
   3238 
   3239 		/* BLOCK SPECIAL */
   3240 
   3241 		if (dblock.dbuf.typeflag == '4' && !Uid) {
   3242 			if (rmdir(namep) < 0) {
   3243 				if (errno == ENOTDIR)
   3244 					(void) unlink(namep);
   3245 			}
   3246 			linkp = templink;
   3247 			if (*linkp != NULL) {
   3248 				if (Aflag && *linkp == '/')
   3249 					linkp++;
   3250 				if (link(linkp, namep) < 0) {
   3251 					(void) fprintf(stderr, gettext(
   3252 					    "tar: %s: cannot link\n"), namep);
   3253 					continue;
   3254 				}
   3255 				if (vflag)
   3256 					(void) fprintf(vfile, gettext(
   3257 					    "x %s linked to %s\n"), namep,
   3258 					    linkp);
   3259 				xcnt++;	 /* increment # files extracted */
   3260 				continue;
   3261 			}
   3262 			if (mknod(namep, (int)(Gen.g_mode|S_IFBLK),
   3263 			    (int)makedev(Gen.g_devmajor, Gen.g_devminor)) < 0) {
   3264 				vperror(0, gettext("%s: mknod failed"), namep);
   3265 				continue;
   3266 			}
   3267 			bytes = stbuf.st_size;
   3268 			blocks = TBLOCKS(bytes);
   3269 			if (vflag) {
   3270 				(void) fprintf(vfile, gettext("x %s, %"
   3271 				    FMT_off_t " bytes, "), namep, bytes);
   3272 				if (NotTape)
   3273 					(void) fprintf(vfile, "%" FMT_blkcnt_t
   3274 					    "K\n", K(blocks));
   3275 				else
   3276 					(void) fprintf(vfile, gettext("%"
   3277 					    FMT_blkcnt_t " tape blocks\n"),
   3278 					    blocks);
   3279 			}
   3280 			goto filedone;
   3281 		} else if (dblock.dbuf.typeflag == '4' && Uid) {
   3282 			(void) fprintf(stderr,
   3283 			    gettext("Can't create special %s\n"), namep);
   3284 			continue;
   3285 		}
   3286 		if (dblock.dbuf.typeflag == '2') {	/* symlink */
   3287 			if ((Tflag) && (lk_rpath_flag == 1))
   3288 				linkp = lk_real_path;
   3289 			else
   3290 				linkp = templink;
   3291 			if (Aflag && *linkp == '/')
   3292 				linkp++;
   3293 			if (rmdir(namep) < 0) {
   3294 				if (errno == ENOTDIR)
   3295 					(void) unlink(namep);
   3296 			}
   3297 			if (symlink(linkp, namep) < 0) {
   3298 				vperror(0, gettext("%s: symbolic link failed"),
   3299 				    namep);
   3300 				continue;
   3301 			}
   3302 			if (vflag)
   3303 				(void) fprintf(vfile, gettext(
   3304 				    "x %s symbolic link to %s\n"),
   3305 				    namep, linkp);
   3306 
   3307 			symflag = AT_SYMLINK_NOFOLLOW;
   3308 			goto filedone;
   3309 		}
   3310 		if (dblock.dbuf.typeflag == '1') {
   3311 			linkp = templink;
   3312 			if (Aflag && *linkp == '/')
   3313 				linkp++;
   3314 			if (unlinkat(dirfd, comp, AT_REMOVEDIR) < 0) {
   3315 				if (errno == ENOTDIR)
   3316 					(void) unlinkat(dirfd, comp, 0);
   3317 			}
   3318 #if defined(O_XATTR)
   3319 			if (xattrp && xattr_linkp) {
   3320 				if (fchdir(dirfd) < 0) {
   3321 					vperror(0, gettext(
   3322 					    "Cannot fchdir to attribute "
   3323 					    "directory %s"),
   3324 					    (attrinfo->attr_parent == NULL) ?
   3325 					    dirp : attrinfo->attr_parent);
   3326 					exit(1);
   3327 				}
   3328 
   3329 				error = link(xattr_linkaname, xattrapath);
   3330 			} else {
   3331 				error = link(linkp, namep);
   3332 			}
   3333 #else
   3334 			error = link(linkp, namep);
   3335 #endif
   3336 
   3337 			if (error < 0) {
   3338 				(void) fprintf(stderr, gettext(
   3339 				    "tar: %s%s%s: cannot link\n"),
   3340 				    namep, (xattr_linkp != NULL) ?
   3341 				    gettext(" attribute ") : "",
   3342 				    (xattr_linkp != NULL) ?
   3343 				    xattrapath : "");
   3344 				continue;
   3345 			}
   3346 			if (vflag)
   3347 				(void) fprintf(vfile, gettext(
   3348 				    "x %s%s%s linked to %s%s%s\n"), namep,
   3349 				    (xattr_linkp != NULL) ?
   3350 				    gettext(" attribute ") : "",
   3351 				    (xattr_linkp != NULL) ?
   3352 				    xattr_linkaname : "",
   3353 				    linkp,
   3354 				    (xattr_linkp != NULL) ?
   3355 				    gettext(" attribute ") : "",
   3356 				    (xattr_linkp != NULL) ? xattrapath : "");
   3357 			xcnt++;		/* increment # files extracted */
   3358 #if defined(O_XATTR)
   3359 			if (xattrp != NULL) {
   3360 				free(xattrhead);
   3361 				xattrp = NULL;
   3362 				xattr_linkp = NULL;
   3363 				xattrhead = NULL;
   3364 			}
   3365 #endif
   3366 			continue;
   3367 		}
   3368 
   3369 		/* REGULAR FILES */
   3370 
   3371 		if (convtoreg(stbuf.st_size)) {
   3372 			convflag = 1;
   3373 			if (errflag) {
   3374 				(void) fprintf(stderr, gettext(
   3375 				    "tar: %s: typeflag '%c' not recognized\n"),
   3376 				    namep, dblock.dbuf.typeflag);
   3377 				done(1);
   3378 			} else {
   3379 				(void) fprintf(stderr, gettext(
   3380 				    "tar: %s: typeflag '%c' not recognized, "
   3381 				    "converting to regular file\n"), namep,
   3382 				    dblock.dbuf.typeflag);
   3383 				Errflg = 1;
   3384 			}
   3385 		}
   3386 		if (dblock.dbuf.typeflag == '0' ||
   3387 		    dblock.dbuf.typeflag == NULL || convflag) {
   3388 			delete_target(dirfd, comp, namep);
   3389 			linkp = templink;
   3390 			if (*linkp != NULL) {
   3391 				if (Aflag && *linkp == '/')
   3392 					linkp++;
   3393 				if (link(linkp, comp) < 0) {
   3394 					(void) fprintf(stderr, gettext(
   3395 					    "tar: %s: cannot link\n"), namep);
   3396 					continue;
   3397 				}
   3398 				if (vflag)
   3399 					(void) fprintf(vfile, gettext(
   3400 					    "x %s linked to %s\n"), comp,
   3401 					    linkp);
   3402 				xcnt++;	 /* increment # files extracted */
   3403 #if defined(O_XATTR)
   3404 				if (xattrp != NULL) {
   3405 					free(xattrhead);
   3406 					xattrp = NULL;
   3407 					xattr_linkp = NULL;
   3408 					xattrhead = NULL;
   3409 				}
   3410 #endif
   3411 				continue;
   3412 			}
   3413 		newfile = ((fstatat(dirfd, comp,
   3414 		    &xtractbuf, 0) == -1) ? TRUE : FALSE);
   3415 		ofile = openat(dirfd, comp, O_RDWR|O_CREAT|O_TRUNC,
   3416 		    stbuf.st_mode & MODEMASK);
   3417 		saveerrno = errno;
   3418 
   3419 #if defined(O_XATTR)
   3420 		if (xattrp != NULL) {
   3421 			if (ofile < 0) {
   3422 				ofile = retry_open_attr(dirfd, cwd,
   3423 				    dirp, attrinfo->attr_parent, comp,
   3424 				    O_RDWR|O_CREAT|O_TRUNC,
   3425 				    stbuf.st_mode & MODEMASK);
   3426 			}
   3427 		}
   3428 #endif
   3429 		if (ofile < 0) {
   3430 			errno = saveerrno;
   3431 			(void) fprintf(stderr, gettext(
   3432 			    "tar: %s%s%s%s - cannot create\n"),
   3433 			    (xattrp == NULL) ? "" : (rw_sysattr ?
   3434 			    gettext("system attribure ") :
   3435 			    gettext("attribute ")),
   3436 			    (xattrp == NULL) ? "" : xattrapath,
   3437 			    (xattrp == NULL) ? "" : gettext(" of "),
   3438 			    (xattrp == NULL) ? comp : namep);
   3439 			if (errflag)
   3440 				done(1);
   3441 			else
   3442 				Errflg = 1;
   3443 #if defined(O_XATTR)
   3444 			if (xattrp != NULL) {
   3445 				dblock.dbuf.typeflag = _XATTR_HDRTYPE;
   3446 				free(xattrhead);
   3447 				xattrp = NULL;
   3448 				xattr_linkp = NULL;
   3449 				xattrhead = NULL;
   3450 			}
   3451 #endif
   3452 			passtape();
   3453 			continue;
   3454 		}
   3455 
   3456 		if (Tflag && (check_ext_attr(namep) == 0)) {
   3457 			if (errflag)
   3458 				done(1);
   3459 			else
   3460 				Errflg = 1;
   3461 			passtape();
   3462 			continue;
   3463 		}
   3464 
   3465 		if (extno != 0) {	/* file is in pieces */
   3466 			if (extotal < 1 || extotal > MAXEXT)
   3467 				(void) fprintf(stderr, gettext(
   3468 				    "tar: ignoring bad extent info for "
   3469 				    "%s%s%s%s\n"),
   3470 				    (xattrp == NULL) ? "" : (rw_sysattr ?
   3471 				    gettext("system attribute ") :
   3472 				    gettext("attribute ")),
   3473 				    (xattrp == NULL) ? "" : xattrapath,
   3474 				    (xattrp == NULL) ? "" : gettext(" of "),
   3475 				    (xattrp == NULL) ? comp : namep);
   3476 			else {
   3477 				/* extract it */
   3478 				(void) xsfile(rw_sysattr, ofile);
   3479 			}
   3480 		}
   3481 		extno = 0;	/* let everyone know file is not split */
   3482 		bytes = stbuf.st_size;
   3483 		blocks = TBLOCKS(bytes);
   3484 		if (vflag) {
   3485 			(void) fprintf(vfile,
   3486 			    "x %s%s%s, %" FMT_off_t " bytes, ",
   3487 			    (xattrp == NULL) ? "" : dirp,
   3488 			    (xattrp == NULL) ? "" : (rw_sysattr ?
   3489 			    gettext(" system attribute ") :
   3490 			    gettext(" attribute ")),
   3491 			    (xattrp == NULL) ? namep : xattrapath, bytes);
   3492 			if (NotTape)
   3493 				(void) fprintf(vfile, "%" FMT_blkcnt_t "K\n",
   3494 				    K(blocks));
   3495 			else
   3496 				(void) fprintf(vfile, gettext("%"
   3497 				    FMT_blkcnt_t " tape blocks\n"), blocks);
   3498 		}
   3499 
   3500 		if (xblocks(rw_sysattr, bytes, ofile) != 0) {
   3501 #if defined(O_XATTR)
   3502 			if (xattrp != NULL) {
   3503 				free(xattrhead);
   3504 				xattrp = NULL;
   3505 				xattr_linkp = NULL;
   3506 				xattrhead = NULL;
   3507 			}
   3508 #endif
   3509 			continue;
   3510 		}
   3511 filedone:
   3512 		if (mflag == 0 && !symflag) {
   3513 			if (dir)
   3514 				doDirTimes(namep, stbuf.st_mtim);
   3515 
   3516 			else
   3517 #if defined(O_XATTR)
   3518 				if (xattrp != NULL) {
   3519 					/*
   3520 					 * Set the time on the attribute unless
   3521 					 * the attribute is a system attribute
   3522 					 * (can't successfully do this) or the
   3523 					 * hidden attribute directory, "." (the
   3524 					 * time on the hidden attribute
   3525 					 * directory will be updated when
   3526 					 * attributes are restored, otherwise
   3527 					 * it's transient).
   3528 					 */
   3529 					if (!rw_sysattr && (Hiddendir == 0)) {
   3530 						setPathTimes(dirfd, comp,
   3531 						    stbuf.st_mtim);
   3532 					}
   3533 				} else
   3534 					setPathTimes(dirfd, comp,
   3535 					    stbuf.st_mtim);
   3536 #else
   3537 				setPathTimes(dirfd, comp, stbuf.st_mtim);
   3538 #endif
   3539 		}
   3540 
   3541 		/* moved this code from above */
   3542 		if (pflag && !symflag && Hiddendir == 0) {
   3543 			if (xattrp != NULL)
   3544 				(void) fchmod(ofile, stbuf.st_mode & MODEMASK);
   3545 			else
   3546 				(void) chmod(namep, stbuf.st_mode & MODEMASK);
   3547 		}
   3548 
   3549 
   3550 		/*
   3551 		 * Because ancillary file preceeds the normal file,
   3552 		 * acl info may have been retrieved (in aclp).
   3553 		 * All file types are directed here (go filedone).
   3554 		 * Always restore ACLs if there are ACLs.
   3555 		 */
   3556 		if (aclp != NULL) {
   3557 			int ret;
   3558 
   3559 #if defined(O_XATTR)
   3560 			if (xattrp != NULL) {
   3561 				if (Hiddendir)
   3562 					ret = facl_set(dirfd, aclp);
   3563 				else
   3564 					ret = facl_set(ofile, aclp);
   3565 			} else {
   3566 				ret = acl_set(namep, aclp);
   3567 			}
   3568 #else
   3569 			ret = acl_set(namep, aclp);
   3570 #endif
   3571 			if (ret < 0) {
   3572 				if (pflag) {
   3573 					(void) fprintf(stderr, gettext(
   3574 					    "%s%s%s%s: failed to set acl "
   3575 					    "entries\n"), namep,
   3576 					    (xattrp == NULL) ? "" :
   3577 					    (rw_sysattr ? gettext(
   3578 					    " system attribute ") :
   3579 					    gettext(" attribute ")),
   3580 					    (xattrp == NULL) ? "" :
   3581 					    xattrapath);
   3582 				}
   3583 				/* else: silent and continue */
   3584 			}
   3585 			acl_free(aclp);
   3586 			aclp = NULL;
   3587 		}
   3588 
   3589 		if (!oflag)
   3590 		    resugname(dirfd, comp, symflag); /* set file ownership */
   3591 
   3592 		if (pflag && newfile == TRUE && !dir &&
   3593 		    (dblock.dbuf.typeflag == '0' ||
   3594 		    dblock.dbuf.typeflag == NULL ||
   3595 		    convflag || dblock.dbuf.typeflag == '1')) {
   3596 			if (fstat(ofile, &xtractbuf) == -1)
   3597 				(void) fprintf(stderr, gettext(
   3598 				    "tar: cannot stat extracted file "
   3599 				    "%s%s%s%s\n"),
   3600 				    (xattrp == NULL) ? "" : (rw_sysattr ?
   3601 				    gettext("system attribute ") :
   3602 				    gettext("attribute ")),
   3603 				    (xattrp == NULL) ? "" : xattrapath,
   3604 				    (xattrp == NULL) ? "" :
   3605 				    gettext(" of "), namep);
   3606 
   3607 			else if ((xtractbuf.st_mode & (MODEMASK & ~S_IFMT))
   3608 			    != (stbuf.st_mode & (MODEMASK & ~S_IFMT))) {
   3609 				(void) fprintf(stderr, gettext(
   3610 				    "tar: warning - file permissions have "
   3611 				    "changed for %s%s%s%s (are 0%o, should be "
   3612 				    "0%o)\n"),
   3613 				    (xattrp == NULL) ? "" : (rw_sysattr ?
   3614 				    gettext("system attribute ") :
   3615 				    gettext("attribute ")),
   3616 				    (xattrp == NULL) ? "" : xattrapath,
   3617 				    (xattrp == NULL) ? "" :
   3618 				    gettext(" of "), namep,
   3619 				    xtractbuf.st_mode, stbuf.st_mode);
   3620 
   3621 			}
   3622 		}
   3623 #if defined(O_XATTR)
   3624 		if (xattrp != NULL) {
   3625 			free(xattrhead);
   3626 			xattrp = NULL;
   3627 			xattr_linkp = NULL;
   3628 			xattrhead = NULL;
   3629 		}
   3630 #endif
   3631 
   3632 		if (ofile != -1) {
   3633 			(void) close(dirfd);
   3634 			dirfd = -1;
   3635 			if (close(ofile) != 0)
   3636 				vperror(2, gettext("close error"));
   3637 			ofile = -1;
   3638 		}
   3639 		xcnt++;			/* increment # files extracted */
   3640 		}
   3641 
   3642 		/*
   3643 		 * Process ancillary file.
   3644 		 *
   3645 		 */
   3646 
   3647 		if (dblock.dbuf.typeflag == 'A') {	/* acl info */
   3648 			char	buf[TBLOCK];
   3649 			char	*secp;
   3650 			char	*tp;
   3651 			int	attrsize;
   3652 			int	cnt;
   3653 
   3654 			/* reset Trusted Extensions flags */
   3655 			dir_flag = 0;
   3656 			mld_flag = 0;
   3657 			lk_rpath_flag = 0;
   3658 			rpath_flag = 0;
   3659 
   3660 			if (pflag) {
   3661 				bytes = stbuf.st_size;
   3662 				if ((secp = malloc((int)bytes)) == NULL) {
   3663 					(void) fprintf(stderr, gettext(
   3664 					    "Insufficient memory for acl\n"));
   3665 					passtape();
   3666 					continue;
   3667 				}
   3668 				tp = secp;
   3669 				blocks = TBLOCKS(bytes);
   3670 
   3671 				/*
   3672 				 * Display a line for each ancillary file.
   3673 				 */
   3674 				if (vflag && Tflag)
   3675 					(void) fprintf(vfile, "x %s(A), %"
   3676 					    FMT_blkcnt_t " bytes, %"
   3677 					    FMT_blkcnt_t " tape blocks\n",
   3678 					    namep, bytes, blocks);
   3679 
   3680 				while (blocks-- > 0) {
   3681 					readtape(buf);
   3682 					if (bytes <= TBLOCK) {
   3683 						(void) memcpy(tp, buf,
   3684 						    (size_t)bytes);
   3685 						break;
   3686 					} else {
   3687 						(void) memcpy(tp, buf,
   3688 						    TBLOCK);
   3689 						tp += TBLOCK;
   3690 					}
   3691 					bytes -= TBLOCK;
   3692 				}
   3693 				bytes = stbuf.st_size;
   3694 				/* got all attributes in secp */
   3695 				tp = secp;
   3696 				do {
   3697 					attr = (struct sec_attr *)tp;
   3698 					switch (attr->attr_type) {
   3699 					case UFSD_ACL:
   3700 					case ACE_ACL:
   3701 						(void) sscanf(attr->attr_len,
   3702 						    "%7o",
   3703 						    (uint_t *)
   3704 						    &cnt);
   3705 						/* header is 8 */
   3706 						attrsize = 8 + (int)strlen(
   3707 						    &attr->attr_info[0]) + 1;
   3708 						error =
   3709 						    acl_fromtext(
   3710 						    &attr->attr_info[0], &aclp);
   3711 
   3712 						if (error != 0) {
   3713 							(void) fprintf(stderr,
   3714 							    gettext(
   3715 							    "aclfromtext "
   3716 							    "failed: %s\n"),
   3717 							    acl_strerror(
   3718 							    error));
   3719 							bytes -= attrsize;
   3720 							break;
   3721 						}
   3722 						if (acl_cnt(aclp) != cnt) {
   3723 							(void) fprintf(stderr,
   3724 							    gettext(
   3725 							    "aclcnt error\n"));
   3726 							bytes -= attrsize;
   3727 							break;
   3728 						}
   3729 						bytes -= attrsize;
   3730 						break;
   3731 
   3732 					/* Trusted Extensions */
   3733 
   3734 					case DIR_TYPE:
   3735 					case LBL_TYPE:
   3736 					case APRIV_TYPE:
   3737 					case FPRIV_TYPE:
   3738 					case COMP_TYPE:
   3739 					case LK_COMP_TYPE:
   3740 					case ATTR_FLAG_TYPE:
   3741 						attrsize =
   3742 						    sizeof (struct sec_attr) +
   3743 						    strlen(&attr->attr_info[0]);
   3744 						bytes -= attrsize;
   3745 						if (Tflag)
   3746 							extract_attr(&namep,
   3747 							    attr);
   3748 						break;
   3749 
   3750 					default:
   3751 						(void) fprintf(stderr, gettext(
   3752 						    "unrecognized attr"
   3753 						    " type\n"));
   3754 						bytes = (off_t)0;
   3755 						break;
   3756 					}
   3757 
   3758 					/* next attributes */
   3759 					tp += attrsize;
   3760 				} while (bytes != 0);
   3761 				free(secp);
   3762 			} else {
   3763 				passtape();
   3764 			}
   3765 		} /* acl */
   3766 
   3767 	} /* for */
   3768 
   3769 	/*
   3770 	 *  Ensure that all the directories still on the directory stack
   3771 	 *  get their modification times set correctly by flushing the
   3772 	 *  stack.
   3773 	 */
   3774 
   3775 	doDirTimes(NULL, time_zero);
   3776 
   3777 #if defined(O_XATTR)
   3778 		if (xattrp != NULL) {
   3779 			free(xattrhead);
   3780 			xattrp = NULL;
   3781 			xattr_linkp = NULL;
   3782 			xattrhead = NULL;
   3783 		}
   3784 #endif
   3785 
   3786 	/*
   3787 	 * Check if the number of files extracted is different from the
   3788 	 * number of files listed on the command line
   3789 	 */
   3790 	if (fcnt > xcnt) {
   3791 		(void) fprintf(stderr,
   3792 		    gettext("tar: %d file(s) not extracted\n"),
   3793 		fcnt-xcnt);
   3794 		Errflg = 1;
   3795 	}
   3796 }
   3797 
   3798 /*
   3799  *	xblocks		extract file/extent from tape to output file
   3800  *
   3801  *	xblocks(issysattr, bytes, ofile);
   3802  *
   3803  *	issysattr			flag set if the files being extracted
   3804  *					is an extended system attribute file.
   3805  *	unsigned long long bytes	size of extent or file to be extracted
   3806  *	ofile				output file
   3807  *
   3808  *	called by doxtract() and xsfile()
   3809  */
   3810 
   3811 static int
   3812 xblocks(int issysattr, off_t bytes, int ofile)
   3813 {
   3814 	char *buf;
   3815 	char tempname[NAMSIZ+1];
   3816 	size_t maxwrite;
   3817 	size_t bytesread;
   3818 	size_t piosize;		/* preferred I/O size */
   3819 	struct stat tsbuf;
   3820 
   3821 	/* Don't need to do anything if this is a zero size file */
   3822 	if (bytes <= 0) {
   3823 		return (0);
   3824 	}
   3825 
   3826 	/*
   3827 	 * To figure out the size of the buffer used to accumulate data
   3828 	 * from readtape() and to write to the file, we need to determine
   3829 	 * the largest chunk of data to be written to the file at one time.
   3830 	 * This is determined based on the smallest of the following two
   3831 	 * things:
   3832 	 *	1) The size of the archived file.
   3833 	 *	2) The preferred I/O size of the file.
   3834 	 */
   3835 	if (issysattr || (bytes <= TBLOCK)) {
   3836 		/*
   3837 		 * Writes to system attribute files must be
   3838 		 * performed in one operation.
   3839 		 */
   3840 		maxwrite = bytes;
   3841 	} else {
   3842 		/*
   3843 		 * fstat() the file to get the preferred I/O size.
   3844 		 * If it fails, then resort back to just writing
   3845 		 * one block at a time.
   3846 		 */
   3847 		if (fstat(ofile, &tsbuf) == 0) {
   3848 			piosize = tsbuf.st_blksize;
   3849 		} else {
   3850 			piosize = TBLOCK;
   3851 		}
   3852 		maxwrite = min(bytes, piosize);
   3853 	}
   3854 
   3855 	/*
   3856 	 * The buffer used to accumulate the data for the write operation
   3857 	 * needs to be the maximum number of bytes to be written rounded up
   3858 	 * to the nearest TBLOCK since readtape reads one block at a time.
   3859 	 */
   3860 	if ((buf = malloc(TBLOCKS(maxwrite) * TBLOCK)) == NULL) {
   3861 		fatal(gettext("cannot allocate buffer"));
   3862 	}
   3863 
   3864 	while (bytes > 0) {
   3865 
   3866 		/*
   3867 		 * readtape() obtains one block (TBLOCK) of data at a time.
   3868 		 * Accumulate as many blocks of data in buf as we can write
   3869 		 * in one operation.
   3870 		 */
   3871 		for (bytesread = 0; bytesread < maxwrite; bytesread += TBLOCK) {
   3872 			readtape(buf + bytesread);
   3873 		}
   3874 
   3875 		if (write(ofile, buf, maxwrite) < 0) {
   3876 			int saveerrno = errno;
   3877 
   3878 			if (xhdr_flgs & _X_PATH)
   3879 				(void) strlcpy(tempname, Xtarhdr.x_path,
   3880 				    sizeof (tempname));
   3881 			else
   3882 				(void) sprintf(tempname, "%.*s", NAMSIZ,
   3883 				    dblock.dbuf.name);
   3884 			/*
   3885 			 * If the extended system attribute being extracted
   3886 			 * contains attributes that the user needs privileges
   3887 			 * for, then just display a warning message, skip
   3888 			 * the extraction of this file, and return.
   3889 			 */
   3890 			if ((saveerrno == EPERM) && issysattr) {
   3891 				(void) fprintf(stderr, gettext(
   3892 				    "tar: unable to extract system attribute "
   3893 				    "%s: insufficient privileges\n"), tempname);
   3894 				Errflg = 1;
   3895 				(void) free(buf);
   3896 				return (1);
   3897 			} else {
   3898 				(void) fprintf(stderr, gettext(
   3899 				    "tar: %s: HELP - extract write error\n"),
   3900 				    tempname);
   3901 				done(2);
   3902 			}
   3903 		}
   3904 		bytes -= maxwrite;
   3905 
   3906 		/*
   3907 		 * If we've reached this point and there is still data
   3908 		 * to be written, maxwrite had to have been determined
   3909 		 * by the preferred I/O size.  If the number of bytes
   3910 		 * left to write is smaller than the preferred I/O size,
   3911 		 * then we're about to do our final write to the file, so
   3912 		 * just set maxwrite to the number of bytes left to write.
   3913 		 */
   3914 		if ((bytes > 0) && (bytes < maxwrite)) {
   3915 			maxwrite = bytes;
   3916 		}
   3917 	}
   3918 	free(buf);
   3919 
   3920 	return (0);
   3921 }
   3922 
   3923 /*
   3924  * 	xsfile	extract split file
   3925  *
   3926  *	xsfile(ofd);	ofd = output file descriptor
   3927  *
   3928  *	file extracted and put in ofd via xblocks()
   3929  *
   3930  *	NOTE:  only called by doxtract() to extract one large file
   3931  */
   3932 
   3933 static	union	hblock	savedblock;	/* to ensure same file across volumes */
   3934 
   3935 static int
   3936 xsfile(int issysattr, int ofd)
   3937 {
   3938 	int i, c;
   3939 	int sysattrerr = 0;
   3940 	char name[PATH_MAX+1];	/* holds name for diagnostics */
   3941 	int extents, totalext;
   3942 	off_t bytes, totalbytes;
   3943 
   3944 	if (xhdr_flgs & _X_PATH)
   3945 		(void) strcpy(name, Xtarhdr.x_path);
   3946 	else
   3947 		(void) sprintf(name, "%.*s", NAMSIZ, dblock.dbuf.name);
   3948 
   3949 	totalbytes = (off_t)0;		/* in case we read in half the file */
   3950 	totalext = 0;		/* these keep count */
   3951 
   3952 	(void) fprintf(stderr, gettext(
   3953 	    "tar: %s split across %d volumes\n"), name, extotal);
   3954 
   3955 	/* make sure we do extractions in order */
   3956 	if (extno != 1) {	/* starting in middle of file? */
   3957 		(void) printf(gettext(
   3958 		    "tar: first extent read is not #1\n"
   3959 		    "OK to read file beginning with extent #%d (%s/%s) ? "),
   3960 		    extno, yesstr, nostr);
   3961 		if (yes() == 0) {
   3962 canit:
   3963 			passtape();
   3964 			if (close(ofd) != 0)
   3965 				vperror(2, gettext("close error"));
   3966 			if (sysattrerr) {
   3967 				return (1);
   3968 			} else {
   3969 				return (0);
   3970 			}
   3971 		}
   3972 	}
   3973 	extents = extotal;
   3974 	i = extno;
   3975 	/*CONSTCOND*/
   3976 	while (1) {
   3977 		if (xhdr_flgs & _X_SIZE) {
   3978 			bytes = extsize;
   3979 		} else {
   3980 			bytes = stbuf.st_size;
   3981 		}
   3982 
   3983 		if (vflag)
   3984 			(void) fprintf(vfile, "+++ x %s [extent #%d], %"
   3985 			    FMT_off_t " bytes, %ldK\n", name, extno, bytes,
   3986 			    (long)K(TBLOCKS(bytes)));
   3987 		if (xblocks(issysattr, bytes, ofd) != 0) {
   3988 			sysattrerr = 1;
   3989 			goto canit;
   3990 		}
   3991 
   3992 		totalbytes += bytes;
   3993 		totalext++;
   3994 		if (++i > extents)
   3995 			break;
   3996 
   3997 		/* get next volume and verify it's the right one */
   3998 		copy(&savedblock, &dblock);
   3999 tryagain:
   4000 		newvol();
   4001 		xhdr_flgs = 0;
   4002 		getdir();
   4003 		if (Xhdrflag > 0)
   4004 			(void) get_xdata();	/* Get x-header & regular hdr */
   4005 		if ((dblock.dbuf.typeflag != 'A') && (xhdr_flgs != 0)) {
   4006 			load_info_from_xtarhdr(xhdr_flgs, &Xtarhdr);
   4007 			xhdr_flgs |= _X_XHDR;
   4008 		}
   4009 		if (endtape()) {	/* seemingly empty volume */
   4010 			(void) fprintf(stderr, gettext(
   4011 			    "tar: first record is null\n"));
   4012 asknicely:
   4013 			(void) fprintf(stderr, gettext(
   4014 			    "tar: need volume with extent #%d of %s\n"),
   4015 			    i, name);
   4016 			goto tryagain;
   4017 		}
   4018 		if (notsame()) {
   4019 			(void) fprintf(stderr, gettext(
   4020 			    "tar: first file on that volume is not "
   4021 			    "the same file\n"));
   4022 			goto asknicely;
   4023 		}
   4024 		if (i != extno) {
   4025 			(void) fprintf(stderr, gettext(
   4026 			    "tar: extent #%d received out of order\ntar: "
   4027 			    "should be #%d\n"), extno, i);
   4028 			(void) fprintf(stderr, gettext(
   4029 			    "Ignore error, Abort this file, or "
   4030 			    "load New volume (i/a/n) ? "));
   4031 			c = response();
   4032 			if (c == 'a')
   4033 				goto canit;
   4034 			if (c != 'i')		/* default to new volume */
   4035 				goto asknicely;
   4036 			i = extno;		/* okay, start from there */
   4037 		}
   4038 	}
   4039 	if (vflag)
   4040 		(void) fprintf(vfile, gettext(
   4041 		    "x %s (in %d extents), %" FMT_off_t " bytes, %ldK\n"),
   4042 		    name, totalext, totalbytes, (long)K(TBLOCKS(totalbytes)));
   4043 
   4044 	return (0);
   4045 }
   4046 
   4047 
   4048 /*
   4049  *	notsame()	check if extract file extent is invalid
   4050  *
   4051  *	returns true if anything differs between savedblock and dblock
   4052  *	except extno (extent number), checksum, or size (extent size).
   4053  *	Determines if this header belongs to the same file as the one we're
   4054  *	extracting.
   4055  *
   4056  *	NOTE:	though rather bulky, it is only called once per file
   4057  *		extension, and it can withstand changes in the definition
   4058  *		of the header structure.
   4059  *
   4060  *	WARNING:	this routine is local to xsfile() above
   4061  */
   4062 
   4063 static int
   4064 notsame(void)
   4065 {
   4066 	return (
   4067 	    (strncmp(savedblock.dbuf.name, dblock.dbuf.name, NAMSIZ)) ||
   4068 	    (strcmp(savedblock.dbuf.mode, dblock.dbuf.mode)) ||
   4069 	    (strcmp(savedblock.dbuf.uid, dblock.dbuf.uid)) ||
   4070 	    (strcmp(savedblock.dbuf.gid, dblock.dbuf.gid)) ||
   4071 	    (strcmp(savedblock.dbuf.mtime, dblock.dbuf.mtime)) ||
   4072 	    (savedblock.dbuf.typeflag != dblock.dbuf.typeflag) ||
   4073 	    (strncmp(savedblock.dbuf.linkname, dblock.dbuf.linkname, NAMSIZ)) ||
   4074 	    (savedblock.dbuf.extotal != dblock.dbuf.extotal) ||
   4075 	    (strcmp(savedblock.dbuf.efsize, dblock.dbuf.efsize)));
   4076 }
   4077 
   4078 static void
   4079 #ifdef	_iBCS2
   4080 dotable(char *argv[], int tbl_cnt)
   4081 #else
   4082 dotable(char *argv[])
   4083 #endif
   4084 
   4085 {
   4086 	int tcnt;			/* count # files tabled */
   4087 	int fcnt;			/* count # files in argv list */
   4088 	char *namep, *dirp, *comp;
   4089 	int want;
   4090 	char aclchar = ' ';			/* either blank or '+' */
   4091 	char templink[PATH_MAX+1];
   4092 	attr_data_t *attrinfo = NULL;
   4093 
   4094 	dumping = 0;
   4095 
   4096 	/* if not on magtape, maximize seek speed */
   4097 	if (NotTape && !bflag) {
   4098 #if SYS_BLOCK > TBLOCK
   4099 		nblock = SYS_BLOCK / TBLOCK;
   4100 #else
   4101 		nblock = 1;
   4102 #endif
   4103 	}
   4104 	/*
   4105 	 * Count the number of files that are to be tabled
   4106 	 */
   4107 	fcnt = tcnt = 0;
   4108 
   4109 #ifdef	_iBCS2
   4110 	initarg(argv, Filefile);
   4111 	while (nextarg() != NULL)
   4112 		++fcnt;
   4113 	fcnt += tbl_cnt;
   4114 #endif	/*  _iBCS2 */
   4115 
   4116 	for (;;) {
   4117 
   4118 		/* namep is set by wantit to point to the full name */
   4119 		if ((want = wantit(argv, &namep, &dirp, &comp, &attrinfo)) == 0)
   4120 			continue;
   4121 		if (want == -1)
   4122 			break;
   4123 		if (dblock.dbuf.typeflag != 'A')
   4124 			++tcnt;
   4125 
   4126 		/*
   4127 		 * ACL support:
   4128 		 * aclchar is introduced to indicate if there are
   4129 		 * acl entries. longt() now takes one extra argument.
   4130 		 */
   4131 		if (vflag) {
   4132 			if (dblock.dbuf.typeflag == 'A') {
   4133 				aclchar = '+';
   4134 				passtape();
   4135 				continue;
   4136 			}
   4137 			longt(&stbuf, aclchar);
   4138 			aclchar = ' ';
   4139 		}
   4140 
   4141 
   4142 #if defined(O_XATTR)
   4143 		if (xattrp != NULL) {
   4144 			int	issysattr;
   4145 			char	*bn = basename(attrinfo->attr_path);
   4146 
   4147 			/*
   4148 			 * We could use sysattr_type() to test whether or not
   4149 			 * the attribute we are processing is really an
   4150 			 * extended system attribute, which as of this writing
   4151 			 * just does a strcmp(), however, sysattr_type() may
   4152 			 * be changed to issue a pathconf() call instead, which
   4153 			 * would require being changed into the parent attribute
   4154 			 * directory.  So instead, just do simple string
   4155 			 * comparisons to see if we are processing an extended
   4156 			 * system attribute.
   4157 			 */
   4158 			issysattr = is_sysattr(bn);
   4159 
   4160 			(void) printf(gettext("%s %sattribute %s"),
   4161 			    xattrp->h_names,
   4162 			    issysattr ? gettext("system ") : "",
   4163 			    attrinfo->attr_path);
   4164 		} else {
   4165 			(void) printf("%s", namep);
   4166 		}
   4167 #else
   4168 			(void) printf("%s", namep);
   4169 #endif
   4170 
   4171 		if (extno != 0) {
   4172 			if (vflag) {
   4173 				/* keep the '\n' for backwards compatibility */
   4174 				(void) fprintf(vfile, gettext(
   4175 				    "\n [extent #%d of %d]"), extno, extotal);
   4176 			} else {
   4177 				(void) fprintf(vfile, gettext(
   4178 				    " [extent #%d of %d]"), extno, extotal);
   4179 			}
   4180 		}
   4181 		if (xhdr_flgs & _X_LINKPATH) {
   4182 			(void) strcpy(templink, Xtarhdr.x_linkpath);
   4183 		} else {
   4184 #if defined(O_XATTR)
   4185 			if (xattrp != NULL) {
   4186 				(void) sprintf(templink,
   4187 				    "file %.*s", NAMSIZ, xattrp->h_names);
   4188 			} else {
   4189 				(void) sprintf(templink, "%.*s", NAMSIZ,
   4190 				    dblock.dbuf.linkname);
   4191 			}
   4192 #else
   4193 			(void) sprintf(templink, "%.*s", NAMSIZ,
   4194 			    dblock.dbuf.linkname);
   4195 #endif
   4196 			templink[NAMSIZ] = '\0';
   4197 		}
   4198 		if (dblock.dbuf.typeflag == '1') {
   4199 			/*
   4200 			 * TRANSLATION_NOTE
   4201 			 *	Subject is omitted here.
   4202 			 *	Translate this as if
   4203 			 *		<subject> linked to %s
   4204 			 */
   4205 #if defined(O_XATTR)
   4206 			if (xattrp != NULL) {
   4207 				(void) printf(
   4208 				    gettext(" linked to attribute %s"),
   4209 				    xattr_linkp->h_names +
   4210 				    strlen(xattr_linkp->h_names) + 1);
   4211 			} else {
   4212 				(void) printf(
   4213 				    gettext(" linked to %s"), templink);
   4214 			}
   4215 #else
   4216 				(void) printf(
   4217 				    gettext(" linked to %s"), templink);
   4218 
   4219