Home | History | Annotate | Download | only in cpio
      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 /*
     30  * Portions of this source code were derived from Berkeley 4.3 BSD
     31  * under license from the Regents of the University of California.
     32  */
     33 
     34 #include <stdio.h>
     35 #include <sys/types.h>
     36 #include <errno.h>
     37 #include <unistd.h>
     38 #include <stdlib.h>
     39 #include <fcntl.h>
     40 #include <memory.h>
     41 #include <string.h>
     42 #include <stdarg.h>
     43 #include <sys/stat.h>
     44 #include <sys/statvfs.h>
     45 #include <sys/mkdev.h>
     46 #include <sys/param.h>
     47 #include <utime.h>
     48 #include <pwd.h>
     49 #include <grp.h>
     50 #include <signal.h>
     51 #include <ctype.h>
     52 #include <locale.h>
     53 #include <sys/ioctl.h>
     54 #include <sys/mtio.h>
     55 #include <sys/fdio.h>
     56 #include "cpio.h"
     57 #include <sys/acl.h>
     58 #include <sys/time.h>
     59 #include <sys/resource.h>
     60 #include <fnmatch.h>
     61 #include <libgen.h>
     62 #include <libintl.h>
     63 #include <dirent.h>
     64 #include <limits.h>
     65 #include <aclutils.h>
     66 #if defined(_PC_SATTR_ENABLED)
     67 #include <libnvpair.h>
     68 #include <attr.h>
     69 #include <libcmdutils.h>
     70 #endif	/* _PC_SATTR_ENABLED */
     71 #ifdef SOLARIS_PRIVS
     72 #include <priv.h>
     73 #endif	/* SOLARIS_PRIVS */
     74 
     75 /*
     76  * Special kludge for off_t being a signed quantity.
     77  */
     78 #if _FILE_OFFSET_BITS == 64
     79 typedef	u_longlong_t	u_off_t;
     80 #else
     81 typedef	ulong_t		u_off_t;
     82 #endif
     83 
     84 #define	SECMODE	0xe080
     85 
     86 #define	DEVNULL		"/dev/null"
     87 #define	XATTRHDR	".hdr"
     88 
     89 #define	NAMELEN		32
     90 #define	TYPELEN 	16
     91 #define	PERMLEN		4
     92 
     93 #define	FILE_COPIED	1
     94 #define	FILE_LINKED	2
     95 #define	FILE_PASS_ERR	-1
     96 
     97 #define	ARCHIVE_NORMAL	0
     98 #define	ARCHIVE_ACL	1
     99 #define	ARCHIVE_XATTR	2
    100 #define	ARCHIVE_SPARSE	3
    101 
    102 #ifndef	VIEW_READONLY
    103 #define	VIEW_READONLY	"SUNWattr_ro"
    104 #endif
    105 
    106 #ifndef	VIEW_READWRITE
    107 #define	VIEW_READWRITE	"SUNWattr_rw"
    108 #endif
    109 
    110 
    111 #define	LSTAT(dir, path, statbuf) fstatat(dir, \
    112     get_component((Gen.g_attrnam_p == NULL) ? \
    113     path : Gen.g_attrnam_p), statbuf, AT_SYMLINK_NOFOLLOW)
    114 #define	STAT(dir, path, statbuf) fstatat(dir, \
    115     get_component((Gen.g_attrnam_p == NULL) ? \
    116     path : Gen.g_attrnam_p), statbuf, 0)
    117 
    118 /*
    119  *	These limits reflect the maximum size regular file that
    120  *	can be archived, depending on the archive type. For archives
    121  *	with character-format headers (odc, tar, ustar) we use
    122  *	CHAR_OFFSET_MAX.  For archives with SVR4 ASCII headers (-c, -H crc)
    123  *	we store filesize in an 8-char hexadecimal string and use
    124  *	ASC_OFFSET_MAX.  Otherwise, we are limited to the size that will
    125  *	fit in a signed long value.
    126  */
    127 #define	CHAR_OFFSET_MAX	077777777777ULL	/* 11 octal digits */
    128 #define	ASC_OFFSET_MAX	0XFFFFFFFF	/* 8 hexadecimal digits */
    129 #define	BIN_OFFSET_MAX	LONG_MAX	/* signed long max value */
    130 
    131 #define	POSIXMODES	07777
    132 
    133 static char	aclchar = ' ';
    134 
    135 static struct Lnk *add_lnk(struct Lnk **);
    136 static int bfill(void);
    137 static void bflush(void);
    138 static int chgreel(int dir);
    139 static int ckname(int);
    140 static void ckopts(long mask);
    141 static long cksum(char hdr, int byt_cnt, int *err);
    142 static int creat_hdr(void);
    143 static int creat_lnk(int dirfd, char *name1_p, char *name2_p);
    144 static int creat_spec(int dirfd);
    145 static int creat_tmp(char *nam_p);
    146 static void data_in(int proc_mode);
    147 static void data_out(void);
    148 static void data_pass(void);
    149 static void file_in(void);
    150 static int file_out(void);
    151 static int file_pass(void);
    152 static void flush_lnks(void);
    153 static int gethdr(void);
    154 static int getname(void);
    155 static void getpats(int largc, char **largv);
    156 static void ioerror(int dir);
    157 static int matched(void);
    158 static int missdir(char *nam_p);
    159 static long mklong(short v[]);
    160 static void mkshort(short sval[], long v);
    161 static int openout(int dirfd);
    162 static int read_hdr(int hdr);
    163 static void reclaim(struct Lnk *l_p);
    164 static void rstbuf(void);
    165 static void setpasswd(char *nam);
    166 static void rstfiles(int over, int dirfd);
    167 static void scan4trail(void);
    168 static void setup(int largc, char **largv);
    169 static void set_tym(int dirfd, char *nam_p, time_t atime, time_t mtime);
    170 static void sigint(int sig);
    171 static void swap(char *buf_p, int cnt);
    172 static void usage(void);
    173 static void verbose(char *nam_p);
    174 static void write_hdr(int arcflag, off_t len);
    175 static void write_trail(void);
    176 static int ustar_dir(void);
    177 static int ustar_spec(void);
    178 static struct stat *convert_to_old_stat(struct stat *, char *, char *);
    179 static void read_bar_vol_hdr(void);
    180 static void read_bar_file_hdr(void);
    181 static void setup_uncompress(FILE **);
    182 static void skip_bar_volhdr(void);
    183 static void bar_file_in(void);
    184 static int g_init(int *devtype, int *fdes);
    185 static int g_read(int, int, char *, unsigned);
    186 static int g_write(int, int, char *, unsigned);
    187 static int is_floppy(int);
    188 static int is_tape(int);
    189 static void write_ancillary(char *buf, size_t len, boolean_t padding);
    190 static int remove_dir(char *);
    191 static int save_cwd(void);
    192 static void rest_cwd(int cwd);
    193 
    194 static void xattrs_out(int (*func)());
    195 static void get_parent(char *path, char *dir);
    196 static void prepare_xattr_hdr(char **attrbuf, char *filename,
    197     char *attrname, char typeflag, struct Lnk *linkinfo, int *rlen);
    198 static char tartype(int type);
    199 static int openfile(int omode);
    200 static mode_t attrmode(char type);
    201 static char *get_component(char *path);
    202 static int open_dir(char *name);
    203 static int open_dirfd();
    204 static void close_dirfd();
    205 static void write_xattr_hdr();
    206 static char *skipslashes(char *string, char *start);
    207 static int read_xattr_hdr();
    208 static void chop_endslashes(char *path);
    209 
    210 
    211 /* helpful types */
    212 
    213 static
    214 struct passwd	*Curpw_p,	/* Current password entry for -t option */
    215 		*Rpw_p,		/* Password entry for -R option */
    216 		*dpasswd;
    217 
    218 static
    219 struct group	*Curgr_p,	/* Current group entry for -t option */
    220 		*dgroup;
    221 
    222 /* Data structure for buffered I/O. */
    223 
    224 static
    225 struct buf_info {
    226 	char	*b_base_p,	/* Pointer to base of buffer */
    227 		*b_out_p,	/* Position to take bytes from buffer at */
    228 		*b_in_p,	/* Position to put bytes into buffer at */
    229 		*b_end_p;	/* Pointer to end of buffer */
    230 	long	b_cnt,		/* Count of unprocessed bytes */
    231 		b_size;		/* Size of buffer in bytes */
    232 } Buffr;
    233 
    234 /* Generic header format */
    235 
    236 static
    237 struct gen_hdr {
    238 	ulong_t	g_magic,	/* Magic number field */
    239 		g_ino,		/* Inode number of file */
    240 		g_mode,		/* Mode of file */
    241 		g_uid,		/* Uid of file */
    242 		g_gid,		/* Gid of file */
    243 		g_nlink,	/* Number of links */
    244 		g_mtime;	/* Modification time */
    245 	off_t	g_filesz;	/* Length of file */
    246 	ulong_t	g_dev,		/* File system of file */
    247 		g_rdev,		/* Major/minor numbers of special files */
    248 		g_namesz,	/* Length of filename */
    249 		g_cksum;	/* Checksum of file */
    250 	char	g_gname[32],
    251 		g_uname[32],
    252 		g_version[2],
    253 		g_tmagic[6],
    254 		g_typeflag;
    255 	char	*g_tname,
    256 		*g_prefix,
    257 		*g_nam_p,	/* Filename */
    258 		*g_attrparent_p, /* attribute parent */
    259 		*g_attrpath_p, /* attribute path */
    260 		*g_attrnam_p,	/* attribute */
    261 		*g_attrfnam_p,  /* Real file name attr belongs to */
    262 		*g_linktoattrfnam_p, /* file linked attribute belongs to */
    263 		*g_linktoattrnam_p,  /* attribute g_attrnam_p is linked to */
    264 		*g_dirpath;	/* dirname currently opened */
    265 	int	g_dirfd;	/* directory file descriptor */
    266 	int	g_passdirfd;	/* directory fd to pass to */
    267 	int	g_rw_sysattr;	/* read-write system attribute */
    268 	int	g_baseparent_fd;	/* base file's parent fd */
    269 	holes_info_t *g_holes;	/* sparse file information */
    270 
    271 } Gen, *G_p;
    272 
    273 /* Data structure for handling multiply-linked files */
    274 static
    275 char	prebuf[PRESIZ+1],
    276 	nambuf[NAMSIZ+1],
    277 	fullnam[MAXNAM+1];
    278 
    279 
    280 static
    281 struct Lnk {
    282 	short	L_cnt,		/* Number of links encountered */
    283 		L_data;		/* Data has been encountered if 1 */
    284 	struct gen_hdr	L_gen;	/* gen_hdr information for this file */
    285 	struct Lnk	*L_nxt_p,	/* Next file in list */
    286 			*L_bck_p,	/* Previous file in list */
    287 			*L_lnk_p;	/* Next link for this file */
    288 } Lnk_hd;
    289 
    290 static
    291 struct hdr_cpio	Hdr;
    292 
    293 /*
    294  * -------------------------------------------------------------------------
    295  *		   Stuff needed to pre-view the name stream
    296  *
    297  * issymlink is used to remember that the current file is a symlink between
    298  * getname() and file_pass(); the former trashes this information immediately
    299  * when -L is specified.
    300  */
    301 
    302 static
    303 int	issymlink = 0;
    304 
    305 static
    306 FILE	*In_p = stdin;		/* Where the input comes from */
    307 
    308 typedef struct sl_info
    309 {
    310 	struct sl_info *llink;	/* Left subtree ptr (tree depth in *sl_head) */
    311 	struct sl_info *rlink;	/* Right subtree ptr */
    312 	int bal;		/* Subtree balance factor */
    313 	ulong_t	sl_count;	/* Number of symlinks */
    314 	int	sl_ftype;	/* file type of inode */
    315 	ino_t	sl_ino;		/* Inode of file */
    316 	ino_t	sl_ino2;	/* alternate inode for -Hodc */
    317 } sl_info_t;
    318 
    319 typedef struct data_in
    320 {
    321 	int		data_in_errno;
    322 	char		data_in_swapfile;
    323 	char		data_in_proc_mode;
    324 	char		data_in_rd_eof;
    325 	char		data_in_wr_part;
    326 	char		data_in_compress_flag;
    327 	long		data_in_cksumval;
    328 	FILE		*data_in_pipef;
    329 } data_in_t;
    330 
    331 /*
    332  * The following structure maintains a hash entry for the
    333  * balancing trees which are allocated for each device nodes.
    334  */
    335 typedef struct sl_info_link
    336 {
    337 	dev_t		dev;
    338 	sl_info_t	*head;
    339 	struct sl_info_link *next;
    340 } sl_info_link_t;
    341 
    342 #define	SL_INFO_ALLOC_CHUNK	1024
    343 #define	NDEVHENTRY		0x40
    344 #define	DEV_HASHKEY(x)		((x) & (NDEVHENTRY -1))
    345 
    346 /*
    347  * For remapping dev,inode for -Hodc archives.
    348  */
    349 
    350 typedef struct sl_remap
    351 {
    352 	dev_t			dev;		/* device */
    353 	int			inode_count;	/* # inodes seen on dev */
    354 	struct sl_remap 	*next;		/* next in the chain */
    355 } sl_remap_t;
    356 
    357 /* forward declarations */
    358 
    359 static sl_info_t 	*sl_info_alloc(void);
    360 static sl_info_t 	*sl_insert(dev_t, ino_t, int);
    361 static ulong_t		sl_numlinks(dev_t, ino_t, int);
    362 static void		sl_preview_synonyms(void);
    363 static void		sl_remember_tgt(const struct stat *, int, int);
    364 static sl_info_t 	*sl_search(dev_t, ino_t, int);
    365 static sl_info_t	*sl_devhash_lookup(dev_t);
    366 static void		sl_devhash_insert(dev_t, sl_info_t *);
    367 
    368 extern int		sl_compare(ino_t, int, ino_t, int);
    369 #define	sl_compare(lino, lftype, rino, rftype)	(lino < rino ? -1 : \
    370 	    (lino > rino ? 1 : (lftype < rftype ? -1 : \
    371 	    (lftype > rftype ? 1 : 0))))
    372 
    373 /* global storage */
    374 
    375 static sl_remap_t  *sl_remap_head = NULL; /* head of the inode-remap list */
    376 static sl_info_link_t	*sl_devhash[NDEVHENTRY]; /* hash table */
    377 
    378 /*
    379  * -------------------------------------------------------------------------
    380  */
    381 
    382 static
    383 struct stat	ArchSt,	/* stat(2) information of the archive */
    384 		SrcSt,	/* stat(2) information of source file */
    385 		DesSt,	/* stat(2) of destination file */
    386 		*OldSt = NULL;	/* stat info converted to svr32 format */
    387 
    388 /*
    389  * bin_mag: Used to validate a binary magic number,
    390  * by combining to bytes into an unsigned short.
    391  */
    392 
    393 static
    394 union bin_mag {
    395 	unsigned char b_byte[2];
    396 	ushort_t b_half;
    397 } Binmag;
    398 
    399 static
    400 union tblock *Thdr_p;	/* TAR header pointer */
    401 
    402 static union b_block *bar_Vhdr;
    403 static struct gen_hdr Gen_bar_vol;
    404 
    405 /*
    406  * swpbuf: Used in swap() to swap bytes within a halfword,
    407  * halfwords within a word, or to reverse the order of the
    408  * bytes within a word.  Also used in mklong() and mkshort().
    409  */
    410 
    411 static
    412 union swpbuf {
    413 	unsigned char	s_byte[4];
    414 	ushort_t	s_half[2];
    415 	ulong_t	s_word;
    416 } *Swp_p;
    417 
    418 static
    419 char	*myname,		/* program name */
    420 	Adir,			/* Flags object as a directory */
    421 	Hiddendir,		/* Processing hidden attribute directory */
    422 	Aspec,			/* Flags object as a special file */
    423 	Do_rename,		/* Indicates rename() is to be used */
    424 	Time[50],		/* Array to hold date and time */
    425 	Ttyname[] = "/dev/tty",	/* Controlling console */
    426 	T_lname[MAXPATHLEN],	/* Array to hold links name for tar */
    427 	*Buf_p,			/* Buffer for file system I/O */
    428 	*Full_p,		/* Pointer to full pathname */
    429 	*Efil_p,		/* -E pattern file string */
    430 	*Eom_p = "Change to part %d and press RETURN key. [q] ",
    431 	*Fullnam_p,		/* Full pathname */
    432 	*Attrfile_p,		/* attribute file */
    433 	*Hdr_p,			/* -H header type string */
    434 	*IOfil_p,		/* -I/-O input/output archive string */
    435 	*Lnkend_p,		/* Pointer to end of Lnknam_p */
    436 	*Lnknam_p,		/* Buffer for linking files with -p option */
    437 	*Nam_p,			/* Array to hold filename */
    438 	*Savenam_p,		/* copy of filename xattr belongs to */
    439 	*Own_p,			/* New owner login id string */
    440 	*Renam_p,		/* Buffer for renaming files */
    441 	*Renam_attr_p,		/* Buffer for renaming attr with sys attrs */
    442 	*Renametmp_p,		/* Tmp Buffer for renaming files */
    443 	*Symlnk_p,		/* Buffer for holding symbolic link name */
    444 	*Over_p,		/* Holds temporary filename when overwriting */
    445 	**Pat_pp = 0,		/* Pattern strings */
    446 	bar_linkflag,		/* flag to indicate if the file is a link */
    447 	bar_linkname[MAXPATHLEN]; /* store the name of the link */
    448 
    449 static
    450 int	Append = 0,	/* Flag set while searching to end of archive */
    451 	Archive,	/* File descriptor of the archive */
    452 	Buf_error = 0,	/* I/O error occurred during buffer fill */
    453 	Compress_sparse = 0,	/* Compress sparse files */
    454 	Def_mode = 0777,	/* Default file/directory protection modes */
    455 	Device,		/* Device type being accessed (used with libgenIO) */
    456 	Error_cnt = 0,	/* Cumulative count of I/O errors */
    457 	Finished = 1,	/* Indicates that a file transfer has completed */
    458 	Hdrsz = ASCSZ,	/* Fixed length portion of the header */
    459 	Hdr_type,		/* Flag to indicate type of header selected */
    460 	Ifile,		/* File des. of file being archived */
    461 	Ofile,		/* File des. of file being extracted from archive */
    462 	Use_old_stat = 0,    /* Create an old style -Hodc hdr (small dev's) */
    463 	Onecopy = 0,	/* Flags old vs. new link handling */
    464 	Pad_val = 0,	/* Indicates the number of bytes to pad (if any) */
    465 	PageSize = 0,	/* The native page size, used for figuring block size */
    466 	Volcnt = 1,	/* Number of archive volumes processed */
    467 	Verbcnt = 0,	/* Count of number of dots '.' output */
    468 	Eomflag = 0,
    469 	Dflag = 0,
    470 	Atflag = 0,	/* Archive/restore extended attributes */
    471 	SysAtflag = 0,	/* Archive/restore extended system attributes */
    472 	Compressed,	/* Flag to indicate if the bar archive is compressed */
    473 	Bar_vol_num = 0, /* Volume number count for bar archive */
    474 	privileged = 0,	/* Flag set if running with higher privileges */
    475 	attr_baseparent_fd = -1;	/* attribute's base file descriptor */
    476 
    477 
    478 static
    479 gid_t	Lastgid = (gid_t)-1;	/* Used with -t & -v to record current gid */
    480 
    481 static
    482 uid_t	Lastuid = (uid_t)-1;	/* Used with -t & -v to record current uid */
    483 
    484 static
    485 long	Args,		/* Mask of selected options */
    486 	Max_namesz = CPATH;	/* Maximum size of pathnames/filenames */
    487 
    488 static
    489 int	Bufsize = BUFSZ;	/* Default block size */
    490 
    491 
    492 static u_longlong_t    Blocks;	/* full blocks transferred */
    493 static u_longlong_t    SBlocks;	/* cumulative char count from short reads */
    494 
    495 
    496 static off_t	Max_offset = BIN_OFFSET_MAX;	/* largest file size */
    497 static off_t	Max_filesz;			/* from getrlimit */
    498 
    499 static ulong_t	Savedev;
    500 
    501 static
    502 FILE	*Ef_p,			/* File pointer of pattern input file */
    503 	*Err_p = stderr,	/* File pointer for error reporting */
    504 	*Out_p = stdout,	/* File pointer for non-archive output */
    505 	*Rtty_p,		/* Input file pointer for interactive rename */
    506 	*Wtty_p;		/* Output file ptr for interactive rename */
    507 
    508 static
    509 ushort_t	Ftype = S_IFMT;	/* File type mask */
    510 
    511 /* ACL support */
    512 static struct sec_attr {
    513 	char	attr_type;
    514 	char	attr_len[7];
    515 	char	attr_info[1];
    516 } *attr;
    517 
    518 static int	Pflag = 0;	/* flag indicates that acl is preserved */
    519 static int	acl_is_set = 0; /* True if an acl was set on the file */
    520 
    521 acl_t *aclp;
    522 
    523 #if defined(O_XATTR)
    524 typedef enum {
    525 	ATTR_OK,
    526 	ATTR_SKIP,
    527 	ATTR_CHDIR_ERR,
    528 	ATTR_OPEN_ERR,
    529 	ATTR_XATTR_ERR,
    530 	ATTR_SATTR_ERR
    531 } attr_status_t;
    532 #endif
    533 
    534 #if defined(O_XATTR)
    535 typedef enum {
    536 	ARC_CREATE,
    537 	ARC_RESTORE
    538 } arc_action_t;
    539 #endif
    540 
    541 
    542 /*
    543  *
    544  * cpio has been changed to support extended attributes.
    545  *
    546  * As part of this change cpio has been changed to use the new *at() syscalls
    547  * such as openat, fchownat(), unlinkat()...
    548  *
    549  * This was done so that attributes can be handled with as few code changes
    550  * as possible.
    551  *
    552  * What this means is that cpio now opens the directory that a file or directory
    553  * resides in and then performs *at() functions to manipulate the entry.
    554  *
    555  * For example a new file is now created like this:
    556  *
    557  * dfd = open(<some dir path>)
    558  * fd = openat(dfd, <name>,....);
    559  *
    560  * or in the case of an extended attribute
    561  *
    562  * dfd = attropen(<pathname>, ".", ....)
    563  *
    564  * Once we have a directory file descriptor all of the *at() functions can
    565  * be applied to it.
    566  *
    567  * unlinkat(dfd, <component name>,...)
    568  * fchownat(dfd, <component name>,..)
    569  *
    570  * This works for both normal namespace files and extended attribute file
    571  *
    572  */
    573 
    574 /*
    575  * Extended attribute layout
    576  *
    577  * Extended attributes are stored in two pieces.
    578  * 1. An attribute header which has information about
    579  *    what file the attribute is for and what the attribute
    580  *    is named.
    581  * 2. The attribute record itself.  Stored as a normal file type
    582  *    of entry.
    583  * Both the header and attribute record have special modes/typeflags
    584  * associated with them.
    585  *
    586  * The names of the header in the archive look like:
    587  * /dev/null/attr.hdr
    588  *
    589  * The name of the attribute looks like:
    590  * /dev/null/attr.
    591  *
    592  * This is done so that an archiver that doesn't understand these formats
    593  * can just dispose of the attribute records unless the user chooses to
    594  * rename them via cpio -r or pax -i
    595  *
    596  * The format is composed of a fixed size header followed
    597  * by a variable sized xattr_buf. If the attribute is a hard link
    598  * to another attribute, then another xattr_buf section is included
    599  * for the link.
    600  *
    601  * The xattr_buf is used to define the necessary "pathing" steps
    602  * to get to the extended attribute.  This is necessary to support
    603  * a fully recursive attribute model where an attribute may itself
    604  * have an attribute.
    605  *
    606  * The basic layout looks like this.
    607  *
    608  *     --------------------------------
    609  *     |                              |
    610  *     |         xattr_hdr            |
    611  *     |                              |
    612  *     --------------------------------
    613  *     --------------------------------
    614  *     |                              |
    615  *     |        xattr_buf             |
    616  *     |                              |
    617  *     --------------------------------
    618  *     --------------------------------
    619  *     |                              |
    620  *     |      (optional link info)    |
    621  *     |                              |
    622  *     --------------------------------
    623  *     --------------------------------
    624  *     |                              |
    625  *     |      attribute itself        |
    626  *     |      stored as normal tar    |
    627  *     |      or cpio data with       |
    628  *     |      special mode or         |
    629  *     |      typeflag                |
    630  *     |                              |
    631  *     --------------------------------
    632  *
    633  */
    634 
    635 /*
    636  * Extended attributes structures
    637  *
    638  * xattrhead is the complete extended attribute header, as read of off
    639  * disk/tape. It includes the variable xattr_buf portion.
    640  *
    641  * xattrp is basically an offset into xattrhead that points to the
    642  * "pathing" section which defines how to get to the attribute.
    643  *
    644  * xattr_linkp is identical to xattrp except that it is used for linked
    645  * attributes.  It provides the pathing steps to get to the linked
    646  * attribute.
    647  *
    648  * These structures are updated when an extended attribute header is read off
    649  * of disk/tape.
    650  */
    651 static struct xattr_hdr	*xattrhead;
    652 static struct xattr_buf	*xattrp;
    653 static struct xattr_buf	*xattr_linkp;
    654 static int 		xattrbadhead;	/* is extended attribute header bad? */
    655 
    656 static int	append_secattr(char **, int *, acl_t *);
    657 
    658 /*
    659  * Note regarding cpio and changes to ensure cpio doesn't try to second
    660  * guess whether it runs with sufficient privileges or not:
    661  *
    662  * cpio has been changed so that it doesn't carry a second implementation of
    663  * the kernel's policy with respect to privileges.  Instead of attempting
    664  * to restore uid and gid from an archive only if cpio is run as uid 0,
    665  * cpio now *always* tries to restore the uid and gid from the archive
    666  * except when the -R option is specified.  When the -R is specified,
    667  * the uid and gid of the restored file will be changed to those of the
    668  * login id specified.  In addition, chown(), set_tym(), and chmod() should
    669  * only be executed once during archive extraction, and to ensure
    670  * setuid/setgid bits are restored properly, chown() should always be
    671  * executed before chmod().
    672  *
    673  * Note regarding debugging mechanism for cpio:
    674  *
    675  * The following mechanism is provided to allow us to debug cpio in complicated
    676  * situations, like when it is part of a pipe.  The idea is that you compile
    677  * with -DWAITAROUND defined, and then add the "-z" command line option to the
    678  * target cpio invocation.  If stderr is available, it will tell you to which
    679  * pid to attach the debugger; otherwise, use ps to find it.  Attach to the
    680  * process from the debugger, and, *PRESTO*, you are there!
    681  *
    682  * Simply assign "waitaround = 0" once you attach to the process, and then
    683  * proceed from there as usual.
    684  */
    685 
    686 #ifdef WAITAROUND
    687 int waitaround = 0;		/* wait for rendezvous with the debugger */
    688 #endif
    689 
    690 #define	EXIT_CODE	(Error_cnt > 255 ? 255 : Error_cnt)
    691 
    692 /*
    693  * main: Call setup() to process options and perform initializations,
    694  * and then select either copy in (-i), copy out (-o), or pass (-p) action.
    695  */
    696 
    697 int
    698 main(int argc, char **argv)
    699 {
    700 	int i;
    701 	int passret;
    702 
    703 	(void) setlocale(LC_ALL, "");
    704 #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
    705 #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
    706 #endif
    707 	(void) textdomain(TEXT_DOMAIN);
    708 
    709 	(void) memset(&Gen, 0, sizeof (Gen));
    710 	myname = e_strdup(E_EXIT, basename(argv[0]));
    711 	setup(argc, argv);
    712 
    713 	if (signal(SIGINT, sigint) == SIG_IGN)
    714 		(void) signal(SIGINT, SIG_IGN);
    715 	switch (Args & (OCi | OCo | OCp)) {
    716 	case OCi: /* COPY IN */
    717 		Hdr_type = NONE;
    718 		if (Atflag || SysAtflag) {
    719 			/*
    720 			 * Save the current working directory, so
    721 			 * we can change back here after cd'ing into
    722 			 * the attribute directory when processing
    723 			 * attributes.
    724 			 */
    725 			if ((attr_baseparent_fd = save_cwd()) < 0) {
    726 				msg(EXT, "Unable to open current directory.");
    727 			}
    728 		}
    729 		while ((i = gethdr()) != 0) {
    730 			Gen.g_dirfd = -1;
    731 			if (i == 1) {
    732 				file_in();
    733 				/*
    734 				 * Any ACL info for this file would or should
    735 				 * have been used after file_in(); clear out
    736 				 * aclp so it is is not erroneously used on
    737 				 * the next file.
    738 				 */
    739 				if (aclp != NULL) {
    740 					acl_free(aclp);
    741 					aclp = NULL;
    742 				}
    743 				acl_is_set = 0;
    744 			}
    745 			(void) memset(&Gen, 0, sizeof (Gen));
    746 		}
    747 		/* Do not count "extra" "read-ahead" buffered data */
    748 		if (Buffr.b_cnt > Bufsize)
    749 			Blocks -=  (u_longlong_t)(Buffr.b_cnt / Bufsize);
    750 		break;
    751 	case OCo: /* COPY OUT */
    752 		if (Args & OCA) {
    753 			scan4trail();
    754 		}
    755 
    756 		Gen.g_dirfd = -1;
    757 		Gen.g_dirpath = NULL;
    758 		sl_preview_synonyms();
    759 
    760 		while ((i = getname()) != 0) {
    761 			if (i == 1) {
    762 				(void) file_out();
    763 				if (Atflag || SysAtflag) {
    764 					if (Gen.g_dirfd != -1) {
    765 						(void) close(Gen.g_dirfd);
    766 					}
    767 					Gen.g_dirfd = -1;
    768 					xattrs_out(file_out);
    769 				}
    770 			}
    771 			if (aclp != NULL) {
    772 				acl_free(aclp);
    773 				aclp = NULL;
    774 				acl_is_set = 0;
    775 			}
    776 		}
    777 		write_trail();
    778 		break;
    779 	case OCp: /* PASS */
    780 		sl_preview_synonyms();
    781 
    782 		Gen.g_dirfd = -1;
    783 		Gen.g_passdirfd = -1;
    784 		Gen.g_dirpath = NULL;
    785 		Compress_sparse = 1;
    786 		while (getname()) {
    787 			/*
    788 			 * If file is a fully qualified path then
    789 			 * file_pass will strip off the leading '/'
    790 			 * and we need to save off the unstripped
    791 			 * name for attribute traversal.
    792 			 */
    793 			if (Atflag || SysAtflag) {
    794 				(void) strcpy(Savenam_p, Gen.g_nam_p);
    795 			}
    796 			passret = file_pass();
    797 			if (aclp != NULL) {
    798 				acl_free(aclp);
    799 				aclp = NULL;
    800 				acl_is_set = 0;
    801 			}
    802 			if (Gen.g_passdirfd != -1)
    803 				(void) close(Gen.g_passdirfd);
    804 			Gen.g_passdirfd = -1;
    805 			if (Atflag || SysAtflag) {
    806 				if (Gen.g_dirfd != -1) {
    807 					(void) close(Gen.g_dirfd);
    808 				}
    809 				Gen.g_dirfd = -1;
    810 				if (passret != FILE_LINKED) {
    811 					Gen.g_nam_p = Savenam_p;
    812 					xattrs_out(file_pass);
    813 				}
    814 			}
    815 		}
    816 		break;
    817 	default:
    818 		msg(EXT, "Impossible action.");
    819 	}
    820 	if (Ofile > 0) {
    821 		if (close(Ofile) != 0)
    822 			msg(EXTN, "close error");
    823 	}
    824 	if (Archive > 0) {
    825 		if (close(Archive) != 0)
    826 			msg(EXTN, "close error");
    827 	}
    828 	Blocks = (u_longlong_t)(Blocks * Bufsize + SBlocks + 0x1FF) >> 9;
    829 	msg(EPOST, "%lld blocks", Blocks);
    830 	if (Error_cnt)
    831 		msg(EPOST, "%d error(s)", Error_cnt);
    832 	return (EXIT_CODE);
    833 }
    834 
    835 /*
    836  * add_lnk: Add a linked file's header to the linked file data structure, by
    837  * either adding it to the end of an existing sub-list or starting
    838  * a new sub-list.  Each sub-list saves the links to a given file.
    839  *
    840  * Directly returns a pointer to the new entry; returns a pointer to the head
    841  * of the sub-list in which that entry is located through the argument.
    842  */
    843 
    844 static struct Lnk *
    845 add_lnk(struct Lnk **sublist_return)
    846 {
    847 	struct Lnk *new_entry, *sublist;
    848 
    849 	for (sublist = Lnk_hd.L_nxt_p;
    850 	    sublist != &Lnk_hd;
    851 	    sublist = sublist->L_nxt_p) {
    852 		if (sublist->L_gen.g_ino == G_p->g_ino &&
    853 		    sublist->L_gen.g_dev == G_p->g_dev) {
    854 			/* found */
    855 			break;
    856 		}
    857 	}
    858 
    859 	new_entry = e_zalloc(E_EXIT, sizeof (struct Lnk));
    860 
    861 	new_entry->L_lnk_p = NULL;
    862 	new_entry->L_gen = *G_p; /* structure copy */
    863 
    864 	new_entry->L_gen.g_nam_p = e_zalloc(E_EXIT, (size_t)G_p->g_namesz);
    865 
    866 	(void) strcpy(new_entry->L_gen.g_nam_p, G_p->g_nam_p);
    867 
    868 	if (sublist == &Lnk_hd) {
    869 		/* start new sub-list */
    870 		new_entry->L_nxt_p = &Lnk_hd;
    871 		new_entry->L_bck_p = Lnk_hd.L_bck_p;
    872 		Lnk_hd.L_bck_p = new_entry->L_bck_p->L_nxt_p = new_entry;
    873 		new_entry->L_lnk_p = NULL;
    874 		new_entry->L_cnt = 1;
    875 		new_entry->L_data = Onecopy ? 0 : 1;
    876 		sublist = new_entry;
    877 	} else {
    878 		/* add to existing sub-list */
    879 		struct Lnk *ptr;
    880 
    881 		sublist->L_cnt++;
    882 
    883 		for (ptr = sublist;
    884 		    ptr->L_lnk_p != NULL;
    885 		    ptr = ptr->L_lnk_p) {
    886 			ptr->L_gen.g_filesz = G_p->g_filesz;
    887 		}
    888 
    889 		ptr->L_gen.g_filesz = G_p->g_filesz;
    890 		ptr->L_lnk_p = new_entry;
    891 	}
    892 
    893 	*sublist_return = sublist;
    894 	return (new_entry);
    895 }
    896 
    897 /*
    898  * bfill: Read req_cnt bytes (out of filelen bytes) from the I/O buffer,
    899  * moving them to rd_buf_p.  When there are no bytes left in the I/O buffer,
    900  * Fillbuf is set and the I/O buffer is filled.  The variable dist is the
    901  * distance to lseek if an I/O error is encountered with the -k option set
    902  * (converted to a multiple of Bufsize).
    903  */
    904 
    905 static int
    906 bfill(void)
    907 {
    908 	int i = 0, rv;
    909 	static int eof = 0;
    910 
    911 	if (!Dflag) {
    912 	while ((Buffr.b_end_p - Buffr.b_in_p) >= Bufsize) {
    913 		errno = 0;
    914 		if ((rv = g_read(Device, Archive, Buffr.b_in_p, Bufsize)) < 0) {
    915 			if (((Buffr.b_end_p - Buffr.b_in_p) >= Bufsize) &&
    916 			    (Eomflag == 0)) {
    917 				Eomflag = 1;
    918 				return (1);
    919 			}
    920 			if (errno == ENOSPC) {
    921 				(void) chgreel(INPUT);
    922 				if (Hdr_type == BAR) {
    923 					skip_bar_volhdr();
    924 				}
    925 				continue;
    926 			} else if (Args & OCk) {
    927 				if (i++ > MX_SEEKS)
    928 					msg(EXT, "Cannot recover.");
    929 				if (lseek(Archive, Bufsize, SEEK_REL) < 0)
    930 					msg(EXTN, "Cannot lseek()");
    931 				Error_cnt++;
    932 				Buf_error++;
    933 				rv = 0;
    934 				continue;
    935 			} else
    936 				ioerror(INPUT);
    937 		} /* (rv = g_read(Device, Archive ... */
    938 		if (Hdr_type != BAR || rv == Bufsize) {
    939 			Buffr.b_in_p += rv;
    940 			Buffr.b_cnt += (long)rv;
    941 		}
    942 		if (rv == Bufsize) {
    943 			eof = 0;
    944 			Blocks++;
    945 		} else if (rv == 0) {
    946 			if (!eof) {
    947 				eof = 1;
    948 				break;
    949 			}
    950 			(void) chgreel(INPUT);
    951 			eof = 0;	/* reset the eof after chgreel	*/
    952 
    953 			/*
    954 			 * if spans multiple volume, skip the volume header of
    955 			 * the next volume so that the file currently being
    956 			 * extracted can continue to be extracted.
    957 			 */
    958 			if (Hdr_type == BAR) {
    959 				skip_bar_volhdr();
    960 			}
    961 
    962 			continue;
    963 		} else {
    964 			eof = 0;
    965 			SBlocks += (u_longlong_t)rv;
    966 		}
    967 	} /* (Buffr.b_end_p - Buffr.b_in_p) <= Bufsize */
    968 
    969 	} else {			/* Dflag */
    970 		errno = 0;
    971 		if ((rv = g_read(Device, Archive, Buffr.b_in_p, Bufsize)) < 0) {
    972 			return (-1);
    973 		} /* (rv = g_read(Device, Archive ... */
    974 		Buffr.b_in_p += rv;
    975 		Buffr.b_cnt += (long)rv;
    976 		if (rv == Bufsize) {
    977 			eof = 0;
    978 			Blocks++;
    979 		} else if (!rv) {
    980 			if (!eof) {
    981 				eof = 1;
    982 				return (rv);
    983 			}
    984 			return (-1);
    985 		} else {
    986 			eof = 0;
    987 			SBlocks += (u_longlong_t)rv;
    988 		}
    989 	}
    990 	return (rv);
    991 }
    992 
    993 /*
    994  * bflush: Move wr_cnt bytes from data_p into the I/O buffer.  When the
    995  * I/O buffer is full, Flushbuf is set and the buffer is written out.
    996  */
    997 
    998 static void
    999 bflush(void)
   1000 {
   1001 	int rv;
   1002 
   1003 	while (Buffr.b_cnt >= Bufsize) {
   1004 		errno = 0;
   1005 		if ((rv = g_write(Device, Archive, Buffr.b_out_p,
   1006 		    Bufsize)) < 0) {
   1007 			if (errno == ENOSPC && !Dflag)
   1008 				rv = chgreel(OUTPUT);
   1009 			else
   1010 				ioerror(OUTPUT);
   1011 		}
   1012 		Buffr.b_out_p += rv;
   1013 		Buffr.b_cnt -= (long)rv;
   1014 		if (rv == Bufsize)
   1015 			Blocks++;
   1016 		else if (rv > 0)
   1017 			SBlocks += (u_longlong_t)rv;
   1018 	}
   1019 	rstbuf();
   1020 }
   1021 
   1022 /*
   1023  * chgreel: Determine if end-of-medium has been reached.  If it has,
   1024  * close the current medium and prompt the user for the next medium.
   1025  */
   1026 
   1027 static int
   1028 chgreel(int dir)
   1029 {
   1030 	int lastchar, tryagain, askagain, rv;
   1031 	int tmpdev;
   1032 	char str[APATH];
   1033 	struct stat statb;
   1034 
   1035 	rv = 0;
   1036 	if (fstat(Archive, &statb) < 0)
   1037 		msg(EXTN, "Error during stat() of archive");
   1038 	if ((statb.st_mode & S_IFMT) != S_IFCHR) {
   1039 		if (dir == INPUT) {
   1040 			msg(EXT, "%s%s\n",
   1041 			    "Can't read input:  end of file encountered ",
   1042 			    "prior to expected end of archive.");
   1043 		}
   1044 	}
   1045 	msg(EPOST, "\007End of medium on \"%s\".", dir ? "output" : "input");
   1046 	if (is_floppy(Archive))
   1047 		(void) ioctl(Archive, FDEJECT, NULL);
   1048 	if ((close(Archive) != 0) && (dir == OUTPUT))
   1049 		msg(EXTN, "close error");
   1050 	Archive = 0;
   1051 	Volcnt++;
   1052 	for (;;) {
   1053 		if (Rtty_p == NULL)
   1054 			Rtty_p = fopen(Ttyname, "r");
   1055 		do { /* tryagain */
   1056 			if (IOfil_p) {
   1057 				do {
   1058 					msg(EPOST, Eom_p, Volcnt);
   1059 					if (!Rtty_p || fgets(str, sizeof (str),
   1060 					    Rtty_p) == NULL)
   1061 						msg(EXT, "Cannot read tty.");
   1062 					askagain = 0;
   1063 					switch (*str) {
   1064 					case '\n':
   1065 						(void) strcpy(str, IOfil_p);
   1066 						break;
   1067 					case 'q':
   1068 						exit(EXIT_CODE);
   1069 					default:
   1070 						askagain = 1;
   1071 					}
   1072 				} while (askagain);
   1073 			} else {
   1074 
   1075 				if (Hdr_type == BAR)
   1076 					Bar_vol_num++;
   1077 
   1078 				msg(EPOST,
   1079 				    "To continue, type device/file name when "
   1080 				    "ready.");
   1081 				if (!Rtty_p || fgets(str, sizeof (str),
   1082 				    Rtty_p) == NULL)
   1083 					msg(EXT, "Cannot read tty.");
   1084 				lastchar = strlen(str) - 1;
   1085 				if (*(str + lastchar) == '\n') /* remove '\n' */
   1086 					*(str + lastchar) = '\0';
   1087 				if (!*str)
   1088 					exit(EXIT_CODE);
   1089 			}
   1090 			tryagain = 0;
   1091 			if ((Archive = open(str, dir)) < 0) {
   1092 				msg(ERRN, "Cannot open \"%s\"", str);
   1093 				tryagain = 1;
   1094 			}
   1095 		} while (tryagain);
   1096 		(void) g_init(&tmpdev, &Archive);
   1097 		if (tmpdev != Device)
   1098 			msg(EXT, "Cannot change media types in mid-stream.");
   1099 		if (dir == INPUT)
   1100 			break;
   1101 		else { /* dir == OUTPUT */
   1102 			errno = 0;
   1103 			if ((rv = g_write(Device, Archive, Buffr.b_out_p,
   1104 			    Bufsize)) == Bufsize)
   1105 				break;
   1106 			else
   1107 				msg(ERR,
   1108 				    "Unable to write this medium, try "
   1109 				    "another.");
   1110 		}
   1111 	} /* ;; */
   1112 	Eomflag = 0;
   1113 	return (rv);
   1114 }
   1115 
   1116 /*
   1117  * ckname: Check filenames against user specified patterns,
   1118  * and/or ask the user for new name when -r is used.
   1119  */
   1120 
   1121 static int
   1122 ckname(int flag)
   1123 {
   1124 	int	lastchar;
   1125 	size_t	rename_bufsz = Max_namesz + 1;
   1126 
   1127 	if (Hdr_type != TAR && Hdr_type != USTAR && Hdr_type != BAR) {
   1128 		/* Re-visit tar size issues later */
   1129 		if (G_p->g_namesz - 1 > Max_namesz) {
   1130 			msg(ERR, "Name exceeds maximum length - skipped.");
   1131 			return (F_SKIP);
   1132 		}
   1133 	}
   1134 
   1135 	if (Pat_pp && !matched())
   1136 		return (F_SKIP);
   1137 
   1138 	/* rename interactively */
   1139 	if ((Args & OCr) && !Adir && !G_p->g_rw_sysattr) {
   1140 		(void) fprintf(Wtty_p, gettext("Rename \"%s%s%s\"? "),
   1141 		    (G_p->g_attrnam_p == NULL) ? G_p->g_nam_p : Renam_p,
   1142 		    (G_p->g_attrnam_p == NULL) ? "" : gettext(" Attribute "),
   1143 		    (G_p->g_attrnam_p == NULL) ? "" : G_p->g_attrnam_p);
   1144 		(void) fflush(Wtty_p);
   1145 		if (fgets(Renametmp_p, rename_bufsz, Rtty_p) == NULL)
   1146 			msg(EXT, "Cannot read tty.");
   1147 		if (feof(Rtty_p))
   1148 			exit(EXIT_CODE);
   1149 		lastchar = strlen(Renametmp_p) - 1;
   1150 
   1151 		/* remove trailing '\n' */
   1152 		if (*(Renametmp_p + lastchar) == '\n')
   1153 			*(Renametmp_p + lastchar) = '\0';
   1154 		if (*Renametmp_p == '\0') {
   1155 			msg(POST, "%s%s%s Skipped.",
   1156 			    (G_p->g_attrnam_p == NULL) ? G_p->g_nam_p :
   1157 			    G_p->g_attrfnam_p,
   1158 			    (G_p->g_attrnam_p == NULL) ? "" :
   1159 			    gettext(" Attribute "),
   1160 			    (G_p->g_attrnam_p == NULL) ? "" : G_p->g_attrnam_p);
   1161 			if (G_p->g_attrparent_p == NULL) {
   1162 				*G_p->g_nam_p = '\0';
   1163 			}
   1164 			if (Renam_attr_p) {
   1165 				*Renam_attr_p = '\0';
   1166 			}
   1167 			return (F_SKIP);
   1168 		} else if (strcmp(Renametmp_p, ".") != 0) {
   1169 			if (G_p->g_attrnam_p == NULL) {
   1170 				if (strlen(Renametmp_p) > strlen(
   1171 				    G_p->g_nam_p)) {
   1172 					if ((G_p->g_nam_p != &nambuf[0]) &&
   1173 					    (G_p->g_nam_p != &fullnam[0])) {
   1174 						free(G_p->g_nam_p);
   1175 						G_p->g_nam_p = e_zalloc(E_EXIT,
   1176 						    rename_bufsz);
   1177 					}
   1178 				}
   1179 				if (Renam_attr_p) {
   1180 					*Renam_attr_p = '\0';
   1181 				}
   1182 				if ((strlcpy(Renam_p, Renametmp_p,
   1183 				    rename_bufsz) > rename_bufsz) ||
   1184 				    (strlcpy(G_p->g_nam_p, Renametmp_p,
   1185 				    rename_bufsz) > rename_bufsz)) {
   1186 					msg(EXTN, "buffer overflow");
   1187 				}
   1188 			} else {
   1189 				if (G_p->g_attrnam_p != NULL) {
   1190 					free(G_p->g_attrnam_p);
   1191 					G_p->g_attrnam_p = e_strdup(E_EXIT,
   1192 					    Renametmp_p);
   1193 					(void) strcpy(G_p->g_nam_p, Renam_p);
   1194 					if (Renam_attr_p) {
   1195 						if (strlcpy(Renam_attr_p,
   1196 						    Renametmp_p, rename_bufsz) >
   1197 						    rename_bufsz) {
   1198 							msg(EXTN,
   1199 							    "buffer overflow");
   1200 						}
   1201 					}
   1202 				}
   1203 			}
   1204 		} else {
   1205 			if (G_p->g_attrnam_p == NULL) {
   1206 				*Renam_p = '\0';
   1207 			}
   1208 			if (Renam_attr_p) {
   1209 				*Renam_attr_p = '\0';
   1210 			}
   1211 		}
   1212 	}
   1213 	if (flag != 0 || Onecopy == 0) {
   1214 		VERBOSE((Args & OCt), G_p->g_nam_p);
   1215 	}
   1216 	if (Args & OCt)
   1217 		return (F_SKIP);
   1218 	return (F_EXTR);
   1219 }
   1220 
   1221 /*
   1222  * ckopts: Check the validity of all command line options.
   1223  */
   1224 
   1225 static void
   1226 ckopts(long mask)
   1227 {
   1228 	int oflag;
   1229 	char *t_p;
   1230 	long errmsk;
   1231 	uid_t	Euid = geteuid();	/* Effective uid of invoker */
   1232 #ifdef SOLARIS_PRIVS
   1233 	priv_set_t *privset;
   1234 	priv_set_t *zones_privset;
   1235 #endif	/* SOLARIS_PRIVS */
   1236 
   1237 	if (mask & OCi) {
   1238 		errmsk = mask & INV_MSK4i;
   1239 	} else if (mask & OCo) {
   1240 		errmsk = mask & INV_MSK4o;
   1241 	} else if (mask & OCp) {
   1242 		errmsk = mask & INV_MSK4p;
   1243 	} else {
   1244 		msg(ERR, "One of -i, -o or -p must be specified.");
   1245 		errmsk = 0;
   1246 	}
   1247 
   1248 	if (errmsk) {
   1249 		/* if non-zero, invalid options were specified */
   1250 		Error_cnt++;
   1251 	}
   1252 
   1253 	if ((mask & OCa) && (mask & OCm) && ((mask & OCi) ||
   1254 	    (mask & OCo))) {
   1255 		msg(ERR, "-a and -m are mutually exclusive.");
   1256 	}
   1257 
   1258 	if ((mask & OCc) && (mask & OCH) &&
   1259 	    (strcmp("odc", Hdr_p) != 0 && strcmp("odc_sparse", Hdr_p) != 0)) {
   1260 		msg(ERR, "-c and -H are mutually exclusive.");
   1261 	}
   1262 
   1263 	if ((mask & OCv) && (mask & OCV)) {
   1264 		msg(ERR, "-v and -V are mutually exclusive.");
   1265 	}
   1266 
   1267 	if ((mask & OCt) && (mask & OCV)) {
   1268 		msg(ERR, "-t and -V are mutually exclusive.");
   1269 	}
   1270 
   1271 	if ((mask & OCB) && (mask & OCC)) {
   1272 		msg(ERR, "-B and -C are mutually exclusive.");
   1273 	}
   1274 
   1275 	if ((mask & OCH) && (mask & OC6)) {
   1276 		msg(ERR, "-H and -6 are mutually exclusive.");
   1277 	}
   1278 
   1279 	if ((mask & OCM) && !((mask & OCI) || (mask & OCO))) {
   1280 		msg(ERR, "-M not meaningful without -O or -I.");
   1281 	}
   1282 
   1283 	if ((mask & OCA) && !(mask & OCO)) {
   1284 		msg(ERR, "-A requires the -O option.");
   1285 	}
   1286 
   1287 	if (Bufsize <= 0) {
   1288 		msg(ERR, "Illegal size given for -C option.");
   1289 	}
   1290 
   1291 	if (mask & OCH) {
   1292 		t_p = Hdr_p;
   1293 
   1294 		while (*t_p != NULL) {
   1295 			if (isupper(*t_p)) {
   1296 				*t_p = 'a' + (*t_p - 'A');
   1297 			}
   1298 
   1299 			t_p++;
   1300 		}
   1301 
   1302 		if (!(strcmp("odc", Hdr_p))) {
   1303 			Hdr_type = CHR;
   1304 			Max_namesz = CPATH;
   1305 			Onecopy = 0;
   1306 			Use_old_stat = 1;
   1307 		} else if (!(strcmp("odc_sparse", Hdr_p))) {
   1308 			Hdr_type = CHR;
   1309 			Max_namesz = CPATH;
   1310 			Onecopy = 0;
   1311 			Use_old_stat = 1;
   1312 			Compress_sparse = 1;
   1313 		} else if (!(strcmp("ascii_sparse", Hdr_p))) {
   1314 			Hdr_type = ASC;
   1315 			Max_namesz = APATH;
   1316 			Onecopy = 1;
   1317 			Compress_sparse = 1;
   1318 		} else if (!(strcmp("crc", Hdr_p))) {
   1319 			Hdr_type = CRC;
   1320 			Max_namesz = APATH;
   1321 			Onecopy = 1;
   1322 		} else if (!(strcmp("tar", Hdr_p))) {
   1323 			if (Args & OCo) {
   1324 				Hdr_type = USTAR;
   1325 				Max_namesz = HNAMLEN - 1;
   1326 			} else {
   1327 				Hdr_type = TAR;
   1328 				Max_namesz = TNAMLEN - 1;
   1329 			}
   1330 			Onecopy = 0;
   1331 		} else if (!(strcmp("ustar", Hdr_p))) {
   1332 			Hdr_type = USTAR;
   1333 			Max_namesz = HNAMLEN - 1;
   1334 			Onecopy = 0;
   1335 		} else if (!(strcmp("bar", Hdr_p))) {
   1336 			if ((Args & OCo) || (Args & OCp)) {
   1337 				msg(ERR,
   1338 				    "Header type bar can only be used with -i");
   1339 			}
   1340 
   1341 			if (Args & OCP) {
   1342 				msg(ERR,
   1343 				    "Can't preserve using bar header");
   1344 			}
   1345 
   1346 			Hdr_type = BAR;
   1347 			Max_namesz = TNAMLEN - 1;
   1348 			Onecopy = 0;
   1349 		} else {
   1350 			msg(ERR, "Invalid header \"%s\" specified", Hdr_p);
   1351 		}
   1352 	}
   1353 
   1354 	if (mask & OCr) {
   1355 		Rtty_p = fopen(Ttyname, "r");
   1356 		Wtty_p = fopen(Ttyname, "w");
   1357 
   1358 		if (Rtty_p == NULL || Wtty_p == NULL) {
   1359 			msg(ERR, "Cannot rename, \"%s\" missing", Ttyname);
   1360 		}
   1361 	}
   1362 
   1363 	if ((mask & OCE) && (Ef_p = fopen(Efil_p, "r")) == NULL) {
   1364 		msg(ERR, "Cannot open \"%s\" to read patterns", Efil_p);
   1365 	}
   1366 
   1367 	if ((mask & OCI) && (Archive = open(IOfil_p, O_RDONLY)) < 0) {
   1368 		msg(ERR, "Cannot open \"%s\" for input", IOfil_p);
   1369 	}
   1370 
   1371 	if (mask & OCO) {
   1372 		if (mask & OCA) {
   1373 			if ((Archive = open(IOfil_p, O_RDWR)) < 0) {
   1374 				msg(ERR,
   1375 				    "Cannot open \"%s\" for append",
   1376 				    IOfil_p);
   1377 			}
   1378 		} else {
   1379 			oflag = (O_WRONLY | O_CREAT | O_TRUNC);
   1380 
   1381 			if ((Archive = open(IOfil_p, oflag, 0777)) < 0) {
   1382 				msg(ERR,
   1383 				    "Cannot open \"%s\" for output",
   1384 				    IOfil_p);
   1385 			}
   1386 		}
   1387 	}
   1388 
   1389 #ifdef SOLARIS_PRIVS
   1390 	if ((privset = priv_allocset()) == NULL) {
   1391 		msg(ERR, "Unable to allocate privilege set");
   1392 	} else if (getppriv(PRIV_EFFECTIVE, privset) != 0) {
   1393 		msg(ERR, "Unable to obtain privilege set");
   1394 	} else {
   1395 		zones_privset = priv_str_to_set("zone", "", NULL);
   1396 		if (zones_privset != NULL) {
   1397 			privileged = (priv_issubset(zones_privset,
   1398 			    privset) == B_TRUE);
   1399 			priv_freeset(zones_privset);
   1400 		} else {
   1401 			msg(ERR, "Unable to map privilege to privilege set");
   1402 		}
   1403 	}
   1404 	if (privset != NULL) {
   1405 		priv_freeset(privset);
   1406 	}
   1407 #else
   1408 	privileged = (Euid == 0);
   1409 #endif	/* SOLARIS_PRIVS */
   1410 
   1411 	if (mask & OCR) {
   1412 		if ((Rpw_p = getpwnam(Own_p)) == NULL) {
   1413 			msg(ERR, "\"%s\" is not a valid user id", Own_p);
   1414 		} else if ((Euid != Rpw_p->pw_uid) && !privileged) {
   1415 			msg(ERR, "R option only valid for super-user or "
   1416 			    "id matches login id of user executing cpio");
   1417 		}
   1418 	}
   1419 
   1420 	if ((mask & OCo) && !(mask & OCO)) {
   1421 		Out_p = stderr;
   1422 	}
   1423 
   1424 	if ((mask & OCp) && ((mask & (OCB|OCC)) == 0)) {
   1425 		/*
   1426 		 * We are in pass mode with no block size specified.  Use the
   1427 		 * larger of the native page size and 8192.
   1428 		 */
   1429 
   1430 		Bufsize = (PageSize > 8192) ? PageSize : 8192;
   1431 	}
   1432 }
   1433 
   1434 /*
   1435  * cksum: Calculate the simple checksum of a file (CRC) or header
   1436  * (TARTYP (TAR and USTAR)).  For -o and the CRC header, the file is opened and
   1437  * the checksum is calculated.  For -i and the CRC header, the checksum
   1438  * is calculated as each block is transferred from the archive I/O buffer
   1439  * to the file system I/O buffer.  The TARTYP (TAR and USTAR) headers calculate
   1440  * the simple checksum of the header (with the checksum field of the
   1441  * header initialized to all spaces (\040).
   1442  */
   1443 
   1444 static long
   1445 cksum(char hdr, int byt_cnt, int *err)
   1446 {
   1447 	char *crc_p, *end_p;
   1448 	int cnt;
   1449 	long checksum = 0L, have;
   1450 	off_t lcnt;
   1451 
   1452 	if (err != NULL)
   1453 		*err = 0;
   1454 	switch (hdr) {
   1455 	case CRC:
   1456 		if (Args & OCi) { /* do running checksum */
   1457 			end_p = Buffr.b_out_p + byt_cnt;
   1458 			for (crc_p = Buffr.b_out_p; crc_p < end_p; crc_p++)
   1459 				checksum += (long)*crc_p;
   1460 			break;
   1461 		}
   1462 		/* OCo - do checksum of file */
   1463 		lcnt = G_p->g_filesz;
   1464 
   1465 		while (lcnt > 0) {
   1466 			have = (lcnt < Bufsize) ? lcnt : Bufsize;
   1467 			errno = 0;
   1468 			if (read(Ifile, Buf_p, have) != have) {
   1469 				msg(ERR, "Error computing checksum.");
   1470 				if (err != NULL)
   1471 					*err = 1;
   1472 				break;
   1473 			}
   1474 			end_p = Buf_p + have;
   1475 			for (crc_p = Buf_p; crc_p < end_p; crc_p++)
   1476 				checksum += (long)*crc_p;
   1477 			lcnt -= have;
   1478 		}
   1479 		if (lseek(Ifile, (off_t)0, SEEK_ABS) < 0)
   1480 			msg(ERRN, "Cannot reset file after checksum");
   1481 		break;
   1482 	case TARTYP: /* TAR and USTAR */
   1483 		crc_p = Thdr_p->tbuf.t_cksum;
   1484 		for (cnt = 0; cnt < TCRCLEN; cnt++) {
   1485 			*crc_p = '\040';
   1486 			crc_p++;
   1487 		}
   1488 		crc_p = (char *)Thdr_p;
   1489 		for (cnt = 0; cnt < TARSZ; cnt++) {
   1490 			/*
   1491 			 * tar uses unsigned checksum, so we must use unsigned
   1492 			 * here in order to be able to read tar archives.
   1493 			 */
   1494 			checksum += (long)((unsigned char)(*crc_p));
   1495 			crc_p++;
   1496 		}
   1497 		break;
   1498 	default:
   1499 		msg(EXT, "Impossible header type.");
   1500 	} /* hdr */
   1501 	return (checksum);
   1502 }
   1503 
   1504 /*
   1505  * creat_hdr: Fill in the generic header structure with the specific
   1506  *            header information based on the value of Hdr_type.
   1507  *
   1508  *            return (1) if this process was successful, and (0) otherwise.
   1509  */
   1510 
   1511 static int
   1512 creat_hdr(void)
   1513 {
   1514 	ushort_t ftype;
   1515 	int fullnamesize;
   1516 	dev_t dev;
   1517 	ino_t ino;
   1518 
   1519 	ftype = SrcSt.st_mode & Ftype;
   1520 	Adir = (ftype == S_IFDIR);
   1521 	Aspec = (ftype == S_IFBLK || ftype == S_IFCHR || ftype == S_IFIFO ||
   1522 	    ftype == S_IFSOCK);
   1523 	switch (Hdr_type) {
   1524 		case BIN:
   1525 			Gen.g_magic = CMN_BIN;
   1526 			break;
   1527 		case CHR:
   1528 			Gen.g_magic = CMN_BIN;
   1529 			break;
   1530 		case ASC:
   1531 			Gen.g_magic = CMN_ASC;
   1532 			break;
   1533 		case CRC:
   1534 			Gen.g_magic = CMN_CRC;
   1535 			break;
   1536 		case USTAR:
   1537 			/*
   1538 			 * If the length of the full name is greater than 256,
   1539 			 * print out a message and return.
   1540 			 */
   1541 			if ((fullnamesize = strlen(Gen.g_nam_p)) > MAXNAM) {
   1542 				msg(ERR,
   1543 				    "%s: file name too long", Gen.g_nam_p);
   1544 				return (0);
   1545 			} else if (fullnamesize > NAMSIZ) {
   1546 				/*
   1547 				 * The length of the full name is greater than
   1548 				 * 100, so we must split the filename from the
   1549 				 * path
   1550 				 */
   1551 				char namebuff[NAMSIZ+1];
   1552 				char prebuff[PRESIZ+1];
   1553 				char *lastslash;
   1554 				int presize, namesize;
   1555 
   1556 				(void) memset(namebuff, '\0',
   1557 				    sizeof (namebuff));
   1558 				(void) memset(prebuff, '\0', sizeof (prebuff));
   1559 
   1560 				lastslash = strrchr(Gen.g_nam_p, '/');
   1561 
   1562 				if (lastslash != NULL) {
   1563 					namesize = strlen(++lastslash);
   1564 					presize = fullnamesize - namesize - 1;
   1565 				} else {
   1566 					namesize = fullnamesize;
   1567 					lastslash = Gen.g_nam_p;
   1568 					presize = 0;
   1569 				}
   1570 
   1571 				/*
   1572 				 * If the filename is greater than 100 we can't
   1573 				 * archive the file
   1574 				 */
   1575 				if (namesize > NAMSIZ) {
   1576 					msg(ERR,
   1577 					    "%s: filename is greater than %d",
   1578 					    lastslash, NAMSIZ);
   1579 					return (0);
   1580 				}
   1581 				(void) strncpy(&namebuff[0], lastslash,
   1582 				    namesize);
   1583 				/*
   1584 				 * If the prefix is greater than 155 we can't
   1585 				 * archive the file.
   1586 				 */
   1587 				if (presize > PRESIZ) {
   1588 					msg(ERR,
   1589 					    "%s: prefix is greater than %d",
   1590 					    Gen.g_nam_p, PRESIZ);
   1591 					return (0);
   1592 				}
   1593 				(void) strncpy(&prebuff[0], Gen.g_nam_p,
   1594 				    presize);
   1595 
   1596 				Gen.g_tname = e_zalloc(E_EXIT, namesize + 1);
   1597 				(void) strcpy(Gen.g_tname, namebuff);
   1598 
   1599 				Gen.g_prefix = e_zalloc(E_EXIT, presize + 1);
   1600 				(void) strcpy(Gen.g_prefix, prebuff);
   1601 			} else {
   1602 				Gen.g_tname = Gen.g_nam_p;
   1603 			}
   1604 			(void) strcpy(Gen.g_tmagic, "ustar");
   1605 			(void) strcpy(Gen.g_version, "00");
   1606 
   1607 			dpasswd = getpwuid(SrcSt.st_uid);
   1608 			if (dpasswd == NULL) {
   1609 				msg(EPOST,
   1610 				    "cpio: could not get passwd information "
   1611 				    "for %s%s%s",
   1612 				    (Gen.g_attrnam_p == NULL) ?
   1613 				    Gen.g_nam_p : Gen.g_attrfnam_p,
   1614 				    (Gen.g_attrnam_p == NULL) ?
   1615 				    "" : Gen.g_rw_sysattr ?
   1616 				    gettext(" System Attribute ") :
   1617 				    gettext(" Attribute "),
   1618 				    (Gen.g_attrnam_p == NULL) ?
   1619 				    "" : Gen.g_attrnam_p);
   1620 				/* make name null string */
   1621 				Gen.g_uname[0] = '\0';
   1622 			} else {
   1623 				(void) strncpy(&Gen.g_uname[0],
   1624 				    dpasswd->pw_name, 32);
   1625 			}
   1626 			dgroup = getgrgid(SrcSt.st_gid);
   1627 			if (dgroup == NULL) {
   1628 				msg(EPOST,
   1629 				    "cpio: could not get group information "
   1630 				    "for %s%s%s",
   1631 				    (Gen.g_attrnam_p == NULL) ?
   1632 				    Gen.g_nam_p : Gen.g_attrfnam_p,
   1633 				    (Gen.g_attrnam_p == NULL) ?
   1634 				    "" : Gen.g_rw_sysattr ?
   1635 				    gettext(" System Attribute ") :
   1636 				    gettext(" Attribute "),
   1637 				    (Gen.g_attrnam_p == NULL) ?
   1638 				    "" : Gen.g_attrnam_p);
   1639 				/* make name null string */
   1640 				Gen.g_gname[0] = '\0';
   1641 			} else {
   1642 				(void) strncpy(&Gen.g_gname[0],
   1643 				    dgroup->gr_name, 32);
   1644 			}
   1645 			Gen.g_typeflag = tartype(ftype);
   1646 			/* FALLTHROUGH */
   1647 		case TAR:
   1648 			(void) memset(T_lname, '\0', sizeof (T_lname));
   1649 			break;
   1650 		default:
   1651 			msg(EXT, "Impossible header type.");
   1652 	}
   1653 
   1654 	if (Use_old_stat && (Gen.g_attrnam_p != NULL)) {
   1655 		/*
   1656 		 * When processing extended attributes, creat_hdr()
   1657 		 * can get called multiple times which means that
   1658 		 * SrcSt.st.st_dev would have gotten converted to
   1659 		 * -Hodc format.  We should always use the original
   1660 		 * device here as we need to be able to match on
   1661 		 * the original device id from the file that was
   1662 		 * previewed in sl_preview_synonyms().
   1663 		 */
   1664 		dev = Savedev;
   1665 	} else {
   1666 		dev = SrcSt.st_dev;
   1667 	}
   1668 	ino = SrcSt.st_ino;
   1669 
   1670 	if (Use_old_stat) {
   1671 		SrcSt = *OldSt;
   1672 	}
   1673 
   1674 	Gen.g_namesz = strlen(Gen.g_nam_p) + 1;
   1675 	Gen.g_uid = SrcSt.st_uid;
   1676 	Gen.g_gid = SrcSt.st_gid;
   1677 	Gen.g_dev = SrcSt.st_dev;
   1678 
   1679 	if (Use_old_stat) {
   1680 		/* -Hodc */
   1681 
   1682 		sl_info_t *p = sl_search(dev, ino, ftype);
   1683 		Gen.g_ino = p ? p->sl_ino2 : -1;
   1684 
   1685 		if (Gen.g_ino == (ulong_t)-1) {
   1686 			msg(ERR, "%s%s%s: cannot be archived - inode too big "
   1687 			    "for -Hodc format",
   1688 			    (Gen.g_attrnam_p == NULL) ?
   1689 			    Gen.g_nam_p : Gen.g_attrfnam_p,
   1690 			    (Gen.g_attrnam_p == NULL) ? "" : Gen.g_rw_sysattr ?
   1691 			    gettext(" System Attribute ") :
   1692 			    gettext(" Attribute "),
   1693 			    (Gen.g_attrnam_p == NULL) ? "" : Gen.g_attrnam_p);
   1694 			return (0);
   1695 		}
   1696 	} else {
   1697 		Gen.g_ino = SrcSt.st_ino;
   1698 	}
   1699 
   1700 	Gen.g_mode = SrcSt.st_mode;
   1701 	Gen.g_mtime = SrcSt.st_mtime;
   1702 	Gen.g_nlink = Adir ? SrcSt.st_nlink : sl_numlinks(dev, ino, ftype);
   1703 
   1704 	if (ftype == S_IFREG || ftype == S_IFLNK)
   1705 		Gen.g_filesz = (off_t)SrcSt.st_size;
   1706 	else
   1707 		Gen.g_filesz = (off_t)0;
   1708 	Gen.g_rdev = SrcSt.st_rdev;
   1709 	return (1);
   1710 }
   1711 
   1712 /*
   1713  * creat_lnk: Create a link from the existing name1_p to name2_p.
   1714  */
   1715 
   1716 static
   1717 int
   1718 creat_lnk(int dirfd, char *name1_p, char *name2_p)
   1719 {
   1720 	int cnt = 0;
   1721 
   1722 	do {
   1723 		errno = 0;
   1724 		if (!link(name1_p, name2_p)) {
   1725 			if (aclp != NULL) {
   1726 				acl_free(aclp);
   1727 				aclp = NULL;
   1728 				acl_is_set = 0;
   1729 			}
   1730 			cnt = 0;
   1731 			break;
   1732 		} else if ((errno == EEXIST) && (cnt == 0)) {
   1733 			struct stat lsb1;
   1734 			struct stat lsb2;
   1735 
   1736 			/*
   1737 			 * Check to see if we are trying to link this
   1738 			 * file to itself.  If so, count the effort as
   1739 			 * successful.  If the two files are different,
   1740 			 * or if either lstat is unsuccessful, proceed
   1741 			 * as we would have otherwise; the appropriate
   1742 			 * error will be reported subsequently.
   1743 			 */
   1744 
   1745 			if (lstat(name1_p, &lsb1) != 0) {
   1746 				msg(ERR, "Cannot lstat source file %s",
   1747 				    name1_p);
   1748 			} else {
   1749 				if (lstat(name2_p, &lsb2) != 0) {
   1750 					msg(ERR, "Cannot lstat "
   1751 					    "destination file %s", name2_p);
   1752 				} else {
   1753 					if (lsb1.st_dev == lsb2.st_dev &&
   1754 					    lsb1.st_ino == lsb2.st_ino) {
   1755 						VERBOSE((Args & (OCv | OCV)),
   1756 						    name2_p);
   1757 						return (0);
   1758 					}
   1759 				}
   1760 			}
   1761 
   1762 			if (!(Args & OCu) && G_p->g_mtime <= DesSt.st_mtime)
   1763 				msg(ERR, "Existing \"%s\" same age or newer",
   1764 				    name2_p);
   1765 			else if (unlinkat(dirfd, get_component(name2_p), 0) < 0)
   1766 				msg(ERRN, "Error cannot unlink \"%s\"",
   1767 				    name2_p);
   1768 		}
   1769 		cnt++;
   1770 	} while ((cnt < 2) && missdir(name2_p) == 0);
   1771 	if (!cnt) {
   1772 		char *newname;
   1773 		char *fromname;
   1774 		char *attrname;
   1775 
   1776 		newname = name2_p;
   1777 		fromname = name1_p;
   1778 		attrname = Gen.g_attrnam_p;
   1779 		if (attrname) {
   1780 			if (Args & OCp) {
   1781 				newname = fromname = Fullnam_p;
   1782 			} else {
   1783 				newname = Gen.g_attrfnam_p;
   1784 			}
   1785 		}
   1786 		if (Args & OCv) {
   1787 			(void) fprintf(Err_p,
   1788 			    gettext("%s%s%s linked to %s%s%s\n"), newname,
   1789 			    (attrname == NULL) ? "" : gettext(" attribute "),
   1790 			    (attrname == NULL) ? "" : attrname,
   1791 			    (attrname == NULL) ? fromname : newname,
   1792 			    (attrname == NULL) ? "" : gettext(" attribute "),
   1793 			    (attrname == NULL) ? "" : name1_p);
   1794 		} else {
   1795 			VERBOSE((Args & (OCv | OCV)), newname);
   1796 		}
   1797 	} else if (cnt == 1)
   1798 		msg(ERRN,
   1799 		    "Unable to create directory for \"%s\"", name2_p);
   1800 	else if (cnt == 2)
   1801 		msg(ERRN,
   1802 		    "Cannot link \"%s\" and \"%s\"", name1_p, name2_p);
   1803 	return (cnt);
   1804 }
   1805 
   1806 /*
   1807  * creat_spec:
   1808  *   Create one of the following:
   1809  *       directory
   1810  *       character special file
   1811  *       block special file
   1812  *       fifo
   1813  *	 socket
   1814  */
   1815 
   1816 static int
   1817 creat_spec(int dirfd)
   1818 {
   1819 	char *nam_p;
   1820 	int cnt, result, rv = 0;
   1821 	char *curdir;
   1822 	char *lastslash;
   1823 
   1824 	Do_rename = 0;	/* creat_tmp() may reset this */
   1825 
   1826 	if (Args & OCp) {
   1827 		nam_p = Fullnam_p;
   1828 	} else {
   1829 		nam_p = G_p->g_nam_p;
   1830 	}
   1831 
   1832 	/*
   1833 	 * Is this the extraction of the hidden attribute directory?
   1834 	 * If we are processing the hidden attribute directory of an
   1835 	 * attribute, then just return as modes and times cannot be set.
   1836 	 * Otherwise, if we are processing a hidden attribute, just set
   1837 	 * the mode/times correctly and return.
   1838 	 */
   1839 
   1840 	if (Hiddendir) {
   1841 		if (G_p->g_attrparent_p == NULL) {
   1842 			if (Args & OCR) {
   1843 				if (fchownat(dirfd, ".", Rpw_p->pw_uid,
   1844 				    Rpw_p->pw_gid, 0) != 0) {
   1845 					msg(ERRN,
   1846 					    "Cannot chown() \"attribute "
   1847 					    "directory of file %s\"",
   1848 					    G_p->g_attrfnam_p);
   1849 				}
   1850 			} else if ((fchownat(dirfd, ".", G_p->g_uid,
   1851 			    G_p->g_gid, 0) != 0) && privileged) {
   1852 				msg(ERRN,
   1853 				    "Cannot chown() \"attribute directory of "
   1854 				    "file %s\"", G_p->g_attrfnam_p);
   1855 			}
   1856 
   1857 			if (fchmod(dirfd, G_p->g_mode) != 0) {
   1858 				msg(ERRN,
   1859 				    "Cannot chmod() \"attribute directory of "
   1860 				    "file %s\"", G_p->g_attrfnam_p);
   1861 			}
   1862 
   1863 			acl_is_set = 0;
   1864 			if (Pflag && aclp != NULL) {
   1865 				if (facl_set(dirfd, aclp) < 0) {
   1866 					msg(ERRN,
   1867 					    "failed to set acl on attribute"
   1868 					    " directory of %s ",
   1869 					    G_p->g_attrfnam_p);
   1870 				} else {
   1871 					acl_is_set = 1;
   1872 				}
   1873 				acl_free(aclp);
   1874 				aclp = NULL;
   1875 			}
   1876 		}
   1877 
   1878 		return (1);
   1879 	}
   1880 
   1881 	result = stat(nam_p, &DesSt);
   1882 
   1883 	if (ustar_dir() || Adir) {
   1884 		/*
   1885 		 *  The archive file is a directory.
   1886 		 *  Skip "." and ".."
   1887 		 */
   1888 
   1889 		curdir = strrchr(nam_p, '.');
   1890 
   1891 		if (curdir != NULL && curdir[1] == NULL) {
   1892 			lastslash = strrchr(nam_p, '/');
   1893 
   1894 			if (lastslash != NULL) {
   1895 				lastslash++;
   1896 			} else {
   1897 				lastslash = nam_p;
   1898 			}
   1899 
   1900 			if (!(strcmp(lastslash, ".")) ||
   1901 			    !(strcmp(lastslash, ".."))) {
   1902 				return (1);
   1903 			}
   1904 		}
   1905 
   1906 		if (result == 0) {
   1907 			/* A file by the same name exists. */
   1908 
   1909 			/* Take care of ACLs */
   1910 			acl_is_set = 0;
   1911 
   1912 			if (Pflag && aclp != NULL) {
   1913 				if (acl_set(nam_p, aclp) < 0) {
   1914 					msg(ERRN,
   1915 					    "\"%s\": failed to set acl",
   1916 					    nam_p);
   1917 				} else {
   1918 					acl_is_set = 1;
   1919 				}
   1920 
   1921 				acl_free(aclp);
   1922 				aclp = NULL;
   1923 			}
   1924 			if (Args & OCd) {
   1925 				/*
   1926 				 * We are creating directories.  Keep the
   1927 				 * existing file.
   1928 				 */
   1929 
   1930 				rstfiles(U_KEEP, dirfd);
   1931 			}
   1932 
   1933 			/* Report success. */
   1934 
   1935 			return (1);
   1936 		}
   1937 	} else {
   1938 		/* The archive file is not a directory. */
   1939 
   1940 		if (result == 0) {
   1941 			/*
   1942 			 * A file by the same name exists.  Move it to a
   1943 			 * temporary file.
   1944 			 */
   1945 
   1946 			if (creat_tmp(nam_p) < 0) {
   1947 				/*
   1948 				 * We weren't able to create the temp file.
   1949 				 * Report failure.
   1950 				 */
   1951 
   1952 				return (0);
   1953 			}
   1954 		}
   1955 	}
   1956 
   1957 	/*
   1958 	 * This pile tries to create the file directly, and, if there is a
   1959 	 * problem, creates missing directories, and then tries to create the
   1960 	 * file again.  Two strikes and you're out.
   1961 	 */
   1962 
   1963 	cnt = 0;
   1964 
   1965 	do {
   1966 		if (ustar_dir() || Adir) {
   1967 			/* The archive file is a directory. */
   1968 
   1969 			result = mkdir(nam_p, G_p->g_mode);
   1970 		} else if (ustar_spec() || Aspec) {
   1971 			/*
   1972 			 * The archive file is block special,
   1973 			 * char special, socket, or a fifo.
   1974 			 * Note that, for a socket, the third
   1975 			 * parameter to mknod() is ignored.
   1976 			 */
   1977 
   1978 			result = mknod(nam_p, (int)G_p->g_mode,
   1979 			    (int)G_p->g_rdev);
   1980 		}
   1981 
   1982 		if (result >= 0) {
   1983 			/*
   1984 			 * The file creation succeeded.  Take care of the ACLs.
   1985 			 */
   1986 
   1987 			acl_is_set = 0;
   1988 
   1989 			if (Pflag && aclp != NULL) {
   1990 				if (acl_set(nam_p, aclp) < 0) {
   1991 					msg(ERRN,
   1992 					    "\"%s\": failed to set acl", nam_p);
   1993 				} else {
   1994 					acl_is_set = 1;
   1995 				}
   1996 
   1997 				acl_free(aclp);
   1998 				aclp = NULL;
   1999 			}
   2000 
   2001 			cnt = 0;
   2002 			break;
   2003 		}
   2004 
   2005 		cnt++;
   2006 	} while (cnt < 2 && missdir(nam_p) == 0);
   2007 
   2008 	switch (cnt) {
   2009 	case 0:
   2010 		rv = 1;
   2011 		rstfiles(U_OVER, dirfd);
   2012 		break;
   2013 
   2014 	case 1:
   2015 		msg(ERRN,
   2016 		    "Cannot create directory for \"%s\"", nam_p);
   2017 
   2018 		if (*Over_p == '\0') {
   2019 			rstfiles(U_KEEP, dirfd);
   2020 		}
   2021 
   2022 		break;
   2023 
   2024 	case 2:
   2025 		if (ustar_dir() || Adir) {
   2026 			msg(ERRN, "Cannot create directory \"%s\"", nam_p);
   2027 		} else if (ustar_spec() || Aspec) {
   2028 			msg(ERRN, "Cannot mknod() \"%s\"", nam_p);
   2029 		}
   2030 
   2031 		if (*Over_p == '\0') {
   2032 			rstfiles(U_KEEP, dirfd);
   2033 		}
   2034 
   2035 		break;
   2036 
   2037 	default:
   2038 		msg(EXT, "Impossible case.");
   2039 	}
   2040 
   2041 	return (rv);
   2042 }
   2043 
   2044 /*
   2045  * creat_tmp:
   2046  */
   2047 
   2048 static int
   2049 creat_tmp(char *nam_p)
   2050 {
   2051 	char *t_p;
   2052 	int	cwd;
   2053 
   2054 	if ((Args & OCp) && G_p->g_ino == DesSt.st_ino &&
   2055 	    G_p->g_dev == DesSt.st_dev) {
   2056 		msg(ERR, "Attempt to pass a file to itself.");
   2057 		return (-1);
   2058 	}
   2059 
   2060 	if (G_p->g_mtime <= DesSt.st_mtime && !(Args & OCu)) {
   2061 		msg(ERR, "Existing \"%s\" same age or newer", nam_p);
   2062 		return (-1);
   2063 	}
   2064 
   2065 	/* Make the temporary file name. */
   2066 
   2067 	(void) strcpy(Over_p, nam_p);
   2068 	t_p = Over_p + strlen(Over_p);
   2069 
   2070 	while (t_p != Over_p) {
   2071 		if (*(t_p - 1) == '/')
   2072 			break;
   2073 		t_p--;
   2074 	}
   2075 
   2076 	(void) strcpy(t_p, "XXXXXX");
   2077 
   2078 	if (G_p->g_attrnam_p != NULL) {
   2079 		/*
   2080 		 * Save our current directory, so we can go into
   2081 		 * the attribute directory to make the temp file
   2082 		 * and then return.
   2083 		 */
   2084 
   2085 		cwd = save_cwd();
   2086 		(void) fchdir(G_p->g_dirfd);
   2087 	}
   2088 
   2089 	(void) mktemp(Over_p);
   2090 
   2091 	if (G_p->g_attrnam_p != NULL) {
   2092 		/* Return to the current directory. */
   2093 
   2094 		rest_cwd(cwd);
   2095 	}
   2096 
   2097 	if (*Over_p == '\0') {
   2098 		/* mktemp reports a failure. */
   2099 
   2100 		msg(ERR, "Cannot get temporary file name.");
   2101 		return (-1);
   2102 	}
   2103 
   2104 	/*
   2105 	 * If it's a regular file, write to the temporary file, and then rename
   2106 	 * in order to accommodate potential executables.
   2107 	 *
   2108 	 * Note: g_typeflag is only defined (set) for USTAR archive types.  It
   2109 	 * defaults to 0 in the cpio-format-regular file case, so this test
   2110 	 * succeeds.
   2111 	 */
   2112 
   2113 	if (G_p->g_typeflag == 0 &&
   2114 	    (DesSt.st_mode & (ulong_t)Ftype) == S_IFREG &&
   2115 	    (G_p->g_mode & (ulong_t)Ftype) == S_IFREG) {
   2116 		/*
   2117 		 * The archive file and the filesystem file are both regular
   2118 		 * files.  We write to the temporary file in this case.
   2119 		 */
   2120 
   2121 		if (Args & OCp) {
   2122 			if (G_p->g_attrnam_p == NULL) {
   2123 				Fullnam_p = Over_p;
   2124 			} else {
   2125 				Attrfile_p = Over_p;
   2126 			}
   2127 		} else {
   2128 			G_p->g_nam_p = Over_p;
   2129 			if (G_p->g_attrnam_p != NULL) {
   2130 				Attrfile_p = Over_p;
   2131 			}
   2132 		}
   2133 
   2134 		if (G_p->g_attrnam_p == NULL) {
   2135 			Over_p = nam_p;
   2136 		} else {
   2137 			Over_p = G_p->g_attrnam_p;
   2138 		}
   2139 
   2140 		Do_rename = 1;
   2141 	} else {
   2142 		/*
   2143 		 * Either the archive file or the filesystem file is not a
   2144 		 * regular file.
   2145 		 */
   2146 
   2147 		Do_rename = 0;
   2148 
   2149 		if (S_ISDIR(DesSt.st_mode)) {
   2150 			/*
   2151 			 * The filesystem file is a directory.
   2152 			 *
   2153 			 * Save the current working directory because we will
   2154 			 * want to restore it back just in case remove_dir()
   2155 			 * fails or get confused about where we should be.
   2156 			 */
   2157 
   2158 			*Over_p = '\0';
   2159 			cwd = save_cwd();
   2160 
   2161 			if (remove_dir(nam_p) < 0) {
   2162 				msg(ERRN,
   2163 				    "Cannot remove the directory \"%s\"",
   2164 				    nam_p);
   2165 				/*
   2166 				 * Restore working directory back to the one
   2167 				 * saved earlier.
   2168 				 */
   2169 
   2170 				rest_cwd(cwd);
   2171 				return (-1);
   2172 			}
   2173 
   2174 			/*
   2175 			 * Restore working directory back to the one
   2176 			 * saved earlier
   2177 			 */
   2178 
   2179 			rest_cwd(cwd);
   2180 		} else {
   2181 			/*
   2182 			 * The file is not a directory. Will use the original
   2183 			 * link/unlink construct, however, if the file is
   2184 			 * namefs, link would fail with EXDEV. Therefore, we
   2185 			 * use rename() first to back up the file.
   2186 			 */
   2187 			if (rename(nam_p, Over_p) < 0) {
   2188 				/*
   2189 				 * If rename failed, try old construction
   2190 				 * method.
   2191 				 */
   2192 				if (link(nam_p, Over_p) < 0) {
   2193 					msg(ERRN,
   2194 					    "Cannot rename temporary file "
   2195 					    "\"%s\" to \"%s\"", Over_p, nam_p);
   2196 					*Over_p = '\0';
   2197 					return (-1);
   2198 				}
   2199 
   2200 				if (unlink(nam_p) < 0) {
   2201 					msg(ERRN,
   2202 					    "Cannot unlink() current \"%s\"",
   2203 					    nam_p);
   2204 					(void) unlink(Over_p);
   2205 					*Over_p = '\0';
   2206 					return (-1);
   2207 				}
   2208 			}
   2209 		}
   2210 	}
   2211 
   2212 	return (1);
   2213 }
   2214 
   2215 /*
   2216  * Copy the datasize amount of data from the input file to buffer.
   2217  *
   2218  * ifd		- Input file descriptor.
   2219  * buffer	- Buffer (allocated by caller) to copy data to.
   2220  * datasize	- The amount of data to read from the input file
   2221  *		and copy to the buffer.
   2222  * error	- When reading from an Archive file, indicates unreadable
   2223  *		data was encountered, otherwise indicates errno.
   2224  * data_in_info	- Information needed when called from data_in().
   2225  */
   2226 static ssize_t
   2227 read_chunk(int ifd, char *buffer, size_t datasize, data_in_t *data_in_info)
   2228 {
   2229 	if (Args & OCp) {
   2230 		return (read(ifd, buffer, datasize));
   2231 	} else {
   2232 		FILL(datasize);
   2233 		if (data_in_info->data_in_proc_mode != P_SKIP) {
   2234 			if (Hdr_type == CRC)
   2235 				data_in_info->data_in_cksumval += cksum(CRC,
   2236 				    datasize, NULL);
   2237 			if (data_in_info->data_in_swapfile)
   2238 				swap(Buffr.b_out_p, datasize);
   2239 
   2240 
   2241 			/*
   2242 			 * if the bar archive is compressed, set up a pipe and
   2243 			 * do the de-compression while reading in the file
   2244 			 */
   2245 			if (Hdr_type == BAR) {
   2246 				if (data_in_info->data_in_compress_flag == 0 &&
   2247 				    Compressed) {
   2248 					setup_uncompress(
   2249 					    &(data_in_info->data_in_pipef));
   2250 					data_in_info->data_in_compress_flag++;
   2251 				}
   2252 			}
   2253 		}
   2254 		(void) memcpy(buffer, Buffr.b_out_p, datasize);
   2255 		Buffr.b_out_p += datasize;
   2256 		Buffr.b_cnt -= datasize;
   2257 		return (datasize);
   2258 	}
   2259 }
   2260 
   2261 /*
   2262  * Read as much data as we can.
   2263  *
   2264  * ifd		- input file descriptor.
   2265  * buf		- Buffer (allocated by caller) to copy data to.
   2266  * bytes	- The amount of data to read from the input file
   2267  *		and copy to the buffer.
   2268  * rdblocksz	- The size of the chunk of data to read.
   2269  *
   2270  * Return number of bytes failed to read.
   2271  * Return -1 when buffer is empty and read failed.
   2272  */
   2273 static int
   2274 read_bytes(int ifd, char *buf, size_t bytes, size_t rdblocksz,
   2275     data_in_t *data_in_info)
   2276 {
   2277 	size_t	bytesread;
   2278 	ssize_t	got;
   2279 
   2280 	for (bytesread = 0; bytesread < bytes; bytesread += got) {
   2281 		/*
   2282 		 * Read the data from either the input file descriptor
   2283 		 * or the archive file.  read_chunk() will only return
   2284 		 * <= 0 if data_copy() was called from data_pass().
   2285 		 */
   2286 		if ((got = read_chunk(ifd, buf + bytesread,
   2287 		    min(bytes - bytesread, rdblocksz),
   2288 		    data_in_info)) <= 0) {
   2289 			/*
   2290 			 * We come here only in the pass mode.
   2291 			 * If data couldn't be read from the input file
   2292 			 * descriptor, return number of bytes in the buf.
   2293 			 * If buffer is empty, return -1.
   2294 			 */
   2295 			if (bytesread == 0) {
   2296 				if (got == 0) /* EOF */
   2297 					data_in_info->data_in_rd_eof = 1;
   2298 				return (-1);
   2299 			}
   2300 			return (bytes - bytesread);
   2301 		}
   2302 	}
   2303 	return (0);
   2304 }
   2305 
   2306 /*
   2307  * Write as much data as we can.
   2308  *
   2309  * ofd		- output file descriptor.
   2310  * buf		- Source buffer to output data from.
   2311  * maxwrite	- The amount of data to write to the output.
   2312  *
   2313  * return 0 upon success.
   2314  */
   2315 static int
   2316 write_bytes(int ofd, char *buf, size_t maxwrite, data_in_t *data_in_info)
   2317 {
   2318 	ssize_t	cnt;
   2319 
   2320 	errno = 0;
   2321 	if ((cnt = write(ofd, buf, maxwrite)) < (ssize_t)maxwrite) {
   2322 		data_in_info->data_in_errno = errno;
   2323 		/*
   2324 		 * data_in() needs to know if it was an actual write(2)
   2325 		 * failure, or if we just couldn't write all of the data
   2326 		 * requested so that we know that the rest of the file's
   2327 		 * data can be read but not written.
   2328 		 */
   2329 		if (cnt != -1)
   2330 			data_in_info->data_in_wr_part = 1;
   2331 		return (1);
   2332 	} else if (Args & OCp) {
   2333 		Blocks += (u_longlong_t)((cnt + (Bufsize - 1)) / Bufsize);
   2334 	}
   2335 	return (0);
   2336 }
   2337 
   2338 /*
   2339  * Perform I/O for given byte size with using limited i/o block size
   2340  * and supplied buffer.
   2341  *
   2342  * ifd/ofd	- i/o file descriptor
   2343  * buf		- buffer to be used for i/o
   2344  * bytes	- Amount to read/write
   2345  * wrblocksz	- Output block size.
   2346  * rdblocksz	- Read block size.
   2347  *
   2348  * Return 0 upon success. Return negative if read failed.
   2349  * Return positive non-zero if write failed.
   2350  */
   2351 static int
   2352 rdwr_bytes(int ifd, int ofd, char *buf, off_t bytes,
   2353     size_t wrblocksz, size_t rdblocksz, data_in_t *data_in_info)
   2354 {
   2355 	int rv, sz;
   2356 	int error = 0;
   2357 	int write_it = (data_in_info->data_in_proc_mode != P_SKIP);
   2358 
   2359 	while (bytes > 0) {
   2360 		/*
   2361 		 * If the number of bytes left to write is smaller than
   2362 		 * the preferred I/O size, then we're about to do our final
   2363 		 * write to the file, so just set wrblocksz to the number of
   2364 		 * bytes left to write.
   2365 		 */
   2366 		if (bytes < wrblocksz)
   2367 			wrblocksz = bytes;
   2368 
   2369 		/* Read input till satisfy output block size */
   2370 		sz = read_bytes(ifd, buf, wrblocksz, rdblocksz, data_in_info);
   2371 		if (sz < 0)
   2372 			return (sz);
   2373 
   2374 		if (write_it) {
   2375 			rv = write_bytes(ofd, buf,
   2376 			    wrblocksz - sz, data_in_info);
   2377 			if (rv != 0) {
   2378 				/*
   2379 				 * If we wrote partial, we return and quits.
   2380 				 * Otherwise, read through the rest of input
   2381 				 * to go to the next file.
   2382 				 */
   2383 				if ((Args & OCp) ||
   2384 				    data_in_info->data_in_wr_part) {
   2385 					return (rv);
   2386 				} else {
   2387 					write_it = 0;
   2388 				}
   2389 				error = 1;
   2390 			}
   2391 		}
   2392 		bytes -= (wrblocksz - sz);
   2393 	}
   2394 	return (error);
   2395 }
   2396 
   2397 /*
   2398  * Write zeros for give size.
   2399  *
   2400  * ofd		- output file descriptor
   2401  * buf		- buffer to fill with zeros
   2402  * bytes	- Amount to write
   2403  * wrblocksz	- Write block size
   2404  *
   2405  * return 0 upon success.
   2406  */
   2407 static int
   2408 write_zeros(int ofd, char *buf, off_t bytes, size_t wrblocksz,
   2409     data_in_t *data_in_info)
   2410 {
   2411 	int	rv;
   2412 
   2413 	(void) memset(buf, 0, min(bytes, wrblocksz));
   2414 	while (bytes > 0) {
   2415 		if (bytes < wrblocksz)
   2416 			wrblocksz = bytes;
   2417 		rv = write_bytes(ofd, buf, wrblocksz, data_in_info);
   2418 		if (rv != 0)
   2419 			return (rv);
   2420 		bytes -= wrblocksz;
   2421 	}
   2422 	return (0);
   2423 }
   2424 
   2425 /*
   2426  * To figure out the size of the buffer used to accumulate data from
   2427  * readtape() and to write to the file, we need to determine the largest
   2428  * chunk of data to be written to the file at one time. This is determined
   2429  * based on the following three things:
   2430  *	1) The size of the archived file.
   2431  *	2) The preferred I/O size of the file.
   2432  *	3) If the file is a read-write system attribute file.
   2433  * If the size of the file is less than the preferred I/O size or it's a
   2434  * read-write system attribute file, which must be written in one operation,
   2435  * then set the maximum write size to the size of the archived file.
   2436  * Otherwise, the maximum write size is preferred I/O size.
   2437  */
   2438 static int
   2439 calc_maxwrite(int ofd, int rw_sysattr, off_t bytes, size_t blocksize)
   2440 {
   2441 	struct stat tsbuf;
   2442 	size_t maxwrite;
   2443 	size_t piosize;		/* preferred I/O size */
   2444 
   2445 	if (rw_sysattr || bytes < blocksize) {
   2446 		maxwrite = bytes;
   2447 	} else {
   2448 		if (fstat(ofd, &tsbuf) == 0) {
   2449 			piosize = tsbuf.st_blksize;
   2450 		} else {
   2451 			piosize = blocksize;
   2452 		}
   2453 		maxwrite = min(bytes, piosize);
   2454 	}
   2455 	return (maxwrite);
   2456 }
   2457 /*
   2458  * data_copy() and data_copy_with_holes() copy data from the input
   2459  * file to output file descriptor. If ifd is -1, then the input file is
   2460  * the archive file.
   2461  *
   2462  * Parameters
   2463  *	ifd		- Input file descriptor to read from.
   2464  *	ofd		- Output file descriptor of extracted file.
   2465  *	rw_sysattr	- Flag indicating if a file is an extended
   2466  *			system attribute file.
   2467  *	bytes		- Amount of data (file size) of copy/write.
   2468  *	blocksize	- Amount of data to read at a time from either
   2469  *			the input file descriptor or from the archive.
   2470  *	data_in_info	- information needed while reading data when
   2471  *			called by data_in().
   2472  *	holes		- Information of holes in the input file.
   2473  *
   2474  * Return code
   2475  *	0		Success
   2476  *	< 0		An error occurred during the read of the input
   2477  *			file
   2478  *	> 0		An error occurred during the write of the output
   2479  *			file descriptor.
   2480  */
   2481 static int
   2482 data_copy(int ifd, int ofd, int rw_sysattr, off_t bytes,
   2483     size_t blocksize, data_in_t *data_in_info)
   2484 {
   2485 	char *buf;
   2486 	size_t maxwrite;
   2487 	int rv;
   2488 
   2489 	/* No data to copy. */
   2490 	if (bytes == 0)
   2491 		return (0);
   2492 
   2493 	maxwrite = calc_maxwrite(ofd, rw_sysattr, bytes, blocksize);
   2494 	buf = e_zalloc(E_EXIT, maxwrite);
   2495 
   2496 	rv = rdwr_bytes(ifd, ofd, buf, bytes, maxwrite,
   2497 	    blocksize, data_in_info);
   2498 
   2499 	free(buf);
   2500 	return (rv);
   2501 }
   2502 
   2503 static int
   2504 data_copy_with_holes(int ifd, int ofd, int rw_sysattr, off_t bytes,
   2505     size_t blocksize, data_in_t *data_in_info, holes_info_t *holes)
   2506 {
   2507 	holes_list_t	*hl;
   2508 	off_t		curpos, noff, datasize;
   2509 	char		*buf;
   2510 	size_t		maxwrite;
   2511 	int		rv, error;
   2512 
   2513 	if (bytes == 0)
   2514 		return (0);
   2515 
   2516 	maxwrite = calc_maxwrite(ofd, rw_sysattr, bytes, blocksize);
   2517 	buf = e_zalloc(E_EXIT, maxwrite);
   2518 
   2519 	error = 0;
   2520 	curpos = 0;
   2521 	for (hl = holes->holes_list; hl != NULL; hl = hl->hl_next) {
   2522 		if (curpos != hl->hl_data) {
   2523 			/* adjust output position */
   2524 			noff = lseek(ofd, hl->hl_data, SEEK_SET);
   2525 			if (noff != hl->hl_data) {
   2526 				/*
   2527 				 * Can't seek to the target, try to adjust
   2528 				 * position by filling with zeros.
   2529 				 */
   2530 				datasize = hl->hl_data - curpos;
   2531 				rv = write_zeros(ofd, buf, datasize,
   2532 				    maxwrite, data_in_info);
   2533 				if (rv != 0)
   2534 					goto errout;
   2535 			}
   2536 			/*
   2537 			 * Data is contiguous in the archive, but fragmented
   2538 			 * in the regular file, so we also adjust the input
   2539 			 * file position in pass mode.
   2540 			 */
   2541 			if (Args & OCp) {
   2542 				/* adjust input position */
   2543 				(void) lseek(ifd, hl->hl_data, SEEK_SET);
   2544 			}
   2545 			curpos = hl->hl_data;
   2546 		}
   2547 		datasize = hl->hl_hole - hl->hl_data;
   2548 		if (datasize == 0) {
   2549 			/*
   2550 			 * There is a hole at the end of file. To create
   2551 			 * such hole, we append one byte, and truncate the
   2552 			 * last block. This is necessary because ftruncate(2)
   2553 			 * alone allocates one block on the end of file.
   2554 			 */
   2555 			rv = write_zeros(ofd, buf, 1, maxwrite, data_in_info);
   2556 			if (rv != 0)
   2557 				goto errout;
   2558 			(void) ftruncate(ofd, hl->hl_data);
   2559 			break;
   2560 		}
   2561 		rv = rdwr_bytes(ifd, ofd, buf, datasize, maxwrite,
   2562 		    blocksize, data_in_info);
   2563 		if (rv != 0) {
   2564 errout:
   2565 			/*
   2566 			 * Return if we got a read error or in pass mode,
   2567 			 * or failed with partial write. Otherwise, we'll
   2568 			 * read through the input stream till next file.
   2569 			 */
   2570 			if (rv < 0 || (Args & OCp) ||
   2571 			    data_in_info->data_in_wr_part) {
   2572 				free(buf);
   2573 				return (rv);
   2574 			}
   2575 			error = 1;
   2576 			hl = hl->hl_next;
   2577 			break;
   2578 		}
   2579 		curpos += datasize;
   2580 	}
   2581 
   2582 	/*
   2583 	 * We should read through the input data to go to the next
   2584 	 * header when non-fatal error occured.
   2585 	 */
   2586 	if (error && !(Args & OCp)) {
   2587 		data_in_info->data_in_proc_mode = P_SKIP;
   2588 		while (hl != NULL) {
   2589 			datasize = hl->hl_hole - hl->hl_data;
   2590 			rv = rdwr_bytes(ifd, ofd, buf, datasize, maxwrite,
   2591 			    blocksize, data_in_info);
   2592 			if (rv != 0)
   2593 				break;
   2594 			hl = hl->hl_next;
   2595 		}
   2596 	}
   2597 
   2598 	free(buf);
   2599 	return (error);
   2600 }
   2601 
   2602 /*
   2603  * Strip off the sparse file information that is prepended to
   2604  * the compressed sparse file. The information is in the following
   2605  * format:
   2606  * 	<prepended info size><SP><orig file size><SP><holes info>
   2607  * where prepended info size is long right justified in 10 bytes.
   2608  * Holesdata consists of the series of offset pairs:
   2609  * 	<data offset><SP><hole offset><SP><data offset><SP><hole offset>...
   2610  * prepended info size and original file size have been read in gethdr().
   2611  * We read the rest of holes information here in this function.
   2612  */
   2613 static int
   2614 read_holesdata(holes_info_t *holes, off_t *fileszp,
   2615     char *nam_p, data_in_t *data_in_info)
   2616 {
   2617 	char		*holesdata;
   2618 	size_t		holesdata_sz;
   2619 
   2620 	/* We've already read the header. */
   2621 	holesdata_sz = holes->holesdata_sz - MIN_HOLES_HDRSIZE;
   2622 
   2623 	if ((holesdata = e_zalloc(E_NORMAL, holesdata_sz)) == NULL) {
   2624 		msg(ERRN, "Could not allocate memory for "
   2625 		    "sparse file information", nam_p);
   2626 		return (1);
   2627 	}
   2628 	/*
   2629 	 * This function is called only in OCi mode. Therefore,
   2630 	 * read_bytes() won't fail, and won't return if error occurs in
   2631 	 * input stream. See rstbuf().
   2632 	 */
   2633 	(void) read_bytes(-1, holesdata, holesdata_sz, CPIOBSZ, data_in_info);
   2634 	*fileszp -= holesdata_sz;
   2635 
   2636 	/* The string should be terminated. */
   2637 	if (holesdata[holesdata_sz - 1] != '\0') {
   2638 invalid:
   2639 		free(holesdata);
   2640 		msg(ERR, "invalid sparse file information", nam_p);
   2641 		return (1);
   2642 	}
   2643 	if (parse_holesdata(holes, holesdata) != 0)
   2644 		goto invalid;
   2645 
   2646 	/* sanity check */
   2647 	if (*fileszp != holes->data_size)
   2648 		goto invalid;
   2649 
   2650 	free(holesdata);
   2651 	return (0);
   2652 }
   2653 
   2654 /*
   2655  * data_in:  If proc_mode == P_PROC, bread() the file's data from the archive
   2656  * and write(2) it to the open fdes gotten from openout().  If proc_mode ==
   2657  * P_SKIP, or becomes P_SKIP (due to errors etc), bread(2) the file's data
   2658  * and ignore it.  If the user specified any of the "swap" options (b, s or S),
   2659  * and the length of the file is not appropriate for that action, do not
   2660  * perform the "swap", otherwise perform the action on a buffer by buffer basis.
   2661  * If the CRC header was selected, calculate a running checksum as each buffer
   2662  * is processed.
   2663  */
   2664 static void
   2665 data_in(int proc_mode)
   2666 {
   2667 	char *nam_p;
   2668 	int pad, rv;
   2669 	int error = 0;
   2670 	int swapfile = 0;
   2671 	int cstatus = 0;
   2672 	off_t	filesz;
   2673 	data_in_t *data_in_info;
   2674 
   2675 	if (G_p->g_attrnam_p != NULL) {
   2676 		nam_p = G_p->g_attrnam_p;
   2677 	} else {
   2678 		nam_p = G_p->g_nam_p;
   2679 	}
   2680 
   2681 	if (((G_p->g_mode & Ftype) == S_IFLNK && proc_mode != P_SKIP) ||
   2682 	    (Hdr_type == BAR && bar_linkflag == '2' && proc_mode != P_SKIP)) {
   2683 		proc_mode = P_SKIP;
   2684 		VERBOSE((Args & (OCv | OCV)), nam_p);
   2685 	}
   2686 	if (Args & (OCb | OCs | OCS)) { /* verfify that swapping is possible */
   2687 		swapfile = 1;
   2688 		if (Args & (OCs | OCb) && G_p->g_filesz % 2) {
   2689 			msg(ERR,
   2690 			    "Cannot swap bytes of \"%s\", odd number of bytes",
   2691 			    nam_p);
   2692 			swapfile = 0;
   2693 		}
   2694 		if (Args & (OCS | OCb) && G_p->g_filesz % 4) {
   2695 			msg(ERR,
   2696 			    "Cannot swap halfwords of \"%s\", odd number "
   2697 			    "of halfwords", nam_p);
   2698 			swapfile = 0;
   2699 		}
   2700 	}
   2701 
   2702 	data_in_info = e_zalloc(E_EXIT, sizeof (data_in_t));
   2703 	data_in_info->data_in_swapfile = swapfile;
   2704 	data_in_info->data_in_proc_mode = proc_mode;
   2705 
   2706 	filesz = G_p->g_filesz;
   2707 
   2708 	if (S_ISSPARSE(G_p->g_mode) && G_p->g_holes != NULL) {
   2709 		/* We've already read the header in gethdr() */
   2710 		filesz -= MIN_HOLES_HDRSIZE;
   2711 
   2712 		/*
   2713 		 * Strip rest of the sparse file information. This includes
   2714 		 * the data/hole offset pairs which will be used to restore
   2715 		 * the holes in the file.
   2716 		 */
   2717 		if (proc_mode == P_SKIP) {
   2718 			/* holes info isn't necessary to skip file */
   2719 			free_holes_info(G_p->g_holes);
   2720 			G_p->g_holes = NULL;
   2721 		} else {
   2722 			rv = read_holesdata(G_p->g_holes, &filesz,
   2723 			    nam_p, data_in_info);
   2724 			if (rv != 0) {
   2725 				/*
   2726 				 * We got an error. Skip this file. holes info
   2727 				 * is no longer necessary.
   2728 				 */
   2729 				free_holes_info(G_p->g_holes);
   2730 				G_p->g_holes = NULL;
   2731 
   2732 				data_in_info->data_in_proc_mode = P_SKIP;
   2733 				error = 1;
   2734 			}
   2735 		}
   2736 	}
   2737 
   2738 	if (G_p->g_holes != NULL) {
   2739 		rv = data_copy_with_holes(-1, Ofile,
   2740 		    (G_p->g_attrnam_p == NULL) ? 0 : G_p->g_rw_sysattr,
   2741 		    G_p->g_holes->orig_size,
   2742 		    CPIOBSZ, data_in_info, G_p->g_holes);
   2743 
   2744 		free_holes_info(G_p->g_holes);
   2745 		G_p->g_holes = NULL;
   2746 	} else {
   2747 		rv = data_copy(-1, Ofile,
   2748 		    (G_p->g_attrnam_p == NULL) ? 0 : G_p->g_rw_sysattr,
   2749 		    filesz, CPIOBSZ, data_in_info);
   2750 	}
   2751 
   2752 	/* This writes out the file from the archive */
   2753 	if (rv != 0 || error) {
   2754 		errno = data_in_info->data_in_errno;
   2755 
   2756 		if (!error) {
   2757 			msg(data_in_info->data_in_wr_part ? EXTN : ERRN,
   2758 			    "Cannot write \"%s%s%s\"",
   2759 			    (G_p->g_attrnam_p == NULL) ? "" :
   2760 			    G_p->g_attrfnam_p,
   2761 			    (G_p->g_attrnam_p == NULL) ? "" :
   2762 			    G_p->g_rw_sysattr ?
   2763 			    gettext(" System Attribute ") :
   2764 			    gettext(" Attribute "), nam_p);
   2765 		}
   2766 		/*
   2767 		 * We've failed to write to the file, and input data
   2768 		 * has been skiped to the next file. We'll need to restore
   2769 		 * the original file, and skip the rest of work.
   2770 		 */
   2771 		proc_mode = P_SKIP;
   2772 		rstfiles(U_KEEP, G_p->g_dirfd);
   2773 		cstatus = close(Ofile);
   2774 		Ofile = 0;
   2775 		if (cstatus != 0) {
   2776 			msg(EXTN, "close error");
   2777 		}
   2778 	}
   2779 
   2780 	/* we must use g_filesz for the amount of padding */
   2781 	pad = (Pad_val + 1 - (G_p->g_filesz & Pad_val)) & Pad_val;
   2782 	if (pad != 0) {
   2783 		FILL(pad);
   2784 		Buffr.b_out_p += pad;
   2785 		Buffr.b_cnt -= pad;
   2786 	}
   2787 	if (proc_mode != P_SKIP) {
   2788 		if (Hdr_type == CRC &&
   2789 		    Gen.g_cksum != data_in_info->data_in_cksumval) {
   2790 			msg(ERR, "\"%s\" - checksum error", nam_p);
   2791 			rstfiles(U_KEEP, G_p->g_dirfd);
   2792 		} else
   2793 			rstfiles(U_OVER, G_p->g_dirfd);
   2794 		if (Hdr_type == BAR && data_in_info->data_in_compress_flag) {
   2795 			(void) pclose(data_in_info->data_in_pipef);
   2796 		} else {
   2797 			cstatus = close(Ofile);
   2798 		}
   2799 		Ofile = 0;
   2800 		if (cstatus != 0) {
   2801 			msg(EXTN, "close error");
   2802 		}
   2803 	}
   2804 	(void) free(data_in_info);
   2805 
   2806 	VERBOSE((proc_mode != P_SKIP && (Args & (OCv | OCV))),
   2807 	    (G_p->g_attrparent_p == NULL) ? G_p->g_nam_p : G_p->g_attrpath_p);
   2808 	Finished = 1;
   2809 }
   2810 
   2811 /*
   2812  * Read regular file. Return number of bytes which weren't read.
   2813  * Upon return, real_filesz will be real file size of input file.
   2814  * When read_exact is specified, read size is adjusted to the given
   2815  * file size.
   2816  */
   2817 static off_t
   2818 read_file(char *nam_p, off_t file_size, off_t *real_filesz,
   2819 	boolean_t read_exact)
   2820 {
   2821 	int	amount_read;
   2822 	off_t	amt_to_read;
   2823 	off_t	readsz;
   2824 
   2825 	if (file_size == 0)
   2826 		return (0);
   2827 
   2828 	amt_to_read = file_size;
   2829 	do {
   2830 		if (read_exact && amt_to_read < CPIOBSZ)
   2831 			readsz = amt_to_read;
   2832 		else
   2833 			readsz = CPIOBSZ;
   2834 
   2835 		FLUSH(readsz);
   2836 		errno = 0;
   2837 
   2838 		if ((amount_read = read(Ifile, Buffr.b_in_p, readsz)) < 0) {
   2839 			msg(EXTN, "Cannot read \"%s%s%s\"",
   2840 			    (Gen.g_attrnam_p == NULL) ?
   2841 			    nam_p : Gen.g_attrfnam_p,
   2842 			    (Gen.g_attrnam_p == NULL) ? "" : Gen.g_rw_sysattr ?
   2843 			    gettext(" System Attribute ") :
   2844 			    gettext(" Attribute "),
   2845 			    (Gen.g_attrnam_p == NULL) ? "" : nam_p);
   2846 			break;
   2847 		}
   2848 
   2849 		if (amount_read == 0) {
   2850 			/* got EOF. the file has shrunk */
   2851 			*real_filesz = file_size - amt_to_read;
   2852 			break;
   2853 		} else if (amount_read > amt_to_read) {
   2854 			/* the file has grown */
   2855 			*real_filesz = file_size +
   2856 			    (amount_read - amt_to_read);
   2857 			amount_read = amt_to_read;
   2858 		} else if (amount_read == amt_to_read) {
   2859 			/* the file is the same size */
   2860 			*real_filesz = file_size;
   2861 		}
   2862 
   2863 		Buffr.b_in_p += amount_read;
   2864 		Buffr.b_cnt += (long)amount_read;
   2865 
   2866 		amt_to_read -= (off_t)amount_read;
   2867 		if (!read_exact &&
   2868 		    amt_to_read == 0 && amount_read == CPIOBSZ) {
   2869 			/*
   2870 			 * If the file size is multiple of CPIOBSZ, we may
   2871 			 * be able to read more from the file even though
   2872 			 * amt_to_read already gets 0.
   2873 			 */
   2874 			FLUSH(CPIOBSZ);
   2875 			amount_read = read(Ifile, Buffr.b_in_p, CPIOBSZ);
   2876 			if (amount_read != 0) {
   2877 				/* the file has grown */
   2878 				*real_filesz = file_size + amount_read;
   2879 			}
   2880 		}
   2881 	} while (amt_to_read != 0);
   2882 
   2883 	return (amt_to_read);
   2884 }
   2885 
   2886 /*
   2887  * Read through the data in files skipping holes.
   2888  */
   2889 static off_t
   2890 read_compress_holes(char *nam_p, off_t file_size, off_t *real_filesz,
   2891     holes_info_t *holes, int *hole_changed)
   2892 {
   2893 	off_t		left;
   2894 	off_t		datasize, realsz;
   2895 	off_t		curpos, npos;
   2896 	holes_list_t	*hl = holes->holes_list;
   2897 
   2898 	curpos = 0;
   2899 	for (hl = holes->holes_list; hl != NULL; hl = hl->hl_next) {
   2900 		datasize = hl->hl_hole - hl->hl_data;
   2901 
   2902 		npos = lseek(Ifile, curpos, SEEK_DATA);
   2903 		if (npos == -1 && errno == ENXIO) {
   2904 			/*
   2905 			 * No more data. There are two cases.
   2906 			 * - we have a hole toward the end of file.
   2907 			 * - file has been shrunk, and we've reached EOF.
   2908 			 */
   2909 			*real_filesz = lseek(Ifile, 0, SEEK_END);
   2910 			if (hl->hl_data == file_size)
   2911 				return (0);
   2912 			/*
   2913 			 * File has been shrunk. Check the amount of data
   2914 			 * left.
   2915 			 */
   2916 			left = 0;
   2917 			while (hl != NULL) {
   2918 				left += (hl->hl_hole - hl->hl_data);
   2919 				hl = hl->hl_next;
   2920 			}
   2921 			return (left);
   2922 		}
   2923 
   2924 		/* found data */
   2925 		curpos = npos;
   2926 		if (curpos != hl->hl_data) {
   2927 			/*
   2928 			 * File has been changed. We shouldn't read data
   2929 			 * from different offset since we've already put
   2930 			 * the holes data.
   2931 			 */
   2932 			*hole_changed = 1;
   2933 			(void) lseek(Ifile, hl->hl_data, SEEK_SET);
   2934 			curpos = hl->hl_data;
   2935 		}
   2936 		left = read_file(nam_p, datasize, &realsz, B_TRUE);
   2937 		if (left != 0) {
   2938 			/* file has been shrunk */
   2939 			*real_filesz = curpos + datasize - left;
   2940 			left = file_size - *real_filesz;
   2941 			return (left);
   2942 		}
   2943 		curpos += datasize;
   2944 	}
   2945 	/*
   2946 	 * We've read exact size of holes. We need to make sure
   2947 	 * that file hasn't grown by reading from the EOF.
   2948 	 */
   2949 	realsz = 0;
   2950 	(void) read_file(nam_p, CPIOBSZ, &realsz, B_FALSE);
   2951 
   2952 	*real_filesz = curpos + realsz;
   2953 	return (0);
   2954 }
   2955 
   2956 /*
   2957  * data_out:  open(2) the file to be archived, compute the checksum
   2958  * of it's data if the CRC header was specified and write the header.
   2959  * read(2) each block of data and bwrite() it to the archive.  For TARTYP (TAR
   2960  * and USTAR) archives, pad the data with NULLs to the next 512 byte boundary.
   2961  */
   2962 static void
   2963 data_out(void)
   2964 {
   2965 	char		*nam_p;
   2966 	int		cnt, pad;
   2967 	off_t		amt_to_read;
   2968 	off_t		real_filesz;
   2969 	int		errret = 0;
   2970 	int		hole_changed = 0;
   2971 	off_t		orig_filesz;
   2972 	holes_info_t	*holes = NULL;
   2973 
   2974 	nam_p = G_p->g_nam_p;
   2975 	if (Aspec) {
   2976 		if (Pflag && aclp != NULL) {
   2977 			char    *secinfo = NULL;
   2978 			int	len = 0;
   2979 
   2980 			/* append security attributes */
   2981 			if (append_secattr(&secinfo, &len, aclp) == -1) {
   2982 				msg(ERR,
   2983 				    "can create security information");
   2984 			}
   2985 			/* call append_secattr() if more than one */
   2986 
   2987 			if (len > 0) {
   2988 			/* write ancillary only if there is sec info */
   2989 				write_hdr(ARCHIVE_ACL, (off_t)len);
   2990 				write_ancillary(secinfo, len, B_TRUE);
   2991 			}
   2992 		}
   2993 		write_hdr(ARCHIVE_NORMAL, (off_t)0);
   2994 		rstfiles(U_KEEP, G_p->g_dirfd);
   2995 		VERBOSE((Args & (OCv | OCV)), nam_p);
   2996 		return;
   2997 	}
   2998 	if ((G_p->g_mode & Ftype) == S_IFLNK && (Hdr_type !=
   2999 	    USTAR && Hdr_type != TAR)) { /* symbolic link */
   3000 		int size;
   3001 		write_hdr(ARCHIVE_NORMAL, (off_t)0);
   3002 
   3003 		FLUSH(G_p->g_filesz);
   3004 		errno = 0;
   3005 
   3006 		/* Note that "size" and G_p->g_filesz are the same number */
   3007 
   3008 		if ((size = readlink(nam_p, Buffr.b_in_p, G_p->g_filesz)) <
   3009 		    0) {
   3010 			msg(ERRN, "Cannot read symbolic link \"%s\"", nam_p);
   3011 			return;
   3012 		}
   3013 
   3014 		/*
   3015 		 * Note that it is OK not to add the NUL after the name read by
   3016 		 * readlink, because it is not being used subsequently.
   3017 		 */
   3018 
   3019 		Buffr.b_in_p += size;
   3020 		Buffr.b_cnt += size;
   3021 		pad = (Pad_val + 1 - (size & Pad_val)) & Pad_val;
   3022 		if (pad != 0) {
   3023 			FLUSH(pad);
   3024 			(void) memset(Buffr.b_in_p, 0, pad);
   3025 			Buffr.b_in_p += pad;
   3026 			Buffr.b_cnt += pad;
   3027 		}
   3028 		VERBOSE((Args & (OCv | OCV)), nam_p);
   3029 		return;
   3030 	} else if ((G_p->g_mode & Ftype) == S_IFLNK &&
   3031 	    (Hdr_type == USTAR || Hdr_type == TAR)) {
   3032 		int size;
   3033 
   3034 		/*
   3035 		 * G_p->g_filesz is the length of the right-hand side of
   3036 		 * the symlink "x -> y".
   3037 		 * The tar link field is only NAMSIZ long.
   3038 		 */
   3039 
   3040 		if (G_p->g_filesz > NAMSIZ) {
   3041 			msg(ERRN,
   3042 			    "Symbolic link too long \"%s\"", nam_p);
   3043 			return;
   3044 		}
   3045 		if ((size = readlink(nam_p, T_lname, G_p->g_filesz)) < 0) {
   3046 			msg(ERRN,
   3047 			    "Cannot read symbolic link \"%s\"", nam_p);
   3048 			return;
   3049 		}
   3050 		T_lname[size] = '\0';
   3051 		G_p->g_filesz = (off_t)0;
   3052 		write_hdr(ARCHIVE_NORMAL, (off_t)0);
   3053 		VERBOSE((Args & (OCv | OCV)), nam_p);
   3054 		return;
   3055 	}
   3056 	if ((Ifile = openfile(O_RDONLY)) < 0) {
   3057 		msg(ERR, "\"%s%s%s\" ?",
   3058 		    (Gen.g_attrnam_p == NULL) ? nam_p : Gen.g_attrfnam_p,
   3059 		    (Gen.g_attrnam_p == NULL) ? "" : Gen.g_rw_sysattr ?
   3060 		    gettext(" System Attribute ") : gettext(" Attribute "),
   3061 		    (Gen.g_attrnam_p == NULL) ? "" :
   3062 		    (Gen.g_attrparent_p == NULL) ? Gen.g_attrnam_p :
   3063 		    Gen.g_attrparent_p);
   3064 		return;
   3065 	}
   3066 
   3067 	/* save original file size */
   3068 	orig_filesz = G_p->g_filesz;
   3069 
   3070 	/*
   3071 	 * Calculate the new compressed file size of a sparse file
   3072 	 * before any of the header information is written
   3073 	 * to the archive.
   3074 	 */
   3075 	if (Compress_sparse && S_ISREG(G_p->g_mode)) {
   3076 		/*
   3077 		 * If the file being processed is a sparse file, gather the
   3078 		 * hole information and the compressed file size.
   3079 		 * G_p->g_filesz will need to be changed to be the size of
   3080 		 * the compressed sparse file plus the the size of the hole
   3081 		 * information that will be prepended to the compressed file
   3082 		 * in the archive.
   3083 		 */
   3084 		holes = get_holes_info(Ifile, G_p->g_filesz, B_FALSE);
   3085 		if (holes != NULL)
   3086 			G_p->g_filesz = holes->holesdata_sz + holes->data_size;
   3087 
   3088 		if (G_p->g_filesz > Max_offset) {
   3089 			msg(ERR, "%s%s%s: too large to archive "
   3090 			    "in current mode",
   3091 			    G_p->g_nam_p,
   3092 			    (G_p->g_attrnam_p == NULL) ? "" :
   3093 			    G_p->g_rw_sysattr ?
   3094 			    gettext(" System Attribute ") :
   3095 			    gettext(" Attribute "),
   3096 			    (G_p->g_attrnam_p == NULL) ? "" :
   3097 			    ((G_p->g_attrparent_p == NULL) ?
   3098 			    G_p->g_attrnam_p:
   3099 			    G_p->g_attrpath_p));
   3100 
   3101 			(void) close(Ifile);
   3102 			if (holes != NULL)
   3103 				free_holes_info(holes);
   3104 			return; /* do not archive if it's too big */
   3105 		}
   3106 	}
   3107 
   3108 	/*
   3109 	 * Dump extended attribute header.
   3110 	 */
   3111 
   3112 	if (Gen.g_attrnam_p != NULL) {
   3113 		write_xattr_hdr();
   3114 	}
   3115 
   3116 	if (Hdr_type == CRC) {
   3117 		long csum = cksum(CRC, 0, &errret);
   3118 		if (errret != 0) {
   3119 			G_p->g_cksum = (ulong_t)-1;
   3120 			msg(POST, "\"%s%s%s\" skipped",
   3121 			    (Gen.g_attrnam_p == NULL) ?
   3122 			    nam_p : Gen.g_attrfnam_p,
   3123 			    (Gen.g_attrnam_p == NULL) ? "" : Gen.g_rw_sysattr ?
   3124 			    gettext(" System Attribute ") :
   3125 			    gettext(" Attribute "),
   3126 			    (Gen.g_attrnam_p == NULL) ? "" : nam_p);
   3127 			if (holes != NULL)
   3128 				free_holes_info(holes);
   3129 			(void) close(Ifile);
   3130 			return;
   3131 		}
   3132 		G_p->g_cksum = csum;
   3133 	} else {
   3134 		G_p->g_cksum = 0;
   3135 	}
   3136 
   3137 	/*
   3138 	 * ACL has been retrieved in getname().
   3139 	 */
   3140 	if (Pflag) {
   3141 		char    *secinfo = NULL;
   3142 		int	len = 0;
   3143 
   3144 		/* append security attributes */
   3145 		if ((append_secattr(&secinfo, &len, aclp)) == -1)
   3146 			msg(ERR, "can create security information");
   3147 
   3148 		/* call append_secattr() if more than one */
   3149 
   3150 		if (len > 0) {
   3151 		/* write ancillary only if there is sec info */
   3152 			write_hdr(ARCHIVE_ACL, (off_t)len);
   3153 			write_ancillary(secinfo, len, B_TRUE);
   3154 		}
   3155 	}
   3156 
   3157 	if (holes != NULL) {
   3158 		/*
   3159 		 * Write the header info with a modified c_mode field to
   3160 		 * indicate a compressed sparse file is being archived,
   3161 		 * as well as the new file size, including the size of the
   3162 		 * compressed file as well as all the prepended data.
   3163 		 */
   3164 		write_hdr(ARCHIVE_SPARSE, (off_t)0);
   3165 		/* Prepend sparse file info */
   3166 		write_ancillary(holes->holesdata,
   3167 		    holes->holesdata_sz, B_FALSE);
   3168 	} else {
   3169 		write_hdr(ARCHIVE_NORMAL, (off_t)0);
   3170 	}
   3171 
   3172 	real_filesz = 0;
   3173 
   3174 	if (holes != NULL) {
   3175 		amt_to_read = read_compress_holes(nam_p, G_p->g_filesz,
   3176 		    &real_filesz, holes, &hole_changed);
   3177 	} else {
   3178 		amt_to_read = read_file(nam_p, G_p->g_filesz,
   3179 		    &real_filesz, B_FALSE);
   3180 	}
   3181 
   3182 	while (amt_to_read > 0) {
   3183 		cnt = (amt_to_read > CPIOBSZ) ? CPIOBSZ : (int)amt_to_read;
   3184 		FLUSH(cnt);
   3185 		(void) memset(Buffr.b_in_p, 0, cnt);
   3186 		Buffr.b_in_p += cnt;
   3187 		Buffr.b_cnt += cnt;
   3188 		amt_to_read -= cnt;
   3189 	}
   3190 
   3191 	pad = (Pad_val + 1 - (G_p->g_filesz & Pad_val)) & Pad_val;
   3192 	if (pad != 0) {
   3193 		FLUSH(pad);
   3194 		(void) memset(Buffr.b_in_p, 0, pad);
   3195 		Buffr.b_in_p += pad;
   3196 		Buffr.b_cnt += pad;
   3197 	}
   3198 
   3199 	if (hole_changed == 1) {
   3200 		msg(ERR,
   3201 		    "File data and hole offsets of \"%s%s%s\" have changed",
   3202 		    (Gen.g_attrnam_p == NULL) ?
   3203 		    G_p->g_nam_p : Gen.g_attrfnam_p,
   3204 		    (Gen.g_attrnam_p == NULL) ? "" : Gen.g_rw_sysattr ?
   3205 		    gettext(" System Attribute ") : gettext(" Attribute "),
   3206 		    (Gen.g_attrnam_p == NULL) ? "" : G_p->g_nam_p);
   3207 	}
   3208 	if (real_filesz > orig_filesz) {
   3209 		msg(ERR, "File size of \"%s%s%s\" has increased by %lld",
   3210 		    (Gen.g_attrnam_p == NULL) ?
   3211 		    G_p->g_nam_p : Gen.g_attrfnam_p,
   3212 		    (Gen.g_attrnam_p == NULL) ? "" : Gen.g_rw_sysattr ?
   3213 		    gettext(" System Attribute ") : gettext(" Attribute "),
   3214 		    (Gen.g_attrnam_p == NULL) ? "" : G_p->g_nam_p,
   3215 		    (real_filesz - orig_filesz));
   3216 	}
   3217 	if (real_filesz < orig_filesz) {
   3218 		msg(ERR, "File size of \"%s%s%s\" has decreased by %lld",
   3219 		    (Gen.g_attrnam_p == NULL) ?
   3220 		    G_p->g_nam_p : Gen.g_attrfnam_p,
   3221 		    (Gen.g_attrnam_p == NULL) ? "" : Gen.g_rw_sysattr ?
   3222 		    gettext(" System Attribute ") : gettext(" Attribute "),
   3223 		    (Gen.g_attrnam_p == NULL) ? "" : G_p->g_nam_p,
   3224 		    (orig_filesz - real_filesz));
   3225 	}
   3226 
   3227 	if (holes != NULL)
   3228 		free_holes_info(holes);
   3229 
   3230 	(void) close(Ifile);
   3231 	rstfiles(U_KEEP, G_p->g_dirfd);
   3232 	VERBOSE((Args & (OCv | OCV)), G_p->g_nam_p);
   3233 }
   3234 
   3235 /*
   3236  * data_pass:  If not a special file (Aspec), open(2) the file to be
   3237  * transferred, read(2) each block of data and write(2) it to the output file
   3238  * Ofile, which was opened in file_pass().
   3239  */
   3240 static void
   3241 data_pass(void)
   3242 {
   3243 	int rv;
   3244 	int cstatus;
   3245 	char *namep = Nam_p;
   3246 	holes_info_t *holes = NULL;
   3247 	data_in_t *data_in_info;
   3248 
   3249 	if (G_p->g_attrnam_p != NULL) {
   3250 		namep = G_p->g_attrnam_p;
   3251 	}
   3252 	if (Aspec) {
   3253 		rstfiles(U_KEEP, G_p->g_passdirfd);
   3254 		cstatus = close(Ofile);
   3255 		Ofile = 0;
   3256 		VERBOSE((Args & (OCv | OCV)), Nam_p);
   3257 		if (cstatus != 0) {
   3258 			msg(EXTN, "close error");
   3259 		}
   3260 		return;
   3261 	}
   3262 	if ((Ifile = openat(G_p->g_dirfd, get_component(namep), 0)) < 0) {
   3263 		msg(ERRN, "Cannot open \"%s%s%s\", skipped",
   3264 		    (G_p->g_attrnam_p == NULL) ? Nam_p : G_p->g_attrfnam_p,
   3265 		    (G_p->g_attrnam_p == NULL) ? "" : G_p->g_rw_sysattr ?
   3266 		    gettext(" System Attribute ") : gettext(" Attribute "),
   3267 		    (G_p->g_attrnam_p == NULL) ? "" : G_p->g_attrnam_p);
   3268 		rstfiles(U_KEEP, G_p->g_passdirfd);
   3269 		cstatus = close(Ofile);
   3270 		Ofile = 0;
   3271 		if (cstatus != 0) {
   3272 			msg(EXTN, "close error");
   3273 		}
   3274 		return;
   3275 	}
   3276 
   3277 	data_in_info = e_zalloc(E_EXIT, sizeof (data_in_t));
   3278 	data_in_info->data_in_proc_mode = P_PROC;
   3279 
   3280 	if (S_ISREG(G_p->g_mode))
   3281 		holes = get_holes_info(Ifile, G_p->g_filesz, B_TRUE);
   3282 
   3283 	if (holes != NULL) {
   3284 		rv = data_copy_with_holes(Ifile, Ofile,
   3285 		    (G_p->g_attrnam_p == NULL) ? 0 : G_p->g_rw_sysattr,
   3286 		    G_p->g_filesz, Bufsize, data_in_info, holes);
   3287 
   3288 		free_holes_info(holes);
   3289 	} else {
   3290 		rv = data_copy(Ifile, Ofile,
   3291 		    (G_p->g_attrnam_p == NULL) ? 0 : G_p->g_rw_sysattr,
   3292 		    G_p->g_filesz, Bufsize, data_in_info);
   3293 	}
   3294 
   3295 	if (rv < 0) {
   3296 		/* read error or unexpected EOF */
   3297 		if (data_in_info->data_in_rd_eof) {
   3298 			/*
   3299 			 * read has reached EOF unexpectedly, but this isn't
   3300 			 * an error since it's the latest shape of the file.
   3301 			 */
   3302 			msg(EPOST, "File size of \"%s%s%s\" has decreased",
   3303 			    (G_p->g_attrnam_p == NULL) ?
   3304 			    Nam_p : G_p->g_attrfnam_p,
   3305 			    (G_p->g_attrnam_p == NULL) ? "" :
   3306 			    G_p->g_rw_sysattr ? gettext(" System Attribute ") :
   3307 			    gettext(" Attribute "),
   3308 			    (G_p->g_attrnam_p == NULL) ? "" : G_p->g_attrnam_p);
   3309 
   3310 			/* It's not error. We'll use the new file */
   3311 			rv = 0;
   3312 		} else {
   3313 			/* read error */
   3314 			msg(ERRN, "Cannot read \"%s%s%s\"",
   3315 			    (G_p->g_attrnam_p == NULL) ?
   3316 			    Nam_p : G_p->g_attrfnam_p,
   3317 			    (G_p->g_attrnam_p == NULL) ? "" :
   3318 			    G_p->g_rw_sysattr ? gettext(" System Attribute ") :
   3319 			    gettext(" Attribute "),
   3320 			    (G_p->g_attrnam_p == NULL) ? "" : G_p->g_attrnam_p);
   3321 		}
   3322 	} else if (rv > 0) {
   3323 		/* write error */
   3324 		if (Do_rename) {
   3325 			msg(ERRN, "Cannot write \"%s%s%s\"", Over_p,
   3326 			    (G_p->g_attrnam_p == NULL) ? "" :
   3327 			    G_p->g_rw_sysattr ? gettext(" System Attribute ") :
   3328 			    gettext(" Attribute "),
   3329 			    (G_p->g_attrnam_p == NULL) ? "" : Over_p);
   3330 		} else {
   3331 			msg(ERRN, "Cannot write \"%s%s%s\"",
   3332 			    Fullnam_p,
   3333 			    (G_p->g_attrnam_p == NULL) ? "" :
   3334 			    G_p->g_rw_sysattr ? gettext(" System Attribute ") :
   3335 			    gettext(" Attribute "),
   3336 			    (G_p->g_attrnam_p == NULL) ? "" : G_p->g_attrnam_p);
   3337 		}
   3338 	}
   3339 
   3340 	free(data_in_info);
   3341 
   3342 	if (rv == 0) {
   3343 		rstfiles(U_OVER, G_p->g_passdirfd);
   3344 	} else {
   3345 		rstfiles(U_KEEP, G_p->g_passdirfd);
   3346 	}
   3347 
   3348 	(void) close(Ifile);
   3349 	cstatus = close(Ofile);
   3350 	Ofile = 0;
   3351 	if (cstatus != 0) {
   3352 		msg(EXTN, "close error");
   3353 	}
   3354 	VERBOSE((Args & (OCv | OCV)), Fullnam_p);
   3355 	Finished = 1;
   3356 }
   3357 
   3358 /*
   3359  * file_in:  Process an object from the archive.  If a TARTYP (TAR or USTAR)
   3360  * archive and g_nlink == 1, link this file to the file name in t_linkname
   3361  * and return.  Handle linked files in one of two ways.  If Onecopy == 0, this
   3362  * is an old style (binary or -c) archive, create and extract the data for the
   3363  * first link found, link all subsequent links to this file and skip their data.
   3364  * If Oncecopy == 1, save links until all have been processed, and then
   3365  * process the links first to last checking their names against the patterns
   3366  * and/or asking the user to rename them.  The first link that is accepted
   3367  * for xtraction is created and the data is read from the archive.
   3368  * All subsequent links that are accepted are linked to this file.
   3369  */
   3370 static void
   3371 file_in(void)
   3372 {
   3373 	struct Lnk *l_p, *tl_p;
   3374 	int lnkem = 0, cleanup = 0;
   3375 	int proc_file;
   3376 	struct Lnk *ttl_p;
   3377 	int typeflag;
   3378 	char savacl;
   3379 	int cwd;
   3380 
   3381 	G_p = &Gen;
   3382 
   3383 	/*
   3384 	 * Now that we've read the extended header,
   3385 	 * determine if we should restore attributes.
   3386 	 * Don't restore the attribute if we are extracting
   3387 	 * a file from an archive (as opposed to doing a table of
   3388 	 * contents) and any of the following are true:
   3389 	 * 1. neither -@ or -/ was specified.
   3390 	 * 2. -@ was specified, -/ wasn't specified, and we're
   3391 	 * processing a hidden attribute directory of an attribute
   3392 	 * or we're processing a read-write system attribute file.
   3393 	 * 3.  -@ wasn't specified, -/ was specified, and the file
   3394 	 * we're processing it not a read-write system attribute file,
   3395 	 * or we're processing the hidden attribute directory of an
   3396 	 * attribute.
   3397 	 *
   3398 	 * We always process the attributes if we're just generating
   3399 	 * generating a table of contents, or if both -@ and -/ were
   3400 	 * specified.
   3401 	 */
   3402 	if (G_p->g_attrnam_p != NULL) {
   3403 		if (((Args & OCt) == 0) &&
   3404 		    ((!Atflag && !SysAtflag) ||
   3405 		    (Atflag && !SysAtflag && ((G_p->g_attrparent_p != NULL) ||
   3406 		    G_p->g_rw_sysattr)) ||
   3407 		    (!Atflag && SysAtflag && ((G_p->g_attrparent_p != NULL) ||
   3408 		    !G_p->g_rw_sysattr)))) {
   3409 			proc_file = F_SKIP;
   3410 			data_in(P_SKIP);
   3411 			return;
   3412 		}
   3413 	}
   3414 
   3415 	/*
   3416 	 * Open target directory if this isn't a skipped file
   3417 	 * and g_nlink == 1
   3418 	 *
   3419 	 * Links are handled further down in this function.
   3420 	 */
   3421 
   3422 	proc_file = ckname(0);
   3423 
   3424 	if (proc_file == F_SKIP && G_p->g_nlink == 1) {
   3425 		/*
   3426 		 * Normally ckname() prints out the file as a side
   3427 		 * effect except for table of contents listing
   3428 		 * when its parameter is zero and Onecopy isn't
   3429 		 * Zero.  Due to this we need to force the name
   3430 		 * to be printed here.
   3431 		 */
   3432 		if (Onecopy == 1) {
   3433 			VERBOSE((Args & OCt), G_p->g_nam_p);
   3434 		}
   3435 		data_in(P_SKIP);
   3436 		return;
   3437 	}
   3438 
   3439 	if (proc_file != F_SKIP && open_dirfd() != 0) {
   3440 		data_in(P_SKIP);
   3441 		return;
   3442 	}
   3443 
   3444 	if (Hdr_type == BAR) {
   3445 		bar_file_in();
   3446 		close_dirfd();
   3447 		return;
   3448 	}
   3449 
   3450 	/*
   3451 	 * For archives in USTAR format, the files are extracted according
   3452 	 * to the typeflag.
   3453 	 */
   3454 	if (Hdr_type == USTAR || Hdr_type == TAR) {
   3455 		typeflag = Thdr_p->tbuf.t_typeflag;
   3456 		if (G_p->g_nlink == 1) {		/* hard link */
   3457 			if (proc_file != F_SKIP) {
   3458 				int i;
   3459 				char lname[NAMSIZ+1];
   3460 				(void) memset(lname, '\0', sizeof (lname));
   3461 
   3462 				(void) strncpy(lname, Thdr_p->tbuf.t_linkname,
   3463 				    NAMSIZ);
   3464 				for (i = 0; i <= NAMSIZ && lname[i] != 0; i++)
   3465 					;
   3466 
   3467 				lname[i] = 0;
   3468 				(void) creat_lnk(G_p->g_dirfd,
   3469 				    &lname[0], G_p->g_nam_p);
   3470 			}
   3471 			close_dirfd();
   3472 			return;
   3473 		}
   3474 		if (typeflag == '3' || typeflag == '4' || typeflag == '5' ||
   3475 		    typeflag == '6') {
   3476 			if (proc_file != F_SKIP &&
   3477 			    creat_spec(G_p->g_dirfd) > 0) {
   3478 				VERBOSE((Args & (OCv | OCV)),
   3479 				    (G_p->g_attrparent_p == NULL) ?
   3480 				    G_p->g_nam_p : G_p->g_attrpath_p);
   3481 			}
   3482 			close_dirfd();
   3483 			return;
   3484 		} else if (Adir || Aspec) {
   3485 			if ((proc_file == F_SKIP) ||
   3486 			    (Ofile = openout(G_p->g_dirfd)) < 0) {
   3487 				data_in(P_SKIP);
   3488 			} else {
   3489 				data_in(P_PROC);
   3490 			}
   3491 			close_dirfd();
   3492 			return;
   3493 		}
   3494 	}
   3495 
   3496 	if (Adir) {
   3497 		if (proc_file != F_SKIP && creat_spec(G_p->g_dirfd) > 0) {
   3498 			VERBOSE((Args & (OCv | OCV)), G_p->g_nam_p);
   3499 		}
   3500 		close_dirfd();
   3501 		if (Onecopy == 1) {
   3502 			VERBOSE((Args & OCt), G_p->g_nam_p);
   3503 		}
   3504 		return;
   3505 	}
   3506 	if (G_p->g_nlink == 1 || (Hdr_type == TAR ||
   3507 	    Hdr_type == USTAR)) {
   3508 		if (Aspec) {
   3509 			if (proc_file != F_SKIP && creat_spec(G_p->g_dirfd) > 0)
   3510 				VERBOSE((Args & (OCv | OCV)), G_p->g_nam_p);
   3511 		} else {
   3512 			if ((proc_file == F_SKIP) ||
   3513 			    (Ofile = openout(G_p->g_dirfd)) < 0) {
   3514 				data_in(P_SKIP);
   3515 			} else {
   3516 				data_in(P_PROC);
   3517 			}
   3518 		}
   3519 		close_dirfd();
   3520 		return;
   3521 	}
   3522 	close_dirfd();
   3523 
   3524 	tl_p = add_lnk(&ttl_p);
   3525 	l_p = ttl_p;
   3526 	if (l_p->L_cnt == l_p->L_gen.g_nlink)
   3527 		cleanup = 1;
   3528 	if (!Onecopy || G_p->g_attrnam_p != NULL) {
   3529 		lnkem = (tl_p != l_p) ? 1 : 0;
   3530 		G_p = &tl_p->L_gen;
   3531 		if (proc_file == F_SKIP) {
   3532 			data_in(P_SKIP);
   3533 		} else {
   3534 			if (open_dirfd() != 0)
   3535 				return;
   3536 			if (!lnkem) {
   3537 				if (Aspec) {
   3538 					if (creat_spec(G_p->g_dirfd) > 0)
   3539 						VERBOSE((Args & (OCv | OCV)),
   3540 						    G_p->g_nam_p);
   3541 				} else if ((Ofile =
   3542 				    openout(G_p->g_dirfd)) < 0) {
   3543 					data_in(P_SKIP);
   3544 					close_dirfd();
   3545 					reclaim(l_p);
   3546 				} else {
   3547 					data_in(P_PROC);
   3548 					close_dirfd();
   3549 				}
   3550 			} else {
   3551 				/*
   3552 				 * Are we linking an attribute?
   3553 				 */
   3554 				cwd = -1;
   3555 				if (l_p->L_gen.g_attrnam_p != NULL) {
   3556 					(void) strcpy(Lnkend_p,
   3557 					    l_p->L_gen.g_attrnam_p);
   3558 					(void) strcpy(Full_p,
   3559 					    tl_p->L_gen.g_attrnam_p);
   3560 					cwd = save_cwd();
   3561 					(void) fchdir(G_p->g_dirfd);
   3562 				} else {
   3563 					(void) strcpy(Lnkend_p,
   3564 					    l_p->L_gen.g_nam_p);
   3565 					(void) strcpy(Full_p,
   3566 					    tl_p->L_gen.g_nam_p);
   3567 				}
   3568 				(void) creat_lnk(G_p->g_dirfd,
   3569 				    Lnkend_p, Full_p);
   3570 				data_in(P_SKIP);
   3571 				close_dirfd();
   3572 				l_p->L_lnk_p = NULL;
   3573 				free(tl_p->L_gen.g_nam_p);
   3574 				free(tl_p);
   3575 				if (cwd != -1)
   3576 					rest_cwd(cwd);
   3577 			}
   3578 		}
   3579 	} else { /* Onecopy */
   3580 		if (tl_p->L_gen.g_filesz)
   3581 			cleanup = 1;
   3582 		if (!cleanup) {
   3583 			close_dirfd();
   3584 			return; /* don't do anything yet */
   3585 		}
   3586 		tl_p = l_p;
   3587 		/*
   3588 		 * ckname will clear aclchar. We need to keep aclchar for
   3589 		 * all links.
   3590 		 */
   3591 		savacl = aclchar;
   3592 		while (tl_p != NULL) {
   3593 			G_p = &tl_p->L_gen;
   3594 			aclchar = savacl;
   3595 			if ((proc_file = ckname(1)) != F_SKIP) {
   3596 				if (open_dirfd() != 0) {
   3597 					return;
   3598 				}
   3599 				if (l_p->L_data) {
   3600 					(void) creat_lnk(G_p->g_dirfd,
   3601 					    l_p->L_gen.g_nam_p,
   3602 					    G_p->g_nam_p);
   3603 				} else if (Aspec) {
   3604 					(void) creat_spec(G_p->g_dirfd);
   3605 					l_p->L_data = 1;
   3606 					VERBOSE((Args & (OCv | OCV)),
   3607 					    G_p->g_nam_p);
   3608 				} else if ((Ofile =
   3609 				    openout(G_p->g_dirfd)) < 0) {
   3610 					proc_file = F_SKIP;
   3611 				} else {
   3612 					data_in(P_PROC);
   3613 					l_p->L_data = 1;
   3614 				}
   3615 			} /* (proc_file = ckname(1)) != F_SKIP */
   3616 
   3617 			tl_p = tl_p->L_lnk_p;
   3618 
   3619 			close_dirfd();
   3620 
   3621 			if (proc_file == F_SKIP && !cleanup) {
   3622 				tl_p->L_nxt_p = l_p->L_nxt_p;
   3623 				tl_p->L_bck_p = l_p->L_bck_p;
   3624 				l_p->L_bck_p->L_nxt_p = tl_p;
   3625 				l_p->L_nxt_p->L_bck_p = tl_p;
   3626 				free(l_p->L_gen.g_nam_p);
   3627 				free(l_p);
   3628 			}
   3629 		} /* tl_p->L_lnk_p != NULL */
   3630 		if (l_p->L_data == 0) {
   3631 			data_in(P_SKIP);
   3632 		}
   3633 	}
   3634 	if (cleanup) {
   3635 		reclaim(l_p);
   3636 	}
   3637 }
   3638 
   3639 /*
   3640  * file_out:  If the current file is not a special file (!Aspec) and it
   3641  * is identical to the archive, skip it (do not archive the archive if it
   3642  * is a regular file).  If creating a TARTYP (TAR or USTAR) archive, the first
   3643  * time a link to a file is encountered, write the header and file out normally.
   3644  * Subsequent links to this file put this file name in their t_linkname field.
   3645  * Otherwise, links are handled in one of two ways, for the old headers
   3646  * (i.e. binary and -c), linked files are written out as they are encountered.
   3647  * For the new headers (ASC and CRC), links are saved up until all the links
   3648  * to each file are found.  For a file with n links, write n - 1 headers with
   3649  * g_filesz set to 0, write the final (nth) header with the correct g_filesz
   3650  * value and write the data for the file to the archive.
   3651  */
   3652 static
   3653 int
   3654 file_out(void)
   3655 {
   3656 	struct Lnk *l_p, *tl_p;
   3657 	int cleanup = 0;
   3658 	struct Lnk *ttl_p;
   3659 
   3660 	G_p = &Gen;
   3661 	if (!Aspec && IDENT(SrcSt, ArchSt))
   3662 		return (1); /* do not archive the archive if it's a reg file */
   3663 	/*
   3664 	 * If compressing sparse files, wait until the compressed file size
   3665 	 * is known to check if file size is too big.
   3666 	 */
   3667 	if (Compress_sparse == 0 && G_p->g_filesz > Max_offset) {
   3668 		msg(ERR, "%s%s%s: too large to archive in current mode",
   3669 		    G_p->g_nam_p,
   3670 		    (G_p->g_attrnam_p == NULL) ? "" : G_p->g_rw_sysattr ?
   3671 		    gettext(" System Attribute ") : gettext(" Attribute "),
   3672 		    (G_p->g_attrnam_p == NULL) ? "" :
   3673 		    ((G_p->g_attrparent_p == NULL) ? G_p->g_attrnam_p:
   3674 		    G_p->g_attrpath_p));
   3675 		return (1); /* do not archive if it's too big */
   3676 	}
   3677 	if (Hdr_type == TAR || Hdr_type == USTAR) { /* TAR and USTAR */
   3678 		if (Adir) {
   3679 			if (Gen.g_attrnam_p != NULL) {
   3680 				write_xattr_hdr();
   3681 			}
   3682 			write_hdr(ARCHIVE_NORMAL, 0);
   3683 			return (0);
   3684 		}
   3685 		if (G_p->g_nlink == 1) {
   3686 			data_out();
   3687 			return (0);
   3688 		}
   3689 		tl_p = add_lnk(&ttl_p);
   3690 		l_p = ttl_p;
   3691 		if (tl_p == l_p) { /* first link to this file encountered */
   3692 			data_out();
   3693 			return (0);
   3694 		}
   3695 		(void) strncpy(T_lname, l_p->L_gen.g_nam_p,
   3696 		    l_p->L_gen.g_namesz);
   3697 
   3698 		/*
   3699 		 * check if linkname is greater than 100 characters
   3700 		 */
   3701 		if (strlen(T_lname) > NAMSIZ) {
   3702 			msg(EPOST, "cpio: %s: linkname %s is greater than %d",
   3703 			    G_p->g_nam_p, T_lname, NAMSIZ);
   3704 			return (1);
   3705 		}
   3706 
   3707 		write_hdr(ARCHIVE_NORMAL, (off_t)0);
   3708 		VERBOSE((Args & (OCv | OCV)), tl_p->L_gen.g_nam_p);
   3709 
   3710 		/* find the lnk entry in sublist, unlink it, and free it */
   3711 		for (; ttl_p->L_lnk_p != NULL;
   3712 		    ttl_p = ttl_p->L_lnk_p) {
   3713 			if (ttl_p->L_lnk_p == tl_p) {
   3714 				ttl_p->L_lnk_p = tl_p->L_lnk_p;
   3715 				free(tl_p->L_gen.g_nam_p);
   3716 				free(tl_p);
   3717 				break;
   3718 			}
   3719 		}
   3720 
   3721 		return (0);
   3722 	}
   3723 	if (Adir) {
   3724 		/*
   3725 		 * ACL has been retrieved in getname().
   3726 		 */
   3727 		if (Pflag) {
   3728 			char    *secinfo = NULL;
   3729 			int	len = 0;
   3730 
   3731 			/* append security attributes */
   3732 			if ((append_secattr(&secinfo, &len, aclp)) == -1)
   3733 				msg(ERR, "can create security information");
   3734 
   3735 			/* call append_secattr() if more than one */
   3736 
   3737 			if (len > 0) {
   3738 			/* write ancillary */
   3739 				write_hdr(ARCHIVE_ACL, (off_t)len);
   3740 				write_ancillary(secinfo, len, B_TRUE);
   3741 			}
   3742 		}
   3743 
   3744 		if (Gen.g_attrnam_p != NULL) {
   3745 			write_xattr_hdr();
   3746 		}
   3747 		write_hdr(ARCHIVE_NORMAL, (off_t)0);
   3748 		VERBOSE((Args & (OCv | OCV)), G_p->g_nam_p);
   3749 		return (0);
   3750 	}
   3751 	if (G_p->g_nlink == 1) {
   3752 		data_out();
   3753 		return (0);
   3754 	} else {
   3755 		tl_p = add_lnk(&ttl_p);
   3756 		l_p = ttl_p;
   3757 
   3758 		if (l_p->L_cnt == l_p->L_gen.g_nlink)
   3759 			cleanup = 1;
   3760 		else if (Onecopy && G_p->g_attrnam_p == NULL) {
   3761 			return (0); /* don't process data yet */
   3762 		}
   3763 	}
   3764 	if (Onecopy && G_p->g_attrnam_p == NULL) {
   3765 		tl_p = l_p;
   3766 		while (tl_p->L_lnk_p != NULL) {
   3767 			G_p = &tl_p->L_gen;
   3768 			G_p->g_filesz = (off_t)0;
   3769 			/* one link with the acl is sufficient */
   3770 			write_hdr(ARCHIVE_NORMAL, (off_t)0);
   3771 			VERBOSE((Args & (OCv | OCV)), G_p->g_nam_p);
   3772 			tl_p = tl_p->L_lnk_p;
   3773 		}
   3774 		G_p = &tl_p->L_gen;
   3775 		if (open_dirfd() != 0)
   3776 			return (1);
   3777 	}
   3778 	/* old style: has acl and data for every link */
   3779 	data_out();
   3780 	if (cleanup)
   3781 		reclaim(l_p);
   3782 	return (0);
   3783 }
   3784 
   3785 /*
   3786  * Verify the underlying file system supports the attribute type.
   3787  * Only archive extended attribute files when '-@' was specified.
   3788  * Only archive system extended attribute files if '-/' was specified.
   3789  */
   3790 #if defined(O_XATTR)
   3791 static attr_status_t
   3792 verify_attr_support(char *filename, int attrflg, arc_action_t actflag,
   3793     int *ext_attrflg)
   3794 {
   3795 	/*
   3796 	 * Verify extended attributes are supported/exist.  We only
   3797 	 * need to check if we are processing a base file, not an
   3798 	 * extended attribute.
   3799 	 */
   3800 	if (attrflg) {
   3801 		*ext_attrflg = (pathconf(filename, (actflag == ARC_CREATE) ?
   3802 		    _PC_XATTR_EXISTS : _PC_XATTR_ENABLED) == 1);
   3803 	}
   3804 	if (Atflag) {
   3805 #if defined(_PC_SATTR_ENABLED)
   3806 		if (!*ext_attrflg) {
   3807 			if (SysAtflag) {
   3808 				/* Verify system attributes are supported */
   3809 				if (sysattr_support(filename,
   3810 				    (actflag == ARC_CREATE) ?_PC_SATTR_EXISTS :
   3811 				    _PC_SATTR_ENABLED) != 1) {
   3812 					return (ATTR_SATTR_ERR);
   3813 				}
   3814 			} else
   3815 				return (ATTR_XATTR_ERR);
   3816 #else
   3817 				return (ATTR_XATTR_ERR);
   3818 #endif  /* _PC_SATTR_ENABLED */
   3819 		}
   3820 
   3821 #if defined(_PC_SATTR_ENABLED)
   3822 	} else if (SysAtflag) {
   3823 		/* Verify system attributes are supported */
   3824 		if (sysattr_support(filename, (actflag == ARC_CREATE) ?
   3825 		    _PC_SATTR_EXISTS : _PC_SATTR_ENABLED) != 1) {
   3826 			return (ATTR_SATTR_ERR);
   3827 	}
   3828 #endif  /* _PC_SATTR_ENABLED */
   3829 	} else {
   3830 		return (ATTR_SKIP);
   3831 	}
   3832 
   3833 return (ATTR_OK);
   3834 }
   3835 #endif
   3836 
   3837 #if defined(O_XATTR)
   3838 /*
   3839  * Verify the attribute, attrname, is an attribute we want to restore.
   3840  * Never restore read-only system attribute files.  Only restore read-write
   3841  * system attributes files when -/ was specified, and only traverse into
   3842  * the 2nd level attribute directory containing only system attributes if
   3843  * -@ was specified.  This keeps us from archiving
   3844  *	<attribute name>/<read-write system attribute file>
   3845  * when -/ was specified without -@.
   3846  *
   3847  * attrname		- attribute file name
   3848  * attrparent		- attribute's parent name within the base file's
   3849  *			attribute digrectory hierarchy
   3850  * arc_rwsysattr	- flag that indicates that read-write system attribute
   3851  *			file should be archived as it contains other than
   3852  *			the default system attributes.
   3853  * rw_sysattr		- on return, flag will indicate if attrname is a
   3854  *			read-write system attribute file.
   3855  */
   3856 static attr_status_t
   3857 verify_attr(char *attrname, char *attrparent, int arc_rwsysattr,
   3858     int *rw_sysattr)
   3859 {
   3860 #if defined(_PC_SATTR_ENABLED)
   3861 	int	attr_supported;
   3862 
   3863 	/* Never restore read-only system attribute files */
   3864 	if ((attr_supported = sysattr_type(attrname)) == _RO_SATTR) {
   3865 		*rw_sysattr = 0;
   3866 		return (ATTR_SKIP);
   3867 	} else {
   3868 		*rw_sysattr = (attr_supported == _RW_SATTR);
   3869 	}
   3870 
   3871 	/*
   3872 	 * Don't archive a read-write system attribute file if
   3873 	 * it contains only the default system attributes.
   3874 	 */
   3875 	if (*rw_sysattr && !arc_rwsysattr) {
   3876 		return (ATTR_SKIP);
   3877 	}
   3878 
   3879 #else
   3880 	/* Never restore read-only system attribute files */
   3881 	if ((*rw_sysattr = is_sysattr(attrname)) == 1) {
   3882 		return (ATTR_SKIP);
   3883 	}
   3884 #endif	/* _PC_SATTR_ENABLED */
   3885 
   3886 	/*
   3887 	 * Only restore read-write system attribute files
   3888 	 * when -/ was specified.  Only restore extended
   3889 	 * attributes when -@ was specified.
   3890 	 */
   3891 	if (Atflag) {
   3892 		if (!SysAtflag) {
   3893 			/*
   3894 			 * Only archive/restore the hidden directory "." if
   3895 			 * we're processing the top level hidden attribute
   3896 			 * directory.  We don't want to process the
   3897 			 * hidden attribute directory of the attribute
   3898 			 * directory that contains only extended system
   3899 			 * attributes.
   3900 			 */
   3901 			if (*rw_sysattr || (Hiddendir &&
   3902 			    (attrparent != NULL))) {
   3903 				return (ATTR_SKIP);
   3904 			}
   3905 		}
   3906 	} else if (SysAtflag) {
   3907 		/*
   3908 		 * Only archive/restore read-write extended system attribute
   3909 		 * files of the base file.
   3910 		 */
   3911 		if (!*rw_sysattr || (attrparent != NULL)) {
   3912 			return (ATTR_SKIP);
   3913 		}
   3914 	} else {
   3915 		return (ATTR_SKIP);
   3916 	}
   3917 
   3918 	return (ATTR_OK);
   3919 }
   3920 #endif
   3921 
   3922 #if defined(O_XATTR)
   3923 static int
   3924 retry_open_attr(int pdirfd, int cwd, char *fullname, char *pattr, char *name,
   3925     int oflag, mode_t mode)
   3926 {
   3927 	int dirfd;
   3928 	int ofilefd = -1;
   3929 	struct timeval times[2];
   3930 	mode_t newmode;
   3931 	struct stat parentstat;
   3932 	acl_t *aclp = NULL;
   3933 	int error;
   3934 
   3935 	/*
   3936 	 * We couldn't get to attrdir. See if its
   3937 	 * just a mode problem on the parent file.
   3938 	 * for example: a mode such as r-xr--r--
   3939 	 * on a ufs file system without extended
   3940 	 * system attribute support won't let us
   3941 	 * create an attribute dir if it doesn't
   3942 	 * already exist, and on a ufs file system
   3943 	 * with extended system attribute support
   3944 	 * won't let us open the attribute for
   3945 	 * write.
   3946 	 *
   3947 	 * If file has a non-trivial ACL, then save it
   3948 	 * off so that we can place it back on after doing
   3949 	 * chmod's.
   3950 	 */
   3951 	if ((dirfd = openat(cwd, (pattr == NULL) ? fullname : pattr,
   3952 	    O_RDONLY)) == -1) {
   3953 		return (-1);
   3954 	}
   3955 	if (fstat(dirfd, &parentstat) == -1) {
   3956 		msg(ERRN, "Cannot stat %sfile %s",
   3957 		    (pdirfd == -1) ? "" : gettext("parent of "),
   3958 		    (pdirfd == -1) ? fullname : name);
   3959 		(void) close(dirfd);
   3960 		return (-1);
   3961 	}
   3962 	if ((error = facl_get(dirfd, ACL_NO_TRIVIAL, &aclp)) != 0) {
   3963 		msg(ERRN, "Failed to retrieve ACL on %sfile %s",
   3964 		    (pdirfd == -1) ? "" : gettext("parent of "),
   3965 		    (pdirfd == -1) ? fullname : name);
   3966 		(void) close(dirfd);
   3967 		return (-1);
   3968 	}
   3969 
   3970 	newmode = S_IWUSR | parentstat.st_mode;
   3971 	if (fchmod(dirfd, newmode) == -1) {
   3972 		msg(ERRN, "Cannot change mode of %sfile %s to %o",
   3973 		    (pdirfd == -1) ? "" : gettext("parent of "),
   3974 		    (pdirfd == -1) ? fullname : name, newmode);
   3975 		if (aclp)
   3976 			acl_free(aclp);
   3977 		(void) close(dirfd);
   3978 		return (-1);
   3979 	}
   3980 
   3981 
   3982 	if (pdirfd == -1) {
   3983 		/*
   3984 		 * We weren't able to create the attribute directory before.
   3985 		 * Now try again.
   3986 		 */
   3987 		ofilefd = attropen(fullname, ".", oflag);
   3988 	} else {
   3989 		/*
   3990 		 * We weren't able to create open the attribute before.
   3991 		 * Now try again.
   3992 		 */
   3993 		ofilefd = openat(pdirfd, name, oflag, mode);
   3994 	}
   3995 
   3996 	/*
   3997 	 * Put mode back to original
   3998 	 */
   3999 	if (fchmod(dirfd, parentstat.st_mode) == -1) {
   4000 		msg(ERRN, "Cannot restore permissions of %sfile %s to %o",
   4001 		    (pdirfd == -1) ? "" : gettext("parent of "),
   4002 		    (pdirfd == -1) ? fullname : name, newmode);
   4003 	}
   4004 
   4005 	if (aclp) {
   4006 		error = facl_set(dirfd, aclp);
   4007 		if (error) {
   4008 			msg(ERRN, "failed to set acl entries on %sfile %s\n",
   4009 			    (pdirfd == -1) ? "" : gettext("parent of "),
   4010 			    (pdirfd == -1) ? fullname : name);
   4011 		}
   4012 		acl_free(aclp);
   4013 	}
   4014 
   4015 	/*
   4016 	 * Put back time stamps
   4017 	 */
   4018 
   4019 	times[0].tv_sec = parentstat.st_atime;
   4020 	times[0].tv_usec = 0;
   4021 	times[1].tv_sec = parentstat.st_mtime;
   4022 	times[1].tv_usec = 0;
   4023 
   4024 	(void) futimesat(cwd, (pattr == NULL) ? fullname : pattr, times);
   4025 
   4026 	(void) close(dirfd);
   4027 
   4028 	return (ofilefd);
   4029 }
   4030 #endif
   4031 
   4032 #if defined(O_XATTR)
   4033 /*
   4034  * Recursively open attribute directories until the attribute directory
   4035  * containing the specified attribute, attrname, is opened.
   4036  *
   4037  * Currently, only 2 directory levels of attributes are supported, (i.e.,
   4038  * extended system attributes on extended attributes).  The following are
   4039  * the possible input combinations:
   4040  *	1.  Open the attribute directory of the base file (don't change
   4041  *	    into it).
   4042  *		attr_parent = NULL
   4043  *		attrname = '.'
   4044  *	2.  Open the attribute directory of the base file and change into it.
   4045  *		attr_parent = NULL
   4046  *		attrname = <attr> | <sys_attr>
   4047  *	3.  Open the attribute directory of the base file, change into it,
   4048  *	    then recursively call open_attr_dir() to open the attribute's
   4049  *	    parent directory (don't change into it).
   4050  *		attr_parent = <attr>
   4051  *		attrname = '.'
   4052  *	4.  Open the attribute directory of the base file, change into it,
   4053  *	    then recursively call open_attr_dir() to open the attribute's
   4054  *	    parent directory and change into it.
   4055  *		attr_parent = <attr>
   4056  *		attrname = <attr> | <sys_attr>
   4057  *
   4058  * An attribute directory will be opened only if the underlying file system
   4059  * supports the attribute type, and if the command line specifications
   4060  * (f_extended_attr and f_sys_attr) enable the processing of the attribute
   4061  * type.
   4062  *
   4063  * On succesful return, attr_parentfd will be the file descriptor of the
   4064  * opened attribute directory.  In addition, if the attribute is a read-write
   4065  * extended system attribute, rw_sysattr will be set to 1, otherwise
   4066  * it will be set to 0.
   4067  *
   4068  * Possible return values:
   4069  * 	ATTR_OK		Successfully opened and, if needed, changed into the
   4070  *			attribute directory containing attrname.
   4071  *	ATTR_SKIP	The command line specifications don't enable the
   4072  *			processing of the attribute type.
   4073  * 	ATTR_CHDIR_ERR	An error occurred while trying to change into an
   4074  *			attribute directory.
   4075  * 	ATTR_OPEN_ERR	An error occurred while trying to open an
   4076  *			attribute directory.
   4077  *	ATTR_XATTR_ERR	The underlying file system doesn't support extended
   4078  *			attributes.
   4079  *	ATTR_SATTR_ERR	The underlying file system doesn't support extended
   4080  *			system attributes.
   4081  */
   4082 static int
   4083 open_attr_dir(char *attrname, char *dirp, int cwd, char *attr_parent,
   4084     int *attr_parentfd, int *rw_sysattr)
   4085 {
   4086 	attr_status_t	rc;
   4087 	int		firsttime = (*attr_parentfd == -1);
   4088 	int		saveerrno;
   4089 	int		ext_attr;
   4090 
   4091 	/*
   4092 	 * open_attr_dir() was recursively called (input combination number 4),
   4093 	 * close the previously opened file descriptor as we've already changed
   4094 	 * into it.
   4095 	 */
   4096 	if (!firsttime) {
   4097 		(void) close(*attr_parentfd);
   4098 		*attr_parentfd = -1;
   4099 	}
   4100 
   4101 	/*
   4102 	 * Verify that the underlying file system supports the restoration
   4103 	 * of the attribute.
   4104 	 */
   4105 	if ((rc = verify_attr_support(dirp, firsttime, ARC_RESTORE,
   4106 	    &ext_attr)) != ATTR_OK) {
   4107 		return (rc);
   4108 	}
   4109 
   4110 	/* Open the base file's attribute directory */
   4111 	if ((*attr_parentfd = attropen(dirp, ".", O_RDONLY)) == -1) {
   4112 		/*
   4113 		 * Save the errno from the attropen so it can be reported
   4114 		 * if the retry of the attropen fails.
   4115 		 */
   4116 		saveerrno = errno;
   4117 		if ((*attr_parentfd = retry_open_attr(-1, cwd, dirp,
   4118 		    NULL, ".", O_RDONLY, 0)) == -1) {
   4119 			(void) close(*attr_parentfd);
   4120 			*attr_parentfd = -1;
   4121 			errno = saveerrno;
   4122 			return (ATTR_OPEN_ERR);
   4123 		}
   4124 	}
   4125 
   4126 	/*
   4127 	 * Change into the parent attribute's directory unless we are
   4128 	 * processing the hidden attribute directory of the base file itself.
   4129 	 */
   4130 	if ((Hiddendir == 0) || (firsttime && (attr_parent != NULL))) {
   4131 		if (fchdir(*attr_parentfd) != 0) {
   4132 			saveerrno = errno;
   4133 			(void) close(*attr_parentfd);
   4134 			*attr_parentfd = -1;
   4135 			errno = saveerrno;
   4136 			return (ATTR_CHDIR_ERR);
   4137 		}
   4138 	}
   4139 
   4140 	/* Determine if the attribute should be processed */
   4141 	if ((rc = verify_attr(attrname, attr_parent, 1,
   4142 	    rw_sysattr)) != ATTR_OK) {
   4143 		saveerrno = errno;
   4144 		(void) close(*attr_parentfd);
   4145 		*attr_parentfd = -1;
   4146 		errno = saveerrno;
   4147 		return (rc);
   4148 	}
   4149 
   4150 	/*
   4151 	 * If the attribute is an extended system attribute of an attribute
   4152 	 * (i.e., <attr>/<sys_attr>), then recursively call open_attr_dir() to
   4153 	 * open the attribute directory of the parent attribute.
   4154 	 */
   4155 	if (firsttime && (attr_parent != NULL)) {
   4156 		return (open_attr_dir(attrname, attr_parent, *attr_parentfd,
   4157 		    attr_parent, attr_parentfd, rw_sysattr));
   4158 	}
   4159 
   4160 	return (ATTR_OK);
   4161 }
   4162 #endif
   4163 
   4164 /*
   4165  * file_pass:  If the -l option is set (link files when possible), and the
   4166  * source and destination file systems are the same, link the source file
   4167  * (G_p->g_nam_p) to the destination file (Fullnam) and return.  If not a
   4168  * linked file, transfer the data.  Otherwise, the first link to a file
   4169  * encountered is transferred normally and subsequent links are linked to it.
   4170  */
   4171 
   4172 static int
   4173 file_pass(void)
   4174 {
   4175 	struct Lnk *l_p, *tl_p;
   4176 	struct Lnk *ttl_p;
   4177 	char *save_name;
   4178 	int size;
   4179 	int cwd;
   4180 	char *lfrom, *lto;
   4181 
   4182 	G_p = &Gen;
   4183 
   4184 	if (Adir && !(Args & OCd)) {
   4185 		msg(ERR, "Use -d option to copy \"%s\"", G_p->g_nam_p);
   4186 		return (FILE_PASS_ERR);
   4187 	}
   4188 
   4189 	save_name = G_p->g_nam_p;
   4190 
   4191 	while (*(G_p->g_nam_p) == '/') {
   4192 		G_p->g_nam_p++;
   4193 	}
   4194 
   4195 	(void) strcpy(Full_p, (G_p->g_attrfnam_p == NULL) ?
   4196 	    G_p->g_nam_p : G_p->g_attrfnam_p);
   4197 
   4198 	if (G_p->g_attrnam_p == NULL) {
   4199 		G_p->g_passdirfd = open_dir(Fullnam_p);
   4200 
   4201 		if (G_p->g_passdirfd == -1) {
   4202 			msg(ERRN,
   4203 			    "Cannot open/create \"%s\"", Fullnam_p);
   4204 			return (FILE_PASS_ERR);
   4205 		}
   4206 	} else {
   4207 		int	rw_sysattr;
   4208 
   4209 		/*
   4210 		 * Open the file's attribute directory.
   4211 		 * Change into the base file's starting directory then call
   4212 		 * open_attr_dir() to open the attribute directory of either
   4213 		 * the base file (if G_p->g_attrparent_p is NULL) or the
   4214 		 * attribute (if G_p->g_attrparent_p is set) of the base file.
   4215 		 */
   4216 
   4217 		G_p->g_passdirfd = -1;
   4218 		(void) fchdir(G_p->g_baseparent_fd);
   4219 		(void) open_attr_dir(G_p->g_attrnam_p, Fullnam_p,
   4220 		    G_p->g_baseparent_fd, (G_p->g_attrparent_p == NULL) ? NULL :
   4221 		    G_p->g_attrparent_p, &G_p->g_passdirfd, &rw_sysattr);
   4222 		if (G_p->g_passdirfd == -1) {
   4223 			msg(ERRN,
   4224 			    "Cannot open attribute directory of "
   4225 			    "%s%s%sfile \"%s\"",
   4226 			    (G_p->g_attrparent_p == NULL) ? "" :
   4227 			    gettext("attribute \""),
   4228 			    (G_p->g_attrparent_p == NULL) ? "" :
   4229 			    G_p->g_attrparent_p,
   4230 			    (G_p->g_attrparent_p == NULL) ? "" :
   4231 			    gettext("\" of "), Fullnam_p);
   4232 			return (FILE_PASS_ERR);
   4233 		}
   4234 	}
   4235 
   4236 	if (Args & OCl) {
   4237 		/* We are linking back to the source directory. */
   4238 
   4239 		if (!Adir) {
   4240 			char *existingfile = save_name;
   4241 
   4242 			if ((Args & OCL) && issymlink) {
   4243 				/* We are chasing symlinks. */
   4244 
   4245 				if ((size = readlink(save_name, Symlnk_p,
   4246 				    MAXPATHLEN)) < 0) {
   4247 					msg(ERRN,
   4248 					    "Cannot read symbolic link \"%s\"",
   4249 					    save_name);
   4250 					return (FILE_PASS_ERR);
   4251 				}
   4252 
   4253 				Symlnk_p[size] = '\0';
   4254 				existingfile = Symlnk_p;
   4255 			}
   4256 
   4257 			if (G_p->g_attrnam_p == NULL) {
   4258 				if (creat_lnk(G_p->g_passdirfd,
   4259 				    existingfile, Fullnam_p) == 0) {
   4260 					return (FILE_LINKED);
   4261 				}
   4262 			}
   4263 		}
   4264 	}
   4265 
   4266 	if ((G_p->g_mode & Ftype) == S_IFLNK && !(Args & OCL)) {
   4267 		/* The archive file is a symlink. */
   4268 
   4269 		errno = 0;
   4270 
   4271 		if ((size = readlink(save_name, Symlnk_p, MAXPATHLEN)) < 0) {
   4272 			msg(ERRN,
   4273 			    "Cannot read symbolic link \"%s\"", save_name);
   4274 			return (FILE_PASS_ERR);
   4275 		}
   4276 
   4277 		errno = 0;
   4278 		(void) missdir(Fullnam_p);
   4279 		*(Symlnk_p + size) = '\0';
   4280 
   4281 		if (symlink(Symlnk_p, Fullnam_p) < 0) {
   4282 			if (errno == EEXIST) {
   4283 				if (openout(G_p->g_passdirfd) < 0) {
   4284 					if (errno != EEXIST) {
   4285 						msg(ERRN,
   4286 						    "Cannot create \"%s\"",
   4287 						    Fullnam_p);
   4288 					}
   4289 					return (FILE_PASS_ERR);
   4290 				}
   4291 			} else {
   4292 				msg(ERRN, "Cannot create \"%s\"", Fullnam_p);
   4293 				return (FILE_PASS_ERR);
   4294 			}
   4295 		} else {
   4296 			if (Args & OCR) {
   4297 				if (lchown(Fullnam_p, (int)Rpw_p->pw_uid,
   4298 				    (int)Rpw_p->pw_gid) < 0) {
   4299 					msg(ERRN,
   4300 					    "Error during chown() of \"%s\"",
   4301 					    Fullnam_p);
   4302 				}
   4303 			} else if ((lchown(Fullnam_p, (int)G_p->g_uid,
   4304 			    (int)G_p->g_gid) < 0) && privileged) {
   4305 				msg(ERRN,
   4306 				    "Error during chown() of \"%s\"",
   4307 				    Fullnam_p);
   4308 			}
   4309 		}
   4310 
   4311 		VERBOSE((Args & (OCv | OCV)), Fullnam_p);
   4312 		return (FILE_PASS_ERR);
   4313 	}
   4314 
   4315 	if (!Adir && G_p->g_nlink > 1) {
   4316 		/* The archive file has hard links. */
   4317 
   4318 		tl_p = add_lnk(&ttl_p);
   4319 		l_p = ttl_p;
   4320 
   4321 		if (tl_p == l_p) {
   4322 			/* The archive file was not found. */
   4323 
   4324 			G_p = &tl_p->L_gen;
   4325 		} else {
   4326 			/* The archive file was found. */
   4327 
   4328 			cwd = -1;
   4329 
   4330 			if (l_p->L_gen.g_attrnam_p != NULL) {
   4331 				/* We are linking an attribute */
   4332 
   4333 				(void) strcpy(Lnkend_p, l_p->L_gen.g_attrnam_p);
   4334 				cwd = save_cwd();
   4335 				(void) fchdir(G_p->g_passdirfd);
   4336 				lfrom = get_component(Lnknam_p);
   4337 				lto = tl_p->L_gen.g_attrnam_p;
   4338 			} else {
   4339 				/* We are not linking an attribute */
   4340 
   4341 				(void) strcpy(Lnkend_p, l_p->L_gen.g_nam_p);
   4342 				(void) strcpy(Full_p, tl_p->L_gen.g_nam_p);
   4343 				lfrom = Lnknam_p;
   4344 				lto = Fullnam_p;
   4345 			}
   4346 
   4347 			(void) creat_lnk(G_p->g_passdirfd, lfrom, lto);
   4348 
   4349 			if (cwd) {
   4350 				rest_cwd(cwd);
   4351 			}
   4352 
   4353 			l_p->L_lnk_p = NULL;
   4354 			free(tl_p->L_gen.g_nam_p);
   4355 			free(tl_p);
   4356 
   4357 			if (l_p->L_cnt == G_p->g_nlink) {
   4358 				reclaim(l_p);
   4359 			}
   4360 
   4361 			return (FILE_LINKED);
   4362 		}
   4363 	}
   4364 
   4365 	if (Adir || Aspec) {
   4366 		/*
   4367 		 * The archive file is a directory,  block special, char
   4368 		 * special or a fifo.
   4369 		 */
   4370 
   4371 		if (creat_spec(G_p->g_passdirfd) > 0) {
   4372 			VERBOSE((Args & (OCv | OCV)), Fullnam_p);
   4373 		}
   4374 	} else if ((Ofile = openout(G_p->g_passdirfd)) > 0) {
   4375 		data_pass();
   4376 	}
   4377 
   4378 	return (FILE_COPIED);
   4379 }
   4380 
   4381 /*
   4382  * flush_lnks: With new linked file handling, linked files are not archived
   4383  * until all links have been collected.  When the end of the list of filenames
   4384  * to archive has been reached, all files that did not encounter all their links
   4385  * are written out with actual (encountered) link counts.  A file with n links
   4386  * (that are archived) will be represented by n headers (one for each link (the
   4387  * first n - 1 have g_filesz set to 0)) followed by the data for the file.
   4388  */
   4389 
   4390 static void
   4391 flush_lnks(void)
   4392 {
   4393 	struct Lnk *l_p, *tl_p;
   4394 	off_t tfsize;
   4395 
   4396 	l_p = Lnk_hd.L_nxt_p;
   4397 	while (l_p != &Lnk_hd) {
   4398 		(void) strcpy(Gen.g_nam_p, l_p->L_gen.g_nam_p);
   4399 		if (stat(Gen.g_nam_p, &SrcSt) == 0) { /* check if file exists */
   4400 			tl_p = l_p;
   4401 			(void) creat_hdr();
   4402 			Gen.g_nlink = l_p->L_cnt; /* "actual" link count */
   4403 			tfsize = Gen.g_filesz;
   4404 			Gen.g_filesz = (off_t)0;
   4405 			G_p = &Gen;
   4406 			while (tl_p != NULL) {
   4407 				Gen.g_nam_p = tl_p->L_gen.g_nam_p;
   4408 				Gen.g_namesz = tl_p->L_gen.g_namesz;
   4409 				if (tl_p->L_lnk_p == NULL) {
   4410 					Gen.g_filesz = tfsize;
   4411 					if (open_dirfd() != 0) {
   4412 						break;
   4413 					}
   4414 					data_out();
   4415 					break;
   4416 				}
   4417 				write_hdr(ARCHIVE_NORMAL,
   4418 				    (off_t)0); /* header only */
   4419 				VERBOSE((Args & (OCv | OCV)), Gen.g_nam_p);
   4420 				tl_p = tl_p->L_lnk_p;
   4421 			}
   4422 			Gen.g_nam_p = Nam_p;
   4423 		} else /* stat(Gen.g_nam_p, &SrcSt) == 0 */
   4424 			msg(ERR, "\"%s%s%s\" has disappeared",
   4425 			    (Gen.g_attrnam_p == NULL) ?
   4426 			    Gen.g_nam_p : Gen.g_attrfnam_p,
   4427 			    (Gen.g_attrnam_p == NULL) ?
   4428 			    "" : Gen.g_rw_sysattr ?
   4429 			    gettext(" System Attribute ") :
   4430 			    gettext(" Attribute "),
   4431 			    (Gen.g_attrnam_p == NULL) ?
   4432 			    "" : Gen.g_attrnam_p);
   4433 		tl_p = l_p;
   4434 		l_p = l_p->L_nxt_p;
   4435 		reclaim(tl_p);
   4436 	} /* l_p != &Lnk_hd */
   4437 }
   4438 
   4439 #if defined(O_XATTR)
   4440 static int
   4441 is_sysattr(char *name)
   4442 {
   4443 	return ((strcmp(name, VIEW_READONLY) == 0) ||
   4444 	    (strcmp(name, VIEW_READWRITE) == 0));
   4445 }
   4446 #endif
   4447 
   4448 /*
   4449  * gethdr: Get a header from the archive, validate it and check for the trailer.
   4450  * Any user specified Hdr_type is ignored (set to NONE in main).  Hdr_type is
   4451  * set appropriately after a valid header is found.  Unless the -k option is
   4452  * set a corrupted header causes an exit with an error.  I/O errors during
   4453  * examination of any part of the header cause gethdr to throw away any current
   4454  * data and start over.  Other errors during examination of any part of the
   4455  * header cause gethdr to advance one byte and continue the examination.
   4456  */
   4457 
   4458 static int
   4459 gethdr(void)
   4460 {
   4461 	ushort_t ftype;
   4462 	int hit = NONE, cnt = 0;
   4463 	int goodhdr, hsize, offset;
   4464 	int bswap = 0;
   4465 	char *preptr;
   4466 	int k = 0;
   4467 	int j;
   4468 	int error;
   4469 	int aclcnt;
   4470 
   4471 	Gen.g_nam_p = Nam_p;
   4472 	do { /* hit == NONE && (Args & OCk) && Buffr.b_cnt > 0 */
   4473 		FILL(Hdrsz);
   4474 		switch (Hdr_type) {
   4475 		case NONE:
   4476 		case BIN:
   4477 			Binmag.b_byte[0] = Buffr.b_out_p[0];
   4478 			Binmag.b_byte[1] = Buffr.b_out_p[1];
   4479 			if ((Binmag.b_half == CMN_BIN) ||
   4480 			    (Binmag.b_half == CMN_BBS)) {
   4481 				hit = read_hdr(BIN);
   4482 				if (Hdr_type == NONE)
   4483 					bswap = 1;
   4484 				hsize = HDRSZ + Gen.g_namesz;
   4485 				break;
   4486 			}
   4487 			if (Hdr_type != NONE)
   4488 				break;
   4489 			/*FALLTHROUGH*/
   4490 		case CHR:
   4491 			if (!(strncmp(Buffr.b_out_p, CMS_CHR, CMS_LEN))) {
   4492 				hit = read_hdr(CHR);
   4493 				hsize = CHRSZ + Gen.g_namesz;
   4494 				break;
   4495 			}
   4496 			if (Hdr_type != NONE)
   4497 				break;
   4498 			/*FALLTHROUGH*/
   4499 		case ASC:
   4500 			if (!(strncmp(Buffr.b_out_p, CMS_ASC, CMS_LEN))) {
   4501 				hit = read_hdr(ASC);
   4502 				hsize = ASCSZ + Gen.g_namesz;
   4503 				Max_namesz = APATH;
   4504 				break;
   4505 			}
   4506 			if (Hdr_type != NONE)
   4507 				break;
   4508 			/*FALLTHROUGH*/
   4509 		case CRC:
   4510 			if (!(strncmp(Buffr.b_out_p, CMS_CRC, CMS_LEN))) {
   4511 				hit = read_hdr(CRC);
   4512 				hsize = ASCSZ + Gen.g_namesz;
   4513 				Max_namesz = APATH;
   4514 				break;
   4515 			}
   4516 			if (Hdr_type != NONE)
   4517 				break;
   4518 			/*FALLTHROUGH*/
   4519 
   4520 		case BAR:
   4521 			if (Hdr_p != NULL && strcmp(Hdr_p, "bar") == 0) {
   4522 				Hdrsz = BARSZ;
   4523 				FILL(Hdrsz);
   4524 				if ((hit = read_hdr(BAR)) == NONE) {
   4525 					Hdrsz = ASCSZ;
   4526 					break;
   4527 				}
   4528 				hit = BAR;
   4529 				hsize = BARSZ;
   4530 				break;
   4531 			}
   4532 			/*FALLTHROUGH*/
   4533 
   4534 		case USTAR:
   4535 			if (Hdr_p != NULL && strcmp(Hdr_p, "ustar") == 0) {
   4536 				Hdrsz = TARSZ;
   4537 				FILL(Hdrsz);
   4538 				if ((hit = read_hdr(USTAR)) == NONE) {
   4539 					Hdrsz = ASCSZ;
   4540 					break;
   4541 				}
   4542 				hit = USTAR;
   4543 				hsize = TARSZ;
   4544 				break;
   4545 			}
   4546 			/*FALLTHROUGH*/
   4547 		case TAR:
   4548 			if (Hdr_p != NULL && strcmp(Hdr_p, "tar") == 0) {
   4549 				Hdrsz = TARSZ;
   4550 				FILL(Hdrsz);
   4551 				if ((hit = read_hdr(TAR)) == NONE) {
   4552 					Hdrsz = ASCSZ;
   4553 					break;
   4554 				}
   4555 				hit = TAR;
   4556 				hsize = TARSZ;
   4557 				break;
   4558 			}
   4559 			/*FALLTHROUGH*/
   4560 		default:
   4561 			msg(EXT, "Impossible header type.");
   4562 		} /* Hdr_type */
   4563 
   4564 		if (hit == TAR || hit == USTAR) {
   4565 			Gen.g_nam_p = &nambuf[0];
   4566 		}
   4567 
   4568 		if (hit != NONE) {
   4569 			FILL(hsize);
   4570 			goodhdr = 1;
   4571 			if (Gen.g_filesz < (off_t)0 || Gen.g_namesz < 1)
   4572 				goodhdr = 0;
   4573 			if ((hit != USTAR) && (hit != TAR))
   4574 				if (Gen.g_namesz - 1 > Max_namesz)
   4575 					goodhdr = 0;
   4576 			/* TAR and USTAR */
   4577 			if ((hit == USTAR) || (hit == TAR)) {
   4578 				if (*Gen.g_nam_p == '\0') { /* tar trailer */
   4579 					goodhdr = 1;
   4580 				} else {
   4581 
   4582 					G_p = &Gen;
   4583 					if (G_p->g_cksum !=
   4584 					    cksum(TARTYP, 0, NULL)) {
   4585 						goodhdr = 0;
   4586 						msg(ERR,
   4587 						    "Bad header - checksum "
   4588 						    "error.");
   4589 					}
   4590 				}
   4591 			} else if (hit != BAR) { /* binary, -c, ASC and CRC */
   4592 				if (Gen.g_nlink <= (ulong_t)0)
   4593 					goodhdr = 0;
   4594 				if (*(Buffr.b_out_p + hsize - 1) != '\0')
   4595 					goodhdr = 0;
   4596 			}
   4597 			if (!goodhdr) {
   4598 				hit = NONE;
   4599 				if (!(Args & OCk))
   4600 					break;
   4601 				msg(ERR,
   4602 				    "Corrupt header, file(s) may be lost.");
   4603 			} else {
   4604 				FILL(hsize);
   4605 			}
   4606 		} /* hit != NONE */
   4607 		if (hit == NONE) {
   4608 			Buffr.b_out_p++;
   4609 			Buffr.b_cnt--;
   4610 			if (!(Args & OCk))
   4611 				break;
   4612 			if (!cnt++)
   4613 				msg(ERR, "Searching for magic number/header.");
   4614 		}
   4615 	} while (hit == NONE);
   4616 	if (hit == NONE) {
   4617 		if (Hdr_type == NONE)
   4618 			msg(EXT, "Not a cpio file, bad header.");
   4619 		else
   4620 			msg(EXT, "Bad magic number/header.");
   4621 	} else if (cnt > 0) {
   4622 		msg(EPOST, "Re-synchronized on magic number/header.");
   4623 	}
   4624 	if (Hdr_type == NONE) {
   4625 		Hdr_type = hit;
   4626 		switch (Hdr_type) {
   4627 		case BIN:
   4628 			if (bswap)
   4629 				Args |= BSM;
   4630 			Hdrsz = HDRSZ;
   4631 			Max_namesz = CPATH;
   4632 			Pad_val = HALFWD;
   4633 			Onecopy = 0;
   4634 			break;
   4635 		case CHR:
   4636 			Hdrsz = CHRSZ;
   4637 			Max_namesz = CPATH;
   4638 			Pad_val = 0;
   4639 			Onecopy = 0;
   4640 			break;
   4641 		case ASC:
   4642 		case CRC:
   4643 			Hdrsz = ASCSZ;
   4644 			Max_namesz = APATH;
   4645 			Pad_val = FULLWD;
   4646 			Onecopy = 1;
   4647 			break;
   4648 		case USTAR:
   4649 			Hdrsz = TARSZ;
   4650 			Max_namesz = HNAMLEN - 1;
   4651 			Pad_val = FULLBK;
   4652 			Onecopy = 0;
   4653 			break;
   4654 		case BAR:
   4655 		case TAR:
   4656 			Hdrsz = TARSZ;
   4657 			Max_namesz = TNAMLEN - 1;
   4658 			Pad_val = FULLBK;
   4659 			Onecopy = 0;
   4660 			break;
   4661 		default:
   4662 			msg(EXT, "Impossible header type.");
   4663 		} /* Hdr_type */
   4664 	} /* Hdr_type == NONE */
   4665 	if ((Hdr_type == USTAR) || (Hdr_type == TAR) ||
   4666 	    (Hdr_type == BAR)) {			/* TAR, USTAR, BAR */
   4667 		Gen.g_namesz = 0;
   4668 		if (Gen.g_nam_p[0] == '\0')
   4669 			return (0);
   4670 		else {
   4671 			preptr = &prebuf[0];
   4672 			if (*preptr != NULL) {
   4673 				k = strlen(&prebuf[0]);
   4674 				if (k < PRESIZ) {
   4675 					(void) strcpy(&fullnam[0], &prebuf[0]);
   4676 					j = 0;
   4677 					fullnam[k++] = '/';
   4678 					while ((j < NAMSIZ) && (&nambuf[j] !=
   4679 					    '\0')) {
   4680 						fullnam[k] = nambuf[j];
   4681 						k++; j++;
   4682 					}
   4683 					fullnam[k] = '\0';
   4684 				} else if (k >= PRESIZ) {
   4685 					k = 0;
   4686 					while ((k < PRESIZ) && (prebuf[k] !=
   4687 					    '\0')) {
   4688 						fullnam[k] = prebuf[k];
   4689 						k++;
   4690 					}
   4691 					fullnam[k++] = '/';
   4692 					j = 0;
   4693 					while ((j < NAMSIZ) && (nambuf[j] !=
   4694 					    '\0')) {
   4695 						fullnam[k] = nambuf[j];
   4696 						k++; j++;
   4697 					}
   4698 					fullnam[k] = '\0';
   4699 				}
   4700 				Gen.g_nam_p = &fullnam[0];
   4701 			} else
   4702 				Gen.g_nam_p = &nambuf[0];
   4703 
   4704 			/*
   4705 			 * initialize the buffer so that the prefix will not
   4706 			 * applied to the next entry in the archive
   4707 			 */
   4708 			(void) memset(prebuf, 0, sizeof (prebuf));
   4709 		}
   4710 	} else if (Hdr_type != BAR) {
   4711 		(void) memcpy(Gen.g_nam_p, Buffr.b_out_p + Hdrsz, Gen.g_namesz);
   4712 		if (!(strcmp(Gen.g_nam_p, "TRAILER!!!")))
   4713 			return (0);
   4714 	}
   4715 	offset = ((hsize + Pad_val) & ~Pad_val);
   4716 	FILL(offset + Hdrsz);
   4717 	Thdr_p = (union tblock *)Buffr.b_out_p;
   4718 	Buffr.b_out_p += offset;
   4719 	Buffr.b_cnt -= (off_t)offset;
   4720 	ftype = Gen.g_mode & Ftype;
   4721 
   4722 #if defined(O_XATTR)
   4723 	/* extended attribute support */
   4724 	if (((Gen.g_mode & S_IFMT) == _XATTR_CPIO_MODE) ||
   4725 	    ((Hdr_type == USTAR || Hdr_type == TAR) &&
   4726 	    Thdr_p->tbuf.t_typeflag == _XATTR_HDRTYPE)) {
   4727 		char	*aname;
   4728 		char	*attrparent = NULL;
   4729 		char	*attrpath = NULL;
   4730 		char	*tapath;
   4731 		char	*taname;
   4732 
   4733 		if (xattrp != NULL) {
   4734 			if (xattrbadhead) {
   4735 				free(xattrhead);
   4736 				xattrp = NULL;
   4737 				xattr_linkp = NULL;
   4738 				xattrhead = NULL;
   4739 				return (1);
   4740 			}
   4741 
   4742 			/*
   4743 			 * At this point, the attribute path contains
   4744 			 * the path to the attribute rooted at the hidden
   4745 			 * attribute directory of the base file.  This can
   4746 			 * be a simple attribute or extended attribute name,
   4747 			 * or it can be something like <attr>/<sys attr> if
   4748 			 * we are processing a system attribute of an attribute.
   4749 			 * Determine the attribute name and attribute parent
   4750 			 * (if there is one).  When we are processing a simple
   4751 			 * attribute or extended attribute name, the attribute
   4752 			 * parent will be set to NULL.  When we are processing
   4753 			 * something like <attr>/<sys attr>, the attribute
   4754 			 * parent will be contain <attr>, and the attribute
   4755 			 * name will contain <sys attr>.
   4756 			 */
   4757 			tapath = xattrp->h_names +
   4758 			    strlen(xattrp->h_names) + 1;
   4759 			attrpath = e_strdup(E_EXIT, tapath);
   4760 			if ((taname = strpbrk(tapath, "/")) != NULL) {
   4761 				aname = taname + 1;
   4762 				*taname = '\0';
   4763 				attrparent = tapath;
   4764 			} else {
   4765 				aname = tapath;
   4766 			}
   4767 
   4768 			Gen.g_rw_sysattr = is_sysattr(aname);
   4769 			Gen.g_baseparent_fd = attr_baseparent_fd;
   4770 
   4771 			if (Gen.g_attrfnam_p != NULL) {
   4772 				free(Gen.g_attrfnam_p);
   4773 				Gen.g_attrfnam_p = NULL;
   4774 			}
   4775 			if (Gen.g_attrnam_p != NULL) {
   4776 				free(Gen.g_attrnam_p);
   4777 				Gen.g_attrnam_p = NULL;
   4778 			}
   4779 			if (Gen.g_attrparent_p != NULL) {
   4780 				free(Gen.g_attrparent_p);
   4781 				Gen.g_attrparent_p = NULL;
   4782 			}
   4783 			if (Gen.g_attrpath_p != NULL) {
   4784 				free(Gen.g_attrpath_p);
   4785 				Gen.g_attrpath_p = NULL;
   4786 			}
   4787 			if (Renam_p && Renam_p[0] != '\0') {
   4788 				Gen.g_attrfnam_p = e_strdup(E_EXIT, Renam_p);
   4789 			} else {
   4790 				Gen.g_attrfnam_p = e_strdup(E_EXIT,
   4791 				    xattrp->h_names);
   4792 			}
   4793 			Gen.g_attrnam_p = e_strdup(E_EXIT, aname);
   4794 
   4795 			if (attrparent != NULL) {
   4796 				if (Renam_attr_p && Renam_attr_p[0] != '\0') {
   4797 					size_t	apathlen = strlen(attrparent) +
   4798 					    strlen(aname) + 2;
   4799 					Gen.g_attrparent_p = e_strdup(E_EXIT,
   4800 					    Renam_attr_p);
   4801 					Gen.g_attrpath_p = e_zalloc(E_EXIT,
   4802 					    apathlen);
   4803 					(void) snprintf(Gen.g_attrpath_p,
   4804 					    apathlen, "%s/%s", Renam_attr_p,
   4805 					    aname);
   4806 					(void) free(attrparent);
   4807 					(void) free(attrpath);
   4808 				} else {
   4809 					Gen.g_attrparent_p = attrparent;
   4810 					Gen.g_attrpath_p = attrpath;
   4811 				}
   4812 			} else {
   4813 				Gen.g_attrpath_p = attrpath;
   4814 			}
   4815 
   4816 			if (xattr_linkp != NULL) {
   4817 				if (Gen.g_linktoattrfnam_p != NULL) {
   4818 					free(Gen.g_linktoattrfnam_p);
   4819 					Gen.g_linktoattrfnam_p = NULL;
   4820 				}
   4821 				if (Gen.g_linktoattrnam_p != NULL) {
   4822 					free(Gen.g_linktoattrnam_p);
   4823 					Gen.g_linktoattrnam_p = NULL;
   4824 				}
   4825 				if (Renam_attr_p && Renam_attr_p[0] != '\0') {
   4826 					Gen.g_linktoattrfnam_p = e_strdup(
   4827 					    E_EXIT, Renam_attr_p);
   4828 				} else {
   4829 					Gen.g_linktoattrfnam_p = e_strdup(
   4830 					    E_EXIT, xattr_linkp->h_names);
   4831 				}
   4832 				Gen.g_linktoattrnam_p = e_strdup(E_EXIT,
   4833 				    aname);
   4834 				xattr_linkp = NULL;
   4835 			}
   4836 			if (Hdr_type != USTAR && Hdr_type != TAR) {
   4837 				Gen.g_mode = Gen.g_mode & (~_XATTR_CPIO_MODE);
   4838 				Gen.g_mode |= attrmode(xattrp->h_typeflag);
   4839 			} else if (Hdr_type == USTAR || Hdr_type == TAR) {
   4840 				Thdr_p->tbuf.t_typeflag = xattrp->h_typeflag;
   4841 			}
   4842 
   4843 			ftype = Gen.g_mode & Ftype;
   4844 			Adir = ftype == S_IFDIR;
   4845 			Aspec = (ftype == S_IFBLK || ftype == S_IFCHR ||
   4846 			    ftype == S_IFIFO || ftype == S_IFSOCK);
   4847 
   4848 			if (Gen.g_attrnam_p[0] == '.' &&
   4849 			    Gen.g_attrnam_p[1] == '\0' &&
   4850 			    xattrp->h_typeflag == DIRTYPE) {
   4851 				Hiddendir = 1;
   4852 			} else {
   4853 				Hiddendir = 0;
   4854 			}
   4855 
   4856 			free(xattrhead);
   4857 			xattrhead = NULL;
   4858 			xattrp = NULL;
   4859 		} else {
   4860 			if (xattrbadhead == 0) {
   4861 				(void) read_xattr_hdr();
   4862 				return (2);
   4863 			}
   4864 		}
   4865 	} else {
   4866 		Hiddendir = 0;
   4867 	}
   4868 #endif /* O_XATTR */
   4869 
   4870 	/* acl support: grab acl info */
   4871 	if ((Gen.g_mode == SECMODE) || ((Hdr_type == USTAR ||
   4872 	    Hdr_type == TAR) && Thdr_p->tbuf.t_typeflag == 'A')) {
   4873 		/* this is an ancillary file */
   4874 		off_t	bytes;
   4875 		char	*secp;
   4876 		int	pad;
   4877 		int	cnt;
   4878 		char	*tp;
   4879 		int	attrsize;
   4880 
   4881 		if (Pflag) {
   4882 			bytes = Gen.g_filesz;
   4883 			secp = e_zalloc(E_EXIT, (uint_t)bytes);
   4884 			tp = secp;
   4885 
   4886 			while (bytes > 0) {
   4887 				cnt = (int)(bytes > CPIOBSZ) ? CPIOBSZ : bytes;
   4888 				FILL(cnt);
   4889 				(void) memcpy(tp, Buffr.b_out_p, cnt);
   4890 				tp += cnt;
   4891 				Buffr.b_out_p += cnt;
   4892 				Buffr.b_cnt -= (off_t)cnt;
   4893 				bytes -= (off_t)cnt;
   4894 			}
   4895 
   4896 			pad = (Pad_val + 1 - (Gen.g_filesz & Pad_val)) &
   4897 			    Pad_val;
   4898 			if (pad != 0) {
   4899 				FILL(pad);
   4900 				Buffr.b_out_p += pad;
   4901 				Buffr.b_cnt -= (off_t)pad;
   4902 			}
   4903 
   4904 			/* got all attributes in secp */
   4905 			tp = secp;
   4906 			do {
   4907 				attr = (struct sec_attr *)tp;
   4908 				switch (attr->attr_type) {
   4909 				case UFSD_ACL:
   4910 				case ACE_ACL:
   4911 					(void) sscanf(attr->attr_len, "%7lo",
   4912 					    (ulong_t *)&aclcnt);
   4913 					/* header is 8 */
   4914 					attrsize = 8 +
   4915 					    strlen(&attr->attr_info[0])
   4916 					    + 1;
   4917 
   4918 					error =
   4919 					    acl_fromtext(&attr->attr_info[0],
   4920 					    &aclp);
   4921 
   4922 					if (error != 0) {
   4923 						msg(ERR,
   4924 						    "aclfromtext failed: %s",
   4925 						    acl_strerror(error));
   4926 						bytes -= attrsize;
   4927 						break;
   4928 					}
   4929 
   4930 					if (aclcnt != acl_cnt(aclp)) {
   4931 						msg(ERR, "acl count error");
   4932 						bytes -= attrsize;
   4933 						break;
   4934 					}
   4935 					bytes -= attrsize;
   4936 					break;
   4937 
   4938 				/* SunFed case goes here */
   4939 
   4940 				default:
   4941 					msg(EXT, "unrecognized attr type");
   4942 					break;
   4943 			}
   4944 			/* next attributes */
   4945 			tp += attrsize;
   4946 			} while (bytes > 0);
   4947 			free(secp);
   4948 		} else {
   4949 			/* skip security info */
   4950 			G_p = &Gen;
   4951 			data_in(P_SKIP);
   4952 		}
   4953 		/*
   4954 		 * We already got the file content, dont call file_in()
   4955 		 * when return. The new return code(2) is used to
   4956 		 *  indicate that.
   4957 		 */
   4958 		VERBOSE((Args & OCt), Gen.g_nam_p);
   4959 		return (2);
   4960 	} /* acl */
   4961 
   4962 	/*
   4963 	 * Sparse file support
   4964 	 * Read header of holesdata to get original file size.
   4965 	 * This is necessary because ckname() or file_in() shows file size
   4966 	 * with OCt before data_in() extracts the holesdata. data_in()
   4967 	 * actually doesn't extract the holesdata since proc_mode will be
   4968 	 * P_SKIP in the OCt mode.
   4969 	 */
   4970 	if ((Hdr_type == CHR || Hdr_type == ASC) &&
   4971 	    S_ISSPARSE(Gen.g_mode) && Gen.g_filesz > MIN_HOLES_HDRSIZE) {
   4972 		char	holesdata[MIN_HOLES_HDRSIZE + 1];
   4973 
   4974 		FILL(MIN_HOLES_HDRSIZE);
   4975 		(void) memcpy(holesdata, Buffr.b_out_p, MIN_HOLES_HDRSIZE);
   4976 		holesdata[MIN_HOLES_HDRSIZE] = '\0';
   4977 
   4978 		Gen.g_holes = read_holes_header(holesdata, Gen.g_filesz);
   4979 		if (Gen.g_holes == NULL) {
   4980 			msg(EXT, "invalid sparse file information");
   4981 		} else {
   4982 			Buffr.b_out_p += MIN_HOLES_HDRSIZE;
   4983 			Buffr.b_cnt -= MIN_HOLES_HDRSIZE;
   4984 		}
   4985 	}
   4986 
   4987 	Adir = (ftype == S_IFDIR);
   4988 	Aspec = (ftype == S_IFBLK || ftype == S_IFCHR || ftype == S_IFIFO ||
   4989 	    ftype == S_IFSOCK);
   4990 
   4991 	/*
   4992 	 * Skip any trailing slashes
   4993 	 */
   4994 	chop_endslashes(Gen.g_nam_p);
   4995 	return (1);
   4996 }
   4997 
   4998 /*
   4999  * getname: Get file names for inclusion in the archive.  When end of file
   5000  * on the input stream of file names is reached, flush the link buffer out.
   5001  * For each filename, remove leading "./"s and multiple "/"s, and remove
   5002  * any trailing newline "\n".  Finally, verify the existence of the file,
   5003  * and call creat_hdr() to fill in the gen_hdr structure.
   5004  */
   5005 
   5006 static int
   5007 getname(void)
   5008 {
   5009 	int goodfile = 0, lastchar, err;
   5010 	char *s;
   5011 	char *dir;
   5012 
   5013 	Gen.g_nam_p = Nam_p;
   5014 	Hiddendir = 0;
   5015 
   5016 	while (!goodfile) {
   5017 		err = 0;
   5018 
   5019 		while ((s = fgets(Gen.g_nam_p, APATH+1, In_p)) != NULL) {
   5020 			lastchar = strlen(s) - 1;
   5021 			issymlink = 0;
   5022 
   5023 			if (s[lastchar] != '\n') {
   5024 				if (lastchar == APATH - 1) {
   5025 					if (!err) {
   5026 						msg(ERR,
   5027 						    "%s name too long.",
   5028 						    Nam_p);
   5029 					}
   5030 					goodfile = 0;
   5031 					err = 1;
   5032 				} else {
   5033 					break;
   5034 				}
   5035 			} else {
   5036 				s[lastchar] = '\0';
   5037 				break;
   5038 			}
   5039 		}
   5040 
   5041 		if (s == NULL) {
   5042 			if (Gen.g_dirfd != -1) {
   5043 				(void) close(Gen.g_dirfd);
   5044 				Gen.g_dirfd = -1;
   5045 			}
   5046 			if (Onecopy && (Args & OCo)) {
   5047 				flush_lnks();
   5048 			}
   5049 			return (0);
   5050 		}
   5051 
   5052 		while (*Gen.g_nam_p == '.' && Gen.g_nam_p[1] == '/') {
   5053 			Gen.g_nam_p += 2;
   5054 			while (*Gen.g_nam_p == '/')
   5055 				Gen.g_nam_p++;
   5056 		}
   5057 
   5058 		/*
   5059 		 * Skip any trailing slashes
   5060 		 */
   5061 		chop_endslashes(Gen.g_nam_p);
   5062 
   5063 		/*
   5064 		 * Figure out parent directory
   5065 		 */
   5066 
   5067 		if (Gen.g_attrnam_p != NULL) {
   5068 			if (Gen.g_dirfd != -1) {
   5069 				(void) close(Gen.g_dirfd);
   5070 			}
   5071 			Gen.g_dirfd = attropen(Gen.g_attrfnam_p, ".", O_RDONLY);
   5072 			if (Gen.g_dirfd == -1) {
   5073 				msg(ERRN,
   5074 				    "Cannot open attribute directory"
   5075 				    " of file %s", Gen.g_attrfnam_p);
   5076 				continue;
   5077 			}
   5078 		} else {
   5079 #ifdef O_XATTR
   5080 			char dirpath[PATH_MAX];
   5081 
   5082 			get_parent(Gen.g_nam_p, dirpath);
   5083 			if (Atflag || SysAtflag) {
   5084 				dir = dirpath;
   5085 				if (Gen.g_dirfd != -1) {
   5086 					(void) close(Gen.g_dirfd);
   5087 				}
   5088 				Gen.g_dirfd = open(dir, O_RDONLY);
   5089 				if (Gen.g_dirfd == -1) {
   5090 					msg(ERRN,
   5091 					    "Cannot open directory %s", dir);
   5092 					continue;
   5093 				}
   5094 			} else {
   5095 				/*
   5096 				 * g_dirpath is the pathname cache maintaining
   5097 				 * the dirname which is currently opened.
   5098 				 * We first check the g_dirpath to see if the
   5099 				 * given dirname matches. If so, we don't need
   5100 				 * to open the dir, but we can use the g_dirfd
   5101 				 * as is if it is still available.
   5102 				 */
   5103 				dir = NULL;
   5104 				if (Gen.g_dirpath == NULL ||
   5105 				    Gen.g_dirfd == -1) {
   5106 					/*
   5107 					 * It's the first time or it has
   5108 					 * all gone.
   5109 					 */
   5110 					dir = e_strdup(E_EXIT, dirpath);
   5111 				} else {
   5112 					if (strcmp(Gen.g_dirpath,
   5113 					    dirpath) != 0) {
   5114 						/* different directory */
   5115 						dir = e_strdup(E_EXIT, dirpath);
   5116 					}
   5117 				}
   5118 				if (dir != NULL) {
   5119 					/*
   5120 					 * We need to open the new directory.
   5121 					 * discard the pathname and dirfd
   5122 					 * for the previous directory.
   5123 					 */
   5124 					if (Gen.g_dirpath != NULL) {
   5125 						free(Gen.g_dirpath);
   5126 						Gen.g_dirpath = NULL;
   5127 					}
   5128 					if (Gen.g_dirfd != -1) {
   5129 						(void) close(Gen.g_dirfd);
   5130 					}
   5131 					/* open the new dir */
   5132 					Gen.g_dirfd = open(dir, O_RDONLY);
   5133 					if (Gen.g_dirfd == -1) {
   5134 						msg(ERRN, "Cannot open "
   5135 						    "directory %s", dir);
   5136 						continue;
   5137 					}
   5138 					Gen.g_dirpath = dir;
   5139 				}
   5140 			}
   5141 #else
   5142 			Gen.g_dirfd = -1;
   5143 #endif
   5144 		}
   5145 
   5146 		/* creat_hdr checks for USTAR filename length */
   5147 
   5148 		if (Hdr_type != USTAR && strlen(Gen.g_nam_p) >
   5149 		    Max_namesz) {
   5150 			if (!err) {
   5151 				msg(ERR, "%s%s%s name too long.",
   5152 				    (Gen.g_attrnam_p == NULL) ?
   5153 				    Nam_p : Gen.g_attrfnam_p,
   5154 				    (Gen.g_attrnam_p == NULL) ?
   5155 				    "" : Gen.g_rw_sysattr ?
   5156 				    gettext(" System Attribute ") :
   5157 				    gettext(" Attribute "),
   5158 				    (Gen.g_attrnam_p == NULL) ?
   5159 				    "" : Gen.g_attrnam_p);
   5160 			}
   5161 			goodfile = 0;
   5162 			err = 1;
   5163 		}
   5164 
   5165 		if (err) {
   5166 			continue;
   5167 		} else {
   5168 			G_p = &Gen;
   5169 			if (!LSTAT(Gen.g_dirfd, Gen.g_nam_p, &SrcSt)) {
   5170 				goodfile = 1;
   5171 
   5172 				if ((SrcSt.st_mode & Ftype) == S_IFLNK) {
   5173 					issymlink = 1;
   5174 
   5175 					if ((Args & OCL)) {
   5176 						errno = 0;
   5177 						if (STAT(Gen.g_dirfd,
   5178 						    G_p->g_nam_p,
   5179 						    &SrcSt) < 0) {
   5180 							msg(ERRN,
   5181 							    "Cannot follow"
   5182 							    " \"%s%s%s\"",
   5183 							    (Gen.g_attrnam_p ==
   5184 							    NULL) ?
   5185 							    Gen.g_nam_p :
   5186 							    Gen.g_attrfnam_p,
   5187 							    (Gen.g_attrnam_p ==
   5188 							    NULL) ? "" :
   5189 							    Gen.g_rw_sysattr ?
   5190 							    gettext(
   5191 							    " System "
   5192 							    "Attribute ") :
   5193 							    gettext(
   5194 							    " Attribute "),
   5195 							    (Gen.g_attrnam_p ==
   5196 							    NULL) ? "" :
   5197 							    Gen.g_attrnam_p);
   5198 							goodfile = 0;
   5199 						}
   5200 					}
   5201 				}
   5202 
   5203 				if (Use_old_stat) {
   5204 					OldSt = convert_to_old_stat(&SrcSt,
   5205 					    Gen.g_nam_p, Gen.g_attrnam_p);
   5206 
   5207 					if (OldSt == NULL) {
   5208 						goodfile = 0;
   5209 					}
   5210 				}
   5211 			} else {
   5212 				msg(ERRN,
   5213 				    "Error with fstatat() of \"%s%s%s\"",
   5214 				    (Gen.g_attrnam_p == NULL) ?
   5215 				    Gen.g_nam_p : Gen.g_attrfnam_p,
   5216 				    (Gen.g_attrnam_p == NULL) ? "" :
   5217 				    Gen.g_rw_sysattr ?
   5218 				    gettext(" System Attribute ") :
   5219 				    gettext(" Attribute "),
   5220 				    (Gen.g_attrnam_p == NULL) ?
   5221 				    "" : Gen.g_attrnam_p);
   5222 			}
   5223 		}
   5224 	}
   5225 
   5226 	/*
   5227 	 * Get ACL info: dont bother allocating space if there are only
   5228 	 * standard permissions, i.e. ACL count < 4
   5229 	 */
   5230 	if ((SrcSt.st_mode & Ftype) != S_IFLNK && Pflag) {
   5231 		if (acl_get(Gen.g_nam_p, ACL_NO_TRIVIAL, &aclp) != 0)
   5232 			msg(ERRN, "Error with acl() of \"%s\"", Gen.g_nam_p);
   5233 	}
   5234 	/* else: only traditional permissions, so proceed as usual */
   5235 	if (creat_hdr())
   5236 		return (1);
   5237 	else return (2);
   5238 }
   5239 
   5240 /*
   5241  * getpats: Save any filenames/patterns specified as arguments.
   5242  * Read additional filenames/patterns from the file specified by the
   5243  * user.  The filenames/patterns must occur one per line.
   5244  */
   5245 
   5246 static void
   5247 getpats(int largc, char **largv)
   5248 {
   5249 	char **t_pp;
   5250 	size_t len;
   5251 	unsigned numpat = largc, maxpat = largc + 2;
   5252 
   5253 	Pat_pp = e_zalloc(E_EXIT, maxpat * sizeof (char *));
   5254 	t_pp = Pat_pp;
   5255 	while (*largv) {
   5256 		*t_pp = e_zalloc(E_EXIT, strlen(*largv) + 1);
   5257 		(void) strcpy(*t_pp, *largv);
   5258 		t_pp++;
   5259 		largv++;
   5260 	}
   5261 	while (fgets(Nam_p, Max_namesz + 1, Ef_p) != NULL) {
   5262 		if (numpat == maxpat - 1) {
   5263 			maxpat += 10;
   5264 			Pat_pp = e_realloc(E_EXIT, Pat_pp,
   5265 			    maxpat * sizeof (char *));
   5266 			t_pp = Pat_pp + numpat;
   5267 		}
   5268 		len = strlen(Nam_p); /* includes the \n */
   5269 		*(Nam_p + len - 1) = '\0'; /* remove the \n */
   5270 		*t_pp = e_zalloc(E_EXIT, len);
   5271 		(void) strcpy(*t_pp, Nam_p);
   5272 		t_pp++;
   5273 		numpat++;
   5274 	}
   5275 	*t_pp = NULL;
   5276 }
   5277 
   5278 static void
   5279 ioerror(int dir)
   5280 {
   5281 	int t_errno;
   5282 
   5283 	t_errno = errno;
   5284 	errno = 0;
   5285 	if (fstat(Archive, &ArchSt) < 0)
   5286 		msg(EXTN, "Error during stat() of archive");
   5287 	errno = t_errno;
   5288 	if ((ArchSt.st_mode & Ftype) != S_IFCHR) {
   5289 		if (dir) {
   5290 			if (errno == EFBIG)
   5291 				msg(EXT, "ulimit reached for output file.");
   5292 			else if (errno == ENOSPC)
   5293 				msg(EXT, "No space left for output file.");
   5294 			else
   5295 				msg(EXTN, "I/O error - cannot continue");
   5296 		} else
   5297 			msg(EXT, "Unexpected end-of-file encountered.");
   5298 	} else
   5299 		msg(EXTN, "\007I/O error on \"%s\"", dir ? "output" : "input");
   5300 }
   5301 
   5302 /*
   5303  * matched: Determine if a filename matches the specified pattern(s).  If the
   5304  * pattern is matched (the second return), return 0 if -f was specified, else
   5305  * return != 0.  If the pattern is not matched (the first and third
   5306  * returns), return 0 if -f was not specified, else return != 0.
   5307  */
   5308 
   5309 static int
   5310 matched(void)
   5311 {
   5312 	char *str_p = G_p->g_nam_p;
   5313 	char **pat_pp = Pat_pp;
   5314 	int negatep, result;
   5315 
   5316 	/*
   5317 	 * Check for attribute
   5318 	 */
   5319 	if (G_p->g_attrfnam_p != NULL)
   5320 		str_p = G_p->g_attrfnam_p;
   5321 
   5322 	for (pat_pp = Pat_pp; *pat_pp; pat_pp++) {
   5323 		negatep = (**pat_pp == '!');
   5324 
   5325 		result = fnmatch(negatep ? (*pat_pp+1) : *pat_pp, str_p, 0);
   5326 
   5327 		if (result != 0 && result != FNM_NOMATCH) {
   5328 			msg(POST, "error matching file %s with pattern"
   5329 			    " %s\n", str_p, *pat_pp);
   5330 			return (Args & OCf);
   5331 		}
   5332 
   5333 		if ((result == 0 && ! negatep) ||
   5334 		    (result == FNM_NOMATCH && negatep)) {
   5335 			/* match occurred */
   5336 			return (!(Args & OCf));
   5337 		}
   5338 	}
   5339 	return (Args & OCf); /* not matched */
   5340 }
   5341 
   5342 /*
   5343  * missdir: Create missing directories for files.
   5344  * (Possible future performance enhancement, if missdir is called, we know
   5345  * that at least the very last directory of the path does not exist, therefore,
   5346  * scan the path from the end
   5347  */
   5348 
   5349 static int
   5350 missdir(char *nam_p)
   5351 {
   5352 	char *c_p;
   5353 	int cnt = 2;
   5354 	char *lastp;
   5355 
   5356 	if (*(c_p = nam_p) == '/') /* skip over 'root slash' */
   5357 		c_p++;
   5358 
   5359 	lastp = c_p + strlen(nam_p) - 1;
   5360 	if (*lastp == '/')
   5361 		*lastp = '\0';
   5362 
   5363 	for (; *c_p; ++c_p) {
   5364 		if (*c_p == '/') {
   5365 			*c_p = '\0';
   5366 			if (stat(nam_p, &DesSt) < 0) {
   5367 				if (Args & OCd) {
   5368 					cnt = mkdir(nam_p, Def_mode);
   5369 					if (cnt != 0) {
   5370 						*c_p = '/';
   5371 						return (cnt);
   5372 					}
   5373 				} else {
   5374 					msg(ERR, "Missing -d option.");
   5375 					*c_p = '/';
   5376 					return (-1);
   5377 				}
   5378 			}
   5379 			*c_p = '/';
   5380 		}
   5381 	}
   5382 	if (cnt == 2) /* the file already exists */
   5383 		cnt = 0;
   5384 	return (cnt);
   5385 }
   5386 
   5387 /*
   5388  * mklong: Convert two shorts into one long.  For VAX, Interdata ...
   5389  */
   5390 
   5391 static long
   5392 mklong(short v[])
   5393 {
   5394 
   5395 	union swpbuf swp_b;
   5396 
   5397 	swp_b.s_word = 1;
   5398 	if (swp_b.s_byte[0]) {
   5399 		swp_b.s_half[0] = v[1];
   5400 		swp_b.s_half[1] = v[0];
   5401 	} else {
   5402 		swp_b.s_half[0] = v[0];
   5403 		swp_b.s_half[1] = v[1];
   5404 	}
   5405 	return (swp_b.s_word);
   5406 }
   5407 
   5408 /*
   5409  * mkshort: Convert a long into 2 shorts, for VAX, Interdata ...
   5410  */
   5411 
   5412 static void
   5413 mkshort(short sval[], long v)
   5414 {
   5415 	union swpbuf *swp_p, swp_b;
   5416 
   5417 	/* LINTED alignment */
   5418 	swp_p = (union swpbuf *)sval;
   5419 	swp_b.s_word = 1;
   5420 	if (swp_b.s_byte[0]) {
   5421 		swp_b.s_word = v;
   5422 		swp_p->s_half[0] = swp_b.s_half[1];
   5423 		swp_p->s_half[1] = swp_b.s_half[0];
   5424 	} else {
   5425 		swp_b.s_word = v;
   5426 		swp_p->s_half[0] = swp_b.s_half[0];
   5427 		swp_p->s_half[1] = swp_b.s_half[1];
   5428 	}
   5429 }
   5430 
   5431 /*
   5432  * msg: Print either a message (no error) (POST), an error message with or
   5433  * without the errno (ERRN or ERR), or print an error message with or without
   5434  * the errno and exit (EXTN or EXT).
   5435  */
   5436 void
   5437 msg(int severity, const char *fmt, ...)
   5438 {
   5439 	FILE *file_p;
   5440 	va_list ap;
   5441 
   5442 	if ((Args & OCV) && Verbcnt) { /* clear current line of dots */
   5443 		(void) fputc('\n', Out_p);
   5444 		Verbcnt = 0;
   5445 	}
   5446 	va_start(ap, fmt);
   5447 	if (severity == POST)
   5448 		file_p = Out_p;
   5449 	else
   5450 		if (severity == EPOST)
   5451 			file_p = Err_p;
   5452 		else {
   5453 			file_p = Err_p;
   5454 			Error_cnt++;
   5455 		}
   5456 	(void) fflush(Out_p);
   5457 	(void) fflush(Err_p);
   5458 	if ((severity != POST) && (severity != EPOST))
   5459 		(void) fprintf(file_p, "cpio: ");
   5460 
   5461 	/* gettext replaces version of string */
   5462 
   5463 	(void) vfprintf(file_p, gettext(fmt), ap);
   5464 	if (severity == ERRN || severity == EXTN) {
   5465 		if (G_p && (G_p->g_attrnam_p != NULL) && G_p->g_rw_sysattr) {
   5466 			if (errno == EPERM) {
   5467 				(void) fprintf(file_p, ", errno %d, %s", errno,
   5468 				    gettext("insufficient privileges\n"));
   5469 			} else if (errno == EINVAL) {
   5470 				(void) fprintf(file_p, ", errno %d, %s",
   5471 				    errno, gettext(
   5472 				    "unsupported on underlying file system\n"));
   5473 			} else {
   5474 				(void) fprintf(file_p, ", errno %d, ", errno);
   5475 				perror("");
   5476 			}
   5477 		} else {
   5478 			(void) fprintf(file_p, ", errno %d, ", errno);
   5479 			perror("");
   5480 		}
   5481 	} else
   5482 		(void) fprintf(file_p, "\n");
   5483 	(void) fflush(file_p);
   5484 	va_end(ap);
   5485 	if (severity == EXT || severity == EXTN) {
   5486 		(void) fprintf(file_p, gettext("%d errors\n"), Error_cnt);
   5487 		exit(EXIT_CODE);
   5488 	}
   5489 }
   5490 
   5491 /*
   5492  * openout: Open files for output and set all necessary information.
   5493  * If the u option is set (unconditionally overwrite existing files),
   5494  * and the current file exists, get a temporary file name from mktemp(3C),
   5495  * link the temporary file to the existing file, and remove the existing file.
   5496  * Finally either creat(2), mkdir(2) or mknod(2) as appropriate.
   5497  *
   5498  */
   5499 
   5500 static int
   5501 openout(int dirfd)
   5502 {
   5503 	char *nam_p;
   5504 	int cnt, result;
   5505 
   5506 	Do_rename = 0;	/* creat_tmp() may reset this */
   5507 
   5508 	if (G_p->g_attrnam_p != NULL) {
   5509 		nam_p = G_p->g_attrnam_p;
   5510 	} else {
   5511 		if (Args & OCp) {
   5512 			nam_p = Fullnam_p;
   5513 		} else {
   5514 			nam_p = G_p->g_nam_p;
   5515 		}
   5516 	}
   5517 
   5518 
   5519 	if ((Max_filesz != RLIM_INFINITY) &&
   5520 	    (Max_filesz < (G_p->g_filesz >> 9))) {
   5521 		/* ... divided by 512 ... */
   5522 		msg(ERR, "Skipping \"%s%s%s\": exceeds ulimit by %lld bytes",
   5523 		    (G_p->g_attrnam_p == NULL) ? nam_p : G_p->g_attrfnam_p,
   5524 		    (G_p->g_attrnam_p == NULL) ? "" : G_p->g_rw_sysattr ?
   5525 		    gettext(" System Attribute ") : gettext(" Attribute "),
   5526 		    (G_p->g_attrnam_p == NULL) ? "" : nam_p,
   5527 		    (off_t)(G_p->g_filesz - (Max_filesz << 9)));
   5528 		return (-1);
   5529 	}
   5530 
   5531 	if (LSTAT(dirfd, nam_p, &DesSt) == 0) {
   5532 		/*
   5533 		 * A file by the same name exists.  Move it to a temporary
   5534 		 * file unless it's a system attribute file.  If we are
   5535 		 * restoring a system attribute file on a file system that
   5536 		 * supports system attributes, then the system attribute file
   5537 		 * will already exist (a default system attribute file will
   5538 		 * get created when the file it is associated with is created).
   5539 		 * If we create a temporary system attribute file, we can't
   5540 		 * overwrite the existing system attribute file using
   5541 		 * renameat().  In addition, only system attributes can exist
   5542 		 * for an attribute of a file, therefore, a temporary file
   5543 		 * cannot be created for a system attribute of an attribute.
   5544 		 * Thus, when restoring a system attribute, we won't move it
   5545 		 * to a temporary file, but will attempt to process it as if
   5546 		 * it didn't already exist.
   5547 		 */
   5548 
   5549 #if defined(_PC_SATTR_ENABLED)
   5550 		if (G_p->g_rw_sysattr == 0)
   5551 #endif	/* _PC_SATTR_ENABLED */
   5552 			if (creat_tmp(nam_p) < 0) {
   5553 				/*
   5554 				 * We weren't able to create the temp file.
   5555 				 * Report failure.
   5556 				 */
   5557 
   5558 				return (-1);
   5559 			}
   5560 	}
   5561 
   5562 	if (Do_rename) {
   5563 		/* nam_p was changed by creat_tmp() above. */
   5564 
   5565 		if (Args & OCp) {
   5566 			if (G_p->g_attrnam_p != NULL) {
   5567 				nam_p = Attrfile_p;
   5568 			} else {
   5569 				nam_p = Fullnam_p;
   5570 			}
   5571 		} else {
   5572 			nam_p = G_p->g_nam_p;
   5573 		}
   5574 	}
   5575 
   5576 	/*
   5577 	 * This pile tries to create the file directly, and, if there is a
   5578 	 * problem, creates missing directories, and then tries to create the
   5579 	 * file again.  Two strikes and you're out.
   5580 	 *
   5581 	 * On XATTR system, the directory has already been created by
   5582 	 * open_dirfd(), so error shouldn't happen in the loop. However,
   5583 	 * on non-XATTR system, symlink/open may fail with ENOENT. In such
   5584 	 * case, we go to create missing directories.
   5585 	 */
   5586 
   5587 	cnt = 0;
   5588 
   5589 	do {
   5590 		errno = 0;
   5591 
   5592 		if (Hdr_type == TAR && Thdr_p->tbuf.t_typeflag == SYMTYPE) {
   5593 			/* The archive file is a TAR symlink. */
   5594 			if ((result =
   5595 			    symlink(Thdr_p->tbuf.t_linkname, nam_p)) >= 0) {
   5596 				cnt = 0;
   5597 				if (Over_p != NULL) {
   5598 					(void) unlinkat(dirfd,
   5599 					    get_component(Over_p), 0);
   5600 					*Over_p = '\0';
   5601 				}
   5602 				break;
   5603 			} else if (errno != ENOENT) {
   5604 				/* The attempt to symlink failed. */
   5605 				msg(ERRN,
   5606 				    "Cannot create symbolic link \"%s\" -> "
   5607 				    "\"%s\"",
   5608 				    Thdr_p->tbuf.t_linkname, nam_p);
   5609 
   5610 				if (*Over_p != '\0') {
   5611 					rstfiles(U_KEEP, dirfd);
   5612 				}
   5613 				return (-1);
   5614 			}
   5615 		} else if (Hdr_type == BAR && bar_linkflag == SYMTYPE) {
   5616 			if ((result = symlink(bar_linkname, nam_p)) >= 0) {
   5617 				cnt = 0;
   5618 				if (Over_p != NULL) {
   5619 					(void) unlinkat(dirfd,
   5620 					    get_component(Over_p), 0);
   5621 					*Over_p = '\0';
   5622 				}
   5623 				break;
   5624 			} else if (errno != ENOENT) {
   5625 				/* The attempt to symlink failed. */
   5626 				msg(ERRN,
   5627 				    "Cannot create symbolic link \"%s\" -> "
   5628 				    "\"%s\"",
   5629 				    bar_linkname, nam_p);
   5630 				if (*Over_p != '\0') {
   5631 					rstfiles(U_KEEP, dirfd);
   5632 				}
   5633 				return (-1);
   5634 			}
   5635 		} else if ((G_p->g_mode & Ftype) == S_IFLNK) {
   5636 			if ((!(Args & OCp)) && !(Hdr_type == USTAR)) {
   5637 				FILL(G_p->g_filesz);
   5638 				(void) strncpy(Symlnk_p,
   5639 				    Buffr.b_out_p, G_p->g_filesz);
   5640 				*(Symlnk_p + G_p->g_filesz) = '\0';
   5641 			} else if ((!(Args & OCp)) && (Hdr_type == USTAR)) {
   5642 				Symlnk_p[NAMSIZ] = '\0';
   5643 				(void) strncpy(Symlnk_p,
   5644 				    &Thdr_p->tbuf.t_linkname[0], NAMSIZ);
   5645 			}
   5646 			if ((result = symlink(Symlnk_p, nam_p)) >= 0) {
   5647 				cnt = 0;
   5648 				if (Over_p != NULL) {
   5649 					(void) unlinkat(dirfd,
   5650 					    get_component(Over_p), 0);
   5651 					*Over_p = '\0';
   5652 				}
   5653 				break;
   5654 			} else if (errno != ENOENT) {
   5655 				/* The attempt to symlink failed. */
   5656 				msg(ERRN,
   5657 				    "Cannot create symbolic link \"%s\" -> "
   5658 				    "\"%s\"",
   5659 				    Symlnk_p, nam_p);
   5660 
   5661 				if (*Over_p != '\0') {
   5662 					rstfiles(U_KEEP, dirfd);
   5663 				}
   5664 				return (-1);
   5665 			}
   5666 		} else {
   5667 			int	saveerrno;
   5668 
   5669 			if ((result = openat(dirfd, get_component(nam_p),
   5670 			    O_CREAT|O_RDWR|O_TRUNC, (int)G_p->g_mode)) < 0) {
   5671 				saveerrno = errno;
   5672 				if (G_p->g_attrnam_p != NULL)  {
   5673 					result = retry_open_attr(dirfd,
   5674 					    Gen.g_baseparent_fd, Fullnam_p,
   5675 					    (G_p->g_attrparent_p == NULL) ?
   5676 					    NULL : G_p->g_attrparent_p, nam_p,
   5677 					    O_CREAT|O_RDWR|O_TRUNC,
   5678 					    (int)G_p->g_mode);
   5679 				}
   5680 			}
   5681 			if (result < 0) {
   5682 				errno = saveerrno;
   5683 				if (errno != ENOENT) {
   5684 					/* The attempt to open failed. */
   5685 					msg(ERRN, "Cannot open file \"%s\"",
   5686 					    nam_p);
   5687 					if (*Over_p != '\0') {
   5688 						rstfiles(U_KEEP, dirfd);
   5689 					}
   5690 					return (-1);
   5691 				}
   5692 			} else {
   5693 				/* acl support */
   5694 				acl_is_set = 0;
   5695 				if (Pflag && aclp != NULL) {
   5696 					if (facl_set(result, aclp) < 0) {
   5697 						msg(ERRN,
   5698 						    "\"%s\": failed to set acl",
   5699 						    nam_p);
   5700 					} else {
   5701 						acl_is_set = 1;
   5702 					}
   5703 					acl_free(aclp);
   5704 					aclp = NULL;
   5705 				}
   5706 				cnt = 0;
   5707 				break;
   5708 			}
   5709 		}
   5710 		cnt++;
   5711 	} while (cnt < 2 && missdir(nam_p) == 0);
   5712 
   5713 	switch (cnt) {
   5714 	case 0:
   5715 		if ((Args & OCi) && (Hdr_type == USTAR)) {
   5716 			setpasswd(nam_p);
   5717 		}
   5718 		if ((G_p->g_mode & Ftype) == S_IFLNK ||
   5719 		    (Hdr_type == BAR && bar_linkflag == SYMTYPE)) {
   5720 			if (Args & OCR) {
   5721 				if (fchownat(dirfd,
   5722 				    get_component(nam_p),
   5723 				    (int)Rpw_p->pw_uid,
   5724 				    (int)Rpw_p->pw_gid,
   5725 				    AT_SYMLINK_NOFOLLOW) < 0) {
   5726 					msg(ERRN,
   5727 					    "Error during chown() of "
   5728 					    "\"%s%s%s\"",
   5729 					    (G_p->g_attrnam_p == NULL) ?
   5730 					    nam_p : G_p->g_attrfnam_p,
   5731 					    (G_p->g_attrnam_p == NULL) ?
   5732 					    "" : G_p->g_rw_sysattr ?
   5733 					    gettext(" System Attribute ") :
   5734 					    gettext(" Attribute "),
   5735 					    (G_p->g_attrnam_p == NULL) ?
   5736 					    "" : nam_p);
   5737 				}
   5738 			} else if ((fchownat(dirfd, get_component(nam_p),
   5739 			    (int)G_p->g_uid, (int)G_p->g_gid,
   5740 			    AT_SYMLINK_NOFOLLOW) < 0) && privileged) {
   5741 				msg(ERRN,
   5742 				    "Error during chown() of \"%s%s%s\"",
   5743 				    (G_p->g_attrnam_p == NULL) ?
   5744 				    nam_p : G_p->g_attrfnam_p,
   5745 				    (G_p->g_attrnam_p == NULL) ? "" :
   5746 				    G_p->g_rw_sysattr ?
   5747 				    gettext(" System Attribute ") :
   5748 				    gettext(" Attribute "),
   5749 				    (G_p->g_attrnam_p == NULL) ? "" : nam_p);
   5750 			}
   5751 		}
   5752 		break;
   5753 
   5754 	case 1:
   5755 		if (Do_rename) {
   5756 			msg(ERRN, "Cannot create directory for \"%s%s%s\"",
   5757 			    (G_p->g_attrnam_p == NULL) ? Over_p :
   5758 			    G_p->g_attrfnam_p,
   5759 			    (G_p->g_attrnam_p == NULL) ? "" :
   5760 			    G_p->g_rw_sysattr ?
   5761 			    gettext(" System Attribute ") :
   5762 			    gettext(" Attribute "),
   5763 			    (G_p->g_attrnam_p == NULL) ? "" : Over_p);
   5764 		} else {
   5765 			msg(ERRN, "Cannot create directory for \"%s%s%s\"",
   5766 			    (G_p->g_attrnam_p == NULL) ? nam_p :
   5767 			    G_p->g_attrfnam_p,
   5768 			    (G_p->g_attrnam_p == NULL) ? "" :
   5769 			    G_p->g_rw_sysattr ?
   5770 			    gettext(" System Attribute ") :
   5771 			    gettext(" Attribute "),
   5772 			    (G_p->g_attrnam_p == NULL) ? "" : nam_p);
   5773 		}
   5774 		break;
   5775 
   5776 	case 2:
   5777 		if (Do_rename) {
   5778 			msg(ERRN, "Cannot create \"%s%s%s\"",
   5779 			    (G_p->g_attrnam_p == NULL) ? Over_p :
   5780 			    G_p->g_attrfnam_p,
   5781 			    (G_p->g_attrnam_p == NULL) ? "" :
   5782 			    G_p->g_rw_sysattr ?
   5783 			    gettext(" System Attribute ") :
   5784 			    gettext(" Attribute "),
   5785 			    (G_p->g_attrnam_p == NULL) ? "" :
   5786 			    Over_p);
   5787 		} else {
   5788 			msg(ERRN, "Cannot create \"%s%s%s\"",
   5789 			    (G_p->g_attrnam_p == NULL) ? nam_p :
   5790 			    G_p->g_attrfnam_p,
   5791 			    (G_p->g_attrnam_p == NULL) ? "" :
   5792 			    G_p->g_rw_sysattr ?
   5793 			    gettext(" System Attribute ") :
   5794 			    gettext(" Attribute "),
   5795 			    (G_p->g_attrnam_p == NULL) ? "" : nam_p);
   5796 		}
   5797 		break;
   5798 
   5799 	default:
   5800 		msg(EXT, "Impossible case.");
   5801 	}
   5802 
   5803 	Finished = 0;
   5804 	return (result);
   5805 }
   5806 
   5807 /*
   5808  * read_hdr: Transfer headers from the selected format
   5809  * in the archive I/O buffer to the generic structure.
   5810  */
   5811 
   5812 static
   5813 int
   5814 read_hdr(int hdr)
   5815 {
   5816 	int rv = NONE;
   5817 	major_t maj, rmaj;
   5818 	minor_t min, rmin;
   5819 	char tmpnull;
   5820 	static int bar_read_cnt = 0;
   5821 
   5822 	if (hdr != BAR) {
   5823 		if (Buffr.b_end_p != (Buffr.b_out_p + Hdrsz)) {
   5824 			tmpnull = *(Buffr.b_out_p + Hdrsz);
   5825 			*(Buffr.b_out_p + Hdrsz) = '\0';
   5826 		}
   5827 	}
   5828 
   5829 	switch (hdr) {
   5830 	case BIN:
   5831 		(void) memcpy(&Hdr, Buffr.b_out_p, HDRSZ);
   5832 		if (Hdr.h_magic == (short)CMN_BBS) {
   5833 			swap((char *)&Hdr, HDRSZ);
   5834 		}
   5835 		Gen.g_magic = Hdr.h_magic;
   5836 		Gen.g_mode = Hdr.h_mode;
   5837 		Gen.g_uid = Hdr.h_uid;
   5838 		Gen.g_gid = Hdr.h_gid;
   5839 		Gen.g_nlink = Hdr.h_nlink;
   5840 		Gen.g_mtime = mklong(Hdr.h_mtime);
   5841 		Gen.g_ino = Hdr.h_ino;
   5842 		Gen.g_dev = Hdr.h_dev;
   5843 		Gen.g_rdev = Hdr.h_rdev;
   5844 		Gen.g_cksum = 0L;
   5845 		Gen.g_filesz = (off_t)mklong(Hdr.h_filesize);
   5846 		Gen.g_namesz = Hdr.h_namesize;
   5847 		rv = BIN;
   5848 		break;
   5849 	case CHR:
   5850 		if (sscanf(Buffr.b_out_p,
   5851 		    "%6lo%6lo%6lo%6lo%6lo%6lo%6lo%6lo%11lo%6o%11llo",
   5852 		    &Gen.g_magic, &Gen.g_dev, &Gen.g_ino, &Gen.g_mode,
   5853 		    &Gen.g_uid, &Gen.g_gid, &Gen.g_nlink, &Gen.g_rdev,
   5854 		    (ulong_t *)&Gen.g_mtime, (uint_t *)&Gen.g_namesz,
   5855 		    (u_off_t *)&Gen.g_filesz) == CHR_CNT) {
   5856 			rv = CHR;
   5857 #define	cpioMAJOR(x)	(int)(((unsigned)x >> 8) & 0x7F)
   5858 #define	cpioMINOR(x)	(int)(x & 0xFF)
   5859 			maj = cpioMAJOR(Gen.g_dev);
   5860 			rmaj = cpioMAJOR(Gen.g_rdev);
   5861 			min = cpioMINOR(Gen.g_dev);
   5862 			rmin = cpioMINOR(Gen.g_rdev);
   5863 			if (Use_old_stat) {
   5864 				/* needs error checking */
   5865 				Gen.g_dev = (maj << 8) | min;
   5866 				Gen.g_rdev = (rmaj << 8) | rmin;
   5867 			} else {
   5868 				Gen.g_dev = makedev(maj, min);
   5869 				Gen.g_rdev = makedev(rmaj, rmin);
   5870 			}
   5871 		}
   5872 		break;
   5873 	case ASC:
   5874 	case CRC:
   5875 		if (sscanf(Buffr.b_out_p,
   5876 		    "%6lx%8lx%8lx%8lx%8lx%8lx%8lx%8llx%8x%8x%8x%8x%8x%8lx",
   5877 		    &Gen.g_magic, &Gen.g_ino, &Gen.g_mode, &Gen.g_uid,
   5878 		    &Gen.g_gid, &Gen.g_nlink, &Gen.g_mtime,
   5879 		    (u_off_t *)&Gen.g_filesz, (uint_t *)&maj, (uint_t *)&min,
   5880 		    (uint_t *)&rmaj, (uint_t *)&rmin, (uint_t *)&Gen.g_namesz,
   5881 		    &Gen.g_cksum) == ASC_CNT) {
   5882 			Gen.g_dev = makedev(maj, min);
   5883 			Gen.g_rdev = makedev(rmaj, rmin);
   5884 			rv = hdr;
   5885 		}
   5886 		break;
   5887 	case USTAR: /* TAR and USTAR */
   5888 		if (*Buffr.b_out_p == '\0') {
   5889 			*Gen.g_nam_p = '\0';
   5890 			nambuf[0] = '\0';
   5891 		} else {
   5892 			Thdr_p = (union tblock *)Buffr.b_out_p;
   5893 			Gen.g_nam_p[0] = '\0';
   5894 			(void) strncpy((char *)&nambuf,
   5895 			    Thdr_p->tbuf.t_name, NAMSIZ);
   5896 			(void) sscanf(Thdr_p->tbuf.t_mode, "%8lo",
   5897 			    &Gen.g_mode);
   5898 			(void) sscanf(Thdr_p->tbuf.t_uid, "%8lo", &Gen.g_uid);
   5899 			(void) sscanf(Thdr_p->tbuf.t_gid, "%8lo", &Gen.g_gid);
   5900 			(void) sscanf(Thdr_p->tbuf.t_size, "%11llo",
   5901 			    (u_off_t *)&Gen.g_filesz);
   5902 			(void) sscanf(Thdr_p->tbuf.t_mtime, "%12lo",
   5903 			    (ulong_t *)&Gen.g_mtime);
   5904 			(void) sscanf(Thdr_p->tbuf.t_cksum, "%8lo",
   5905 			    (ulong_t *)&Gen.g_cksum);
   5906 			if (Thdr_p->tbuf.t_linkname[0] != '\0')
   5907 				Gen.g_nlink = 1;
   5908 			else
   5909 				Gen.g_nlink = 0;
   5910 
   5911 			switch (Thdr_p->tbuf.t_typeflag) {
   5912 			case SYMTYPE:
   5913 				/* Symbolic Link */
   5914 				Gen.g_nlink = 2;
   5915 				break;
   5916 			case CHRTYPE:
   5917 				Gen.g_mode |= (S_IFMT & S_IFCHR);
   5918 				break;
   5919 			case BLKTYPE:
   5920 				Gen.g_mode |= (S_IFMT & S_IFBLK);
   5921 				break;
   5922 			case DIRTYPE:
   5923 				Gen.g_mode |= (S_IFMT & S_IFDIR);
   5924 				break;
   5925 			case FIFOTYPE:
   5926 				Gen.g_mode |= (S_IFMT & S_IFIFO);
   5927 				break;
   5928 			}
   5929 
   5930 			(void) sscanf(Thdr_p->tbuf.t_magic, "%8lo",
   5931 			    /* LINTED alignment */
   5932 			    (ulong_t *)&Gen.g_tmagic);
   5933 			(void) sscanf(Thdr_p->tbuf.t_version, "%8lo",
   5934 			    /* LINTED alignment */
   5935 			    (ulong_t *)&Gen.g_version);
   5936 			(void) sscanf(Thdr_p->tbuf.t_uname, "%32s",
   5937 			    (char *)&Gen.g_uname);
   5938 			(void) sscanf(Thdr_p->tbuf.t_gname, "%32s",
   5939 			    (char *)&Gen.g_gname);
   5940 			(void) sscanf(Thdr_p->tbuf.t_devmajor, "%8lo",
   5941 			    &Gen.g_dev);
   5942 			(void) sscanf(Thdr_p->tbuf.t_devminor, "%8lo",
   5943 			    &Gen.g_rdev);
   5944 			(void) strncpy((char *)&prebuf,
   5945 			    Thdr_p->tbuf.t_prefix, PRESIZ);
   5946 			Gen.g_namesz = strlen(Gen.g_nam_p) + 1;
   5947 			Gen.g_dev = makedev(maj, min);
   5948 		}
   5949 		rv = USTAR;
   5950 		break;
   5951 	case TAR:
   5952 		if (*Buffr.b_out_p == '\0') {
   5953 			*Gen.g_nam_p = '\0';
   5954 			nambuf[0] = '\0';
   5955 		} else {
   5956 			Thdr_p = (union tblock *)Buffr.b_out_p;
   5957 			Gen.g_nam_p[0] = '\0';
   5958 			(void) sscanf(Thdr_p->tbuf.t_mode, "%lo", &Gen.g_mode);
   5959 			(void) sscanf(Thdr_p->tbuf.t_uid, "%lo", &Gen.g_uid);
   5960 			(void) sscanf(Thdr_p->tbuf.t_gid, "%lo", &Gen.g_gid);
   5961 			(void) sscanf(Thdr_p->tbuf.t_size, "%llo",
   5962 			    (u_off_t *)&Gen.g_filesz);
   5963 			(void) sscanf(Thdr_p->tbuf.t_mtime, "%lo",
   5964 			    &Gen.g_mtime);
   5965 			(void) sscanf(Thdr_p->tbuf.t_cksum, "%lo",
   5966 			    &Gen.g_cksum);
   5967 			if (Thdr_p->tbuf.t_typeflag == '1')	/* hardlink */
   5968 				Gen.g_nlink = 1;
   5969 			else
   5970 				Gen.g_nlink = 0;
   5971 			(void) strncpy(Gen.g_nam_p,
   5972 			    Thdr_p->tbuf.t_name, NAMSIZ);
   5973 			Gen.g_namesz = strlen(Gen.g_nam_p) + 1;
   5974 			(void) strcpy(nambuf, Gen.g_nam_p);
   5975 		}
   5976 		rv = TAR;
   5977 		break;
   5978 	case BAR:
   5979 		if (Bar_vol_num == 0 && bar_read_cnt == 0) {
   5980 			read_bar_vol_hdr();
   5981 			bar_read_cnt++;
   5982 		}
   5983 		else
   5984 			read_bar_file_hdr();
   5985 		rv = BAR;
   5986 		break;
   5987 	default:
   5988 		msg(EXT, "Impossible header type.");
   5989 	}
   5990 
   5991 	if (hdr != BAR) {
   5992 		if (Buffr.b_end_p != (Buffr.b_out_p + Hdrsz))
   5993 			*(Buffr.b_out_p + Hdrsz) = tmpnull;
   5994 	}
   5995 
   5996 	return (rv);
   5997 }
   5998 
   5999 /*
   6000  * reclaim: Reclaim linked file structure storage.
   6001  */
   6002 
   6003 static void
   6004 reclaim(struct Lnk *p)
   6005 {
   6006 	p->L_bck_p->L_nxt_p = p->L_nxt_p;
   6007 	p->L_nxt_p->L_bck_p = p->L_bck_p;
   6008 
   6009 	while (p != NULL) {
   6010 		struct Lnk *new_p = p->L_lnk_p;
   6011 
   6012 		free(p->L_gen.g_nam_p);
   6013 		free(p);
   6014 		p = new_p;
   6015 	}
   6016 }
   6017 
   6018 /*
   6019  * rstbuf: Reset the I/O buffer, move incomplete potential headers to
   6020  * the front of the buffer and force bread() to refill the buffer.  The
   6021  * return value from bread() is returned (to identify I/O errors).  On the
   6022  * 3B2, reads must begin on a word boundary, therefore, with the -i option,
   6023  * any remaining bytes in the buffer must be moved to the base of the buffer
   6024  * in such a way that the destination locations of subsequent reads are
   6025  * word aligned.
   6026  */
   6027 
   6028 static void
   6029 rstbuf(void)
   6030 {
   6031 	int pad;
   6032 
   6033 	if ((Args & OCi) || Append) {
   6034 		if (Buffr.b_out_p != Buffr.b_base_p) {
   6035 			pad = ((Buffr.b_cnt + FULLWD) & ~FULLWD);
   6036 			Buffr.b_in_p = Buffr.b_base_p + pad;
   6037 			pad -= Buffr.b_cnt;
   6038 			(void) memcpy(Buffr.b_base_p + pad, Buffr.b_out_p,
   6039 			    (int)Buffr.b_cnt);
   6040 			Buffr.b_out_p = Buffr.b_base_p + pad;
   6041 		}
   6042 		if (bfill() < 0)
   6043 			msg(EXT, "Unexpected end-of-archive encountered.");
   6044 	} else { /* OCo */
   6045 		(void) memcpy(Buffr.b_base_p, Buffr.b_out_p, (int)Buffr.b_cnt);
   6046 		Buffr.b_out_p = Buffr.b_base_p;
   6047 		Buffr.b_in_p = Buffr.b_base_p + Buffr.b_cnt;
   6048 	}
   6049 }
   6050 
   6051 static void
   6052 setpasswd(char *nam)
   6053 {
   6054 	if ((dpasswd = getpwnam(&Gen.g_uname[0])) == NULL) {
   6055 		msg(EPOST, "cpio: problem reading passwd entry");
   6056 		msg(EPOST, "cpio: %s: owner not changed", nam);
   6057 		if (Gen.g_uid == UID_NOBODY && S_ISREG(Gen.g_mode))
   6058 			Gen.g_mode &= ~S_ISUID;
   6059 	} else
   6060 		Gen.g_uid = dpasswd->pw_uid;
   6061 
   6062 	if ((dgroup = getgrnam(&Gen.g_gname[0])) == NULL) {
   6063 		msg(EPOST, "cpio: problem reading group entry");
   6064 		msg(EPOST, "cpio: %s: group not changed", nam);
   6065 		if (Gen.g_gid == GID_NOBODY && S_ISREG(Gen.g_mode))
   6066 			Gen.g_mode &= ~S_ISGID;
   6067 	} else
   6068 		Gen.g_gid = dgroup->gr_gid;
   6069 	G_p = &Gen;
   6070 }
   6071 
   6072 /*
   6073  * rstfiles:  Perform final changes to the file.  If the -u option is set,
   6074  * and overwrite == U_OVER, remove the temporary file, else if overwrite
   6075  * == U_KEEP, unlink the current file, and restore the existing version
   6076  * of the file.  In addition, where appropriate, set the access or modification
   6077  * times, change the owner and change the modes of the file.
   6078  *
   6079  * Note that if Do_rename is set, then the roles of original and temporary
   6080  * file are reversed. If all went well, we will rename() the temporary file
   6081  * over the original in order to accommodate potentially executing files.
   6082  */
   6083 static void
   6084 rstfiles(int over, int dirfd)
   6085 {
   6086 	char *inam_p, *onam_p, *nam_p;
   6087 	int error;
   6088 
   6089 #if defined(_PC_SATTR_ENABLED)
   6090 	/* Time or permissions cannot be set on system attribute files */
   6091 	if ((Gen.g_attrnam_p != NULL) && (Gen.g_rw_sysattr == 1)) {
   6092 		return;
   6093 	}
   6094 #endif	/* _PC_SATTR_ENABLED */
   6095 
   6096 	if (Args & OCp) {
   6097 		if (G_p->g_attrnam_p == NULL) {
   6098 			nam_p = Fullnam_p;
   6099 		} else {
   6100 			nam_p = G_p->g_attrnam_p;
   6101 		}
   6102 	} else {
   6103 		if (Gen.g_nlink > (ulong_t)0) {
   6104 			nam_p = G_p->g_nam_p;
   6105 		} else {
   6106 			nam_p = Gen.g_nam_p;
   6107 		}
   6108 	}
   6109 	if (Gen.g_attrnam_p != NULL) {
   6110 		nam_p = Gen.g_attrnam_p;
   6111 	}
   6112 
   6113 	if ((Args & OCi) && (Hdr_type == USTAR)) {
   6114 		setpasswd(nam_p);
   6115 	}
   6116 	if (over == U_KEEP && *Over_p != '\0') {
   6117 		if (Do_rename) {
   6118 			msg(POST, "Restoring existing \"%s%s%s\"",
   6119 			    (G_p->g_attrnam_p == NULL) ? Over_p : Fullnam_p,
   6120 			    (G_p->g_attrnam_p == NULL) ? "" :
   6121 			    G_p->g_rw_sysattr ? gettext(" System Attribute ") :
   6122 			    gettext(" Attribute "),
   6123 			    (G_p->g_attrnam_p == NULL) ? "" : Over_p);
   6124 		} else {
   6125 			msg(POST, "Restoring existing \"%s%s%s\"",
   6126 			    (G_p->g_attrnam_p == NULL) ? nam_p : Fullnam_p,
   6127 			    (G_p->g_attrnam_p == NULL) ? "" :
   6128 			    G_p->g_rw_sysattr ? gettext(" System Attribute ") :
   6129 			    gettext(" Attribute "),
   6130 			    (G_p->g_attrnam_p == NULL) ? "" : nam_p);
   6131 		}
   6132 
   6133 		/* delete what we just built */
   6134 		(void) unlinkat(dirfd, get_component(nam_p), 0);
   6135 
   6136 		/* If the old file needs restoring, do the necessary links */
   6137 		if (Do_rename) {
   6138 			char *tmp_ptr;
   6139 
   6140 			if (Args & OCp) {
   6141 				tmp_ptr = Fullnam_p;
   6142 				Fullnam_p = Over_p;
   6143 			} else {
   6144 				tmp_ptr = G_p->g_nam_p;
   6145 				G_p->g_nam_p = Over_p;
   6146 			}
   6147 			Over_p = tmp_ptr;
   6148 
   6149 			Do_rename = 0;	/* names now have original values */
   6150 		} else {
   6151 			if (rename(Over_p, nam_p) < 0) {
   6152 				if (link(Over_p, nam_p) < 0) {
   6153 					msg(EXTN,
   6154 					    "Cannot recover original version"
   6155 					    " of \"%s%s%s\"",
   6156 					    (G_p->g_attrnam_p == NULL) ?
   6157 					    nam_p : Fullnam_p,
   6158 					    (G_p->g_attrnam_p == NULL) ? "" :
   6159 					    G_p->g_rw_sysattr ?
   6160 					    gettext(" System Attribute ") :
   6161 					    gettext(" Attribute "),
   6162 					    (G_p->g_attrnam_p == NULL) ?
   6163 					    "" : nam_p);
   6164 				}
   6165 				if (unlinkat(dirfd, get_component(Over_p), 0)) {
   6166 					msg(ERRN,
   6167 					    "Cannot remove temp file "
   6168 					    "\"%s%s%s\"",
   6169 					    (G_p->g_attrnam_p == NULL) ?
   6170 					    Over_p : Fullnam_p,
   6171 					    (G_p->g_attrnam_p == NULL) ? "" :
   6172 					    G_p->g_rw_sysattr ?
   6173 					    gettext(" System Attribute ") :
   6174 					    gettext(" Attribute "),
   6175 					    (G_p->g_attrnam_p == NULL) ?
   6176 					    "" : Over_p);
   6177 				}
   6178 			}
   6179 		}
   6180 		*Over_p = '\0';
   6181 		return;
   6182 	} else if (over == U_OVER && *Over_p != '\0') {
   6183 		if (Do_rename) {
   6184 			char *tmp_ptr;
   6185 
   6186 			(void) renameat(dirfd, get_component(nam_p),
   6187 			    dirfd, get_component(Over_p));
   6188 			if (Args & OCp) {
   6189 				if (G_p->g_attrnam_p == NULL) {
   6190 					tmp_ptr = Fullnam_p;
   6191 					Fullnam_p = Over_p;
   6192 					Over_p = tmp_ptr;
   6193 				} else {
   6194 					/*
   6195 					 * Over_p is pointing at g_attrnam_p
   6196 					 * which must be preserved.
   6197 					 *
   6198 					 * We don't want the tmp_ptr and so
   6199 					 * on to throw away our only copy of
   6200 					 * the name.
   6201 					 */
   6202 					Over_p = Attrfile_p;
   6203 				}
   6204 			} else {
   6205 				tmp_ptr = G_p->g_nam_p;
   6206 				G_p->g_nam_p = Over_p;
   6207 				Over_p = tmp_ptr;
   6208 			}
   6209 			Do_rename = 0;	/* names now have original values */
   6210 		} else {
   6211 			if (unlinkat(dirfd, get_component(Over_p), 0) < 0) {
   6212 				msg(ERRN,
   6213 				    "Cannot unlink() temp file \"%s%s%s\"",
   6214 				    (G_p->g_attrnam_p == NULL) ?
   6215 				    Over_p : Fullnam_p,
   6216 				    (G_p->g_attrnam_p == NULL) ? "" :
   6217 				    G_p->g_rw_sysattr ?
   6218 				    gettext(" System Attribute ") :
   6219 				    gettext(" Attribute "),
   6220 				    (G_p->g_attrnam_p == NULL) ? "" : Over_p);
   6221 			}
   6222 		}
   6223 		*Over_p = '\0';
   6224 	}
   6225 	if (Args & OCp) {
   6226 		if (G_p->g_attrnam_p != NULL) {
   6227 			inam_p = G_p->g_attrfnam_p;
   6228 			onam_p = G_p->g_attrnam_p;
   6229 		} else {
   6230 			inam_p = Nam_p;
   6231 			onam_p = Fullnam_p;
   6232 		}
   6233 	} else /* OCi only uses onam_p, OCo only uses inam_p */
   6234 		if (G_p->g_attrnam_p != NULL) {
   6235 			inam_p = onam_p = G_p->g_attrnam_p;
   6236 		} else {
   6237 			inam_p = onam_p = G_p->g_nam_p;
   6238 		}
   6239 
   6240 	/*
   6241 	 * Change the owner, time, and mode to those of the file
   6242 	 * originally created in the archive.  Note: time and
   6243 	 * mode do not need to be restored for a symbolic link
   6244 	 * since rstfiles() is not called when the archived file
   6245 	 * is a symlink.
   6246 	 */
   6247 	if (!(Args & OCo)) {
   6248 		if (Args & OCR) {
   6249 			if (fchownat(dirfd, get_component(onam_p),
   6250 			    Rpw_p->pw_uid, Rpw_p->pw_gid,
   6251 			    AT_SYMLINK_NOFOLLOW) < 0) {
   6252 				msg(ERRN, "Cannot chown() \"%s%s%s\"",
   6253 				    onam_p,
   6254 				    (G_p->g_attrnam_p == NULL) ? "" :
   6255 				    G_p->g_rw_sysattr ?
   6256 				    gettext(" System Attribute ") :
   6257 				    gettext(" Attribute "),
   6258 				    (G_p->g_attrnam_p == NULL) ? "" : onam_p);
   6259 			}
   6260 		} else {
   6261 			if ((fchownat(dirfd, get_component(onam_p),
   6262 			    G_p->g_uid, G_p->g_gid,
   6263 			    AT_SYMLINK_NOFOLLOW) < 0) && privileged) {
   6264 				msg(ERRN, "Cannot chown() \"%s%s%s\"",
   6265 				    onam_p,
   6266 				    (G_p->g_attrnam_p == NULL) ? "" :
   6267 				    G_p->g_rw_sysattr ?
   6268 				    gettext(" System Attribute ") :
   6269 				    gettext(" Attribute "),
   6270 				    (G_p->g_attrnam_p == NULL) ? "" : onam_p);
   6271 			}
   6272 		}
   6273 
   6274 		if (Args & OCm) {
   6275 			set_tym(dirfd, get_component(onam_p),
   6276 			    G_p->g_mtime, G_p->g_mtime);
   6277 		}
   6278 
   6279 		/* Acl was not set, so we must chmod */
   6280 		if (!acl_is_set) {
   6281 			mode_t orig_mask, new_mask;
   6282 
   6283 			/*
   6284 			 * use fchmod for attributes, since
   6285 			 * we known they are always regular
   6286 			 * files, whereas when it isn't an
   6287 			 * attribute it could be for a fifo
   6288 			 * or something other that we don't
   6289 			 * open and don't have a valid Ofile
   6290 			 * for.
   6291 			 */
   6292 			if (privileged) {
   6293 				new_mask = G_p->g_mode;
   6294 			} else {
   6295 				orig_mask = umask(0);
   6296 				new_mask = G_p->g_mode & ~orig_mask;
   6297 			}
   6298 
   6299 			if (G_p->g_attrnam_p != NULL) {
   6300 				error = fchmod(Ofile, new_mask);
   6301 			} else {
   6302 				error = chmod(onam_p, new_mask);
   6303 			}
   6304 			if (error < 0) {
   6305 				msg(ERRN,
   6306 				    "Cannot chmod() \"%s%s%s\"",
   6307 				    (G_p->g_attrnam_p == NULL) ?
   6308 				    onam_p : G_p->g_attrfnam_p,
   6309 				    (G_p->g_attrnam_p == NULL) ? "" :
   6310 				    G_p->g_rw_sysattr ?
   6311 				    gettext(" System Attribute ") :
   6312 				    gettext(" Attribute "),
   6313 				    (G_p->g_attrnam_p == NULL) ? "" : onam_p);
   6314 			}
   6315 			if (!privileged) {
   6316 				(void) umask(orig_mask);
   6317 			}
   6318 		}
   6319 	}
   6320 
   6321 	if (!(Args & OCi) && (Args & OCa)) {
   6322 		/*
   6323 		 * Use dirfd since we are updating original file
   6324 		 * and not just created file
   6325 		 */
   6326 		set_tym(G_p->g_dirfd, get_component(inam_p),
   6327 		    (ulong_t)SrcSt.st_atime, (ulong_t)SrcSt.st_mtime);
   6328 	}
   6329 }
   6330 
   6331 /*
   6332  * scan4trail: Scan the archive looking for the trailer.
   6333  * When found, back the archive up over the trailer and overwrite
   6334  * the trailer with the files to be added to the archive.
   6335  */
   6336 
   6337 static void
   6338 scan4trail(void)
   6339 {
   6340 	int rv;
   6341 	off_t off1, off2;
   6342 
   6343 	Append = 1;
   6344 	Hdr_type = NONE;
   6345 	G_p = NULL;
   6346 	while (gethdr()) {
   6347 		G_p = &Gen;
   6348 		data_in(P_SKIP);
   6349 	}
   6350 	off1 = Buffr.b_cnt;
   6351 	off2 = Bufsize - (Buffr.b_cnt % Bufsize);
   6352 	Buffr.b_out_p = Buffr.b_in_p = Buffr.b_base_p;
   6353 	Buffr.b_cnt = (off_t)0;
   6354 	if (lseek(Archive, -(off1 + off2), SEEK_REL) < 0)
   6355 		msg(EXTN, "Unable to append to this archive");
   6356 	if ((rv = g_read(Device, Archive, Buffr.b_in_p, Bufsize)) < 0)
   6357 		msg(EXTN, "Cannot append to this archive");
   6358 	if (lseek(Archive, (off_t)-rv, SEEK_REL) < 0)
   6359 		msg(EXTN, "Unable to append to this archive");
   6360 	Buffr.b_cnt = off2;
   6361 	Buffr.b_in_p = Buffr.b_base_p + Buffr.b_cnt;
   6362 	Append = 0;
   6363 }
   6364 
   6365 /*
   6366  * setup:  Perform setup and initialization functions.  Parse the options
   6367  * using getopt(3C), call ckopts to check the options and initialize various
   6368  * structures and pointers.  Specifically, for the -i option, save any
   6369  * patterns, for the -o option, check (via stat(2)) the archive, and for
   6370  * the -p option, validate the destination directory.
   6371  */
   6372 
   6373 static void
   6374 setup(int largc, char **largv)
   6375 {
   6376 	extern int optind;
   6377 	extern char *optarg;
   6378 
   6379 #if defined(O_XATTR)
   6380 #if defined(_PC_SATTR_ENABLED)
   6381 #ifdef WAITAROUND
   6382 	char	*opts_p = "zabcdfiklmoprstuvABC:DE:H:I:LM:O:PR:SV6@/";
   6383 #else
   6384 	char	*opts_p = "abcdfiklmoprstuvABC:DE:H:I:LM:O:PR:SV6@/";
   6385 #endif	/* WAITAROUND */
   6386 
   6387 #else	/* _PC_SATTR_ENABLED */
   6388 #ifdef WAITAROUND
   6389 	char	*opts_p = "zabcdfiklmoprstuvABC:DE:H:I:LM:O:PR:SV6@";
   6390 #else
   6391 	char	*opts_p = "abcdfiklmoprstuvABC:DE:H:I:LM:O:PR:SV6@";
   6392 #endif	/* WAITAROUND */
   6393 #endif	/* _PC_SATTR_ENABLED */
   6394 
   6395 #else	/* O_XATTR */
   6396 #ifdef WAITAROUND
   6397 	char	*opts_p = "zabcdfiklmoprstuvABC:DE:H:I:LM:O:PR:SV6";
   6398 #else
   6399 	char	*opts_p = "abcdfiklmoprstuvABC:DE:H:I:LM:O:PR:SV6";
   6400 #endif	/* WAITAROUND */
   6401 #endif	/* O_XATTR */
   6402 
   6403 	char   *dupl_p = "Only one occurrence of -%c allowed";
   6404 	int option;
   6405 	int blk_cnt, blk_cnt_max;
   6406 	struct rlimit rlim;
   6407 
   6408 	/* Remember the native page size. */
   6409 
   6410 	PageSize = sysconf(_SC_PAGESIZE);
   6411 
   6412 	if (PageSize == -1) {
   6413 		/*
   6414 		 * This sysconf call will almost certainly never fail.  The
   6415 		 * symbol PAGESIZE itself resolves to the above sysconf call,
   6416 		 * so we should go ahead and define our own constant.
   6417 		 */
   6418 		PageSize = 8192;
   6419 	}
   6420 
   6421 	Hdr_type = BIN;
   6422 	Max_offset = (off_t)(BIN_OFFSET_MAX);
   6423 	Efil_p = Hdr_p = Own_p = IOfil_p = NULL;
   6424 	while ((option = getopt(largc, largv, opts_p)) != EOF) {
   6425 		switch (option) {
   6426 #ifdef WAITAROUND
   6427 		case 'z':
   6428 			/* rendezvous with the debugger */
   6429 			waitaround = 1;
   6430 			break;
   6431 #endif
   6432 		case 'a':	/* reset access time */
   6433 			Args |= OCa;
   6434 			break;
   6435 		case 'b':	/* swap bytes and halfwords */
   6436 			Args |= OCb;
   6437 			break;
   6438 		case 'c':	/* select character header */
   6439 			Args |= OCc;
   6440 			Hdr_type = ASC;
   6441 			Max_namesz = APATH;
   6442 			Onecopy = 1;
   6443 			break;
   6444 		case 'd':	/* create directories as needed */
   6445 			Args |= OCd;
   6446 			break;
   6447 		case 'f':	/* select files not in patterns */
   6448 			Args |= OCf;
   6449 			break;
   6450 		case 'i':	/* "copy in" */
   6451 			Args |= OCi;
   6452 			Archive = 0;
   6453 			break;
   6454 		case 'k':	/* retry after I/O errors */
   6455 			Args |= OCk;
   6456 			break;
   6457 		case 'l':	/* link files when possible */
   6458 			Args |= OCl;
   6459 			break;
   6460 		case 'm':	/* retain modification time */
   6461 			Args |= OCm;
   6462 			break;
   6463 		case 'o':	/* "copy out" */
   6464 			Args |= OCo;
   6465 			Archive = 1;
   6466 			break;
   6467 		case 'p':	/* "pass" */
   6468 			Max_namesz = APATH;
   6469 			Args |= OCp;
   6470 			break;
   6471 		case 'r':	/* rename files interactively */
   6472 			Args |= OCr;
   6473 			break;
   6474 		case 's':	/* swap bytes */
   6475 			Args |= OCs;
   6476 			break;
   6477 		case 't':	/* table of contents */
   6478 			Args |= OCt;
   6479 			break;
   6480 		case 'u':	/* copy unconditionally */
   6481 			Args |= OCu;
   6482 			break;
   6483 		case 'v':	/* verbose - print file names */
   6484 			Args |= OCv;
   6485 			break;
   6486 		case 'A':	/* append to existing archive */
   6487 			Args |= OCA;
   6488 			break;
   6489 		case 'B':	/* set block size to 5120 bytes */
   6490 			Args |= OCB;
   6491 			Bufsize = 5120;
   6492 			break;
   6493 		case 'C':	/* set arbitrary block size */
   6494 			if (Args & OCC)
   6495 				msg(ERR, dupl_p, 'C');
   6496 			else {
   6497 				Args |= OCC;
   6498 				Bufsize = atoi(optarg);
   6499 			}
   6500 			break;
   6501 		case 'D':
   6502 			Dflag = 1;
   6503 			break;
   6504 		case 'E':	/* alternate file for pattern input */
   6505 			if (Args & OCE)
   6506 				msg(ERR, dupl_p, 'E');
   6507 			else {
   6508 				Args |= OCE;
   6509 				Efil_p = optarg;
   6510 			}
   6511 			break;
   6512 		case 'H':	/* select header type */
   6513 			if (Args & OCH)
   6514 				msg(ERR, dupl_p, 'H');
   6515 			else {
   6516 				Args |= OCH;
   6517 				Hdr_p = optarg;
   6518 			}
   6519 			break;
   6520 		case 'I':	/* alternate file for archive input */
   6521 			if (Args & OCI)
   6522 				msg(ERR, dupl_p, 'I');
   6523 			else {
   6524 				Args |= OCI;
   6525 				IOfil_p = optarg;
   6526 			}
   6527 			break;
   6528 		case 'L':	/* follow symbolic links */
   6529 			Args |= OCL;
   6530 			break;
   6531 		case 'M':	/* specify new end-of-media message */
   6532 			if (Args & OCM)
   6533 				msg(ERR, dupl_p, 'M');
   6534 			else {
   6535 				Args |= OCM;
   6536 				Eom_p = optarg;
   6537 			}
   6538 			break;
   6539 		case 'O':	/* alternate file for archive output */
   6540 			if (Args & OCO)
   6541 				msg(ERR, dupl_p, 'O');
   6542 			else {
   6543 				Args |= OCO;
   6544 				IOfil_p = optarg;
   6545 			}
   6546 			break;
   6547 		case 'P':	/* preserve acls */
   6548 			Args |= OCP;
   6549 			Pflag++;
   6550 			break;
   6551 		case 'R':	/* change owner/group of files */
   6552 			if (Args & OCR)
   6553 				msg(ERR, dupl_p, 'R');
   6554 			else {
   6555 				Args |= OCR;
   6556 				Own_p = optarg;
   6557 			}
   6558 			break;
   6559 		case 'S':	/* swap halfwords */
   6560 			Args |= OCS;
   6561 			break;
   6562 		case 'V':	/* print a dot '.' for each file */
   6563 			Args |= OCV;
   6564 			break;
   6565 		case '6':	/* for old, sixth-edition files */
   6566 			Args |= OC6;
   6567 			Ftype = SIXTH;
   6568 			break;
   6569 #if defined(O_XATTR)
   6570 		case '@':
   6571 			Atflag++;
   6572 			break;
   6573 #if defined(_PC_SATTR_ENABLED)
   6574 		case '/':
   6575 			SysAtflag++;
   6576 			break;
   6577 #endif	/* _PC_SATTR_ENABLED */
   6578 #endif	/* O_XATTR */
   6579 		default:
   6580 			Error_cnt++;
   6581 		} /* option */
   6582 	} /* (option = getopt(largc, largv, opts_p)) != EOF */
   6583 
   6584 #ifdef WAITAROUND
   6585 	if (waitaround) {
   6586 		(void) fprintf(stderr, gettext("Rendezvous with cpio on pid"
   6587 		    " %d\n"), getpid());
   6588 
   6589 		while (waitaround) {
   6590 			(void) sleep(10);
   6591 		}
   6592 	}
   6593 #endif
   6594 
   6595 	largc -= optind;
   6596 	largv += optind;
   6597 	ckopts(Args);
   6598 	if (!Error_cnt) {
   6599 		if (Args & OCr) {
   6600 			Renam_p = e_zalloc(E_EXIT, APATH + 1);
   6601 			Renametmp_p = e_zalloc(E_EXIT, APATH + 1);
   6602 #if defined(_PC_SATTR_ENABLED)
   6603 			Renam_attr_p = e_zalloc(E_EXIT, APATH + 1);
   6604 #endif
   6605 		}
   6606 		Symlnk_p = e_zalloc(E_EXIT, APATH);
   6607 		Over_p = e_zalloc(E_EXIT, APATH);
   6608 		Nam_p = e_zalloc(E_EXIT, APATH + 1);
   6609 		if (Args & OCp) {
   6610 			Savenam_p = e_zalloc(E_EXIT, APATH + 1);
   6611 		}
   6612 		Fullnam_p = e_zalloc(E_EXIT, APATH);
   6613 		Lnknam_p = e_zalloc(E_EXIT, APATH);
   6614 		Gen.g_nam_p = Nam_p;
   6615 		if ((Fullnam_p = getcwd(NULL, APATH)) == NULL)
   6616 			msg(EXT, "Unable to determine current directory.");
   6617 		if (Args & OCi) {
   6618 			if (largc > 0) /* save patterns for -i option, if any */
   6619 				Pat_pp = largv;
   6620 			if (Args & OCE)
   6621 				getpats(largc, largv);
   6622 		} else if (Args & OCo) {
   6623 			if (largc != 0) /* error if arguments left with -o */
   6624 				Error_cnt++;
   6625 			else if (fstat(Archive, &ArchSt) < 0)
   6626 				msg(ERRN, "Error during stat() of archive");
   6627 			switch (Hdr_type) {
   6628 			case BIN:
   6629 				Hdrsz = HDRSZ;
   6630 				Pad_val = HALFWD;
   6631 				break;
   6632 			case CHR:
   6633 				Hdrsz = CHRSZ;
   6634 				Pad_val = 0;
   6635 				Max_offset = (off_t)(CHAR_OFFSET_MAX);
   6636 				break;
   6637 			case ASC:
   6638 			case CRC:
   6639 				Hdrsz = ASCSZ;
   6640 				Pad_val = FULLWD;
   6641 				Max_offset = (off_t)(ASC_OFFSET_MAX);
   6642 				break;
   6643 			case TAR:
   6644 			/* FALLTHROUGH */
   6645 			case USTAR: /* TAR and USTAR */
   6646 				Hdrsz = TARSZ;
   6647 				Pad_val = FULLBK;
   6648 				Max_offset = (off_t)(CHAR_OFFSET_MAX);
   6649 				break;
   6650 			default:
   6651 				msg(EXT, "Impossible header type.");
   6652 			}
   6653 		} else { /* directory must be specified */
   6654 			if (largc != 1)
   6655 				Error_cnt++;
   6656 			else if (access(*largv, 2) < 0 && (errno != EACCES))
   6657 				/*
   6658 				 * EACCES is ignored here as it may occur
   6659 				 * when any directory component of the path
   6660 				 * does not have write permission, even though
   6661 				 * the destination subdirectory has write
   6662 				 * access. Writing to a read only directory
   6663 				 * is handled later, as in "copy in" mode.
   6664 				 */
   6665 				msg(ERRN,
   6666 				    "Error during access() of \"%s\"", *largv);
   6667 		}
   6668 	}
   6669 	if (Error_cnt)
   6670 		usage(); /* exits! */
   6671 	if (Args & (OCi | OCo)) {
   6672 		if (!Dflag) {
   6673 			if (Args & (OCB | OCC)) {
   6674 				if (g_init(&Device, &Archive) < 0)
   6675 					msg(EXTN,
   6676 					    "Error during initialization");
   6677 			} else {
   6678 				if ((Bufsize = g_init(&Device, &Archive)) < 0)
   6679 					msg(EXTN,
   6680 					    "Error during initialization");
   6681 			}
   6682 		}
   6683 
   6684 		blk_cnt_max = _20K / Bufsize;
   6685 		if (blk_cnt_max < MX_BUFS) {
   6686 			blk_cnt_max = MX_BUFS;
   6687 		}
   6688 
   6689 		Buffr.b_base_p = NULL;
   6690 
   6691 		for (blk_cnt = blk_cnt_max; blk_cnt > 1; blk_cnt--) {
   6692 			Buffr.b_size = (size_t)(Bufsize * blk_cnt);
   6693 			Buffr.b_base_p = e_valloc(E_NORMAL, Buffr.b_size);
   6694 			if (Buffr.b_base_p != NULL) {
   6695 				break;
   6696 			}
   6697 		}
   6698 		if (Buffr.b_base_p == NULL || Buffr.b_size < (2 * CPIOBSZ)) {
   6699 			msg(EXT, "Out of memory");
   6700 		}
   6701 
   6702 		Buffr.b_out_p = Buffr.b_in_p = Buffr.b_base_p;
   6703 		Buffr.b_cnt = 0L;
   6704 		Buffr.b_end_p = Buffr.b_base_p + Buffr.b_size;
   6705 	}
   6706 
   6707 	/*
   6708 	 * Now that Bufsize has stabilized, we can allocate our i/o buffer
   6709 	 */
   6710 	Buf_p = e_valloc(E_EXIT, Bufsize);
   6711 
   6712 	if (Args & OCp) { /* get destination directory */
   6713 		(void) strcpy(Fullnam_p, *largv);
   6714 		if (stat(Fullnam_p, &DesSt) < 0)
   6715 			msg(EXTN, "Error during stat() of \"%s\"", Fullnam_p);
   6716 		if ((DesSt.st_mode & Ftype) != S_IFDIR)
   6717 			msg(EXT, "\"%s\" is not a directory", Fullnam_p);
   6718 	}
   6719 	Full_p = Fullnam_p + strlen(Fullnam_p) - 1;
   6720 	if (*Full_p != '/') {
   6721 		Full_p++;
   6722 		*Full_p = '/';
   6723 	}
   6724 	Full_p++;
   6725 	*Full_p = '\0';
   6726 	(void) strcpy(Lnknam_p, Fullnam_p);
   6727 	Lnkend_p = Lnknam_p + strlen(Lnknam_p);
   6728 	(void) getrlimit(RLIMIT_FSIZE, &rlim);
   6729 	Max_filesz = (off_t)rlim.rlim_cur;
   6730 	Lnk_hd.L_nxt_p = Lnk_hd.L_bck_p = &Lnk_hd;
   6731 	Lnk_hd.L_lnk_p = NULL;
   6732 }
   6733 
   6734 /*
   6735  * set_tym: Set the access and/or modification times for a file.
   6736  */
   6737 
   6738 static void
   6739 set_tym(int dirfd, char *nam_p, time_t atime, time_t mtime)
   6740 {
   6741 	struct timeval times[2];
   6742 
   6743 	times[0].tv_sec = atime;
   6744 	times[0].tv_usec = 0;
   6745 	times[1].tv_sec = mtime;
   6746 	times[1].tv_usec = 0;
   6747 
   6748 	if (futimesat(dirfd, nam_p, times) < 0) {
   6749 		if (Args & OCa) {
   6750 			msg(ERRN,
   6751 			    "Unable to reset access time for \"%s%s%s\"",
   6752 			    (G_p->g_attrnam_p == NULL) ? nam_p : Fullnam_p,
   6753 			    (G_p->g_attrnam_p == NULL) ? "" :
   6754 			    G_p->g_rw_sysattr ? gettext(" System Attribute ") :
   6755 			    gettext(" Attribute "),
   6756 			    (G_p->g_attrnam_p == NULL) ? "" : nam_p);
   6757 		} else {
   6758 			msg(ERRN,
   6759 			    "Unable to reset modification time for \"%s%s%s\"",
   6760 			    (G_p->g_attrnam_p == NULL) ? nam_p : Fullnam_p,
   6761 			    (G_p->g_attrnam_p == NULL) ? "" :
   6762 			    G_p->g_rw_sysattr ? gettext(" System Attribute ") :
   6763 			    gettext(" Attribute "),
   6764 			    (G_p->g_attrnam_p == NULL) ? "" : nam_p);
   6765 		}
   6766 	}
   6767 }
   6768 
   6769 /*
   6770  * sigint:  Catch interrupts.  If an interrupt occurs during the extraction
   6771  * of a file from the archive with the -u option set, and the filename did
   6772  * exist, remove the current file and restore the original file.  Then exit.
   6773  */
   6774 
   6775 /*ARGSUSED*/
   6776 static void
   6777 sigint(int sig)
   6778 {
   6779 	char *nam_p;
   6780 
   6781 	(void) signal(SIGINT, SIG_IGN); /* block further signals */
   6782 	if (!Finished) {
   6783 		if (Args & OCi)
   6784 			nam_p = G_p->g_nam_p;
   6785 		else /* OCp */
   6786 			nam_p = Fullnam_p;
   6787 		if (*Over_p != '\0') { /* There is a temp file */
   6788 			if (unlink(nam_p) < 0) {
   6789 				msg(ERRN,
   6790 				    "Cannot remove incomplete \"%s\"", nam_p);
   6791 			}
   6792 			if (rename(Over_p, nam_p) < 0) {
   6793 				if (link(Over_p, nam_p) < 0) {
   6794 					msg(ERRN,
   6795 					    "Cannot recover original \"%s\"",
   6796 					    nam_p);
   6797 				}
   6798 				if (unlink(Over_p)) {
   6799 					msg(ERRN,
   6800 					    "Cannot remove temp file \"%s\"",
   6801 					    Over_p);
   6802 				}
   6803 			}
   6804 		} else if (unlink(nam_p))
   6805 			msg(ERRN,
   6806 			    "Cannot remove incomplete \"%s\"", nam_p);
   6807 			*Over_p = '\0';
   6808 	}
   6809 	exit(EXIT_CODE);
   6810 }
   6811 
   6812 /*
   6813  * swap: Swap bytes (-s), halfwords (-S) or or both halfwords and bytes (-b).
   6814  */
   6815 
   6816 static void
   6817 swap(char *buf_p, int cnt)
   6818 {
   6819 	unsigned char tbyte;
   6820 	int tcnt;
   6821 	int rcnt;
   6822 	ushort_t thalf;
   6823 
   6824 	rcnt = cnt % 4;
   6825 	cnt /= 4;
   6826 	if (Args & (OCb | OCs | BSM)) {
   6827 		tcnt = cnt;
   6828 		/* LINTED alignment */
   6829 		Swp_p = (union swpbuf *)buf_p;
   6830 		while (tcnt-- > 0) {
   6831 			tbyte = Swp_p->s_byte[0];
   6832 			Swp_p->s_byte[0] = Swp_p->s_byte[1];
   6833 			Swp_p->s_byte[1] = tbyte;
   6834 			tbyte = Swp_p->s_byte[2];
   6835 			Swp_p->s_byte[2] = Swp_p->s_byte[3];
   6836 			Swp_p->s_byte[3] = tbyte;
   6837 			Swp_p++;
   6838 		}
   6839 		if (rcnt >= 2) {
   6840 		tbyte = Swp_p->s_byte[0];
   6841 		Swp_p->s_byte[0] = Swp_p->s_byte[1];
   6842 		Swp_p->s_byte[1] = tbyte;
   6843 		tbyte = Swp_p->s_byte[2];
   6844 		}
   6845 	}
   6846 	if (Args & (OCb | OCS)) {
   6847 		tcnt = cnt;
   6848 		/* LINTED alignment */
   6849 		Swp_p = (union swpbuf *)buf_p;
   6850 		while (tcnt-- > 0) {
   6851 			thalf = Swp_p->s_half[0];
   6852 			Swp_p->s_half[0] = Swp_p->s_half[1];
   6853 			Swp_p->s_half[1] = thalf;
   6854 			Swp_p++;
   6855 		}
   6856 	}
   6857 }
   6858 
   6859 /*
   6860  * usage: Print the usage message on stderr and exit.
   6861  */
   6862 
   6863 static void
   6864 usage(void)
   6865 {
   6866 
   6867 	(void) fflush(stdout);
   6868 #if defined(O_XATTR)
   6869 	(void) fprintf(stderr, gettext("USAGE:\n"
   6870 	    "\tcpio -i[bcdfkmrstuv@BSV6] [-C size] "
   6871 	    "[-E file] [-H hdr] [-I file [-M msg]] "
   6872 	    "[-R id] [patterns]\n"
   6873 	    "\tcpio -o[acv@ABLV] [-C size] "
   6874 	    "[-H hdr] [-O file [-M msg]]\n"
   6875 	    "\tcpio -p[adlmuv@LV] [-R id] directory\n"));
   6876 #else
   6877 	(void) fprintf(stderr, gettext("USAGE:\n"
   6878 	    "\tcpio -i[bcdfkmrstuvBSV6] [-C size] "
   6879 	    "[-E file] [-H hdr] [-I file [-M msg]] "
   6880 	    "[-R id] [patterns]\n"
   6881 	    "\tcpio -o[acvABLV] [-C size] "
   6882 	    "[-H hdr] [-O file [-M msg]]\n"
   6883 	    "\tcpio -p[adlmuvLV] [-R id] directory\n"));
   6884 #endif
   6885 	(void) fflush(stderr);
   6886 	exit(EXIT_CODE);
   6887 }
   6888 
   6889 /*
   6890  * verbose: For each file, print either the filename (-v) or a dot (-V).
   6891  * If the -t option (table of contents) is set, print either the filename,
   6892  * or if the -v option is also set, print an "ls -l"-like listing.
   6893  */
   6894 
   6895 static void
   6896 verbose(char *nam_p)
   6897 {
   6898 	int i, j, temp;
   6899 	mode_t mode;
   6900 	char modestr[12];
   6901 	time_t	ttime;
   6902 
   6903 	/*
   6904 	 * The printf format and associated arguments to print the current
   6905 	 * filename.  Normally, just nam_p.  If we're processing an extended
   6906 	 * attribute, these are overridden.
   6907 	 */
   6908 	char *name_fmt = "%s";
   6909 	const char *name = nam_p;
   6910 	const char *attribute = NULL;
   6911 
   6912 	if (Gen.g_attrnam_p != NULL) {
   6913 		/*
   6914 		 * Translation note:
   6915 		 * 'attribute' is a noun.
   6916 		 */
   6917 
   6918 		if (Gen.g_rw_sysattr) {
   6919 			name_fmt = gettext("%s system attribute %s");
   6920 		} else if ((Args & OCt) &&
   6921 		    (is_sysattr(basename(Gen.g_attrnam_p)))) {
   6922 			name_fmt = gettext("%s system attribute %s");
   6923 		} else {
   6924 			name_fmt = gettext("%s attribute %s");
   6925 		}
   6926 
   6927 		name = (Args & OCp) ? nam_p : Gen.g_attrfnam_p;
   6928 		if (Gen.g_attrparent_p == NULL) {
   6929 			attribute = Gen.g_attrnam_p;
   6930 		} else {
   6931 			attribute = Gen.g_attrpath_p;
   6932 		}
   6933 	}
   6934 
   6935 	if ((Gen.g_mode == SECMODE) || ((Hdr_type == USTAR ||
   6936 	    Hdr_type == TAR) && Thdr_p->tbuf.t_typeflag == 'A')) {
   6937 		/* dont print ancillary file */
   6938 		aclchar = '+';
   6939 		return;
   6940 	}
   6941 	for (i = 0; i < 11; i++)
   6942 		modestr[i] = '-';
   6943 	modestr[i] = '\0';
   6944 	modestr[i-1] = aclchar;
   6945 	aclchar = ' ';
   6946 
   6947 	if ((Args & OCt) && (Args & OCv)) {
   6948 		mode = Gen.g_mode;
   6949 		for (i = 0; i < 3; i++) {
   6950 			temp = (mode >> (6 - (i * 3)));
   6951 			j = (i * 3) + 1;
   6952 			if (S_IROTH & temp)
   6953 				modestr[j] = 'r';
   6954 			if (S_IWOTH & temp)
   6955 				modestr[j + 1] = 'w';
   6956 			if (S_IXOTH & temp)
   6957 				modestr[j + 2] = 'x';
   6958 		}
   6959 
   6960 		if (Hdr_type != BAR) {
   6961 			temp = Gen.g_mode & Ftype;
   6962 			switch (temp) {
   6963 			case (S_IFIFO):
   6964 				modestr[0] = 'p';
   6965 				break;
   6966 			case (S_IFSOCK):
   6967 				modestr[0] = 's';
   6968 				break;
   6969 			case (S_IFCHR):
   6970 				modestr[0] = 'c';
   6971 				break;
   6972 			case (S_IFDIR):
   6973 				modestr[0] = 'd';
   6974 				break;
   6975 			case (S_IFBLK):
   6976 				modestr[0] = 'b';
   6977 				break;
   6978 			case (S_IFREG): /* was initialized to '-' */
   6979 				break;
   6980 			case (S_IFLNK):
   6981 				modestr[0] = 'l';
   6982 				break;
   6983 			default:
   6984 				msg(ERR, "Impossible file type");
   6985 			}
   6986 		} else {		/* bar */
   6987 			temp = Gen.g_mode & Ftype;
   6988 			switch (temp) {
   6989 			case (S_IFIFO):
   6990 				modestr[0] = 'p';
   6991 				break;
   6992 			case (S_IFSOCK):
   6993 				modestr[0] = 's';
   6994 				break;
   6995 			case (S_IFCHR):
   6996 				modestr[0] = 'c';
   6997 				break;
   6998 			case (S_IFDIR):
   6999 				modestr[0] = 'd';
   7000 				break;
   7001 			case (S_IFBLK):
   7002 				modestr[0] = 'b';
   7003 				break;
   7004 			}
   7005 			if (bar_linkflag == SYMTYPE)
   7006 				modestr[0] = 'l';
   7007 		}
   7008 		if ((S_ISUID & Gen.g_mode) == S_ISUID)
   7009 			modestr[3] = 's';
   7010 		if ((S_ISVTX & Gen.g_mode) == S_ISVTX)
   7011 			modestr[9] = 't';
   7012 		if ((S_ISGID & G_p->g_mode) == S_ISGID && modestr[6] == 'x')
   7013 			modestr[6] = 's';
   7014 		else if ((S_ENFMT & Gen.g_mode) == S_ENFMT && modestr[6] != 'x')
   7015 			modestr[6] = 'l';
   7016 		if ((Hdr_type == TAR || Hdr_type == USTAR) && Gen.g_nlink == 0)
   7017 			(void) printf("%s%4d ", modestr, (int)Gen.g_nlink+1);
   7018 		else
   7019 			(void) printf("%s%4d ", modestr, (int)Gen.g_nlink);
   7020 		if (Lastuid == (uid_t)Gen.g_uid) {
   7021 			if (Lastuid == (uid_t)-1)
   7022 				(void) printf("-1       ");
   7023 			else
   7024 				(void) printf("%-9s", Curpw_p->pw_name);
   7025 		} else {
   7026 			if (Curpw_p = getpwuid((int)Gen.g_uid)) {
   7027 				(void) printf("%-9s", Curpw_p->pw_name);
   7028 				Lastuid = (uid_t)Gen.g_uid;
   7029 			} else {
   7030 				(void) printf("%-9d", (int)Gen.g_uid);
   7031 				Lastuid = (uid_t)-1;
   7032 			}
   7033 		}
   7034 		if (Lastgid == (gid_t)Gen.g_gid) {
   7035 			if (Lastgid == (gid_t)-1)
   7036 				(void) printf("-1       ");
   7037 			else
   7038 				(void) printf("%-9s", Curgr_p->gr_name);
   7039 		} else {
   7040 			if (Curgr_p = getgrgid((int)Gen.g_gid)) {
   7041 				(void) printf("%-9s", Curgr_p->gr_name);
   7042 				Lastgid = (gid_t)Gen.g_gid;
   7043 			} else {
   7044 				(void) printf("%-9d", (int)Gen.g_gid);
   7045 				Lastgid = (gid_t)-1;
   7046 			}
   7047 		}
   7048 
   7049 		/* print file size */
   7050 		if (!Aspec || ((Gen.g_mode & Ftype) == S_IFIFO) ||
   7051 		    ((Gen.g_mode & Ftype) == S_IFSOCK) ||
   7052 		    (Hdr_type == BAR && bar_linkflag == SYMTYPE)) {
   7053 			off_t filesz = Gen.g_filesz;
   7054 
   7055 			if (S_ISSPARSE(Gen.g_mode) && Gen.g_holes != NULL)
   7056 				filesz = Gen.g_holes->orig_size;
   7057 
   7058 			if (filesz < (1LL << 31))
   7059 				(void) printf("%7lld ", (offset_t)filesz);
   7060 			else
   7061 				(void) printf("%11lld ", (offset_t)filesz);
   7062 		} else
   7063 			(void) printf("%3d,%3d ", (int)major(Gen.g_rdev),
   7064 			    (int)minor(Gen.g_rdev));
   7065 		ttime = Gen.g_mtime;
   7066 		(void) strftime(Time, sizeof (Time),
   7067 		    dcgettext(NULL, FORMAT, LC_TIME), localtime(&ttime));
   7068 		(void) printf("%s, ", Time);
   7069 		str_fprintf(stdout, name_fmt, name, attribute);
   7070 		if ((Gen.g_mode & Ftype) == S_IFLNK) {
   7071 			if (Hdr_type == USTAR || Hdr_type == TAR)
   7072 				(void) strcpy(Symlnk_p,
   7073 				    Thdr_p->tbuf.t_linkname);
   7074 			else {
   7075 				FILL(Gen.g_filesz);
   7076 				(void) strncpy(Symlnk_p, Buffr.b_out_p,
   7077 				    Gen.g_filesz);
   7078 				*(Symlnk_p + Gen.g_filesz) = '\0';
   7079 			}
   7080 			(void) printf(" -> %s", Symlnk_p);
   7081 		}
   7082 		if (Hdr_type == BAR) {
   7083 			if (bar_linkflag == SYMTYPE)
   7084 				(void) printf(gettext(" symbolic link to %s"),
   7085 				    bar_linkname);
   7086 			else if (bar_linkflag == '1')
   7087 				(void) printf(gettext(" linked to %s"),
   7088 				    bar_linkname);
   7089 		}
   7090 		if ((Hdr_type == USTAR || Hdr_type == TAR) &&
   7091 		    Thdr_p->tbuf.t_typeflag == '1') {
   7092 			(void) printf(gettext(" linked to %s%s%s"),
   7093 			    (Gen.g_attrnam_p == NULL) ?
   7094 			    Thdr_p->tbuf.t_linkname : Gen.g_attrfnam_p,
   7095 			    (Gen.g_attrnam_p == NULL) ? "" :
   7096 			    gettext(" attribute "),
   7097 			    (Gen.g_attrnam_p == NULL) ?
   7098 			    "" : Gen.g_linktoattrnam_p);
   7099 		}
   7100 		(void) printf("\n");
   7101 	} else if ((Args & OCt) || (Args & OCv)) {
   7102 		str_fprintf(Out_p, name_fmt, name, attribute);
   7103 		(void) fputc('\n', Out_p);
   7104 	} else { /* OCV */
   7105 		(void) fputc('.', Out_p);
   7106 		if (Verbcnt++ >= 49) { /* start a new line of dots */
   7107 			Verbcnt = 0;
   7108 			(void) fputc('\n', Out_p);
   7109 		}
   7110 	}
   7111 	(void) fflush(Out_p);
   7112 }
   7113 
   7114 #define	MK_USHORT(a)	(a & 00000177777)
   7115 
   7116 /*
   7117  * write_hdr: Transfer header information for the generic structure
   7118  * into the format for the selected header and bwrite() the header.
   7119  */
   7120 
   7121 static void
   7122 write_hdr(int arcflag, off_t len)
   7123 {
   7124 	int cnt, pad;
   7125 	mode_t mode;
   7126 	uid_t uid;
   7127 	gid_t gid;
   7128 	const char warnfmt[] = "%s%s%s : %s";
   7129 
   7130 	switch (arcflag) {
   7131 	case ARCHIVE_ACL:
   7132 		mode = SECMODE;
   7133 		break;
   7134 
   7135 	case ARCHIVE_XATTR:
   7136 	case ARCHIVE_NORMAL:
   7137 		/*
   7138 		 * If attribute is being archived in cpio format then
   7139 		 * zap off the file type bits since those are truly a
   7140 		 * mask and reset them with _XATTR_CPIO_MODE
   7141 		 */
   7142 		/*
   7143 		 * len is the value of g_filesz for normal files
   7144 		 * and the length of the special header buffer in
   7145 		 * the case of acl and xattr headers.
   7146 		 */
   7147 		if (G_p->g_attrnam_p != NULL && Hdr_type != USTAR &&
   7148 		    Hdr_type != TAR) {
   7149 			mode = (G_p->g_mode & POSIXMODES) | _XATTR_CPIO_MODE;
   7150 		} else {
   7151 			mode = G_p->g_mode;
   7152 		}
   7153 		if (arcflag != ARCHIVE_XATTR) {
   7154 			len = G_p->g_filesz;
   7155 		}
   7156 		break;
   7157 
   7158 	case ARCHIVE_SPARSE:
   7159 		mode = G_p->g_mode | C_ISSPARSE;
   7160 		len = G_p->g_filesz;
   7161 		break;
   7162 	}
   7163 
   7164 	uid = G_p->g_uid;
   7165 	gid = G_p->g_gid;
   7166 	/*
   7167 	 * Handle EFT uids and gids.  If they get too big
   7168 	 * to be represented in a particular format, force 'em to 'nobody'.
   7169 	 */
   7170 	switch (Hdr_type) {
   7171 	case BIN:			/* 16-bits of u_short */
   7172 		if ((ulong_t)uid > (ulong_t)USHRT_MAX)
   7173 			uid = UID_NOBODY;
   7174 		if ((ulong_t)gid > (ulong_t)USHRT_MAX)
   7175 			gid = GID_NOBODY;
   7176 		break;
   7177 	case CHR:			/* %.6lo => 262143 base 10 */
   7178 		if ((ulong_t)uid > (ulong_t)0777777)
   7179 			uid = UID_NOBODY;
   7180 		if ((ulong_t)gid > (ulong_t)0777777)
   7181 			gid = GID_NOBODY;
   7182 		break;
   7183 	case ASC:			/* %.8lx => full 32 bits */
   7184 	case CRC:
   7185 		break;
   7186 	case USTAR:
   7187 	case TAR:			/* %.7lo => 2097151 base 10 */
   7188 		if ((ulong_t)uid > (ulong_t)07777777)
   7189 			uid = UID_NOBODY;
   7190 		if ((ulong_t)gid > (ulong_t)07777777)
   7191 			gid = GID_NOBODY;
   7192 		break;
   7193 	default:
   7194 		msg(EXT, "Impossible header type.");
   7195 	}
   7196 
   7197 	/*
   7198 	 * Since cpio formats -don't- encode the symbolic names, print
   7199 	 * a warning message when we map the uid or gid this way.
   7200 	 * Also, if the ownership just changed, clear set[ug]id bits
   7201 	 *
   7202 	 * (Except for USTAR format of course, where we have a string
   7203 	 * representation of the username embedded in the header)
   7204 	 */
   7205 	if (uid != G_p->g_uid && Hdr_type != USTAR) {
   7206 		msg(ERR, warnfmt,
   7207 		    (G_p->g_attrnam_p == NULL) ?
   7208 		    G_p->g_nam_p : G_p->g_attrfnam_p,
   7209 		    (G_p->g_attrnam_p == NULL) ? "" : G_p->g_rw_sysattr ?
   7210 		    gettext(" System Attribute ") : gettext(" Attribute "),
   7211 		    (G_p->g_attrnam_p == NULL) ? "" : G_p->g_attrnam_p,
   7212 		    gettext("uid too large for archive format"));
   7213 		if (S_ISREG(mode))
   7214 			mode &= ~S_ISUID;
   7215 	}
   7216 	if (gid != G_p->g_gid && Hdr_type != USTAR) {
   7217 		msg(ERR, warnfmt,
   7218 		    (G_p->g_attrnam_p == NULL) ?
   7219 		    G_p->g_nam_p : G_p->g_attrfnam_p,
   7220 		    (G_p->g_attrnam_p == NULL) ? "" : G_p->g_rw_sysattr ?
   7221 		    gettext(" System Attribute ") : gettext(" Attribute "),
   7222 		    (G_p->g_attrnam_p == NULL) ? "" : G_p->g_attrnam_p,
   7223 		    gettext("gid too large for archive format"));
   7224 		if (S_ISREG(mode))
   7225 			mode &= ~S_ISGID;
   7226 	}
   7227 
   7228 	switch (Hdr_type) {
   7229 	case BIN:
   7230 	case CHR:
   7231 	case ASC:
   7232 	case CRC:
   7233 		cnt = Hdrsz + G_p->g_namesz;
   7234 		break;
   7235 	case TAR:
   7236 		/*FALLTHROUGH*/
   7237 	case USTAR: /* TAR and USTAR */
   7238 		cnt = TARSZ;
   7239 		break;
   7240 	default:
   7241 		msg(EXT, "Impossible header type.");
   7242 	}
   7243 	FLUSH(cnt);
   7244 
   7245 	switch (Hdr_type) {
   7246 	case BIN:
   7247 		Hdr.h_magic = (short)G_p->g_magic;
   7248 		Hdr.h_dev = G_p->g_dev;
   7249 		Hdr.h_ino = G_p->g_ino;
   7250 		Hdr.h_uid = uid;
   7251 		Hdr.h_gid = gid;
   7252 		Hdr.h_mode = mode;
   7253 		Hdr.h_nlink = G_p->g_nlink;
   7254 		Hdr.h_rdev = G_p->g_rdev;
   7255 		mkshort(Hdr.h_mtime, (long)G_p->g_mtime);
   7256 		Hdr.h_namesize = (short)G_p->g_namesz;
   7257 		mkshort(Hdr.h_filesize, (long)len);
   7258 		(void) strcpy(Hdr.h_name, G_p->g_nam_p);
   7259 		(void) memcpy(Buffr.b_in_p, &Hdr, cnt);
   7260 		break;
   7261 	case CHR:
   7262 		/*LINTED*/
   7263 		(void) sprintf(Buffr.b_in_p,
   7264 		    "%.6lo%.6lo%.6lo%.6lo%.6lo%.6lo%.6lo%.6lo%.11lo%.6lo%."
   7265 		    "11llo%s", G_p->g_magic, G_p->g_dev, G_p->g_ino, mode,
   7266 		    (long)uid, (long)gid, G_p->g_nlink, MK_USHORT(G_p->g_rdev),
   7267 		    G_p->g_mtime, (long)G_p->g_namesz, (offset_t)len,
   7268 		    G_p->g_nam_p);
   7269 		break;
   7270 	case ASC:
   7271 	case CRC:
   7272 		/*LINTED*/
   7273 		(void) sprintf(Buffr.b_in_p,
   7274 		    "%.6lx%.8lx%.8lx%.8lx%.8lx%.8lx%.8lx%.8lx%.8lx%.8lx%."
   7275 		    "8lx%.8lx%.8lx%.8lx%s",
   7276 		    G_p->g_magic, G_p->g_ino, mode, G_p->g_uid,
   7277 		    G_p->g_gid, G_p->g_nlink, G_p->g_mtime, (ulong_t)len,
   7278 		    major(G_p->g_dev), minor(G_p->g_dev),
   7279 		    major(G_p->g_rdev), minor(G_p->g_rdev),
   7280 		    G_p->g_namesz, G_p->g_cksum, G_p->g_nam_p);
   7281 		break;
   7282 	case USTAR:
   7283 		Thdr_p = (union tblock *)Buffr.b_in_p;
   7284 		(void) memset(Thdr_p, 0, TARSZ);
   7285 		(void) strncpy(Thdr_p->tbuf.t_name, G_p->g_tname,
   7286 		    (int)strlen(G_p->g_tname));
   7287 		(void) sprintf(Thdr_p->tbuf.t_mode, "%07o", (int)mode);
   7288 		(void) sprintf(Thdr_p->tbuf.t_uid, "%07o", (int)uid);
   7289 		(void) sprintf(Thdr_p->tbuf.t_gid, "%07o", (int)gid);
   7290 		(void) sprintf(Thdr_p->tbuf.t_size, "%011llo",
   7291 		    (offset_t)len);
   7292 		(void) sprintf(Thdr_p->tbuf.t_mtime, "%011lo", G_p->g_mtime);
   7293 		if (arcflag == ARCHIVE_ACL) {
   7294 			Thdr_p->tbuf.t_typeflag = 'A';	/* ACL file type */
   7295 		} else if (arcflag == ARCHIVE_XATTR ||
   7296 		    (G_p->g_attrnam_p != NULL)) {
   7297 			Thdr_p->tbuf.t_typeflag = _XATTR_HDRTYPE;
   7298 		} else {
   7299 			Thdr_p->tbuf.t_typeflag = G_p->g_typeflag;
   7300 		}
   7301 		if (T_lname[0] != '\0') {
   7302 			/*
   7303 			 * if not a symbolic link
   7304 			 */
   7305 			if (((G_p->g_mode & Ftype) != S_IFLNK) &&
   7306 			    (G_p->g_attrnam_p == NULL)) {
   7307 				Thdr_p->tbuf.t_typeflag = LNKTYPE;
   7308 				(void) sprintf(Thdr_p->tbuf.t_size,
   7309 				    "%011lo", 0L);
   7310 			}
   7311 			(void) strncpy(Thdr_p->tbuf.t_linkname, T_lname,
   7312 			    strlen(T_lname));
   7313 		}
   7314 		(void) strcpy(Thdr_p->tbuf.t_magic, TMAGIC);
   7315 		(void) strcpy(Thdr_p->tbuf.t_version, TVERSION);
   7316 		(void) strcpy(Thdr_p->tbuf.t_uname, G_p->g_uname);
   7317 		(void) strcpy(Thdr_p->tbuf.t_gname, G_p->g_gname);
   7318 		(void) sprintf(Thdr_p->tbuf.t_devmajor, "%07o",
   7319 		    (int)major(G_p->g_rdev));
   7320 		(void) sprintf(Thdr_p->tbuf.t_devminor, "%07o",
   7321 		    (int)minor(G_p->g_rdev));
   7322 		if (Gen.g_prefix) {
   7323 			(void) strcpy(Thdr_p->tbuf.t_prefix, Gen.g_prefix);
   7324 			free(Gen.g_prefix);
   7325 			Gen.g_prefix = NULL;
   7326 		} else {
   7327 			Thdr_p->tbuf.t_prefix[0] = '\0';
   7328 		}
   7329 		(void) sprintf(Thdr_p->tbuf.t_cksum, "%07o",
   7330 		    (int)cksum(TARTYP, 0, NULL));
   7331 		break;
   7332 	case TAR:
   7333 		Thdr_p = (union tblock *)Buffr.b_in_p;
   7334 		(void) memset(Thdr_p, 0, TARSZ);
   7335 		(void) strncpy(Thdr_p->tbuf.t_name, G_p->g_nam_p,
   7336 		    G_p->g_namesz);
   7337 		(void) sprintf(Thdr_p->tbuf.t_mode, "%07o ", (int)mode);
   7338 		(void) sprintf(Thdr_p->tbuf.t_uid, "%07o ", (int)uid);
   7339 		(void) sprintf(Thdr_p->tbuf.t_gid, "%07o ", (int)gid);
   7340 		(void) sprintf(Thdr_p->tbuf.t_size, "%011llo ",
   7341 		    (offset_t)len);
   7342 		(void) sprintf(Thdr_p->tbuf.t_mtime, "%011o ",
   7343 		    (int)G_p->g_mtime);
   7344 		if (T_lname[0] != '\0') {
   7345 			Thdr_p->tbuf.t_typeflag = '1';
   7346 		} else {
   7347 			Thdr_p->tbuf.t_typeflag = '\0';
   7348 		}
   7349 		(void) strncpy(Thdr_p->tbuf.t_linkname, T_lname,
   7350 		    strlen(T_lname));
   7351 		break;
   7352 	default:
   7353 		msg(EXT, "Impossible header type.");
   7354 	} /* Hdr_type */
   7355 
   7356 	Buffr.b_in_p += cnt;
   7357 	Buffr.b_cnt += cnt;
   7358 	pad = ((cnt + Pad_val) & ~Pad_val) - cnt;
   7359 	if (pad != 0) {
   7360 		FLUSH(pad);
   7361 		(void) memset(Buffr.b_in_p, 0, pad);
   7362 		Buffr.b_in_p += pad;
   7363 		Buffr.b_cnt += pad;
   7364 	}
   7365 }
   7366 
   7367 /*
   7368  * write_trail: Create the appropriate trailer for the selected header type
   7369  * and bwrite the trailer.  Pad the buffer with nulls out to the next Bufsize
   7370  * boundary, and force a write.  If the write completes, or if the trailer is
   7371  * completely written (but not all of the padding nulls (as can happen on end
   7372  * of medium)) return.  Otherwise, the trailer was not completely written out,
   7373  * so re-pad the buffer with nulls and try again.
   7374  */
   7375 
   7376 static void
   7377 write_trail(void)
   7378 {
   7379 	int cnt, need;
   7380 
   7381 	switch (Hdr_type) {
   7382 	case BIN:
   7383 		Gen.g_magic = CMN_BIN;
   7384 		break;
   7385 	case CHR:
   7386 		Gen.g_magic = CMN_BIN;
   7387 		break;
   7388 	case ASC:
   7389 		Gen.g_magic = CMN_ASC;
   7390 		break;
   7391 	case CRC:
   7392 		Gen.g_magic = CMN_CRC;
   7393 		break;
   7394 	}
   7395 
   7396 	switch (Hdr_type) {
   7397 	case BIN:
   7398 	case CHR:
   7399 	case ASC:
   7400 	case CRC:
   7401 		Gen.g_mode = Gen.g_uid = Gen.g_gid = 0;
   7402 		Gen.g_nlink = 1;
   7403 		Gen.g_mtime = Gen.g_ino = Gen.g_dev = 0;
   7404 		Gen.g_rdev = Gen.g_cksum = 0;
   7405 		Gen.g_filesz = (off_t)0;
   7406 		Gen.g_namesz = strlen("TRAILER!!!") + 1;
   7407 		(void) strcpy(Gen.g_nam_p, "TRAILER!!!");
   7408 		G_p = &Gen;
   7409 		write_hdr(ARCHIVE_NORMAL, (off_t)0);
   7410 		break;
   7411 	case TAR:
   7412 	/*FALLTHROUGH*/
   7413 	case USTAR: /* TAR and USTAR */
   7414 		for (cnt = 0; cnt < 3; cnt++) {
   7415 			FLUSH(TARSZ);
   7416 			(void) memset(Buffr.b_in_p, 0, TARSZ);
   7417 			Buffr.b_in_p += TARSZ;
   7418 			Buffr.b_cnt += TARSZ;
   7419 		}
   7420 		break;
   7421 	default:
   7422 		msg(EXT, "Impossible header type.");
   7423 	}
   7424 	need = Bufsize - (Buffr.b_cnt % Bufsize);
   7425 	if (need == Bufsize)
   7426 		need = 0;
   7427 
   7428 	while (Buffr.b_cnt > 0) {
   7429 		while (need > 0) {
   7430 			cnt = (need < TARSZ) ? need : TARSZ;
   7431 			need -= cnt;
   7432 			FLUSH(cnt);
   7433 			(void) memset(Buffr.b_in_p, 0, cnt);
   7434 			Buffr.b_in_p += cnt;
   7435 			Buffr.b_cnt += cnt;
   7436 		}
   7437 		bflush();
   7438 	}
   7439 }
   7440 
   7441 /*
   7442  * if archives in USTAR format, check if typeflag == '5' for directories
   7443  */
   7444 static int
   7445 ustar_dir(void)
   7446 {
   7447 	if (Hdr_type == USTAR || Hdr_type == TAR) {
   7448 		if (Thdr_p->tbuf.t_typeflag == '5')
   7449 			return (1);
   7450 	}
   7451 	return (0);
   7452 }
   7453 
   7454 /*
   7455  * if archives in USTAR format, check if typeflag == '3' || '4' || '6'
   7456  * for character, block, fifo special files
   7457  */
   7458 static int
   7459 ustar_spec(void)
   7460 {
   7461 	int typeflag;
   7462 
   7463 	if (Hdr_type == USTAR || Hdr_type == TAR) {
   7464 		typeflag = Thdr_p->tbuf.t_typeflag;
   7465 		if (typeflag == '3' || typeflag == '4' || typeflag == '6')
   7466 			return (1);
   7467 	}
   7468 	return (0);
   7469 }
   7470 
   7471 /*
   7472  * The return value is a pointer to a converted copy of the information in
   7473  * FromStat if the file is representable in -Hodc format, and NULL otherwise.
   7474  */
   7475 
   7476 static struct stat *
   7477 convert_to_old_stat(struct stat *FromStat, char *namep, char *attrp)
   7478 {
   7479 	static struct stat ToSt;
   7480 	cpioinfo_t TmpSt;
   7481 
   7482 	(void) memset(&TmpSt, 0, sizeof (cpioinfo_t));
   7483 	stat_to_svr32_stat(&TmpSt, FromStat);
   7484 	(void) memset(&ToSt, 0, sizeof (ToSt));
   7485 
   7486 	if (TmpSt.st_rdev == (o_dev_t)NODEV &&
   7487 	    (((TmpSt.st_mode & Ftype) == S_IFCHR) ||
   7488 	    ((TmpSt.st_mode & Ftype) == S_IFBLK))) {
   7489 		/*
   7490 		 * Encountered a problem representing the rdev information.
   7491 		 * Don't archive it.
   7492 		 */
   7493 
   7494 		msg(ERR, "Error -Hodc format can't support expanded"
   7495 		    "types on %s%s%s",
   7496 		    namep,
   7497 		    (attrp == NULL) ? "" : gettext(" Attribute"),
   7498 		    (attrp == NULL) ? "" : attrp);
   7499 		return (NULL);
   7500 	}
   7501 
   7502 	if (TmpSt.st_dev == (o_dev_t)NODEV) {
   7503 		/*
   7504 		 * Having trouble representing the device/inode pair.  We can't
   7505 		 * track links in this case; break them all into separate
   7506 		 * files.
   7507 		 */
   7508 
   7509 		TmpSt.st_ino = 0;
   7510 
   7511 		if (((TmpSt.st_mode & Ftype) != S_IFDIR) &&
   7512 		    TmpSt.st_nlink > 1)
   7513 			msg(POST,
   7514 			    "Warning: file %s%s%s has large "
   7515 			    "device number - linked "
   7516 			    "files will be restored as "
   7517 			    "separate files",
   7518 			    namep,
   7519 			    (attrp == NULL) ? "" : gettext(" Attribute"),
   7520 			    (attrp == NULL) ? "" : attrp);
   7521 
   7522 		/* ensure no links */
   7523 
   7524 		TmpSt.st_nlink = 1;
   7525 	}
   7526 
   7527 	/* Start converting values */
   7528 
   7529 	if (TmpSt.st_dev < 0) {
   7530 		ToSt.st_dev = 0;
   7531 	} else {
   7532 		ToSt.st_dev = (dev_t)TmpSt.st_dev;
   7533 	}
   7534 
   7535 	/* -actual- not truncated uid */
   7536 
   7537 	ToSt.st_uid = TmpSt.st_uid;
   7538 
   7539 	/* -actual- not truncated gid */
   7540 
   7541 	ToSt.st_gid = TmpSt.st_gid;
   7542 	ToSt.st_ino = (ino_t)TmpSt.st_ino;
   7543 	ToSt.st_mode = (mode_t)TmpSt.st_mode;
   7544 	ToSt.st_mtime = (ulong_t)TmpSt.st_modtime;
   7545 	ToSt.st_nlink = (nlink_t)TmpSt.st_nlink;
   7546 	ToSt.st_size = (off_t)TmpSt.st_size;
   7547 	ToSt.st_rdev = (dev_t)TmpSt.st_rdev;
   7548 
   7549 	return (&ToSt);
   7550 }
   7551 
   7552 /*
   7553  * In the beginning of each bar archive, there is a header which describes the
   7554  * current volume being created, followed by a header which describes the
   7555  * current file being created, followed by the file itself.  If there is
   7556  * more than one file to be created, a separate header will be created for
   7557  * each additional file.  This structure may be repeated if the bar archive
   7558  * contains multiple volumes.  If a file spans across volumes, its header
   7559  * will not be repeated in the next volume.
   7560  *               +------------------+
   7561  *               |    vol header    |
   7562  *               |------------------|
   7563  *               |   file header i  |     i = 0
   7564  *               |------------------|
   7565  *               |     <file i>     |
   7566  *               |------------------|
   7567  *               |  file header i+1 |
   7568  *               |------------------|
   7569  *               |    <file i+1>    |
   7570  *               |------------------|
   7571  *               |        .         |
   7572  *               |        .         |
   7573  *               |        .         |
   7574  *               +------------------+
   7575  */
   7576 
   7577 /*
   7578  * read in the header that describes the current volume of the bar archive
   7579  * to be extracted.
   7580  */
   7581 static void
   7582 read_bar_vol_hdr(void)
   7583 {
   7584 	union b_block *tmp_hdr;
   7585 
   7586 	tmp_hdr = (union b_block *)Buffr.b_out_p;
   7587 	if (tmp_hdr->dbuf.bar_magic[0] == BAR_VOLUME_MAGIC) {
   7588 
   7589 		if (bar_Vhdr == NULL) {
   7590 			bar_Vhdr = e_zalloc(E_EXIT, TBLOCK);
   7591 		}
   7592 		(void) memcpy(&(bar_Vhdr->dbuf), &(tmp_hdr->dbuf), TBLOCK);
   7593 	} else {
   7594 		(void) fprintf(stderr, gettext(
   7595 		    "bar error: cannot read volume header\n"));
   7596 		exit(1);
   7597 	}
   7598 
   7599 	(void) sscanf(bar_Vhdr->dbuf.mode, "%8lo", &Gen_bar_vol.g_mode);
   7600 	(void) sscanf(bar_Vhdr->dbuf.uid, "%8d", (int *)&Gen_bar_vol.g_uid);
   7601 	(void) sscanf(bar_Vhdr->dbuf.gid, "%8d", (int *)&Gen_bar_vol.g_gid);
   7602 	(void) sscanf(bar_Vhdr->dbuf.size, "%12llo",
   7603 	    (u_off_t *)&Gen_bar_vol.g_filesz);
   7604 	(void) sscanf(bar_Vhdr->dbuf.mtime, "%12lo", &Gen_bar_vol.g_mtime);
   7605 	(void) sscanf(bar_Vhdr->dbuf.chksum, "%8lo", &Gen_bar_vol.g_cksum);
   7606 
   7607 	/* set the compress flag */
   7608 	if (bar_Vhdr->dbuf.compressed == '1')
   7609 		Compressed = 1;
   7610 	else
   7611 		Compressed = 0;
   7612 
   7613 	Buffr.b_out_p += 512;
   7614 	Buffr.b_cnt -= 512;
   7615 
   7616 	/*
   7617 	 * not the first volume; exit
   7618 	 */
   7619 	if (strcmp(bar_Vhdr->dbuf.volume_num, "1") != 0) {
   7620 		(void) fprintf(stderr,
   7621 		    gettext("error: This is not volume 1.  "));
   7622 		(void) fprintf(stderr, gettext("This is volume %s.  "),
   7623 		    bar_Vhdr->dbuf.volume_num);
   7624 		(void) fprintf(stderr, gettext("Please insert volume 1.\n"));
   7625 		exit(1);
   7626 	}
   7627 
   7628 	read_bar_file_hdr();
   7629 }
   7630 
   7631 /*
   7632  * read in the header that describes the current file to be extracted
   7633  */
   7634 static void
   7635 read_bar_file_hdr(void)
   7636 {
   7637 	union b_block *tmp_hdr;
   7638 	char *start_of_name, *name_p;
   7639 	char *tmp;
   7640 
   7641 	if (*Buffr.b_out_p == '\0') {
   7642 		*Gen.g_nam_p = '\0';
   7643 		exit(0);
   7644 	}
   7645 
   7646 	tmp_hdr = (union b_block *)Buffr.b_out_p;
   7647 
   7648 	tmp = &tmp_hdr->dbuf.mode[1];
   7649 	(void) sscanf(tmp, "%8lo", &Gen.g_mode);
   7650 	(void) sscanf(tmp_hdr->dbuf.uid, "%8lo", &Gen.g_uid);
   7651 	(void) sscanf(tmp_hdr->dbuf.gid, "%8lo", &Gen.g_gid);
   7652 	(void) sscanf(tmp_hdr->dbuf.size, "%12llo",
   7653 	    (u_off_t *)&Gen.g_filesz);
   7654 	(void) sscanf(tmp_hdr->dbuf.mtime, "%12lo", &Gen.g_mtime);
   7655 	(void) sscanf(tmp_hdr->dbuf.chksum, "%8lo", &Gen.g_cksum);
   7656 	(void) sscanf(tmp_hdr->dbuf.rdev, "%8lo", &Gen.g_rdev);
   7657 
   7658 #define	to_new_major(x)	(int)((unsigned)((x) & OMAXMAJ) << NBITSMINOR)
   7659 #define	to_new_minor(x)	(int)((x) & OMAXMIN)
   7660 	Gen.g_rdev = to_new_major(Gen.g_rdev) | to_new_minor(Gen.g_rdev);
   7661 	bar_linkflag = tmp_hdr->dbuf.linkflag;
   7662 	start_of_name = &tmp_hdr->dbuf.start_of_name;
   7663 
   7664 
   7665 	name_p = Gen.g_nam_p;
   7666 	while (*name_p++ = *start_of_name++)
   7667 		;
   7668 	*name_p = '\0';
   7669 	if (bar_linkflag == LNKTYPE || bar_linkflag == SYMTYPE)
   7670 		(void) strcpy(bar_linkname, start_of_name);
   7671 
   7672 	Gen.g_namesz = strlen(Gen.g_nam_p) + 1;
   7673 	(void) strcpy(nambuf, Gen.g_nam_p);
   7674 }
   7675 
   7676 /*
   7677  * if the bar archive is compressed, set up a pipe and do the de-compression
   7678  * as the compressed file is read in.
   7679  */
   7680 static void
   7681 setup_uncompress(FILE **pipef)
   7682 {
   7683 	char *cmd_buf;
   7684 	size_t cmdlen;
   7685 
   7686 	cmd_buf = e_zalloc(E_EXIT, MAXPATHLEN * 2);
   7687 
   7688 	if (access(Gen.g_nam_p, W_OK) != 0) {
   7689 		cmdlen = snprintf(cmd_buf, MAXPATHLEN * 2,
   7690 		    "chmod +w '%s'; uncompress -c > '%s'; "
   7691 		    "chmod 0%o '%s'",
   7692 		    Gen.g_nam_p, Gen.g_nam_p, (int)G_p->g_mode, Gen.g_nam_p);
   7693 	} else {
   7694 		cmdlen = snprintf(cmd_buf, MAXPATHLEN * 2,
   7695 		    "uncompress -c > '%s'", Gen.g_nam_p);
   7696 	}
   7697 
   7698 	if (cmdlen >= MAXPATHLEN * 2 ||
   7699 	    (*pipef = popen(cmd_buf, "w")) == NULL) {
   7700 		(void) fprintf(stderr, gettext("error\n"));
   7701 		exit(1);
   7702 	}
   7703 
   7704 	if (close(Ofile) != 0)
   7705 		msg(EXTN, "close error");
   7706 	Ofile = fileno(*pipef);
   7707 
   7708 	free(cmd_buf);
   7709 }
   7710 
   7711 /*
   7712  * if the bar archive spans multiple volumes, read in the header that
   7713  * describes the next volume.
   7714  */
   7715 static void
   7716 skip_bar_volhdr(void)
   7717 {
   7718 	char *buff;
   7719 	union b_block *tmp_hdr;
   7720 
   7721 	buff = e_zalloc(E_EXIT, (uint_t)Bufsize);
   7722 
   7723 	if (g_read(Device, Archive, buff, Bufsize) < 0) {
   7724 		(void) fprintf(stderr, gettext(
   7725 		    "error in skip_bar_volhdr\n"));
   7726 	} else {
   7727 
   7728 		tmp_hdr = (union b_block *)buff;
   7729 		if (tmp_hdr->dbuf.bar_magic[0] == BAR_VOLUME_MAGIC) {
   7730 
   7731 			if (bar_Vhdr == NULL) {
   7732 				bar_Vhdr = e_zalloc(E_EXIT, TBLOCK);
   7733 			}
   7734 			(void) memcpy(&(bar_Vhdr->dbuf),
   7735 			    &(tmp_hdr->dbuf), TBLOCK);
   7736 		} else {
   7737 			(void) fprintf(stderr,
   7738 			    gettext("cpio error: cannot read bar volume "
   7739 			    "header\n"));
   7740 			exit(1);
   7741 		}
   7742 
   7743 		(void) sscanf(bar_Vhdr->dbuf.mode, "%8lo",
   7744 		    &Gen_bar_vol.g_mode);
   7745 		(void) sscanf(bar_Vhdr->dbuf.uid, "%8lo",
   7746 		    &Gen_bar_vol.g_uid);
   7747 		(void) sscanf(bar_Vhdr->dbuf.gid, "%8lo",
   7748 		    &Gen_bar_vol.g_gid);
   7749 		(void) sscanf(bar_Vhdr->dbuf.size, "%12llo",
   7750 		    (u_off_t *)&Gen_bar_vol.g_filesz);
   7751 		(void) sscanf(bar_Vhdr->dbuf.mtime, "%12lo",
   7752 		    &Gen_bar_vol.g_mtime);
   7753 		(void) sscanf(bar_Vhdr->dbuf.chksum, "%8lo",
   7754 		    &Gen_bar_vol.g_cksum);
   7755 		if (bar_Vhdr->dbuf.compressed == '1')
   7756 			Compressed = 1;
   7757 		else
   7758 			Compressed = 0;
   7759 	}
   7760 
   7761 	/*
   7762 	 * Now put the rest of the bytes read in into the data buffer.
   7763 	 */
   7764 	(void) memcpy(Buffr.b_in_p, &buff[512], (Bufsize - 512));
   7765 	Buffr.b_in_p += (Bufsize - 512);
   7766 	Buffr.b_cnt += (long)(Bufsize - 512);
   7767 
   7768 	free(buff);
   7769 }
   7770 
   7771 /*
   7772  * check the linkflag which indicates the type of the file to be extracted,
   7773  * invoke the corresponding routine to extract the file.
   7774  */
   7775 static void
   7776 bar_file_in(void)
   7777 {
   7778 	/*
   7779 	 * the file is a directory
   7780 	 */
   7781 	if (Adir) {
   7782 		if (ckname(1) != F_SKIP && creat_spec(G_p->g_dirfd) > 0) {
   7783 			VERBOSE((Args & (OCv | OCV)), G_p->g_nam_p);
   7784 		}
   7785 		return;
   7786 	}
   7787 
   7788 	switch (bar_linkflag) {
   7789 	case REGTYPE:
   7790 		/* regular file */
   7791 		if ((ckname(1) == F_SKIP) ||
   7792 		    (Ofile = openout(G_p->g_dirfd)) < 0) {
   7793 			data_in(P_SKIP);
   7794 		} else {
   7795 			data_in(P_PROC);
   7796 		}
   7797 		break;
   7798 	case LNKTYPE:
   7799 		/* hard link */
   7800 		if (ckname(1) == F_SKIP) {
   7801 			break;
   7802 		}
   7803 		(void) creat_lnk(G_p->g_dirfd, bar_linkname, G_p->g_nam_p);
   7804 		break;
   7805 	case SYMTYPE:
   7806 		/* symbolic link */
   7807 		if ((ckname(1) == F_SKIP) ||
   7808 		    (Ofile = openout(G_p->g_dirfd)) < 0) {
   7809 			data_in(P_SKIP);
   7810 		} else {
   7811 			data_in(P_PROC);
   7812 		}
   7813 		break;
   7814 	case CHRTYPE:
   7815 		/* character device or FIFO */
   7816 		if (ckname(1) != F_SKIP && creat_spec(G_p->g_dirfd) > 0) {
   7817 			VERBOSE((Args & (OCv | OCV)), G_p->g_nam_p);
   7818 		}
   7819 		break;
   7820 	default:
   7821 		(void) fprintf(stderr, gettext("error: unknown file type\n"));
   7822 		break;
   7823 	}
   7824 }
   7825 
   7826 
   7827 /*
   7828  * This originally came from libgenIO/g_init.c
   7829  * XXX	And it is very broken.
   7830  */
   7831 
   7832 /* #include <sys/statvfs.h> */
   7833 #include <ftw.h>
   7834 /* #include <libgenIO.h> */
   7835 #define	G_TM_TAPE	1	/* Tapemaster controller    */
   7836 #define	G_XY_DISK	3	/* xy disks		*/
   7837 #define	G_SD_DISK	7	/* scsi sd disk		*/
   7838 #define	G_XT_TAPE	8	/* xt tapes		*/
   7839 #define	G_SF_FLOPPY	9	/* sf floppy		*/
   7840 #define	G_XD_DISK	10	/* xd disks		*/
   7841 #define	G_ST_TAPE	11	/* scsi tape		*/
   7842 #define	G_NS		12	/* noswap pseudo-dev	*/
   7843 #define	G_RAM		13	/* ram pseudo-dev	*/
   7844 #define	G_FT		14	/* tftp			*/
   7845 #define	G_HD		15	/* 386 network disk	*/
   7846 #define	G_FD		16	/* 386 AT disk		*/
   7847 #define	G_FILE		28	/* file, not a device	*/
   7848 #define	G_NO_DEV	29	/* device does not require special treatment */
   7849 #define	G_DEV_MAX	30	/* last valid device type */
   7850 
   7851 /*
   7852  * g_init: Determine the device being accessed, set the buffer size,
   7853  * and perform any device specific initialization. Since at this point
   7854  * Sun has no system call to read the configuration, the major numbers
   7855  * are assumed to be static and types are figured out as such. However,
   7856  * as a rough estimate, the buffer size for all types is set to 512
   7857  * as a default.
   7858  */
   7859 
   7860 static int
   7861 g_init(int *devtype, int *fdes)
   7862 {
   7863 	int bufsize;
   7864 	struct stat st_buf;
   7865 	struct statvfs stfs_buf;
   7866 
   7867 	*devtype = G_NO_DEV;
   7868 	bufsize = -1;
   7869 	if (fstat(*fdes, &st_buf) == -1)
   7870 		return (-1);
   7871 	if (!S_ISCHR(st_buf.st_mode) && !S_ISBLK(st_buf.st_mode)) {
   7872 		if (S_ISFIFO(st_buf.st_mode)) {
   7873 			bufsize = 512;
   7874 		} else {
   7875 			/* find block size for this file system */
   7876 			*devtype = G_FILE;
   7877 			if (fstatvfs(*fdes, &stfs_buf) < 0) {
   7878 					bufsize = -1;
   7879 					errno = ENODEV;
   7880 			} else
   7881 				bufsize = stfs_buf.f_bsize;
   7882 		}
   7883 
   7884 		return (bufsize);
   7885 
   7886 	/*
   7887 	 * We'll have to add a remote attribute to stat but this
   7888 	 * should work for now.
   7889 	 */
   7890 	} else if (st_buf.st_dev & 0x8000)	/* if remote  rdev */
   7891 		return (512);
   7892 
   7893 	bufsize = 512;
   7894 
   7895 	if (Hdr_type == BAR) {
   7896 		if (is_tape(*fdes)) {
   7897 			bufsize = BAR_TAPE_SIZE;
   7898 			(void) fprintf(stderr, "Archiving to tape");
   7899 			(void) fprintf(stderr, " blocking factor 126\n");
   7900 		} else if (is_floppy(*fdes)) {
   7901 			bufsize = BAR_FLOPPY_SIZE;
   7902 			(void) fprintf(stderr, "Archiving to floppy");
   7903 			(void) fprintf(stderr, " blocking factor 18\n");
   7904 		}
   7905 	}
   7906 
   7907 	return (bufsize);
   7908 }
   7909 
   7910 /*
   7911  * This originally came from libgenIO/g_read.c
   7912  */
   7913 
   7914 /*
   7915  * g_read: Read nbytes of data from fdes (of type devtype) and place
   7916  * data in location pointed to by buf.  In case of end of medium,
   7917  * translate (where necessary) device specific EOM indications into
   7918  * the generic EOM indication of rv = -1, errno = ENOSPC.
   7919  */
   7920 
   7921 static int
   7922 g_read(int devtype, int fdes, char *buf, unsigned nbytes)
   7923 {
   7924 	int rv;
   7925 
   7926 	if (devtype < 0 || devtype >= G_DEV_MAX) {
   7927 		errno = ENODEV;
   7928 		return (-1);
   7929 	}
   7930 
   7931 	rv = read(fdes, buf, nbytes);
   7932 
   7933 	/* st devices return 0 when no space left */
   7934 	if ((rv == 0 && errno == 0 && Hdr_type != BAR) ||
   7935 	    (rv == -1 && errno == EIO)) {
   7936 		errno = 0;
   7937 		rv = 0;
   7938 	}
   7939 
   7940 	return (rv);
   7941 }
   7942 
   7943 /*
   7944  * This originally came from libgenIO/g_write.c
   7945  */
   7946 
   7947 /*
   7948  * g_write: Write nbytes of data to fdes (of type devtype) from
   7949  * the location pointed to by buf.  In case of end of medium,
   7950  * translate (where necessary) device specific EOM indications into
   7951  * the generic EOM indication of rv = -1, errno = ENOSPC.
   7952  */
   7953 
   7954 static int
   7955 g_write(int devtype, int fdes, char *buf, unsigned nbytes)
   7956 {
   7957 	int rv;
   7958 
   7959 	if (devtype < 0 || devtype >= G_DEV_MAX) {
   7960 		errno = ENODEV;
   7961 		return (-1);
   7962 	}
   7963 
   7964 	rv = write(fdes, buf, nbytes);
   7965 
   7966 	/* st devices return 0 when no more space left */
   7967 	if ((rv == 0 && errno == 0) || (rv == -1 && errno == EIO)) {
   7968 		errno = ENOSPC;
   7969 		rv = -1;
   7970 	}
   7971 
   7972 	return (rv);
   7973 }
   7974 
   7975 /*
   7976  * Test for tape
   7977  */
   7978 
   7979 static int
   7980 is_tape(int fd)
   7981 {
   7982 	struct mtget stuff;
   7983 
   7984 	/*
   7985 	 * try to do a generic tape ioctl, just to see if
   7986 	 * the thing is in fact a tape drive(er).
   7987 	 */
   7988 	if (ioctl(fd, MTIOCGET, &stuff) != -1) {
   7989 		/* the ioctl succeeded, must have been a tape */
   7990 		return (1);
   7991 	}
   7992 	return (0);
   7993 }
   7994 
   7995 /*
   7996  * Test for floppy
   7997  */
   7998 
   7999 static int
   8000 is_floppy(int fd)
   8001 {
   8002 	struct fd_char stuff;
   8003 
   8004 	/*
   8005 	 * try to get the floppy drive characteristics, just to see if
   8006 	 * the thing is in fact a floppy drive(er).
   8007 	 */
   8008 	if (ioctl(fd, FDIOGCHAR, &stuff) != -1) {
   8009 		/* the ioctl succeeded, must have been a floppy */
   8010 		return (1);
   8011 	}
   8012 
   8013 	return (0);
   8014 }
   8015 
   8016 /*
   8017  * New functions for ACLs and other security attributes
   8018  */
   8019 
   8020 /*
   8021  * The function appends the new security attribute info to the end of
   8022  * existing secinfo.
   8023  */
   8024 static int
   8025 append_secattr(
   8026 	char		**secinfo,	/* existing security info */
   8027 	int		*secinfo_len,	/* length of existing security info */
   8028 	acl_t		*aclp) 	/* new attribute data pointer */
   8029 {
   8030 	char	*new_secinfo;
   8031 	char	*attrtext;
   8032 	size_t	newattrsize;
   8033 	int	oldsize;
   8034 
   8035 	/* no need to add */
   8036 	if (aclp == NULL) {
   8037 		return (0);
   8038 	}
   8039 
   8040 	switch (acl_type(aclp)) {
   8041 	case ACLENT_T:
   8042 	case ACE_T:
   8043 		attrtext = acl_totext(aclp, ACL_APPEND_ID | ACL_COMPACT_FMT |
   8044 		    ACL_SID_FMT);
   8045 		if (attrtext == NULL) {
   8046 			(void) fprintf(stderr, "acltotext failed\n");
   8047 			return (-1);
   8048 		}
   8049 		/* header: type + size = 8 */
   8050 		newattrsize = 8 + strlen(attrtext) + 1;
   8051 		attr = e_zalloc(E_NORMAL, newattrsize);
   8052 		if (attr == NULL) {
   8053 			(void) fprintf(stderr, "can't allocate memory\n");
   8054 			return (-1);
   8055 		}
   8056 		attr->attr_type = (acl_type(aclp) == ACLENT_T) ?
   8057 		    UFSD_ACL : ACE_ACL;
   8058 		/* acl entry count */
   8059 		(void) sprintf(attr->attr_len, "%06o", acl_cnt(aclp));
   8060 		(void) strcpy((char *)&attr->attr_info[0], attrtext);
   8061 		free(attrtext);
   8062 		break;
   8063 
   8064 		/* SunFed's case goes here */
   8065 
   8066 	default:
   8067 		(void) fprintf(stderr, "unrecognized attribute type\n");
   8068 		return (-1);
   8069 	}
   8070 
   8071 	/* old security info + new attr header(8) + new attr */
   8072 	oldsize = *secinfo_len;
   8073 	*secinfo_len += newattrsize;
   8074 	new_secinfo = e_zalloc(E_NORMAL, (uint_t)*secinfo_len);
   8075 	if (new_secinfo == NULL) {
   8076 		(void) fprintf(stderr, "can't allocate memory\n");
   8077 		*secinfo_len -= newattrsize;
   8078 		return (-1);
   8079 	}
   8080 
   8081 	(void) memcpy(new_secinfo, *secinfo, oldsize);
   8082 	(void) memcpy(new_secinfo + oldsize, attr, newattrsize);
   8083 
   8084 	free(*secinfo);
   8085 	*secinfo = new_secinfo;
   8086 	return (0);
   8087 }
   8088 
   8089 /*
   8090  * Append size amount of data from buf to the archive.
   8091  */
   8092 static void
   8093 write_ancillary(char *buf, size_t len, boolean_t padding)
   8094 {
   8095 	int	pad, cnt;
   8096 
   8097 	if (len == 0)
   8098 		return;
   8099 
   8100 	while (len > 0) {
   8101 		cnt = (unsigned)(len > CPIOBSZ) ? CPIOBSZ : len;
   8102 		FLUSH(cnt);
   8103 		errno = 0;
   8104 		(void) memcpy(Buffr.b_in_p, buf, (unsigned)cnt);
   8105 		Buffr.b_in_p += cnt;
   8106 		Buffr.b_cnt += cnt;
   8107 		len -= cnt;
   8108 		buf += cnt;
   8109 	}
   8110 	if (padding) {
   8111 		pad = (Pad_val + 1 - (cnt & Pad_val)) & Pad_val;
   8112 		if (pad != 0) {
   8113 			FLUSH(pad);
   8114 			(void) memset(Buffr.b_in_p, 0, pad);
   8115 			Buffr.b_in_p += pad;
   8116 			Buffr.b_cnt += pad;
   8117 		}
   8118 	}
   8119 }
   8120 
   8121 static int
   8122 remove_dir(char *path)
   8123 {
   8124 	DIR		*name;
   8125 	struct dirent	*direct;
   8126 	struct stat	sbuf;
   8127 	char		*path_copy;
   8128 
   8129 #define	MSG1	"remove_dir() failed to stat(\"%s\") "
   8130 #define	MSG2	"remove_dir() failed to remove_dir(\"%s\") "
   8131 #define	MSG3	"remove_dir() failed to unlink(\"%s\") "
   8132 
   8133 	/*
   8134 	 * Open the directory for reading.
   8135 	 */
   8136 	if ((name = opendir(path)) == NULL) {
   8137 		msg(ERRN, "remove_dir() failed to opendir(\"%s\") ", path);
   8138 		return (-1);
   8139 	}
   8140 
   8141 	if (chdir(path) == -1) {
   8142 		msg(ERRN, "remove_dir() failed to chdir(\"%s\") ", path);
   8143 		return (-1);
   8144 	}
   8145 
   8146 	/*
   8147 	 * Read every directory entry.
   8148 	 */
   8149 	while ((direct = readdir(name)) != NULL) {
   8150 		/*
   8151 		 * Ignore "." and ".." entries.
   8152 		 */
   8153 		if (strcmp(direct->d_name, ".") == 0 ||
   8154 		    strcmp(direct->d_name, "..") == 0)
   8155 			continue;
   8156 
   8157 			if (lstat(direct->d_name, &sbuf) == -1) {
   8158 				msg(ERRN, MSG1, direct->d_name);
   8159 				(void) closedir(name);
   8160 			return (-1);
   8161 		}
   8162 
   8163 		if (S_ISDIR(sbuf.st_mode)) {
   8164 			if (remove_dir(direct->d_name) == -1) {
   8165 				msg(ERRN, MSG2, direct->d_name);
   8166 				(void) closedir(name);
   8167 				return (-1);
   8168 			}
   8169 		} else {
   8170 			if (unlink(direct->d_name) == -1) {
   8171 				msg(ERRN, MSG3, direct->d_name);
   8172 				(void) closedir(name);
   8173 				return (-1);
   8174 			}
   8175 		}
   8176 
   8177 	}
   8178 
   8179 	/*
   8180 	 * Close the directory we just finished reading.
   8181 	 */
   8182 	(void) closedir(name);
   8183 
   8184 	/*
   8185 	 * Change directory to the parent directory...
   8186 	 */
   8187 	if (chdir("..") == -1) {
   8188 		msg(ERRN, "remove_dir() failed to chdir(\"..\") ");
   8189 		return (-1);
   8190 	}
   8191 
   8192 	/*
   8193 	 * ...and finally remove the directory; note we have to
   8194 	 * make a copy since basename is free to modify its input.
   8195 	 */
   8196 	path_copy = e_strdup(E_NORMAL, path);
   8197 	if (path_copy == NULL) {
   8198 		msg(ERRN, "cannot strdup() the directory pathname ");
   8199 		return (-1);
   8200 	}
   8201 
   8202 	if (rmdir(basename(path_copy)) == -1) {
   8203 		free(path_copy);
   8204 		msg(ERRN, "remove_dir() failed to rmdir(\"%s\") ", path);
   8205 		return (-1);
   8206 	}
   8207 
   8208 	free(path_copy);
   8209 	return (0);
   8210 
   8211 }
   8212 
   8213 static int
   8214 save_cwd(void)
   8215 {
   8216 	return (open(".", O_RDONLY));
   8217 }
   8218 
   8219 static void
   8220 rest_cwd(int cwd)
   8221 {
   8222 	(void) fchdir(cwd);
   8223 	(void) close(cwd);
   8224 }
   8225 
   8226 #if defined(O_XATTR)
   8227 static void
   8228 xattrs_out(int (*func)())
   8229 {
   8230 	int dirpfd;
   8231 	int filefd;
   8232 	int arc_rwsysattr = 0;
   8233 	int rw_sysattr = 0;
   8234 	int ext_attr = 0;
   8235 	DIR *dirp;
   8236 	struct dirent *dp;
   8237 	int slen;
   8238 	int plen;
   8239 	char *namep, *savenamep;
   8240 	char *apathp;
   8241 	char *attrparent = Gen.g_attrparent_p;
   8242 	char *filename;
   8243 
   8244 	if (attrparent == NULL) {
   8245 		filename = Gen.g_nam_p;
   8246 	} else {
   8247 		filename = Gen.g_attrnam_p;
   8248 	}
   8249 
   8250 	/*
   8251 	 * If the underlying file system supports it, then
   8252 	 * archive the extended attributes if -@ was specified,
   8253 	 * and the extended system attributes if -/ was
   8254 	 * specified.
   8255 	 */
   8256 	if (verify_attr_support(filename, (attrparent == NULL), ARC_CREATE,
   8257 	    &ext_attr) != ATTR_OK) {
   8258 		return;
   8259 	}
   8260 
   8261 #if defined(_PC_SATTR_ENABLED)
   8262 	if (SysAtflag) {
   8263 		int		filefd;
   8264 		nvlist_t 	*slist = NULL;
   8265 
   8266 		/*
   8267 		 * Determine if there are non-transient system
   8268 		 * attributes.
   8269 		 */
   8270 		errno = 0;
   8271 		if ((filefd = open(filename, O_RDONLY)) == -1) {
   8272 			if (attrparent == NULL) {
   8273 				msg(EXTN,
   8274 				    "unable to open %s%s%sfile %s",
   8275 				    (attrparent == NULL) ? "" :
   8276 				    gettext("attribute "),
   8277 				    (attrparent == NULL) ? "" : attrparent,
   8278 				    (attrparent == NULL) ? "" : gettext(" of "),
   8279 				    (attrparent == NULL) ? G_p->g_nam_p :
   8280 				    G_p->g_attrfnam_p);
   8281 			}
   8282 		}
   8283 		if (((slist = sysattr_list(myname, filefd,
   8284 		    filename)) != NULL) || (errno != 0)) {
   8285 			arc_rwsysattr = 1;
   8286 		}
   8287 		if (slist != NULL) {
   8288 			(void) nvlist_free(slist);
   8289 			slist = NULL;
   8290 		}
   8291 		(void) close(filefd);
   8292 	}
   8293 
   8294 	/*
   8295 	 * If we aren't archiving extended system attributes, and we are
   8296 	 * processing an attribute, or if we are archiving extended system
   8297 	 * attributes, and there are are no extended attributes, then there's
   8298 	 * no need to open up the attribute directory of the file unless the
   8299 	 * extended system attributes are not transient (i.e, the system
   8300 	 * attributes are not the default values).
   8301 	 */
   8302 	if ((arc_rwsysattr == 0) && ((attrparent != NULL) ||
   8303 	    (SysAtflag && !ext_attr))) {
   8304 		return;
   8305 	}
   8306 
   8307 #endif	/* _PC_SATTR_ENABLED */
   8308 
   8309 	/*
   8310 	 * If aclp still exists then free it since it is was set when base
   8311 	 * file was extracted.
   8312 	 */
   8313 	if (aclp != NULL) {
   8314 		acl_free(aclp);
   8315 		aclp = NULL;
   8316 		acl_is_set = 0;
   8317 	}
   8318 
   8319 	Gen.g_dirfd = attropen(filename, ".", O_RDONLY);
   8320 	if (Gen.g_dirfd == -1) {
   8321 		msg(ERRN, "Cannot open attribute directory of file \"%s%s%s\"",
   8322 		    (attrparent == NULL) ? "" : gettext("attribute "),
   8323 		    (attrparent == NULL) ? "" : attrparent,
   8324 		    (attrparent == NULL) ? "" : gettext(" of "), filename);
   8325 		return;
   8326 
   8327 	}
   8328 
   8329 	if (attrparent == NULL) {
   8330 		savenamep = G_p->g_nam_p;
   8331 	} else {
   8332 		savenamep = G_p->g_attrfnam_p;
   8333 	}
   8334 
   8335 	if ((dirpfd = dup(Gen.g_dirfd)) == -1)  {
   8336 		msg(ERRN, "Cannot dup(2) attribute directory descriptor");
   8337 		return;
   8338 	}
   8339 
   8340 	if ((dirp = fdopendir(dirpfd)) == NULL) {
   8341 		msg(ERRN, "Cannot fdopendir(2) directory file descriptor");
   8342 		return;
   8343 	}
   8344 
   8345 	if (attrparent == NULL) {
   8346 		Gen.g_baseparent_fd = save_cwd();
   8347 	}
   8348 
   8349 	while ((dp = readdir(dirp)) != NULL) {
   8350 		if (strcmp(dp->d_name, "..") == 0) {
   8351 			continue;
   8352 		}
   8353 		if (verify_attr(dp->d_name, attrparent,
   8354 		    arc_rwsysattr, &rw_sysattr) != ATTR_OK) {
   8355 			continue;
   8356 		}
   8357 
   8358 		if (strcmp(dp->d_name, ".") == 0) {
   8359 			Hiddendir = 1;
   8360 		} else {
   8361 			Hiddendir = 0;
   8362 		}
   8363 
   8364 		Gen.g_rw_sysattr = rw_sysattr;
   8365 		Gen.g_attrnam_p = dp->d_name;
   8366 
   8367 		if (STAT(Gen.g_dirfd, Gen.g_nam_p, &SrcSt) == -1) {
   8368 			msg(ERRN,
   8369 			    "Could not fstatat(2) attribute \"%s\" of"
   8370 			    " file \"%s\"", dp->d_name, (attrparent == NULL) ?
   8371 			    savenamep : Gen.g_attrfnam_p);
   8372 			continue;
   8373 		}
   8374