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