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