xref: /illumos-gate/usr/src/cmd/tar/tar.c (revision f8c3982ab1838a24e4b671d13329f52bbbebc2a7)
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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
27 /*	  All Rights Reserved  	*/
28 
29 /*	Copyright (c) 1987, 1988 Microsoft Corporation	*/
30 /*	  All Rights Reserved	*/
31 
32 /*
33  * Portions of this source code were derived from Berkeley 4.3 BSD
34  * under license from the Regents of the University of California.
35  */
36 
37 #pragma ident	"%Z%%M%	%I%	%E% SMI"
38 
39 #include <unistd.h>
40 #include <sys/types.h>
41 #include <sys/param.h>
42 #include <sys/stat.h>
43 #include <sys/mkdev.h>
44 #include <sys/wait.h>
45 #include <dirent.h>
46 #include <errno.h>
47 #include <stdio.h>
48 #include <signal.h>
49 #include <ctype.h>
50 #include <locale.h>
51 #include <nl_types.h>
52 #include <langinfo.h>
53 #include <pwd.h>
54 #include <grp.h>
55 #include <fcntl.h>
56 #include <string.h>
57 #include <malloc.h>
58 #include <time.h>
59 #include <utime.h>
60 #include <stdlib.h>
61 #include <stdarg.h>
62 #include <widec.h>
63 #include <sys/mtio.h>
64 #include <sys/acl.h>
65 #include <strings.h>
66 #include <deflt.h>
67 #include <limits.h>
68 #include <iconv.h>
69 #include <assert.h>
70 #include <libgen.h>
71 #include <libintl.h>
72 #include <aclutils.h>
73 #include <libnvpair.h>
74 #include <archives.h>
75 
76 #if defined(__SunOS_5_6) || defined(__SunOS_5_7)
77 extern int defcntl();
78 #endif
79 #if defined(_PC_SATTR_ENABLED)
80 #include <attr.h>
81 #include <libcmdutils.h>
82 #endif
83 
84 /* Trusted Extensions */
85 #include <zone.h>
86 #include <tsol/label.h>
87 #include <sys/tsol/label_macro.h>
88 
89 #include "getresponse.h"
90 /*
91  * Source compatibility
92  */
93 
94 /*
95  * These constants come from archives.h and sys/fcntl.h
96  * and were introduced by the extended attributes project
97  * in Solaris 9.
98  */
99 #if !defined(O_XATTR)
100 #define	AT_SYMLINK_NOFOLLOW	0x1000
101 #define	AT_REMOVEDIR		0x1
102 #define	AT_FDCWD		0xffd19553
103 #define	_XATTR_HDRTYPE		'E'
104 static int attropen();
105 static int fstatat();
106 static int renameat();
107 static int unlinkat();
108 static int openat();
109 static int fchownat();
110 static int futimesat();
111 #endif
112 
113 /*
114  * Compiling with -D_XPG4_2 gets this but produces other problems, so
115  * instead of including sys/time.h and compiling with -D_XPG4_2, I'm
116  * explicitly doing the declaration here.
117  */
118 int utimes(const char *path, const struct timeval timeval_ptr[]);
119 
120 #ifndef MINSIZE
121 #define	MINSIZE 250
122 #endif
123 #define	DEF_FILE "/etc/default/tar"
124 
125 #define	min(a, b)  ((a) < (b) ? (a) : (b))
126 #define	max(a, b)  ((a) > (b) ? (a) : (b))
127 
128 /* -DDEBUG	ONLY for debugging */
129 #ifdef	DEBUG
130 #undef	DEBUG
131 #define	DEBUG(a, b, c)\
132 	(void) fprintf(stderr, "DEBUG - "), (void) fprintf(stderr, a, b, c)
133 #endif
134 
135 #define	TBLOCK	512	/* tape block size--should be universal */
136 
137 #ifdef	BSIZE
138 #define	SYS_BLOCK BSIZE	/* from sys/param.h:  secondary block size */
139 #else	/* BSIZE */
140 #define	SYS_BLOCK 512	/* default if no BSIZE in param.h */
141 #endif	/* BSIZE */
142 
143 #define	NBLOCK	20
144 #define	NAMSIZ	100
145 #define	PRESIZ	155
146 #define	MAXNAM	256
147 #define	MODEMASK 0777777	/* file creation mode mask */
148 #define	POSIXMODES 07777	/* mask for POSIX mode bits */
149 #define	MAXEXT	9	/* reasonable max # extents for a file */
150 #define	EXTMIN	50	/* min blks left on floppy to split a file */
151 
152 /* max value dblock.dbuf.efsize can store */
153 #define	TAR_EFSIZE_MAX	 0777777777
154 
155 /*
156  * Symbols which specify the values at which the use of the 'E' function
157  * modifier is required to properly store a file.
158  *
159  *     TAR_OFFSET_MAX    - the largest file size we can archive
160  *     OCTAL7CHAR        - the limit for ustar gid, uid, dev
161  */
162 
163 #ifdef XHDR_DEBUG
164 /* tiny values which force the creation of extended header entries */
165 #define	TAR_OFFSET_MAX 9
166 #define	OCTAL7CHAR 2
167 #else
168 /* normal values */
169 #define	TAR_OFFSET_MAX	077777777777ULL
170 #define	OCTAL7CHAR	07777777
171 #endif
172 
173 #define	TBLOCKS(bytes)	(((bytes) + TBLOCK - 1) / TBLOCK)
174 #define	K(tblocks)	((tblocks+1)/2)	/* tblocks to Kbytes for printing */
175 
176 #define	MAXLEV	(PATH_MAX / 2)
177 #define	LEV0	1
178 #define	SYMLINK_LEV0	0
179 
180 #define	TRUE	1
181 #define	FALSE	0
182 
183 #define	XATTR_FILE	1
184 #define	NORMAL_FILE	0
185 
186 #define	PUT_AS_LINK	1
187 #define	PUT_NOTAS_LINK	0
188 
189 #ifndef VIEW_READONLY
190 #define	VIEW_READONLY	"SUNWattr_ro"
191 #endif
192 
193 #ifndef VIEW_READWRITE
194 #define	VIEW_READWRITE	"SUNWattr_rw"
195 #endif
196 
197 #if _FILE_OFFSET_BITS == 64
198 #define	FMT_off_t "lld"
199 #define	FMT_off_t_o "llo"
200 #define	FMT_blkcnt_t "lld"
201 #else
202 #define	FMT_off_t "ld"
203 #define	FMT_off_t_o "lo"
204 #define	FMT_blkcnt_t "ld"
205 #endif
206 
207 /* ACL support */
208 
209 static
210 struct	sec_attr {
211 	char	attr_type;
212 	char	attr_len[7];
213 	char	attr_info[1];
214 } *attr;
215 
216 #if defined(O_XATTR)
217 typedef enum {
218 	ATTR_OK,
219 	ATTR_SKIP,
220 	ATTR_CHDIR_ERR,
221 	ATTR_OPEN_ERR,
222 	ATTR_XATTR_ERR,
223 	ATTR_SATTR_ERR
224 } attr_status_t;
225 #endif
226 
227 #if defined(O_XATTR)
228 typedef enum {
229 	ARC_CREATE,
230 	ARC_RESTORE
231 } arc_action_t;
232 #endif
233 
234 typedef struct attr_data {
235 	char	*attr_parent;
236 	char	*attr_path;
237 	int	attr_parentfd;
238 	int	attr_rw_sysattr;
239 } attr_data_t;
240 
241 /*
242  *
243  * Tar has been changed to support extended attributes.
244  *
245  * As part of this change tar now uses the new *at() syscalls
246  * such as openat, fchownat(), unlinkat()...
247  *
248  * This was done so that attributes can be handled with as few code changes
249  * as possible.
250  *
251  * What this means is that tar now opens the directory that a file or directory
252  * resides in and then performs *at() functions to manipulate the entry.
253  *
254  * For example a new file is now created like this:
255  *
256  * dfd = open(<some dir path>)
257  * fd = openat(dfd, <name>,....);
258  *
259  * or in the case of an extended attribute
260  *
261  * dfd = attropen(<pathname>, ".", ....)
262  *
263  * Once we have a directory file descriptor all of the *at() functions can
264  * be applied to it.
265  *
266  * unlinkat(dfd, <component name>,...)
267  * fchownat(dfd, <component name>,..)
268  *
269  * This works for both normal namespace files and extended attribute file
270  *
271  */
272 
273 /*
274  *
275  * Extended attribute Format
276  *
277  * Extended attributes are stored in two pieces.
278  * 1. An attribute header which has information about
279  *    what file the attribute is for and what the attribute
280  *    is named.
281  * 2. The attribute record itself.  Stored as a normal file type
282  *    of entry.
283  * Both the header and attribute record have special modes/typeflags
284  * associated with them.
285  *
286  * The names of the header in the archive look like:
287  * /dev/null/attr.hdr
288  *
289  * The name of the attribute looks like:
290  * /dev/null/attr
291  *
292  * This is done so that an archiver that doesn't understand these formats
293  * can just dispose of the attribute records.
294  *
295  * The format is composed of a fixed size header followed
296  * by a variable sized xattr_buf. If the attribute is a hard link
297  * to another attribute then another xattr_buf section is included
298  * for the link.
299  *
300  * The xattr_buf is used to define the necessary "pathing" steps
301  * to get to the extended attribute.  This is necessary to support
302  * a fully recursive attribute model where an attribute may itself
303  * have an attribute.
304  *
305  * The basic layout looks like this.
306  *
307  *     --------------------------------
308  *     |                              |
309  *     |         xattr_hdr            |
310  *     |                              |
311  *     --------------------------------
312  *     --------------------------------
313  *     |                              |
314  *     |        xattr_buf             |
315  *     |                              |
316  *     --------------------------------
317  *     --------------------------------
318  *     |                              |
319  *     |      (optional link info)    |
320  *     |                              |
321  *     --------------------------------
322  *     --------------------------------
323  *     |                              |
324  *     |      attribute itself        |
325  *     |      stored as normal tar    |
326  *     |      or cpio data with       |
327  *     |      special mode or         |
328  *     |      typeflag                |
329  *     |                              |
330  *     --------------------------------
331  *
332  */
333 
334 /*
335  * xattrhead is a pointer to the xattr_hdr
336  *
337  * xattrp is a pointer to the xattr_buf structure
338  * which contains the "pathing" steps to get to attributes
339  *
340  * xattr_linkp is a pointer to another xattr_buf structure that is
341  * only used when an attribute is actually linked to another attribute
342  *
343  */
344 
345 static struct xattr_hdr *xattrhead;
346 static struct xattr_buf *xattrp;
347 static struct xattr_buf *xattr_linkp;	/* pointer to link info, if any */
348 static char *xattrapath;		/* attribute name */
349 static char *xattr_linkaname;		/* attribute attribute is linked to */
350 static char Hiddendir;			/* are we processing hidden xattr dir */
351 static char xattrbadhead;
352 
353 /* Was statically allocated tbuf[NBLOCK] */
354 static
355 union hblock {
356 	char dummy[TBLOCK];
357 	struct header {
358 		char name[NAMSIZ];	/* If non-null prefix, path is	*/
359 					/* <prefix>/<name>;  otherwise	*/
360 					/* <name>			*/
361 		char mode[8];
362 		char uid[8];
363 		char gid[8];
364 		char size[12];		/* size of this extent if file split */
365 		char mtime[12];
366 		char chksum[8];
367 		char typeflag;
368 		char linkname[NAMSIZ];
369 		char magic[6];
370 		char version[2];
371 		char uname[32];
372 		char gname[32];
373 		char devmajor[8];
374 		char devminor[8];
375 		char prefix[PRESIZ];	/* Together with "name", the path of */
376 					/* the file:  <prefix>/<name>	*/
377 		char extno;		/* extent #, null if not split */
378 		char extotal;		/* total extents */
379 		char efsize[10];	/* size of entire file */
380 	} dbuf;
381 } dblock, *tbuf, xhdr_buf;
382 
383 static
384 struct xtar_hdr {
385 	uid_t		x_uid,		/* Uid of file */
386 			x_gid;		/* Gid of file */
387 	major_t		x_devmajor;	/* Device major node */
388 	minor_t		x_devminor;	/* Device minor node */
389 	off_t		x_filesz;	/* Length of file */
390 	char		*x_uname,	/* Pointer to name of user */
391 			*x_gname,	/* Pointer to gid of user */
392 			*x_linkpath,	/* Path for a hard/symbolic link */
393 			*x_path;	/* Path of file */
394 	timestruc_t	x_mtime;	/* Seconds and nanoseconds */
395 } Xtarhdr;
396 
397 static
398 struct gen_hdr {
399 	ulong_t		g_mode;		/* Mode of file */
400 	uid_t		g_uid,		/* Uid of file */
401 			g_gid;		/* Gid of file */
402 	off_t		g_filesz;	/* Length of file */
403 	time_t		g_mtime;	/* Modification time */
404 	uint_t		g_cksum;	/* Checksum of file */
405 	ulong_t		g_devmajor,	/* File system of file */
406 			g_devminor;	/* Major/minor of special files */
407 } Gen;
408 
409 static
410 struct linkbuf {
411 	ino_t	inum;
412 	dev_t	devnum;
413 	int	count;
414 	char	pathname[MAXNAM+1];	/* added 1 for last NULL */
415 	char 	attrname[MAXNAM+1];
416 	struct	linkbuf *nextp;
417 } *ihead;
418 
419 /* see comments before build_table() */
420 #define	TABLE_SIZE 512
421 struct	file_list	{
422 	char	*name;			/* Name of file to {in,ex}clude */
423 	struct	file_list	*next;	/* Linked list */
424 };
425 static	struct	file_list	*exclude_tbl[TABLE_SIZE],
426 				*include_tbl[TABLE_SIZE];
427 
428 static int	append_secattr(char **, int *, int, char *, char);
429 static void	write_ancillary(union hblock *, char *, int, char);
430 
431 static void add_file_to_table(struct file_list *table[], char *str);
432 static void assert_string(char *s, char *msg);
433 static int istape(int fd, int type);
434 static void backtape(void);
435 static void build_table(struct file_list *table[], char *file);
436 static int check_prefix(char **namep, char **dirp, char **compp);
437 static void closevol(void);
438 static void copy(void *dst, void *src);
439 static int convtoreg(off_t);
440 static void delete_target(int fd, char *comp, char *namep);
441 static void doDirTimes(char *name, timestruc_t modTime);
442 static void done(int n);
443 static void dorep(char *argv[]);
444 #ifdef	_iBCS2
445 static void dotable(char *argv[], int cnt);
446 static void doxtract(char *argv[], int cnt);
447 #else
448 static void dotable(char *argv[]);
449 static void doxtract(char *argv[]);
450 #endif
451 static void fatal(char *format, ...);
452 static void vperror(int exit_status, char *fmt, ...);
453 static void flushtape(void);
454 static void getdir(void);
455 static void *getmem(size_t);
456 static void longt(struct stat *st, char aclchar);
457 static void load_info_from_xtarhdr(u_longlong_t flag, struct xtar_hdr *xhdrp);
458 static int makeDir(char *name);
459 static void mterr(char *operation, int i, int exitcode);
460 static void newvol(void);
461 static void passtape(void);
462 static void putempty(blkcnt_t n);
463 static int putfile(char *longname, char *shortname, char *parent,
464     attr_data_t *attrinfo, int filetype, int lev, int symlink_lev);
465 static void readtape(char *buffer);
466 static void seekdisk(blkcnt_t blocks);
467 static void setPathTimes(int dirfd, char *path, timestruc_t modTime);
468 static void setbytes_to_skip(struct stat *st, int err);
469 static void splitfile(char *longname, int ifd, char *name,
470 	char *prefix, int filetype);
471 static void tomodes(struct stat *sp);
472 static void usage(void);
473 static int xblocks(int issysattr, off_t bytes, int ofile);
474 static int xsfile(int issysattr, int ofd);
475 static void resugname(int dirfd, char *name, int symflag);
476 static int bcheck(char *bstr);
477 static int checkdir(char *name);
478 static int checksum(union hblock *dblockp);
479 #ifdef	EUC
480 static int checksum_signed(union hblock *dblockp);
481 #endif	/* EUC */
482 static int checkupdate(char *arg);
483 static int checkw(char c, char *name);
484 static int cmp(char *b, char *s, int n);
485 static int defset(char *arch);
486 static int endtape(void);
487 static int is_in_table(struct file_list *table[], char *str);
488 static int notsame(void);
489 static int is_prefix(char *s1, char *s2);
490 static int response(void);
491 static int build_dblock(const char *, const char *, const char,
492 	const int filetype, const struct stat *, const dev_t, const char *);
493 static unsigned int hash(char *str);
494 
495 #ifdef	_iBCS2
496 static void initarg(char *argv[], char *file);
497 static char *nextarg();
498 #endif
499 static blkcnt_t kcheck(char *kstr);
500 static off_t bsrch(char *s, int n, off_t l, off_t h);
501 static void onintr(int sig);
502 static void onquit(int sig);
503 static void onhup(int sig);
504 static uid_t getuidbyname(char *);
505 static gid_t getgidbyname(char *);
506 static char *getname(gid_t);
507 static char *getgroup(gid_t);
508 static int checkf(char *name, int mode, int howmuch);
509 static int writetbuf(char *buffer, int n);
510 static int wantit(char *argv[], char **namep, char **dirp, char **comp,
511     attr_data_t **attrinfo);
512 static void append_ext_attr(char *shortname, char **secinfo, int *len);
513 static int get_xdata(void);
514 static void gen_num(const char *keyword, const u_longlong_t number);
515 static void gen_date(const char *keyword, const timestruc_t time_value);
516 static void gen_string(const char *keyword, const char *value);
517 static void get_xtime(char *value, timestruc_t *xtime);
518 static int chk_path_build(char *name, char *longname, char *linkname,
519     char *prefix, char type, int filetype);
520 static int gen_utf8_names(const char *filename);
521 static int utf8_local(char *option, char **Xhdr_ptrptr, char *target,
522     const char *src, int max_val);
523 static int local_utf8(char **Xhdr_ptrptr, char *target, const char *src,
524     iconv_t iconv_cd, int xhdrflg, int max_val);
525 static int c_utf8(char *target, const char *source);
526 static int getstat(int dirfd, char *longname, char *shortname,
527     char *attrparent);
528 static void xattrs_put(char *, char *, char *, char *);
529 static void prepare_xattr(char **, char	*, char	*,
530     char, struct linkbuf *, int *);
531 static int put_link(char *name, char *longname, char *component,
532     char *longattrname, char *prefix, int filetype, char typeflag);
533 static int put_extra_attributes(char *longname, char *shortname,
534     char *longattrname, char *prefix, int filetype, char typeflag);
535 static int put_xattr_hdr(char *longname, char *shortname, char *longattrname,
536     char *prefix, int typeflag, int filetype, struct linkbuf *lp);
537 static int read_xattr_hdr(attr_data_t **attrinfo);
538 
539 /* Trusted Extensions */
540 #define	AUTO_ZONE	"/zone"
541 
542 static void extract_attr(char **file_ptr, struct sec_attr *);
543 static int check_ext_attr(char *filename);
544 static void rebuild_comp_path(char *str, char **namep);
545 static int rebuild_lk_comp_path(char *str, char **namep);
546 
547 static void get_parent(char *path, char *dir);
548 static char *get_component(char *path);
549 static int retry_open_attr(int pdirfd, int cwd, char *dirp, char *pattr,
550     char *name, int oflag, mode_t mode);
551 static char *skipslashes(char *string, char *start);
552 static void chop_endslashes(char *path);
553 
554 static	struct stat stbuf;
555 
556 static	char	*myname;
557 static	int	checkflag = 0;
558 #ifdef	_iBCS2
559 static	int	Fileflag;
560 char    *sysv3_env;
561 #endif
562 static	int	Xflag, Fflag, iflag, hflag, Bflag, Iflag;
563 static	int	rflag, xflag, vflag, tflag, mt, cflag, mflag, pflag;
564 static	int	uflag;
565 static	int	eflag, errflag, qflag;
566 static	int	oflag;
567 static	int	bflag, kflag, Aflag;
568 static 	int	Pflag;			/* POSIX conformant archive */
569 static	int	Eflag;			/* Allow files greater than 8GB */
570 static	int	atflag;			/* traverse extended attributes */
571 static	int	saflag;			/* traverse extended sys attributes */
572 static	int	Dflag;			/* Data change flag */
573 /* Trusted Extensions */
574 static	int	Tflag;			/* Trusted Extensions attr flags */
575 static	int	dir_flag;		/* for attribute extract */
576 static	int	mld_flag;		/* for attribute extract */
577 static	char	*orig_namep;		/* original namep - unadorned */
578 static	int	rpath_flag;		/* MLD real path is rebuilt */
579 static	char	real_path[MAXPATHLEN];	/* MLD real path */
580 static	int	lk_rpath_flag;		/* linked to real path is rebuilt */
581 static	char	lk_real_path[MAXPATHLEN]; /* linked real path */
582 static	bslabel_t	bs_label;	/* for attribute extract */
583 static	bslabel_t	admin_low;
584 static	bslabel_t	admin_high;
585 static	int	ignored_aprivs = 0;
586 static	int	ignored_fprivs = 0;
587 static	int	ignored_fattrs = 0;
588 
589 static	int	term, chksum, wflag,
590 		first = TRUE, defaults_used = FALSE, linkerrok;
591 static	blkcnt_t	recno;
592 static	int	freemem = 1;
593 static	int	nblock = NBLOCK;
594 static	int	Errflg = 0;
595 static	int	exitflag = 0;
596 
597 static	dev_t	mt_dev;		/* device containing output file */
598 static	ino_t	mt_ino;		/* inode number of output file */
599 static	int	mt_devtype;	/* dev type of archive, from stat structure */
600 
601 static	int update = 1;		/* for `open' call */
602 
603 static	off_t	low;
604 static	off_t	high;
605 
606 static	FILE	*tfile;
607 static	FILE	*vfile = stdout;
608 static	char	tname[] = "/tmp/tarXXXXXX";
609 static	char	archive[] = "archive0=";
610 static	char	*Xfile;
611 static	char	*usefile;
612 static	char	*Filefile;
613 
614 static	int	mulvol;		/* multi-volume option selected */
615 static	blkcnt_t	blocklim; /* number of blocks to accept per volume */
616 static	blkcnt_t	tapepos; /* current block number to be written */
617 static	int	NotTape;	/* true if tape is a disk */
618 static	int	dumping;	/* true if writing a tape or other archive */
619 static	int	extno;		/* number of extent:  starts at 1 */
620 static	int	extotal;	/* total extents in this file */
621 static	off_t	extsize;	/* size of current extent during extraction */
622 static	ushort_t	Oumask = 0;	/* old umask value */
623 static 	int is_posix;	/* true if archive we're reading is POSIX-conformant */
624 static	const	char	*magic_type = "ustar";
625 static	size_t	xrec_size = 8 * PATH_MAX;	/* extended rec initial size */
626 static	char	*xrec_ptr;
627 static	off_t	xrec_offset = 0;
628 static	int	Xhdrflag;
629 static	int	charset_type = 0;
630 
631 static	u_longlong_t	xhdr_flgs;	/* Bits set determine which items */
632 					/*   need to be in extended header. */
633 #define	_X_DEVMAJOR	0x1
634 #define	_X_DEVMINOR	0x2
635 #define	_X_GID		0x4
636 #define	_X_GNAME	0x8
637 #define	_X_LINKPATH	0x10
638 #define	_X_PATH		0x20
639 #define	_X_SIZE		0x40
640 #define	_X_UID		0x80
641 #define	_X_UNAME	0x100
642 #define	_X_ATIME	0x200
643 #define	_X_CTIME	0x400
644 #define	_X_MTIME	0x800
645 #define	_X_XHDR		0x1000	/* Bit flag that determines whether 'X' */
646 				/* typeflag was followed by 'A' or non 'A' */
647 				/* typeflag. */
648 #define	_X_LAST		0x40000000
649 
650 #define	PID_MAX_DIGITS		(10 * sizeof (pid_t) / 4)
651 #define	TIME_MAX_DIGITS		(10 * sizeof (time_t) / 4)
652 #define	LONG_MAX_DIGITS		(10 * sizeof (long) / 4)
653 #define	ULONGLONG_MAX_DIGITS	(10 * sizeof (u_longlong_t) / 4)
654 /*
655  * UTF_8 encoding requires more space than the current codeset equivalent.
656  * Currently a factor of 2-3 would suffice, but it is possible for a factor
657  * of 6 to be needed in the future, so for saftey, we use that here.
658  */
659 #define	UTF_8_FACTOR	6
660 
661 static	u_longlong_t	xhdr_count = 0;
662 static char		xhdr_dirname[PRESIZ + 1];
663 static char		pidchars[PID_MAX_DIGITS + 1];
664 static char		*tchar = "";		/* null linkpath */
665 
666 static	char	local_path[UTF_8_FACTOR * PATH_MAX + 1];
667 static	char	local_linkpath[UTF_8_FACTOR * PATH_MAX + 1];
668 static	char	local_gname[UTF_8_FACTOR * _POSIX_NAME_MAX + 1];
669 static	char	local_uname[UTF_8_FACTOR * _POSIX_NAME_MAX + 1];
670 
671 /*
672  * The following mechanism is provided to allow us to debug tar in complicated
673  * situations, like when it is part of a pipe.  The idea is that you compile
674  * with -DWAITAROUND defined, and then add the 'z' function modifier to the
675  * target tar invocation, eg. "tar czf tarfile file".  If stderr is available,
676  * it will tell you to which pid to attach the debugger; otherwise, use ps to
677  * find it.  Attach to the process from the debugger, and, *PRESTO*, you are
678  * there!
679  *
680  * Simply assign "waitaround = 0" once you attach to the process, and then
681  * proceed from there as usual.
682  */
683 
684 #ifdef WAITAROUND
685 int waitaround = 0;		/* wait for rendezvous with the debugger */
686 #endif
687 
688 
689 int
690 main(int argc, char *argv[])
691 {
692 	char		*cp;
693 	char		*tmpdirp;
694 	pid_t		thispid;
695 
696 #ifdef	_iBCS2
697 	int	tbl_cnt = 0;
698 	sysv3_env = getenv("SYSV3");
699 #endif
700 	(void) setlocale(LC_ALL, "");
701 #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
702 #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
703 #endif
704 	(void) textdomain(TEXT_DOMAIN);
705 	if (argc < 2)
706 		usage();
707 
708 	tfile = NULL;
709 	if ((myname = strdup(argv[0])) == NULL) {
710 		(void) fprintf(stderr, gettext(
711 		    "tar: cannot allocate program name\n"));
712 		exit(1);
713 	}
714 
715 	if (init_yes() < 0) {
716 		(void) fprintf(stderr, gettext(ERR_MSG_INIT_YES),
717 		    strerror(errno));
718 		exit(2);
719 	}
720 
721 	/*
722 	 *  For XPG4 compatibility, we must be able to accept the "--"
723 	 *  argument normally recognized by getopt; it is used to delimit
724 	 *  the end opt the options section, and so can only appear in
725 	 *  the position of the first argument.  We simply skip it.
726 	 */
727 
728 	if (strcmp(argv[1], "--") == 0) {
729 		argv++;
730 		argc--;
731 		if (argc < 3)
732 			usage();
733 	}
734 
735 	argv[argc] = NULL;
736 	argv++;
737 
738 	/*
739 	 * Set up default values.
740 	 * Search the operand string looking for the first digit or an 'f'.
741 	 * If you find a digit, use the 'archive#' entry in DEF_FILE.
742 	 * If 'f' is given, bypass looking in DEF_FILE altogether.
743 	 * If no digit or 'f' is given, still look in DEF_FILE but use '0'.
744 	 */
745 	if ((usefile = getenv("TAPE")) == (char *)NULL) {
746 		for (cp = *argv; *cp; ++cp)
747 			if (isdigit(*cp) || *cp == 'f')
748 				break;
749 		if (*cp != 'f') {
750 			archive[7] = (*cp)? *cp: '0';
751 			if (!(defaults_used = defset(archive))) {
752 				usefile = NULL;
753 				nblock = 1;
754 				blocklim = 0;
755 				NotTape = 0;
756 			}
757 		}
758 	}
759 
760 	for (cp = *argv++; *cp; cp++)
761 		switch (*cp) {
762 #ifdef WAITAROUND
763 		case 'z':
764 			/* rendezvous with the debugger */
765 			waitaround = 1;
766 			break;
767 #endif
768 		case 'f':
769 			assert_string(*argv, gettext(
770 			    "tar: tarfile must be specified with 'f' "
771 			    "function modifier\n"));
772 			usefile = *argv++;
773 			break;
774 		case 'F':
775 #ifdef	_iBCS2
776 			if (sysv3_env) {
777 				assert_string(*argv, gettext(
778 				    "tar: 'F' requires a file name\n"));
779 				Filefile = *argv++;
780 				Fileflag++;
781 			} else
782 #endif	/*  _iBCS2 */
783 				Fflag++;
784 			break;
785 		case 'c':
786 			cflag++;
787 			rflag++;
788 			update = 1;
789 			break;
790 #if defined(O_XATTR)
791 		case '@':
792 			atflag++;
793 			break;
794 #endif	/* O_XATTR */
795 #if defined(_PC_SATTR_ENABLED)
796 		case '/':
797 			saflag++;
798 			break;
799 #endif	/* _PC_SATTR_ENABLED */
800 		case 'u':
801 			uflag++;	/* moved code after signals caught */
802 			rflag++;
803 			update = 2;
804 			break;
805 		case 'r':
806 			rflag++;
807 			update = 2;
808 			break;
809 		case 'v':
810 			vflag++;
811 			break;
812 		case 'w':
813 			wflag++;
814 			break;
815 		case 'x':
816 			xflag++;
817 			break;
818 		case 'X':
819 			assert_string(*argv, gettext(
820 			    "tar: exclude file must be specified with 'X' "
821 			    "function modifier\n"));
822 			Xflag = 1;
823 			Xfile = *argv++;
824 			build_table(exclude_tbl, Xfile);
825 			break;
826 		case 't':
827 			tflag++;
828 			break;
829 		case 'm':
830 			mflag++;
831 			break;
832 		case 'p':
833 			pflag++;
834 			break;
835 		case 'D':
836 			Dflag++;
837 			break;
838 		case '-':
839 			/* ignore this silently */
840 			break;
841 		case '0':	/* numeric entries used only for defaults */
842 		case '1':
843 		case '2':
844 		case '3':
845 		case '4':
846 		case '5':
847 		case '6':
848 		case '7':
849 			break;
850 		case 'b':
851 			assert_string(*argv, gettext(
852 			    "tar: blocking factor must be specified "
853 			    "with 'b' function modifier\n"));
854 			bflag++;
855 			nblock = bcheck(*argv++);
856 			break;
857 		case 'q':
858 			qflag++;
859 			break;
860 		case 'k':
861 			assert_string(*argv, gettext(
862 			    "tar: size value must be specified with 'k' "
863 			    "function modifier\n"));
864 			kflag++;
865 			blocklim = kcheck(*argv++);
866 			break;
867 		case 'n':		/* not a magtape (instead of 'k') */
868 			NotTape++;	/* assume non-magtape */
869 			break;
870 		case 'l':
871 			linkerrok++;
872 			break;
873 		case 'e':
874 #ifdef	_iBCS2
875 			/* If sysv3 IS set, don't be as verbose */
876 			if (!sysv3_env)
877 #endif	/* _iBCS2 */
878 				errflag++;
879 			eflag++;
880 			break;
881 		case 'o':
882 			oflag++;
883 			break;
884 		case 'h':
885 			hflag++;
886 			break;
887 		case 'i':
888 			iflag++;
889 			break;
890 		case 'B':
891 			Bflag++;
892 			break;
893 		case 'P':
894 			Pflag++;
895 			break;
896 		case 'E':
897 			Eflag++;
898 			Pflag++;	/* Only POSIX archive made */
899 			break;
900 		case 'T':
901 			Tflag++;	/* Handle Trusted Extensions attrs */
902 			pflag++;	/* also set flag for ACL */
903 			break;
904 		default:
905 			(void) fprintf(stderr, gettext(
906 			"tar: %c: unknown function modifier\n"), *cp);
907 			usage();
908 		}
909 
910 #ifdef	_iBCS2
911 	if (Xflag && Fileflag) {
912 		(void) fprintf(stderr, gettext(
913 		"tar: specify only one of X or F.\n"));
914 		usage();
915 	}
916 #endif	/*  _iBCS2 */
917 
918 	if (!rflag && !xflag && !tflag)
919 		usage();
920 	if ((rflag && xflag) || (xflag && tflag) || (rflag && tflag)) {
921 		(void) fprintf(stderr, gettext(
922 		"tar: specify only one of [ctxru].\n"));
923 		usage();
924 	}
925 	/* Trusted Extensions attribute handling */
926 	if (Tflag && ((getzoneid() != GLOBAL_ZONEID) ||
927 	    !is_system_labeled())) {
928 		(void) fprintf(stderr, gettext(
929 		"tar: the 'T' option is only available with "
930 		    "Trusted Extensions\nand must be run from "
931 		    "the global zone.\n"));
932 		usage();
933 	}
934 	if (cflag && *argv == NULL && Filefile == NULL)
935 		fatal(gettext("Missing filenames"));
936 	if (usefile == NULL)
937 		fatal(gettext("device argument required"));
938 
939 	/* alloc a buffer of the right size */
940 	if ((tbuf = (union hblock *)
941 	    calloc(sizeof (union hblock) * nblock, sizeof (char))) ==
942 	    (union hblock *)NULL) {
943 		(void) fprintf(stderr, gettext(
944 		"tar: cannot allocate physio buffer\n"));
945 		exit(1);
946 	}
947 
948 	if ((xrec_ptr = malloc(xrec_size)) == NULL) {
949 		(void) fprintf(stderr, gettext(
950 		    "tar: cannot allocate extended header buffer\n"));
951 		exit(1);
952 	}
953 
954 #ifdef WAITAROUND
955 	if (waitaround) {
956 		(void) fprintf(stderr, gettext("Rendezvous with tar on pid"
957 		    " %d\n"), getpid());
958 
959 		while (waitaround) {
960 			(void) sleep(10);
961 		}
962 	}
963 #endif
964 
965 	thispid = getpid();
966 	(void) sprintf(pidchars, "%ld", thispid);
967 	thispid = strlen(pidchars);
968 
969 	if ((tmpdirp = getenv("TMPDIR")) == (char *)NULL)
970 		(void) strcpy(xhdr_dirname, "/tmp");
971 	else {
972 		/*
973 		 * Make sure that dir is no longer than what can
974 		 * fit in the prefix part of the header.
975 		 */
976 		if (strlen(tmpdirp) > (size_t)(PRESIZ - thispid - 12)) {
977 			(void) strcpy(xhdr_dirname, "/tmp");
978 			if ((vflag > 0) && (Eflag > 0))
979 				(void) fprintf(stderr, gettext(
980 				    "Ignoring TMPDIR\n"));
981 		} else
982 			(void) strcpy(xhdr_dirname, tmpdirp);
983 	}
984 	(void) strcat(xhdr_dirname, "/PaxHeaders.");
985 	(void) strcat(xhdr_dirname, pidchars);
986 
987 	if (rflag) {
988 		if (cflag && tfile != NULL)
989 			usage();
990 		if (signal(SIGINT, SIG_IGN) != SIG_IGN)
991 			(void) signal(SIGINT, onintr);
992 		if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
993 			(void) signal(SIGHUP, onhup);
994 		if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
995 			(void) signal(SIGQUIT, onquit);
996 		if (uflag) {
997 			int tnum;
998 			if ((tnum = mkstemp(tname)) == -1)
999 				vperror(1, "%s", tname);
1000 			if ((tfile = fdopen(tnum, "w")) == NULL)
1001 				vperror(1, "%s", tname);
1002 		}
1003 		if (strcmp(usefile, "-") == 0) {
1004 			if (cflag == 0)
1005 				fatal(gettext(
1006 				"can only create standard output archives."));
1007 			vfile = stderr;
1008 			mt = dup(1);
1009 			++bflag;
1010 		} else {
1011 			if (cflag)
1012 				mt = open(usefile,
1013 				    O_RDWR|O_CREAT|O_TRUNC, 0666);
1014 			else
1015 				mt = open(usefile, O_RDWR);
1016 
1017 			if (mt < 0) {
1018 				if (cflag == 0 || (mt =  creat(usefile, 0666))
1019 				    < 0)
1020 				vperror(1, "%s", usefile);
1021 			}
1022 		}
1023 		/* Get inode and device number of output file */
1024 		(void) fstat(mt, &stbuf);
1025 		mt_ino = stbuf.st_ino;
1026 		mt_dev = stbuf.st_dev;
1027 		mt_devtype = stbuf.st_mode & S_IFMT;
1028 		NotTape = !istape(mt, mt_devtype);
1029 
1030 		if (rflag && !cflag && (mt_devtype == S_IFIFO))
1031 			fatal(gettext("cannot append to pipe or FIFO."));
1032 
1033 		if (Aflag && vflag)
1034 			(void) printf(
1035 			gettext("Suppressing absolute pathnames\n"));
1036 		dorep(argv);
1037 	} else if (xflag || tflag) {
1038 		/*
1039 		 * for each argument, check to see if there is a "-I file" pair.
1040 		 * if so, move the 3rd argument into "-I"'s place, build_table()
1041 		 * using "file"'s name and increment argc one (the second
1042 		 * increment appears in the for loop) which removes the two
1043 		 * args "-I" and "file" from the argument vector.
1044 		 */
1045 		for (argc = 0; argv[argc]; argc++) {
1046 			if (strcmp(argv[argc], "-I") == 0) {
1047 				if (!argv[argc+1]) {
1048 					(void) fprintf(stderr, gettext(
1049 					"tar: missing argument for -I flag\n"));
1050 					done(2);
1051 				} else {
1052 					Iflag = 1;
1053 					argv[argc] = argv[argc+2];
1054 					build_table(include_tbl, argv[++argc]);
1055 #ifdef	_iBCS2
1056 					if (Fileflag) {
1057 						(void) fprintf(stderr, gettext(
1058 						"tar: only one of I or F.\n"));
1059 						usage();
1060 					}
1061 #endif	/*  _iBCS2 */
1062 
1063 				}
1064 			}
1065 		}
1066 		if (strcmp(usefile, "-") == 0) {
1067 			mt = dup(0);
1068 			++bflag;
1069 			/* try to recover from short reads when reading stdin */
1070 			++Bflag;
1071 		} else if ((mt = open(usefile, 0)) < 0)
1072 			vperror(1, "%s", usefile);
1073 
1074 		if (xflag) {
1075 			if (Aflag && vflag)
1076 				(void) printf(gettext(
1077 				    "Suppressing absolute pathnames.\n"));
1078 
1079 #ifdef	_iBCS2
1080 			doxtract(argv, tbl_cnt);
1081 #else
1082 			doxtract(argv);
1083 #endif
1084 		} else if (tflag)
1085 
1086 #ifdef	_iBCS2
1087 			dotable(argv, tbl_cnt);
1088 #else
1089 			dotable(argv);
1090 #endif
1091 	}
1092 	else
1093 		usage();
1094 
1095 	done(Errflg);
1096 
1097 	/* Not reached:  keep compiler quiet */
1098 	return (1);
1099 }
1100 
1101 static void
1102 usage(void)
1103 {
1104 
1105 #ifdef	_iBCS2
1106 	if (sysv3_env) {
1107 		(void) fprintf(stderr, gettext(
1108 #if defined(O_XATTR)
1109 #if defined(_PC_SATTR_ENABLED)
1110 		"Usage: tar {c|r|t|u|x}[BDeEhilmnopPqTvw@/[0-7]][bfFk][X...] "
1111 #else
1112 		"Usage: tar {c|r|t|u|x}[BDeEhilmnopPqTvw@[0-7]][bfFk][X...] "
1113 #endif	/* _PC_SATTR_ENABLED */
1114 #else
1115 		"Usage: tar {c|r|t|u|x}[BDeEhilmnopPqTvw[0-7]][bfFk][X...] "
1116 #endif	/* O_XATTR */
1117 		"[blocksize] [tarfile] [filename] [size] [exclude-file...] "
1118 		"{file | -I include-file | -C directory file}...\n"));
1119 	} else
1120 #endif	/* _iBCS2 */
1121 	{
1122 		(void) fprintf(stderr, gettext(
1123 #if defined(O_XATTR)
1124 #if defined(_PC_SATTR_ENABLED)
1125 		"Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqTvw@/[0-7]][bfk][X...] "
1126 #else
1127 		"Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqTvw@[0-7]][bfk][X...] "
1128 #endif	/* _PC_SATTR_ENABLED */
1129 #else
1130 		"Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqTvw[0-7]][bfk][X...] "
1131 #endif	/* O_XATTR */
1132 		"[blocksize] [tarfile] [size] [exclude-file...] "
1133 		"{file | -I include-file | -C directory file}...\n"));
1134 	}
1135 	done(1);
1136 }
1137 
1138 /*
1139  * dorep - do "replacements"
1140  *
1141  *	Dorep is responsible for creating ('c'),  appending ('r')
1142  *	and updating ('u');
1143  */
1144 
1145 static void
1146 dorep(char *argv[])
1147 {
1148 	char *cp, *cp2, *p;
1149 	char wdir[PATH_MAX+2], tempdir[PATH_MAX+2], *parent;
1150 	char file[PATH_MAX*2], origdir[PATH_MAX+1];
1151 	FILE *fp = (FILE *)NULL;
1152 	FILE *ff = (FILE *)NULL;
1153 	int archtype;
1154 	int ret;
1155 
1156 
1157 	if (!cflag) {
1158 		xhdr_flgs = 0;
1159 		getdir();			/* read header for next file */
1160 		if (Xhdrflag > 0) {
1161 			if (!Eflag)
1162 				fatal(gettext("Archive contains extended"
1163 				    " header.  -E flag required.\n"));
1164 			ret = get_xdata();	/* Get extended header items */
1165 						/*   and regular header */
1166 		} else {
1167 			if (Eflag)
1168 				fatal(gettext("Archive contains no extended"
1169 				    " header.  -E flag not allowed.\n"));
1170 		}
1171 		while (!endtape()) {		/* changed from a do while */
1172 			setbytes_to_skip(&stbuf, ret);
1173 			passtape();		/* skip the file data */
1174 			if (term)
1175 				done(Errflg);	/* received signal to stop */
1176 			xhdr_flgs = 0;
1177 			getdir();
1178 			if (Xhdrflag > 0)
1179 				ret = get_xdata();
1180 		}
1181 		if (ret == 0) {
1182 			if ((dblock.dbuf.typeflag != 'A') &&
1183 			    (xhdr_flgs != 0)) {
1184 				load_info_from_xtarhdr(xhdr_flgs,
1185 				    &Xtarhdr);
1186 				xhdr_flgs |= _X_XHDR;
1187 			}
1188 		}
1189 		backtape();			/* was called by endtape */
1190 		if (tfile != NULL) {
1191 			char buf[200];
1192 
1193 			(void) sprintf(buf, "sort +0 -1 +1nr %s -o %s; awk '$1 "
1194 			    "!= prev {print; prev=$1}' %s >%sX;mv %sX %s",
1195 			    tname, tname, tname, tname, tname, tname);
1196 			(void) fflush(tfile);
1197 			(void) system(buf);
1198 			(void) freopen(tname, "r", tfile);
1199 			(void) fstat(fileno(tfile), &stbuf);
1200 			high = stbuf.st_size;
1201 		}
1202 	}
1203 
1204 	dumping = 1;
1205 	if (mulvol) {	/* SP-1 */
1206 		if (nblock && (blocklim%nblock) != 0)
1207 			fatal(gettext(
1208 			"Volume size not a multiple of block size."));
1209 		blocklim -= 2;			/* for trailer records */
1210 		if (vflag)
1211 			(void) fprintf(vfile, gettext("Volume ends at %"
1212 			    FMT_blkcnt_t "K, blocking factor = %dK\n"),
1213 			    K((blocklim - 1)), K(nblock));
1214 	}
1215 
1216 #ifdef	_iBCS2
1217 	if (Fileflag) {
1218 		if (Filefile != NULL) {
1219 			if ((ff = fopen(Filefile, "r")) == NULL)
1220 				vperror(0, "%s", Filefile);
1221 		} else {
1222 			(void) fprintf(stderr, gettext(
1223 			    "tar: F requires a file name.\n"));
1224 			usage();
1225 		}
1226 	}
1227 #endif	/*  _iBCS2 */
1228 
1229 	/*
1230 	 * Save the original directory before it gets
1231 	 * changed.
1232 	 */
1233 	if (getcwd(origdir, (PATH_MAX+1)) == NULL) {
1234 		vperror(0, gettext("A parent directory cannot be read"));
1235 		exit(1);
1236 	}
1237 
1238 	(void) strcpy(wdir, origdir);
1239 
1240 	while ((*argv || fp || ff) && !term) {
1241 		if (fp || (strcmp(*argv, "-I") == 0)) {
1242 #ifdef	_iBCS2
1243 			if (Fileflag) {
1244 				(void) fprintf(stderr, gettext(
1245 				"tar: only one of I or F.\n"));
1246 				usage();
1247 			}
1248 #endif	/*  _iBCS2 */
1249 			if (fp == NULL) {
1250 				if (*++argv == NULL)
1251 					fatal(gettext(
1252 					    "missing file name for -I flag."));
1253 				else if ((fp = fopen(*argv++, "r")) == NULL)
1254 					vperror(0, "%s", argv[-1]);
1255 				continue;
1256 			} else if ((fgets(file, PATH_MAX-1, fp)) == NULL) {
1257 				(void) fclose(fp);
1258 				fp = NULL;
1259 				continue;
1260 			} else {
1261 				cp = cp2 = file;
1262 				if ((p = strchr(cp2, '\n')))
1263 					*p = 0;
1264 			}
1265 		} else if ((strcmp(*argv, "-C") == 0) && argv[1]) {
1266 #ifdef	_iBCS2
1267 			if (Fileflag) {
1268 				(void) fprintf(stderr, gettext(
1269 				"tar: only one of F or C\n"));
1270 				usage();
1271 			}
1272 #endif	/*  _iBCS2 */
1273 
1274 			if (chdir(*++argv) < 0)
1275 				vperror(0, gettext(
1276 				    "can't change directories to %s"), *argv);
1277 			else
1278 				(void) getcwd(wdir, (sizeof (wdir)));
1279 			argv++;
1280 			continue;
1281 #ifdef	_iBCS2
1282 		} else if (Fileflag && (ff != NULL)) {
1283 			if ((fgets(file, PATH_MAX-1, ff)) == NULL) {
1284 				(void) fclose(ff);
1285 				ff = NULL;
1286 				continue;
1287 			} else {
1288 				cp = cp2 = file;
1289 				if (p = strchr(cp2, '\n'))
1290 					*p = 0;
1291 			}
1292 #endif	/*  _iBCS2 */
1293 		} else
1294 			cp = cp2 = strcpy(file, *argv++);
1295 
1296 		/*
1297 		 * point cp2 to the last '/' in file, but not
1298 		 * to a trailing '/'
1299 		 */
1300 		for (; *cp; cp++) {
1301 			if (*cp == '/') {
1302 				while (*(cp+1) == '/') {
1303 					++cp;
1304 				}
1305 				if (*(cp+1) != '\0') {
1306 					/* not trailing slash */
1307 					cp2 = cp;
1308 				}
1309 			}
1310 		}
1311 		if (cp2 != file) {
1312 			*cp2 = '\0';
1313 			if (chdir(file) < 0) {
1314 				vperror(0, gettext(
1315 				    "can't change directories to %s"), file);
1316 				continue;
1317 			}
1318 			*cp2 = '/';
1319 			cp2++;
1320 		}
1321 
1322 		parent = getcwd(tempdir, (sizeof (tempdir)));
1323 
1324 		archtype = putfile(file, cp2, parent, NULL, NORMAL_FILE,
1325 		    LEV0, SYMLINK_LEV0);
1326 
1327 #if defined(O_XATTR)
1328 		if (!exitflag) {
1329 			if ((atflag || saflag) &&
1330 			    (archtype == PUT_NOTAS_LINK)) {
1331 				xattrs_put(file, cp2, parent, NULL);
1332 			}
1333 		}
1334 #endif
1335 
1336 		if (chdir(origdir) < 0)
1337 			vperror(0, gettext("cannot change back?: %s"), origdir);
1338 
1339 		if (exitflag) {
1340 			/*
1341 			 * If e function modifier has been specified
1342 			 * write the files (that are listed before the
1343 			 * file causing the error) to tape.  exitflag is
1344 			 * used because only some of the error conditions
1345 			 * in putfile() recognize the e function modifier.
1346 			 */
1347 			break;
1348 		}
1349 	}
1350 
1351 	putempty((blkcnt_t)2);
1352 	flushtape();
1353 	closevol();	/* SP-1 */
1354 	if (linkerrok == 1)
1355 		for (; ihead != NULL; ihead = ihead->nextp) {
1356 			if (ihead->count == 0)
1357 				continue;
1358 			(void) fprintf(stderr, gettext(
1359 			"tar: missing links to %s\n"), ihead->pathname);
1360 			if (errflag)
1361 				done(1);
1362 			else
1363 				Errflg = 1;
1364 		}
1365 }
1366 
1367 
1368 /*
1369  * endtape - check for tape at end
1370  *
1371  *	endtape checks the entry in dblock.dbuf to see if its the
1372  *	special EOT entry.  Endtape is usually called after getdir().
1373  *
1374  *	endtape used to call backtape; it no longer does, he who
1375  *	wants it backed up must call backtape himself
1376  *	RETURNS:	0 if not EOT, tape position unaffected
1377  *			1 if	 EOT, tape position unaffected
1378  */
1379 
1380 static int
1381 endtape(void)
1382 {
1383 	if (dblock.dbuf.name[0] == '\0') {	/* null header = EOT */
1384 		return (1);
1385 	} else
1386 		return (0);
1387 }
1388 
1389 /*
1390  *	getdir - get directory entry from tar tape
1391  *
1392  *	getdir reads the next tarblock off the tape and cracks
1393  *	it as a directory. The checksum must match properly.
1394  *
1395  *	If tfile is non-null getdir writes the file name and mod date
1396  *	to tfile.
1397  */
1398 
1399 static void
1400 getdir(void)
1401 {
1402 	struct stat *sp;
1403 #ifdef EUC
1404 	static int warn_chksum_sign = 0;
1405 #endif /* EUC */
1406 
1407 top:
1408 	readtape((char *)&dblock);
1409 	if (dblock.dbuf.name[0] == '\0')
1410 		return;
1411 	sp = &stbuf;
1412 	(void) sscanf(dblock.dbuf.mode, "%8lo", &Gen.g_mode);
1413 	(void) sscanf(dblock.dbuf.uid, "%8lo", (ulong_t *)&Gen.g_uid);
1414 	(void) sscanf(dblock.dbuf.gid, "%8lo", (ulong_t *)&Gen.g_gid);
1415 	(void) sscanf(dblock.dbuf.size, "%12" FMT_off_t_o, &Gen.g_filesz);
1416 	(void) sscanf(dblock.dbuf.mtime, "%12lo", (ulong_t *)&Gen.g_mtime);
1417 	(void) sscanf(dblock.dbuf.chksum, "%8o", &Gen.g_cksum);
1418 	(void) sscanf(dblock.dbuf.devmajor, "%8lo", &Gen.g_devmajor);
1419 	(void) sscanf(dblock.dbuf.devminor, "%8lo", &Gen.g_devminor);
1420 
1421 	is_posix = (strcmp(dblock.dbuf.magic, magic_type) == 0);
1422 
1423 	sp->st_mode = Gen.g_mode;
1424 	if (is_posix && (sp->st_mode & S_IFMT) == 0)
1425 		switch (dblock.dbuf.typeflag) {
1426 		case '0': case 0: case _XATTR_HDRTYPE:
1427 			sp->st_mode |= S_IFREG;
1428 			break;
1429 		case '1':	/* hard link */
1430 			break;
1431 		case '2':
1432 			sp->st_mode |= S_IFLNK;
1433 			break;
1434 		case '3':
1435 			sp->st_mode |= S_IFCHR;
1436 			break;
1437 		case '4':
1438 			sp->st_mode |= S_IFBLK;
1439 			break;
1440 		case '5':
1441 			sp->st_mode |= S_IFDIR;
1442 			break;
1443 		case '6':
1444 			sp->st_mode |= S_IFIFO;
1445 			break;
1446 		default:
1447 			if (convtoreg(Gen.g_filesz))
1448 				sp->st_mode |= S_IFREG;
1449 			break;
1450 		}
1451 
1452 	if (dblock.dbuf.typeflag == 'X')
1453 		Xhdrflag = 1;	/* Currently processing extended header */
1454 	else
1455 		Xhdrflag = 0;
1456 
1457 	sp->st_uid = Gen.g_uid;
1458 	sp->st_gid = Gen.g_gid;
1459 	sp->st_size = Gen.g_filesz;
1460 	sp->st_mtime = Gen.g_mtime;
1461 	chksum = Gen.g_cksum;
1462 
1463 	if (dblock.dbuf.extno != '\0') {	/* split file? */
1464 		extno = dblock.dbuf.extno;
1465 		extsize = Gen.g_filesz;
1466 		extotal = dblock.dbuf.extotal;
1467 	} else {
1468 		extno = 0;	/* tell others file not split */
1469 		extsize = 0;
1470 		extotal = 0;
1471 	}
1472 
1473 #ifdef	EUC
1474 	if (chksum != checksum(&dblock)) {
1475 		if (chksum != checksum_signed(&dblock)) {
1476 			(void) fprintf(stderr, gettext(
1477 			    "tar: directory checksum error\n"));
1478 			if (iflag)
1479 				goto top;
1480 			done(2);
1481 		} else {
1482 			if (! warn_chksum_sign) {
1483 				warn_chksum_sign = 1;
1484 				(void) fprintf(stderr, gettext(
1485 			"tar: warning: tar file made with signed checksum\n"));
1486 			}
1487 		}
1488 	}
1489 #else
1490 	if (chksum != checksum(&dblock)) {
1491 		(void) fprintf(stderr, gettext(
1492 		"tar: directory checksum error\n"));
1493 		if (iflag)
1494 			goto top;
1495 		done(2);
1496 	}
1497 #endif	/* EUC */
1498 	if (tfile != NULL && Xhdrflag == 0) {
1499 		/*
1500 		 * If an extended header is present, then time is available
1501 		 * in nanoseconds in the extended header data, so set it.
1502 		 * Otherwise, give an invalid value so that checkupdate will
1503 		 * not test beyond seconds.
1504 		 */
1505 		if ((xhdr_flgs & _X_MTIME))
1506 			sp->st_mtim.tv_nsec = Xtarhdr.x_mtime.tv_nsec;
1507 		else
1508 			sp->st_mtim.tv_nsec = -1;
1509 
1510 		if (xhdr_flgs & _X_PATH)
1511 			(void) fprintf(tfile, "%s %10ld.%9.9ld\n",
1512 			    Xtarhdr.x_path, sp->st_mtim.tv_sec,
1513 			    sp->st_mtim.tv_nsec);
1514 		else
1515 			(void) fprintf(tfile, "%.*s %10ld.%9.9ld\n",
1516 			    NAMSIZ, dblock.dbuf.name, sp->st_mtim.tv_sec,
1517 			    sp->st_mtim.tv_nsec);
1518 	}
1519 
1520 #if defined(O_XATTR)
1521 	Hiddendir = 0;
1522 	if (xattrp && dblock.dbuf.typeflag == _XATTR_HDRTYPE) {
1523 		if (xattrbadhead) {
1524 			free(xattrhead);
1525 			xattrp = NULL;
1526 			xattr_linkp = NULL;
1527 			xattrhead = NULL;
1528 		} else {
1529 			char	*aname = basename(xattrapath);
1530 			size_t	xindex  = aname - xattrapath;
1531 
1532 			if (xattrapath[xindex] == '.' &&
1533 			    xattrapath[xindex + 1] == '\0' &&
1534 			    xattrp->h_typeflag == '5') {
1535 				Hiddendir = 1;
1536 				sp->st_mode =
1537 				    (S_IFDIR | (sp->st_mode & POSIXMODES));
1538 			}
1539 			dblock.dbuf.typeflag = xattrp->h_typeflag;
1540 		}
1541 	}
1542 #endif
1543 }
1544 
1545 
1546 /*
1547  *	passtape - skip over a file on the tape
1548  *
1549  *	passtape skips over the next data file on the tape.
1550  *	The tape directory entry must be in dblock.dbuf. This
1551  *	routine just eats the number of blocks computed from the
1552  *	directory size entry; the tape must be (logically) positioned
1553  *	right after thee directory info.
1554  */
1555 
1556 static void
1557 passtape(void)
1558 {
1559 	blkcnt_t blocks;
1560 	char buf[TBLOCK];
1561 
1562 	/*
1563 	 * Types link(1), sym-link(2), char special(3), blk special(4),
1564 	 *  directory(5), and FIFO(6) do not have data blocks associated
1565 	 *  with them so just skip reading the data block.
1566 	 */
1567 	if (dblock.dbuf.typeflag == '1' || dblock.dbuf.typeflag == '2' ||
1568 	    dblock.dbuf.typeflag == '3' || dblock.dbuf.typeflag == '4' ||
1569 	    dblock.dbuf.typeflag == '5' || dblock.dbuf.typeflag == '6')
1570 		return;
1571 	blocks = TBLOCKS(stbuf.st_size);
1572 
1573 	/* if operating on disk, seek instead of reading */
1574 	if (NotTape)
1575 		seekdisk(blocks);
1576 	else
1577 		while (blocks-- > 0)
1578 			readtape(buf);
1579 }
1580 
1581 #if defined(O_XATTR)
1582 static int
1583 is_sysattr(char *name)
1584 {
1585 	return ((strcmp(name, VIEW_READONLY) == 0) ||
1586 	    (strcmp(name, VIEW_READWRITE) == 0));
1587 }
1588 #endif
1589 
1590 #if defined(O_XATTR)
1591 /*
1592  * Verify the attribute, attrname, is an attribute we want to restore.
1593  * Never restore read-only system attribute files.  Only restore read-write
1594  * system attributes files when -/ was specified, and only traverse into
1595  * the 2nd level attribute directory containing only system attributes if
1596  * -@ was specified.  This keeps us from archiving
1597  *	<attribute name>/<read-write system attribute file>
1598  * when -/ was specified without -@.
1599  *
1600  * attrname	- attribute file name
1601  * attrparent	- attribute's parent name within the base file's attribute
1602  *		directory hierarchy
1603  */
1604 static attr_status_t
1605 verify_attr(char *attrname, char *attrparent, int arc_rwsysattr,
1606     int *rw_sysattr)
1607 {
1608 #if defined(_PC_SATTR_ENABLED)
1609 	int	attr_supported;
1610 
1611 	/* Never restore read-only system attribute files */
1612 	if ((attr_supported = sysattr_type(attrname)) == _RO_SATTR) {
1613 		*rw_sysattr = 0;
1614 		return (ATTR_SKIP);
1615 	} else {
1616 		*rw_sysattr = (attr_supported == _RW_SATTR);
1617 	}
1618 #else
1619 	/*
1620 	 * Only need to check if this attribute is an extended system
1621 	 * attribute.
1622 	 */
1623 	if (*rw_sysattr = is_sysattr(attrname)) {
1624 		return (ATTR_SKIP);
1625 	} else {
1626 		return (ATTR_OK);
1627 	}
1628 #endif	/* _PC_SATTR_ENABLED */
1629 
1630 	/*
1631 	 * If the extended system attribute file is specified with the
1632 	 * arc_rwsysattr flag, as being transient (default extended
1633 	 * attributes), then don't archive it.
1634 	 */
1635 	if (*rw_sysattr && !arc_rwsysattr) {
1636 		return (ATTR_SKIP);
1637 	}
1638 
1639 	/*
1640 	 * Only restore read-write system attribute files
1641 	 * when -/ was specified.  Only restore extended
1642 	 * attributes when -@ was specified.
1643 	 */
1644 	if (atflag) {
1645 		if (!saflag) {
1646 			/*
1647 			 * Only archive/restore the hidden directory "." if
1648 			 * we're processing the top level hidden attribute
1649 			 * directory.  We don't want to process the
1650 			 * hidden attribute directory of the attribute
1651 			 * directory that contains only extended system
1652 			 * attributes.
1653 			 */
1654 			if (*rw_sysattr || (Hiddendir &&
1655 			    (attrparent != NULL))) {
1656 				return (ATTR_SKIP);
1657 			}
1658 		}
1659 	} else if (saflag) {
1660 		/*
1661 		 * Only archive/restore read-write extended system attribute
1662 		 * files of the base file.
1663 		 */
1664 		if (!*rw_sysattr || (attrparent != NULL)) {
1665 			return (ATTR_SKIP);
1666 		}
1667 	} else {
1668 		return (ATTR_SKIP);
1669 	}
1670 
1671 	return (ATTR_OK);
1672 }
1673 #endif
1674 
1675 static int
1676 putfile(char *longname, char *shortname, char *parent, attr_data_t *attrinfo,
1677     int filetype, int lev, int symlink_lev)
1678 {
1679 	int infile = -1;	/* deliberately invalid */
1680 	blkcnt_t blocks;
1681 	char buf[PATH_MAX + 2];	/* Add trailing slash and null */
1682 	char *bigbuf;
1683 	int	maxread;
1684 	int	hint;		/* amount to write to get "in sync" */
1685 	char filetmp[PATH_MAX + 1];
1686 	char *cp;
1687 	char *name;
1688 	char *attrparent = NULL;
1689 	char *longattrname = NULL;
1690 	struct dirent *dp;
1691 	DIR *dirp;
1692 	int i;
1693 	long l;
1694 	int split;
1695 	int dirfd = -1;
1696 	int rc = PUT_NOTAS_LINK;
1697 	int archtype = 0;
1698 	int rw_sysattr = 0;
1699 	char newparent[PATH_MAX + MAXNAMLEN + 1];
1700 	char *prefix = "";
1701 	char *tmpbuf;
1702 	char goodbuf[PRESIZ + 2];
1703 	char junkbuf[MAXNAM+1];
1704 	char *lastslash;
1705 	int j;
1706 	struct stat sbuf;
1707 	int readlink_max;
1708 
1709 	(void) memset(goodbuf, '\0', sizeof (goodbuf));
1710 	(void) memset(junkbuf, '\0', sizeof (junkbuf));
1711 
1712 	xhdr_flgs = 0;
1713 
1714 	if (filetype == XATTR_FILE) {
1715 		attrparent = attrinfo->attr_parent;
1716 		longattrname = attrinfo->attr_path;
1717 		dirfd = attrinfo->attr_parentfd;
1718 		rw_sysattr = attrinfo->attr_rw_sysattr;
1719 	} else {
1720 		dirfd = open(".", O_RDONLY);
1721 	}
1722 
1723 	if (dirfd == -1) {
1724 		(void) fprintf(stderr, gettext(
1725 		    "tar: unable to open%sdirectory %s%s%s%s\n"),
1726 		    (filetype == XATTR_FILE) ? gettext(" attribute ") : " ",
1727 		    (attrparent == NULL) ? "" : gettext("of attribute "),
1728 		    (attrparent == NULL) ? "" : attrparent,
1729 		    (attrparent == NULL) ? "" : gettext(" of "),
1730 		    (filetype == XATTR_FILE) ? longname : parent);
1731 		goto out;
1732 	}
1733 
1734 	if (lev > MAXLEV) {
1735 		(void) fprintf(stderr,
1736 		    gettext("tar: directory nesting too deep, %s not dumped\n"),
1737 		    longname);
1738 		goto out;
1739 	}
1740 
1741 	if (getstat(dirfd, longname, shortname, attrparent))
1742 		goto out;
1743 
1744 	if (hflag) {
1745 		/*
1746 		 * Catch nesting where a file is a symlink to its directory.
1747 		 */
1748 		j = fstatat(dirfd, shortname, &sbuf, AT_SYMLINK_NOFOLLOW);
1749 		if (S_ISLNK(sbuf.st_mode)) {
1750 			if (symlink_lev++ >= MAXSYMLINKS) {
1751 				(void) fprintf(stderr, gettext(
1752 				    "tar: %s: Number of symbolic links "
1753 				    "encountered during path name traversal "
1754 				    "exceeds MAXSYMLINKS\n"), longname);
1755 				Errflg = 1;
1756 				goto out;
1757 			}
1758 		}
1759 	}
1760 
1761 	/*
1762 	 * Check if the input file is the same as the tar file we
1763 	 * are creating
1764 	 */
1765 	if ((mt_ino == stbuf.st_ino) && (mt_dev == stbuf.st_dev)) {
1766 		(void) fprintf(stderr, gettext(
1767 		    "tar: %s%s%s%s%s same as archive file\n"),
1768 		    rw_sysattr ? gettext("system ") : "",
1769 		    (longattrname == NULL) ? "" : gettext("attribute "),
1770 		    (longattrname == NULL) ? "" : longattrname,
1771 		    (longattrname == NULL) ? "" : gettext(" of "),
1772 		    longname);
1773 		Errflg = 1;
1774 		goto out;
1775 	}
1776 	/*
1777 	 * Check size limit - we can't archive files that
1778 	 * exceed TAR_OFFSET_MAX bytes because of header
1779 	 * limitations. Exclude file types that set
1780 	 * st_size to zero below because they take no
1781 	 * archive space to represent contents.
1782 	 */
1783 	if ((stbuf.st_size > (off_t)TAR_OFFSET_MAX) &&
1784 	    !S_ISDIR(stbuf.st_mode) &&
1785 	    !S_ISCHR(stbuf.st_mode) &&
1786 	    !S_ISBLK(stbuf.st_mode) &&
1787 	    (Eflag == 0)) {
1788 		(void) fprintf(stderr, gettext(
1789 		    "tar: %s%s%s%s%s too large to archive.  "
1790 		    "Use E function modifier.\n"),
1791 		    rw_sysattr ? gettext("system ") : "",
1792 		    (longattrname == NULL) ? "" : gettext("attribute "),
1793 		    (longattrname == NULL) ? "" : longattrname,
1794 		    (longattrname == NULL) ? "" : gettext(" of "),
1795 		    longname);
1796 		if (errflag)
1797 			exitflag = 1;
1798 		Errflg = 1;
1799 		goto out;
1800 	}
1801 
1802 	if (tfile != NULL && checkupdate(longname) == 0) {
1803 		goto out;
1804 	}
1805 	if (checkw('r', longname) == 0) {
1806 		goto out;
1807 	}
1808 
1809 	if (Fflag && checkf(shortname, stbuf.st_mode, Fflag) == 0)
1810 		goto out;
1811 
1812 	if (Xflag) {
1813 		if (is_in_table(exclude_tbl, longname)) {
1814 			if (vflag) {
1815 				(void) fprintf(vfile, gettext(
1816 				    "a %s excluded\n"), longname);
1817 			}
1818 			goto out;
1819 		}
1820 	}
1821 
1822 	/*
1823 	 * If the length of the fullname is greater than MAXNAM,
1824 	 * print out a message and return (unless extended headers are used,
1825 	 * in which case fullname is limited to PATH_MAX).
1826 	 */
1827 
1828 	if ((((split = (int)strlen(longname)) > MAXNAM) && (Eflag == 0)) ||
1829 	    (split > PATH_MAX)) {
1830 		(void) fprintf(stderr, gettext(
1831 		    "tar: %s: file name too long\n"), longname);
1832 		if (errflag)
1833 			exitflag = 1;
1834 		Errflg = 1;
1835 		goto out;
1836 	}
1837 
1838 	/*
1839 	 * We split the fullname into prefix and name components if any one
1840 	 * of three conditions holds:
1841 	 *	-- the length of the fullname exceeds NAMSIZ,
1842 	 *	-- the length of the fullname equals NAMSIZ, and the shortname
1843 	 *	   is less than NAMSIZ, (splitting in this case preserves
1844 	 *	   compatibility with 5.6 and 5.5.1 tar), or
1845 	 * 	-- the length of the fullname equals NAMSIZ, the file is a
1846 	 *	   directory and we are not in POSIX-conformant mode (where
1847 	 *	   trailing slashes are removed from directories).
1848 	 */
1849 	if ((split > NAMSIZ) ||
1850 	    (split == NAMSIZ && strlen(shortname) < NAMSIZ) ||
1851 	    (split == NAMSIZ && S_ISDIR(stbuf.st_mode) && !Pflag)) {
1852 		/*
1853 		 * Since path is limited to PRESIZ characters, look for the
1854 		 * last slash within PRESIZ + 1 characters only.
1855 		 */
1856 		(void) strncpy(&goodbuf[0], longname, min(split, PRESIZ + 1));
1857 		tmpbuf = goodbuf;
1858 		lastslash = strrchr(tmpbuf, '/');
1859 		if (lastslash == NULL) {
1860 			i = split;		/* Length of name */
1861 			j = 0;			/* Length of prefix */
1862 			goodbuf[0] = '\0';
1863 		} else {
1864 			*lastslash = '\0';	/* Terminate the prefix */
1865 			j = strlen(tmpbuf);
1866 			i = split - j - 1;
1867 		}
1868 		/*
1869 		 * If the filename is greater than NAMSIZ we can't
1870 		 * archive the file unless we are using extended headers.
1871 		 */
1872 		if ((i > NAMSIZ) || (i == NAMSIZ && S_ISDIR(stbuf.st_mode) &&
1873 		    !Pflag)) {
1874 			/* Determine which (filename or path) is too long. */
1875 			lastslash = strrchr(longname, '/');
1876 			if (lastslash != NULL)
1877 				i = strlen(lastslash + 1);
1878 			if (Eflag > 0) {
1879 				xhdr_flgs |= _X_PATH;
1880 				Xtarhdr.x_path = longname;
1881 				if (i <= NAMSIZ)
1882 					(void) strcpy(junkbuf, lastslash + 1);
1883 				else
1884 					(void) sprintf(junkbuf, "%llu",
1885 					    xhdr_count + 1);
1886 				if (split - i - 1 > PRESIZ)
1887 					(void) strcpy(goodbuf, xhdr_dirname);
1888 			} else {
1889 				if ((i > NAMSIZ) || (i == NAMSIZ &&
1890 				    S_ISDIR(stbuf.st_mode) && !Pflag))
1891 					(void) fprintf(stderr, gettext(
1892 					    "tar: %s: filename is greater than "
1893 					    "%d\n"), lastslash == NULL ?
1894 					    longname : lastslash + 1, NAMSIZ);
1895 				else
1896 					(void) fprintf(stderr, gettext(
1897 					    "tar: %s: prefix is greater than %d"
1898 					    "\n"), longname, PRESIZ);
1899 				if (errflag)
1900 					exitflag = 1;
1901 				Errflg = 1;
1902 				goto out;
1903 			}
1904 		} else
1905 			(void) strncpy(&junkbuf[0], longname + j + 1,
1906 			    strlen(longname + j + 1));
1907 		name = junkbuf;
1908 		prefix = goodbuf;
1909 	} else {
1910 		name = longname;
1911 	}
1912 	if (Aflag) {
1913 		if ((prefix != NULL) && (*prefix != '\0'))
1914 			while (*prefix == '/')
1915 				++prefix;
1916 		else
1917 			while (*name == '/')
1918 				++name;
1919 	}
1920 
1921 	switch (stbuf.st_mode & S_IFMT) {
1922 	case S_IFDIR:
1923 		stbuf.st_size = (off_t)0;
1924 		blocks = TBLOCKS(stbuf.st_size);
1925 
1926 		if (filetype != XATTR_FILE && Hiddendir == 0) {
1927 			i = 0;
1928 			cp = buf;
1929 			while ((*cp++ = longname[i++]))
1930 				;
1931 			*--cp = '/';
1932 			*++cp = 0;
1933 		}
1934 		if (!oflag) {
1935 			tomodes(&stbuf);
1936 			if (build_dblock(name, tchar, '5', filetype,
1937 			    &stbuf, stbuf.st_dev, prefix) != 0) {
1938 				goto out;
1939 			}
1940 			if (!Pflag) {
1941 				/*
1942 				 * Old archives require a slash at the end
1943 				 * of a directory name.
1944 				 *
1945 				 * XXX
1946 				 * If directory name is too long, will
1947 				 * slash overfill field?
1948 				 */
1949 				if (strlen(name) > (unsigned)NAMSIZ-1) {
1950 					(void) fprintf(stderr, gettext(
1951 					    "tar: %s: filename is greater "
1952 					    "than %d\n"), name, NAMSIZ);
1953 					if (errflag)
1954 						exitflag = 1;
1955 					Errflg = 1;
1956 					goto out;
1957 				} else {
1958 					if (strlen(name) == (NAMSIZ - 1)) {
1959 						(void) memcpy(dblock.dbuf.name,
1960 						    name, NAMSIZ);
1961 						dblock.dbuf.name[NAMSIZ-1]
1962 						    = '/';
1963 					} else
1964 						(void) sprintf(dblock.dbuf.name,
1965 						    "%s/", name);
1966 
1967 					/*
1968 					 * need to recalculate checksum
1969 					 * because the name changed.
1970 					 */
1971 					(void) sprintf(dblock.dbuf.chksum,
1972 					    "%07o", checksum(&dblock));
1973 				}
1974 			}
1975 
1976 			if (put_extra_attributes(longname, shortname,
1977 			    longattrname, prefix, filetype, '5') != 0)
1978 				goto out;
1979 
1980 #if defined(O_XATTR)
1981 			/*
1982 			 * Reset header typeflag when archiving directory, since
1983 			 * build_dblock changed it on us.
1984 			 */
1985 			if (filetype == XATTR_FILE) {
1986 				dblock.dbuf.typeflag = _XATTR_HDRTYPE;
1987 			} else {
1988 				dblock.dbuf.typeflag = '5';
1989 			}
1990 #else
1991 			dblock.dbuf.typeflag = '5';
1992 #endif
1993 
1994 			(void) sprintf(dblock.dbuf.chksum, "%07o",
1995 			    checksum(&dblock));
1996 
1997 			(void) writetbuf((char *)&dblock, 1);
1998 		}
1999 		if (vflag) {
2000 #ifdef DEBUG
2001 			if (NotTape)
2002 				DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
2003 				    0);
2004 #endif
2005 			if (filetype == XATTR_FILE && Hiddendir) {
2006 				(void) fprintf(vfile, "a %s attribute %s ",
2007 				    longname, longattrname);
2008 
2009 			} else {
2010 				(void) fprintf(vfile, "a %s/ ", longname);
2011 			}
2012 			if (NotTape)
2013 				(void) fprintf(vfile, "%" FMT_blkcnt_t "K\n",
2014 				    K(blocks));
2015 			else
2016 				(void) fprintf(vfile, gettext("%" FMT_blkcnt_t
2017 				    " tape blocks\n"), blocks);
2018 		}
2019 
2020 		/*
2021 		 * If hidden dir then break now since xattrs_put() will do
2022 		 * the iterating of the directory.
2023 		 *
2024 		 * At the moment, there can only be system attributes on
2025 		 * attributes.  There can be no attributes on attributes or
2026 		 * directories within the attributes hidden directory hierarchy.
2027 		 */
2028 		if (filetype == XATTR_FILE)
2029 			break;
2030 
2031 		if (*shortname != '/')
2032 			(void) sprintf(newparent, "%s/%s", parent, shortname);
2033 		else
2034 			(void) sprintf(newparent, "%s", shortname);
2035 
2036 		if (chdir(shortname) < 0) {
2037 			vperror(0, "%s", newparent);
2038 			goto out;
2039 		}
2040 
2041 		if ((dirp = opendir(".")) == NULL) {
2042 			vperror(0, gettext(
2043 			    "can't open directory %s"), longname);
2044 			if (chdir(parent) < 0)
2045 				vperror(0, gettext("cannot change back?: %s"),
2046 				    parent);
2047 			goto out;
2048 		}
2049 
2050 		while ((dp = readdir(dirp)) != NULL && !term) {
2051 			if ((strcmp(".", dp->d_name) == 0) ||
2052 			    (strcmp("..", dp->d_name) == 0))
2053 				continue;
2054 			(void) strcpy(cp, dp->d_name);
2055 			if (stat(dp->d_name, &sbuf) < 0 ||
2056 			    (sbuf.st_mode & S_IFMT) == S_IFDIR) {
2057 				l = telldir(dirp);
2058 				(void) closedir(dirp);
2059 			} else
2060 				l = -1;
2061 
2062 			archtype = putfile(buf, cp, newparent, NULL,
2063 			    NORMAL_FILE, lev + 1, symlink_lev);
2064 
2065 			if (!exitflag) {
2066 				if ((atflag || saflag) &&
2067 				    (archtype == PUT_NOTAS_LINK)) {
2068 					xattrs_put(buf, cp, newparent, NULL);
2069 				}
2070 			}
2071 			if (exitflag)
2072 				break;
2073 
2074 			/*
2075 			 * If the directory was not closed, then it does
2076 			 * not need to be reopened.
2077 			 */
2078 			if (l < 0)
2079 				continue;
2080 			if ((dirp = opendir(".")) == NULL) {
2081 				vperror(0, gettext(
2082 				    "can't open directory %s"), longname);
2083 				if (chdir(parent) < 0)
2084 					vperror(0,
2085 					    gettext("cannot change back?: %s"),
2086 					    parent);
2087 				goto out;
2088 			}
2089 			seekdir(dirp, l);
2090 
2091 		}
2092 		(void) closedir(dirp);
2093 
2094 		if (chdir(parent) < 0) {
2095 			vperror(0, gettext("cannot change back?: %s"), parent);
2096 		}
2097 
2098 		break;
2099 
2100 	case S_IFLNK:
2101 		readlink_max = NAMSIZ;
2102 		if (stbuf.st_size > NAMSIZ) {
2103 			if (Eflag > 0) {
2104 				xhdr_flgs |= _X_LINKPATH;
2105 				readlink_max = PATH_MAX;
2106 			} else {
2107 				(void) fprintf(stderr, gettext(
2108 				    "tar: %s: symbolic link too long\n"),
2109 				    longname);
2110 				if (errflag)
2111 					exitflag = 1;
2112 				Errflg = 1;
2113 				goto out;
2114 			}
2115 		}
2116 		/*
2117 		 * Sym-links need header size of zero since you
2118 		 * don't store any data for this type.
2119 		 */
2120 		stbuf.st_size = (off_t)0;
2121 		tomodes(&stbuf);
2122 		i = readlink(shortname, filetmp, readlink_max);
2123 		if (i < 0) {
2124 			vperror(0, gettext(
2125 			    "can't read symbolic link %s"), longname);
2126 			goto out;
2127 		} else {
2128 			filetmp[i] = 0;
2129 		}
2130 		if (vflag)
2131 			(void) fprintf(vfile, gettext(
2132 			    "a %s symbolic link to %s\n"),
2133 			    longname, filetmp);
2134 		if (xhdr_flgs & _X_LINKPATH) {
2135 			Xtarhdr.x_linkpath = filetmp;
2136 			if (build_dblock(name, tchar, '2', filetype, &stbuf,
2137 			    stbuf.st_dev, prefix) != 0)
2138 				goto out;
2139 		} else
2140 			if (build_dblock(name, filetmp, '2', filetype, &stbuf,
2141 			    stbuf.st_dev, prefix) != 0)
2142 				goto out;
2143 		(void) writetbuf((char *)&dblock, 1);
2144 		/*
2145 		 * No acls for symlinks: mode is always 777
2146 		 * dont call write ancillary
2147 		 */
2148 		rc = PUT_AS_LINK;
2149 		break;
2150 	case S_IFREG:
2151 		if ((infile = openat(dirfd, shortname, 0)) < 0) {
2152 			vperror(0, "unable to open %s%s%s%s", longname,
2153 			    rw_sysattr ? gettext(" system") : "",
2154 			    (filetype == XATTR_FILE) ?
2155 			    gettext(" attribute ") : "",
2156 			    (filetype == XATTR_FILE) ? (longattrname == NULL) ?
2157 			    shortname : longattrname : "");
2158 			goto out;
2159 		}
2160 
2161 		blocks = TBLOCKS(stbuf.st_size);
2162 
2163 		if (put_link(name, longname, shortname, longattrname,
2164 		    prefix, filetype, '1') == 0) {
2165 			(void) close(infile);
2166 			rc = PUT_AS_LINK;
2167 			goto out;
2168 		}
2169 
2170 		tomodes(&stbuf);
2171 
2172 		/* correctly handle end of volume */
2173 		while (mulvol && tapepos + blocks + 1 > blocklim) {
2174 			/* file won't fit */
2175 			if (eflag) {
2176 				if (blocks <= blocklim) {
2177 					newvol();
2178 					break;
2179 				}
2180 				(void) fprintf(stderr, gettext(
2181 				    "tar: Single file cannot fit on volume\n"));
2182 				done(3);
2183 			}
2184 			/* split if floppy has some room and file is large */
2185 			if (((blocklim - tapepos) >= EXTMIN) &&
2186 			    ((blocks + 1) >= blocklim/10)) {
2187 				splitfile(longname, infile,
2188 				    name, prefix, filetype);
2189 				(void) close(dirfd);
2190 				(void) close(infile);
2191 				goto out;
2192 			}
2193 			newvol();	/* not worth it--just get new volume */
2194 		}
2195 #ifdef DEBUG
2196 		DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,
2197 		    blocks);
2198 #endif
2199 		if (build_dblock(name, tchar, '0', filetype,
2200 		    &stbuf, stbuf.st_dev, prefix) != 0) {
2201 			goto out;
2202 		}
2203 		if (vflag) {
2204 #ifdef DEBUG
2205 			if (NotTape)
2206 				DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
2207 				    0);
2208 #endif
2209 			(void) fprintf(vfile, "a %s%s%s%s ", longname,
2210 			    rw_sysattr ? gettext(" system") : "",
2211 			    (filetype == XATTR_FILE) ? gettext(
2212 			    " attribute ") : "",
2213 			    (filetype == XATTR_FILE) ?
2214 			    longattrname : "");
2215 			if (NotTape)
2216 				(void) fprintf(vfile, "%" FMT_blkcnt_t "K\n",
2217 				    K(blocks));
2218 			else
2219 				(void) fprintf(vfile,
2220 				    gettext("%" FMT_blkcnt_t " tape blocks\n"),
2221 				    blocks);
2222 		}
2223 
2224 		if (put_extra_attributes(longname, shortname, longattrname,
2225 		    prefix, filetype, '0') != 0)
2226 			goto out;
2227 
2228 		/*
2229 		 * No need to reset typeflag for extended attribute here, since
2230 		 * put_extra_attributes already set it and we haven't called
2231 		 * build_dblock().
2232 		 */
2233 		(void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock));
2234 		hint = writetbuf((char *)&dblock, 1);
2235 		maxread = max(min(stbuf.st_blksize, stbuf.st_size),
2236 		    (nblock * TBLOCK));
2237 		if ((bigbuf = calloc((unsigned)maxread, sizeof (char))) == 0) {
2238 			maxread = TBLOCK;
2239 			bigbuf = buf;
2240 		}
2241 
2242 		while (((i = (int)
2243 		    read(infile, bigbuf, min((hint*TBLOCK), maxread))) > 0) &&
2244 		    blocks) {
2245 			blkcnt_t nblks;
2246 
2247 			nblks = ((i-1)/TBLOCK)+1;
2248 			if (nblks > blocks)
2249 				nblks = blocks;
2250 			hint = writetbuf(bigbuf, nblks);
2251 			blocks -= nblks;
2252 		}
2253 		(void) close(infile);
2254 		if (bigbuf != buf)
2255 			free(bigbuf);
2256 		if (i < 0)
2257 			vperror(0, gettext("Read error on %s"), longname);
2258 		else if (blocks != 0 || i != 0) {
2259 			(void) fprintf(stderr, gettext(
2260 			"tar: %s: file changed size\n"), longname);
2261 			if (errflag) {
2262 				exitflag = 1;
2263 				Errflg = 1;
2264 			} else if (!Dflag) {
2265 				Errflg = 1;
2266 			}
2267 		}
2268 		putempty(blocks);
2269 		break;
2270 	case S_IFIFO:
2271 		blocks = TBLOCKS(stbuf.st_size);
2272 		stbuf.st_size = (off_t)0;
2273 
2274 		if (put_link(name, longname, shortname, longattrname,
2275 		    prefix, filetype, '6') == 0) {
2276 			rc = PUT_AS_LINK;
2277 			goto out;
2278 		}
2279 		tomodes(&stbuf);
2280 
2281 		while (mulvol && tapepos + blocks + 1 > blocklim) {
2282 			if (eflag) {
2283 				if (blocks <= blocklim) {
2284 					newvol();
2285 					break;
2286 				}
2287 				(void) fprintf(stderr, gettext(
2288 				    "tar: Single file cannot fit on volume\n"));
2289 				done(3);
2290 			}
2291 
2292 			if (((blocklim - tapepos) >= EXTMIN) &&
2293 			    ((blocks + 1) >= blocklim/10)) {
2294 				splitfile(longname, infile, name,
2295 				    prefix, filetype);
2296 				(void) close(dirfd);
2297 				(void) close(infile);
2298 				goto out;
2299 			}
2300 			newvol();
2301 		}
2302 #ifdef DEBUG
2303 		DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,
2304 		    blocks);
2305 #endif
2306 		if (vflag) {
2307 #ifdef DEBUG
2308 			if (NotTape)
2309 				DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
2310 				    0);
2311 #endif
2312 			if (NotTape)
2313 				(void) fprintf(vfile, gettext("a %s %"
2314 				    FMT_blkcnt_t "K\n "), longname, K(blocks));
2315 			else
2316 				(void) fprintf(vfile, gettext(
2317 				    "a %s %" FMT_blkcnt_t " tape blocks\n"),
2318 				    longname, blocks);
2319 		}
2320 		if (build_dblock(name, tchar, '6', filetype,
2321 		    &stbuf, stbuf.st_dev, prefix) != 0)
2322 			goto out;
2323 
2324 		if (put_extra_attributes(longname, shortname, longattrname,
2325 		    prefix, filetype, '6') != 0)
2326 			goto out;
2327 
2328 		(void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock));
2329 		dblock.dbuf.typeflag = '6';
2330 
2331 		(void) writetbuf((char *)&dblock, 1);
2332 		break;
2333 	case S_IFCHR:
2334 		stbuf.st_size = (off_t)0;
2335 		blocks = TBLOCKS(stbuf.st_size);
2336 		if (put_link(name, longname, shortname, longattrname,
2337 		    prefix, filetype, '3') == 0) {
2338 			rc = PUT_AS_LINK;
2339 			goto out;
2340 		}
2341 		tomodes(&stbuf);
2342 
2343 		while (mulvol && tapepos + blocks + 1 > blocklim) {
2344 			if (eflag) {
2345 				if (blocks <= blocklim) {
2346 					newvol();
2347 					break;
2348 				}
2349 				(void) fprintf(stderr, gettext(
2350 				    "tar: Single file cannot fit on volume\n"));
2351 				done(3);
2352 			}
2353 
2354 			if (((blocklim - tapepos) >= EXTMIN) &&
2355 			    ((blocks + 1) >= blocklim/10)) {
2356 				splitfile(longname, infile, name,
2357 				    prefix, filetype);
2358 				(void) close(dirfd);
2359 				goto out;
2360 			}
2361 			newvol();
2362 		}
2363 #ifdef DEBUG
2364 		DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,
2365 		    blocks);
2366 #endif
2367 		if (vflag) {
2368 #ifdef DEBUG
2369 			if (NotTape)
2370 				DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
2371 				    0);
2372 #endif
2373 			if (NotTape)
2374 				(void) fprintf(vfile, gettext("a %s %"
2375 				    FMT_blkcnt_t "K\n"), longname, K(blocks));
2376 			else
2377 				(void) fprintf(vfile, gettext("a %s %"
2378 				    FMT_blkcnt_t " tape blocks\n"), longname,
2379 				    blocks);
2380 		}
2381 		if (build_dblock(name, tchar, '3',
2382 		    filetype, &stbuf, stbuf.st_rdev, prefix) != 0)
2383 			goto out;
2384 
2385 		if (put_extra_attributes(longname, shortname, longattrname,
2386 		    prefix, filetype, '3') != 0)
2387 			goto out;
2388 
2389 		(void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock));
2390 		dblock.dbuf.typeflag = '3';
2391 
2392 		(void) writetbuf((char *)&dblock, 1);
2393 		break;
2394 	case S_IFBLK:
2395 		stbuf.st_size = (off_t)0;
2396 		blocks = TBLOCKS(stbuf.st_size);
2397 		if (put_link(name, longname, shortname, longattrname,
2398 		    prefix, filetype, '4') == 0) {
2399 			rc = PUT_AS_LINK;
2400 			goto out;
2401 		}
2402 		tomodes(&stbuf);
2403 
2404 		while (mulvol && tapepos + blocks + 1 > blocklim) {
2405 			if (eflag) {
2406 				if (blocks <= blocklim) {
2407 					newvol();
2408 					break;
2409 				}
2410 				(void) fprintf(stderr, gettext(
2411 				    "tar: Single file cannot fit on volume\n"));
2412 				done(3);
2413 			}
2414 
2415 			if (((blocklim - tapepos) >= EXTMIN) &&
2416 			    ((blocks + 1) >= blocklim/10)) {
2417 				splitfile(longname, infile,
2418 				    name, prefix, filetype);
2419 				(void) close(dirfd);
2420 				goto out;
2421 			}
2422 			newvol();
2423 		}
2424 #ifdef DEBUG
2425 		DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,
2426 		    blocks);
2427 #endif
2428 		if (vflag) {
2429 #ifdef DEBUG
2430 			if (NotTape)
2431 				DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
2432 				    0);
2433 #endif
2434 			(void) fprintf(vfile, "a %s ", longname);
2435 			if (NotTape)
2436 				(void) fprintf(vfile, "%" FMT_blkcnt_t "K\n",
2437 				    K(blocks));
2438 			else
2439 				(void) fprintf(vfile, gettext("%"
2440 				    FMT_blkcnt_t " tape blocks\n"), blocks);
2441 		}
2442 		if (build_dblock(name, tchar, '4',
2443 		    filetype, &stbuf, stbuf.st_rdev, prefix) != 0)
2444 			goto out;
2445 
2446 		if (put_extra_attributes(longname, shortname, longattrname,
2447 		    prefix, filetype, '4') != 0)
2448 			goto out;
2449 
2450 		(void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock));
2451 		dblock.dbuf.typeflag = '4';
2452 
2453 		(void) writetbuf((char *)&dblock, 1);
2454 		break;
2455 	default:
2456 		(void) fprintf(stderr, gettext(
2457 		    "tar: %s is not a file. Not dumped\n"), longname);
2458 		if (errflag)
2459 			exitflag = 1;
2460 		Errflg = 1;
2461 		goto out;
2462 	}
2463 
2464 out:
2465 	if ((dirfd != -1) && (filetype != XATTR_FILE)) {
2466 		(void) close(dirfd);
2467 	}
2468 	return (rc);
2469 }
2470 
2471 
2472 /*
2473  *	splitfile	dump a large file across volumes
2474  *
2475  *	splitfile(longname, fd);
2476  *		char *longname;		full name of file
2477  *		int ifd;		input file descriptor
2478  *
2479  *	NOTE:  only called by putfile() to dump a large file.
2480  */
2481 
2482 static void
2483 splitfile(char *longname, int ifd, char *name, char *prefix, int filetype)
2484 {
2485 	blkcnt_t blocks;
2486 	off_t bytes, s;
2487 	char buf[TBLOCK];
2488 	int i, extents;
2489 
2490 	blocks = TBLOCKS(stbuf.st_size);	/* blocks file needs */
2491 
2492 	/*
2493 	 * # extents =
2494 	 *	size of file after using up rest of this floppy
2495 	 *		blocks - (blocklim - tapepos) + 1	(for header)
2496 	 *	plus roundup value before divide by blocklim-1
2497 	 *		+ (blocklim - 1) - 1
2498 	 *	all divided by blocklim-1 (one block for each header).
2499 	 * this gives
2500 	 *	(blocks - blocklim + tapepos + 1 + blocklim - 2)/(blocklim-1)
2501 	 * which reduces to the expression used.
2502 	 * one is added to account for this first extent.
2503 	 *
2504 	 * When one is dealing with extremely large archives, one may want
2505 	 * to allow for a large number of extents.  This code should be
2506 	 * revisited to determine if extents should be changed to something
2507 	 * larger than an int.
2508 	 */
2509 	extents = (int)((blocks + tapepos - 1ULL)/(blocklim - 1ULL) + 1);
2510 
2511 	if (extents < 2 || extents > MAXEXT) {	/* let's be reasonable */
2512 		(void) fprintf(stderr, gettext(
2513 		    "tar: %s needs unusual number of volumes to split\n"
2514 		    "tar: %s not dumped\n"), longname, longname);
2515 		return;
2516 	}
2517 	if (build_dblock(name, tchar, '0', filetype,
2518 	    &stbuf, stbuf.st_dev, prefix) != 0)
2519 		return;
2520 
2521 	dblock.dbuf.extotal = extents;
2522 	bytes = stbuf.st_size;
2523 
2524 	/*
2525 	 * The value contained in dblock.dbuf.efsize was formerly used when the
2526 	 * v flag was specified in conjunction with the t flag. Although it is
2527 	 * no longer used, older versions of tar will expect the former
2528 	 * behaviour, so we must continue to write it to the archive.
2529 	 *
2530 	 * Since dblock.dbuf.efsize is 10 chars in size, the maximum value it
2531 	 * can store is TAR_EFSIZE_MAX. If bytes exceeds that value, simply
2532 	 * store 0.
2533 	 */
2534 	if (bytes <= TAR_EFSIZE_MAX)
2535 		(void) sprintf(dblock.dbuf.efsize, "%9" FMT_off_t_o, bytes);
2536 	else
2537 		(void) sprintf(dblock.dbuf.efsize, "%9" FMT_off_t_o, (off_t)0);
2538 
2539 	(void) fprintf(stderr, gettext(
2540 	    "tar: large file %s needs %d extents.\n"
2541 	    "tar: current device seek position = %" FMT_blkcnt_t "K\n"),
2542 	    longname, extents, K(tapepos));
2543 
2544 	s = (off_t)(blocklim - tapepos - 1) * TBLOCK;
2545 	for (i = 1; i <= extents; i++) {
2546 		if (i > 1) {
2547 			newvol();
2548 			if (i == extents)
2549 				s = bytes;	/* last ext. gets true bytes */
2550 			else
2551 				s = (off_t)(blocklim - 1)*TBLOCK; /* all */
2552 		}
2553 		bytes -= s;
2554 		blocks = TBLOCKS(s);
2555 
2556 		(void) sprintf(dblock.dbuf.size, "%011" FMT_off_t_o, s);
2557 		dblock.dbuf.extno = i;
2558 		(void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock));
2559 		(void) writetbuf((char *)&dblock, 1);
2560 
2561 		if (vflag)
2562 			(void) fprintf(vfile,
2563 			    "+++ a %s %" FMT_blkcnt_t "K [extent #%d of %d]\n",
2564 			    longname, K(blocks), i, extents);
2565 		while (blocks && read(ifd, buf, TBLOCK) > 0) {
2566 			blocks--;
2567 			(void) writetbuf(buf, 1);
2568 		}
2569 		if (blocks != 0) {
2570 			(void) fprintf(stderr, gettext(
2571 			    "tar: %s: file changed size\n"), longname);
2572 			(void) fprintf(stderr, gettext(
2573 			    "tar: aborting split file %s\n"), longname);
2574 			(void) close(ifd);
2575 			return;
2576 		}
2577 	}
2578 	(void) close(ifd);
2579 	if (vflag)
2580 		(void) fprintf(vfile, gettext("a %s %" FMT_off_t "K (in %d "
2581 		    "extents)\n"), longname, K(TBLOCKS(stbuf.st_size)),
2582 		    extents);
2583 }
2584 
2585 /*
2586  *	convtoreg - determines whether the file should be converted to a
2587  *	            regular file when extracted
2588  *
2589  *	Returns 1 when file size > 0 and typeflag is not recognized
2590  * 	Otherwise returns 0
2591  */
2592 static int
2593 convtoreg(off_t size)
2594 {
2595 	if ((size > 0) && (dblock.dbuf.typeflag != '0') &&
2596 	    (dblock.dbuf.typeflag != NULL) && (dblock.dbuf.typeflag != '1') &&
2597 	    (dblock.dbuf.typeflag != '2') && (dblock.dbuf.typeflag != '3') &&
2598 	    (dblock.dbuf.typeflag != '4') && (dblock.dbuf.typeflag != '5') &&
2599 	    (dblock.dbuf.typeflag != '6') && (dblock.dbuf.typeflag != 'A') &&
2600 	    (dblock.dbuf.typeflag != _XATTR_HDRTYPE) &&
2601 	    (dblock.dbuf.typeflag != 'X')) {
2602 		return (1);
2603 	}
2604 	return (0);
2605 }
2606 
2607 #if defined(O_XATTR)
2608 static int
2609 save_cwd(void)
2610 {
2611 	return (open(".", O_RDONLY));
2612 }
2613 #endif
2614 
2615 #if defined(O_XATTR)
2616 static void
2617 rest_cwd(int *cwd)
2618 {
2619 	if (*cwd != -1) {
2620 		if (fchdir(*cwd) < 0) {
2621 			vperror(0, gettext(
2622 			    "Cannot fchdir to attribute directory"));
2623 			exit(1);
2624 		}
2625 		(void) close(*cwd);
2626 		*cwd = -1;
2627 	}
2628 }
2629 #endif
2630 
2631 /*
2632  * Verify the underlying file system supports the attribute type.
2633  * Only archive extended attribute files when '-@' was specified.
2634  * Only archive system extended attribute files if '-/' was specified.
2635  */
2636 #if defined(O_XATTR)
2637 static attr_status_t
2638 verify_attr_support(char *filename, int attrflg, arc_action_t actflag,
2639     int *ext_attrflg)
2640 {
2641 	/*
2642 	 * Verify extended attributes are supported/exist.  We only
2643 	 * need to check if we are processing a base file, not an
2644 	 * extended attribute.
2645 	 */
2646 	if (attrflg) {
2647 		*ext_attrflg = (pathconf(filename, (actflag == ARC_CREATE) ?
2648 		    _PC_XATTR_EXISTS : _PC_XATTR_ENABLED) == 1);
2649 	}
2650 
2651 	if (atflag) {
2652 		if (!*ext_attrflg) {
2653 #if defined(_PC_SATTR_ENABLED)
2654 			if (saflag) {
2655 				/* Verify system attributes are supported */
2656 				if (sysattr_support(filename,
2657 				    (actflag == ARC_CREATE) ? _PC_SATTR_EXISTS :
2658 				    _PC_SATTR_ENABLED) != 1) {
2659 					return (ATTR_SATTR_ERR);
2660 				}
2661 			} else
2662 				return (ATTR_XATTR_ERR);
2663 #else
2664 				return (ATTR_XATTR_ERR);
2665 #endif	/* _PC_SATTR_ENABLED */
2666 		}
2667 
2668 #if defined(_PC_SATTR_ENABLED)
2669 	} else if (saflag) {
2670 		/* Verify system attributes are supported */
2671 		if (sysattr_support(filename, (actflag == ARC_CREATE) ?
2672 		    _PC_SATTR_EXISTS : _PC_SATTR_ENABLED) != 1) {
2673 			return (ATTR_SATTR_ERR);
2674 		}
2675 #endif	/* _PC_SATTR_ENABLED */
2676 	} else {
2677 		return (ATTR_SKIP);
2678 	}
2679 
2680 	return (ATTR_OK);
2681 }
2682 #endif
2683 
2684 #if defined(O_XATTR)
2685 /*
2686  * Recursively open attribute directories until the attribute directory
2687  * containing the specified attribute, attrname, is opened.
2688  *
2689  * Currently, only 2 directory levels of attributes are supported, (i.e.,
2690  * extended system attributes on extended attributes).  The following are
2691  * the possible input combinations:
2692  *	1.  Open the attribute directory of the base file (don't change
2693  *	    into it).
2694  *		attrinfo->parent = NULL
2695  *		attrname = '.'
2696  *	2.  Open the attribute directory of the base file and change into it.
2697  *		attrinfo->parent = NULL
2698  *		attrname = <attr> | <sys_attr>
2699  *	3.  Open the attribute directory of the base file, change into it,
2700  *	    then recursively call open_attr_dir() to open the attribute's
2701  *	    parent directory (don't change into it).
2702  *		attrinfo->parent = <attr>
2703  *		attrname = '.'
2704  *	4.  Open the attribute directory of the base file, change into it,
2705  *	    then recursively call open_attr_dir() to open the attribute's
2706  *	    parent directory and change into it.
2707  *		attrinfo->parent = <attr>
2708  *		attrname = <attr> | <sys_attr>
2709  *
2710  * An attribute directory will be opened only if the underlying file system
2711  * supports the attribute type, and if the command line specifications (atflag
2712  * and saflag) enable the processing of the attribute type.
2713  *
2714  * On succesful return, attrinfo->parentfd will be the file descriptor of the
2715  * opened attribute directory.  In addition, if the attribute is a read-write
2716  * extended system attribute, attrinfo->rw_sysattr will be set to 1, otherwise
2717  * it will be set to 0.
2718  *
2719  * Possible return values:
2720  * 	ATTR_OK		Successfully opened and, if needed, changed into the
2721  *			attribute directory containing attrname.
2722  *	ATTR_SKIP	The command line specifications don't enable the
2723  *			processing of the attribute type.
2724  * 	ATTR_CHDIR_ERR	An error occurred while trying to change into an
2725  *			attribute directory.
2726  * 	ATTR_OPEN_ERR	An error occurred while trying to open an
2727  *			attribute directory.
2728  *	ATTR_XATTR_ERR	The underlying file system doesn't support extended
2729  *			attributes.
2730  *	ATTR_SATTR_ERR	The underlying file system doesn't support extended
2731  *			system attributes.
2732  */
2733 static int
2734 open_attr_dir(char *attrname, char *dirp, int cwd, attr_data_t *attrinfo)
2735 {
2736 	attr_status_t	rc;
2737 	int		firsttime = (attrinfo->attr_parentfd == -1);
2738 	int		saveerrno;
2739 	int		ext_attr;
2740 
2741 	/*
2742 	 * open_attr_dir() was recursively called (input combination number 4),
2743 	 * close the previously opened file descriptor as we've already changed
2744 	 * into it.
2745 	 */
2746 	if (!firsttime) {
2747 		(void) close(attrinfo->attr_parentfd);
2748 		attrinfo->attr_parentfd = -1;
2749 	}
2750 
2751 	/*
2752 	 * Verify that the underlying file system supports the restoration
2753 	 * of the attribute.
2754 	 */
2755 	if ((rc = verify_attr_support(dirp, firsttime, ARC_RESTORE,
2756 	    &ext_attr)) != ATTR_OK) {
2757 		return (rc);
2758 	}
2759 
2760 	/* Open the base file's attribute directory */
2761 	if ((attrinfo->attr_parentfd = attropen(dirp, ".", O_RDONLY)) == -1) {
2762 		/*
2763 		 * Save the errno from the attropen so it can be reported
2764 		 * if the retry of the attropen fails.
2765 		 */
2766 		saveerrno = errno;
2767 		if ((attrinfo->attr_parentfd = retry_open_attr(-1, cwd, dirp,
2768 		    NULL, ".", O_RDONLY, 0)) == -1) {
2769 			/*
2770 			 * Reset typeflag back to real value so passtape
2771 			 * will skip ahead correctly.
2772 			 */
2773 			dblock.dbuf.typeflag = _XATTR_HDRTYPE;
2774 			(void) close(attrinfo->attr_parentfd);
2775 			attrinfo->attr_parentfd = -1;
2776 			errno = saveerrno;
2777 			return (ATTR_OPEN_ERR);
2778 		}
2779 	}
2780 
2781 	/*
2782 	 * Change into the parent attribute's directory unless we are
2783 	 * processing the hidden attribute directory of the base file itself.
2784 	 */
2785 	if ((Hiddendir == 0) || (firsttime && attrinfo->attr_parent != NULL)) {
2786 		if (fchdir(attrinfo->attr_parentfd) != 0) {
2787 			saveerrno = errno;
2788 			(void) close(attrinfo->attr_parentfd);
2789 			attrinfo->attr_parentfd = -1;
2790 			errno = saveerrno;
2791 			return (ATTR_CHDIR_ERR);
2792 		}
2793 	}
2794 
2795 	/* Determine if the attribute should be processed */
2796 	if ((rc = verify_attr(attrname, attrinfo->attr_parent, 1,
2797 	    &attrinfo->attr_rw_sysattr)) != ATTR_OK) {
2798 		saveerrno = errno;
2799 		(void) close(attrinfo->attr_parentfd);
2800 		attrinfo->attr_parentfd = -1;
2801 		errno = saveerrno;
2802 		return (rc);
2803 	}
2804 
2805 	/*
2806 	 * If the attribute is an extended attribute, or extended system
2807 	 * attribute, of an attribute (i.e., <attr>/<sys_attr>), then
2808 	 * recursively call open_attr_dir() to open the attribute directory
2809 	 * of the parent attribute.
2810 	 */
2811 	if (firsttime && (attrinfo->attr_parent != NULL)) {
2812 		return (open_attr_dir(attrname, attrinfo->attr_parent,
2813 		    attrinfo->attr_parentfd, attrinfo));
2814 	}
2815 
2816 	return (ATTR_OK);
2817 }
2818 #endif
2819 
2820 static void
2821 #ifdef	_iBCS2
2822 doxtract(char *argv[], int tbl_cnt)
2823 #else
2824 doxtract(char *argv[])
2825 #endif
2826 {
2827 	struct	stat	xtractbuf;	/* stat on file after extracting */
2828 	blkcnt_t blocks;
2829 	off_t bytes;
2830 	int ofile;
2831 	int newfile;			/* Does the file already exist  */
2832 	int xcnt = 0;			/* count # files extracted */
2833 	int fcnt = 0;			/* count # files in argv list */
2834 	int dir;
2835 	int dirfd = -1;
2836 	int cwd = -1;
2837 	int rw_sysattr;
2838 	int saveerrno;
2839 	uid_t Uid;
2840 	char *namep, *dirp, *comp, *linkp; /* for removing absolute paths */
2841 	char dirname[PATH_MAX+1];
2842 	char templink[PATH_MAX+1];	/* temp link with terminating NULL */
2843 	int once = 1;
2844 	int error;
2845 	int symflag;
2846 	int want;
2847 	attr_data_t *attrinfo = NULL;	/* attribute info */
2848 	acl_t	*aclp = NULL;	/* acl info */
2849 	char dot[] = ".";		/* dirp for using realpath */
2850 	timestruc_t	time_zero;	/* used for call to doDirTimes */
2851 	int		dircreate;
2852 	int convflag;
2853 	time_zero.tv_sec = 0;
2854 	time_zero.tv_nsec = 0;
2855 
2856 	/* reset Trusted Extensions variables */
2857 	rpath_flag = 0;
2858 	lk_rpath_flag = 0;
2859 	dir_flag = 0;
2860 	mld_flag = 0;
2861 	bslundef(&bs_label);
2862 	bsllow(&admin_low);
2863 	bslhigh(&admin_high);
2864 	orig_namep = 0;
2865 
2866 	dumping = 0;	/* for newvol(), et al:  we are not writing */
2867 
2868 	/*
2869 	 * Count the number of files that are to be extracted
2870 	 */
2871 	Uid = getuid();
2872 
2873 #ifdef	_iBCS2
2874 	initarg(argv, Filefile);
2875 	while (nextarg() != NULL)
2876 		++fcnt;
2877 	fcnt += tbl_cnt;
2878 #endif	/*  _iBCS2 */
2879 
2880 	for (;;) {
2881 		convflag = 0;
2882 		symflag = 0;
2883 		dir = 0;
2884 		Hiddendir = 0;
2885 		rw_sysattr = 0;
2886 		ofile = -1;
2887 
2888 		if (dirfd != -1) {
2889 			(void) close(dirfd);
2890 			dirfd = -1;
2891 		}
2892 		if (ofile != -1) {
2893 			if (close(ofile) != 0)
2894 				vperror(2, gettext("close error"));
2895 		}
2896 
2897 #if defined(O_XATTR)
2898 		if (cwd != -1) {
2899 			rest_cwd(&cwd);
2900 		}
2901 #endif
2902 
2903 		/* namep is set by wantit to point to the full name */
2904 		if ((want = wantit(argv, &namep, &dirp, &comp,
2905 		    &attrinfo)) == 0) {
2906 #if defined(O_XATTR)
2907 			if (xattrp != NULL) {
2908 				free(xattrhead);
2909 				xattrp = NULL;
2910 				xattr_linkp = NULL;
2911 				xattrhead = NULL;
2912 			}
2913 #endif
2914 			continue;
2915 		}
2916 		if (want == -1)
2917 			break;
2918 
2919 /* Trusted Extensions */
2920 		/*
2921 		 * During tar extract (x):
2922 		 * If the pathname of the restored file has been
2923 		 * reconstructed from the ancillary file,
2924 		 * use it to process the normal file.
2925 		 */
2926 		if (mld_flag) {		/* Skip over .MLD. directory */
2927 			mld_flag = 0;
2928 			passtape();
2929 			continue;
2930 		}
2931 		orig_namep = namep;	/* save original */
2932 		if (rpath_flag) {
2933 			namep = real_path;	/* use zone path */
2934 			comp = real_path;	/* use zone path */
2935 			dirp = dot;		/* work from the top */
2936 			rpath_flag = 0;		/* reset */
2937 		}
2938 
2939 		if (dirfd != -1)
2940 			(void) close(dirfd);
2941 
2942 		(void) strcpy(&dirname[0], namep);
2943 		dircreate = checkdir(&dirname[0]);
2944 
2945 #if defined(O_XATTR)
2946 		if (xattrp != NULL) {
2947 			int	rc;
2948 
2949 			if (((cwd = save_cwd()) == -1) ||
2950 			    ((rc = open_attr_dir(comp, dirp, cwd,
2951 			    attrinfo)) != ATTR_OK)) {
2952 				if (cwd == -1) {
2953 					vperror(0, gettext(
2954 					    "unable to save current working "
2955 					    "directory while processing "
2956 					    "attribute %s of %s"),
2957 					    dirp, attrinfo->attr_path);
2958 				} else if (rc != ATTR_SKIP) {
2959 					(void) fprintf(vfile,
2960 					    gettext("tar: cannot open "
2961 					    "%sattribute %s of file %s: %s\n"),
2962 					    attrinfo->attr_rw_sysattr ? gettext(
2963 					    "system ") : "",
2964 					    comp, dirp, strerror(errno));
2965 				}
2966 				free(xattrhead);
2967 				xattrp = NULL;
2968 				xattr_linkp = NULL;
2969 				xattrhead = NULL;
2970 
2971 				passtape();
2972 				continue;
2973 			} else {
2974 				dirfd = attrinfo->attr_parentfd;
2975 				rw_sysattr = attrinfo->attr_rw_sysattr;
2976 			}
2977 		} else {
2978 			dirfd = open(dirp, O_RDONLY);
2979 		}
2980 #else
2981 		dirfd = open(dirp, O_RDONLY);
2982 #endif
2983 		if (dirfd == -1) {
2984 			(void) fprintf(vfile, gettext(
2985 			    "tar: cannot open %s: %s\n"),
2986 			    dirp, strerror(errno));
2987 			passtape();
2988 			continue;
2989 		}
2990 
2991 		if (xhdr_flgs & _X_LINKPATH)
2992 			(void) strcpy(templink, Xtarhdr.x_linkpath);
2993 		else {
2994 #if defined(O_XATTR)
2995 			if (xattrp && dblock.dbuf.typeflag == '1') {
2996 				(void) sprintf(templink, "%.*s", NAMSIZ,
2997 				    xattrp->h_names);
2998 			} else {
2999 				(void) sprintf(templink, "%.*s", NAMSIZ,
3000 				    dblock.dbuf.linkname);
3001 			}
3002 #else
3003 			(void) sprintf(templink, "%.*s", NAMSIZ,
3004 			    dblock.dbuf.linkname);
3005 #endif
3006 		}
3007 
3008 		if (Fflag) {
3009 			char *s;
3010 
3011 			if ((s = strrchr(namep, '/')) == 0)
3012 				s = namep;
3013 
3014 			else
3015 				s++;
3016 			if (checkf(s, stbuf.st_mode, Fflag) == 0) {
3017 				passtape();
3018 				continue;
3019 			}
3020 		}
3021 
3022 		if (checkw('x', namep) == 0) {
3023 			passtape();
3024 			continue;
3025 		}
3026 		if (once) {
3027 			if (strcmp(dblock.dbuf.magic, magic_type) == 0) {
3028 				if (geteuid() == (uid_t)0) {
3029 					checkflag = 1;
3030 					pflag = 1;
3031 				} else {
3032 					/* get file creation mask */
3033 					Oumask = umask(0);
3034 					(void) umask(Oumask);
3035 				}
3036 				once = 0;
3037 			} else {
3038 				if (geteuid() == (uid_t)0) {
3039 					pflag = 1;
3040 					checkflag = 2;
3041 				}
3042 				if (!pflag) {
3043 					/* get file creation mask */
3044 					Oumask = umask(0);
3045 					(void) umask(Oumask);
3046 				}
3047 				once = 0;
3048 			}
3049 		}
3050 
3051 #if defined(O_XATTR)
3052 		/*
3053 		 * Handle extraction of hidden attr dir.
3054 		 * Dir is automatically created, we only
3055 		 * need to update mode and perm's.
3056 		 */
3057 		if ((xattrp != NULL) && Hiddendir == 1) {
3058 			bytes = stbuf.st_size;
3059 			blocks = TBLOCKS(bytes);
3060 			if (vflag) {
3061 				(void) fprintf(vfile,
3062 				    "x %s%s%s, %" FMT_off_t " bytes, ", namep,
3063 				    gettext(" attribute "),
3064 				    xattrapath, bytes);
3065 				if (NotTape)
3066 					(void) fprintf(vfile,
3067 					    "%" FMT_blkcnt_t "K\n", K(blocks));
3068 				else
3069 					(void) fprintf(vfile, gettext("%"
3070 					    FMT_blkcnt_t " tape blocks\n"),
3071 					    blocks);
3072 			}
3073 
3074 			/*
3075 			 * Set the permissions and mode of the attribute
3076 			 * unless the attribute is a system attribute (can't
3077 			 * successfully do this) or the hidden attribute
3078 			 * directory (".") of an attribute (when the attribute
3079 			 * is restored, the hidden attribute directory of an
3080 			 * attribute is transient).  Note:  when the permissions
3081 			 * and mode are set for the hidden attribute directory
3082 			 * of a file on a system supporting extended system
3083 			 * attributes, even though it returns successfully, it
3084 			 * will not have any affect since the attribute
3085 			 * directory is transient.
3086 			 */
3087 			if (attrinfo->attr_parent == NULL) {
3088 				if (fchownat(dirfd, ".", stbuf.st_uid,
3089 				    stbuf.st_gid, 0) != 0) {
3090 					vperror(0, gettext(
3091 					    "%s%s%s: failed to set ownership "
3092 					    "of attribute directory"), namep,
3093 					    gettext(" attribute "), xattrapath);
3094 				}
3095 
3096 				if (fchmod(dirfd, stbuf.st_mode) != 0) {
3097 					vperror(0, gettext(
3098 					    "%s%s%s: failed to set permissions "
3099 					    "of attribute directory"), namep,
3100 					    gettext(" attribute "), xattrapath);
3101 				}
3102 			}
3103 			goto filedone;
3104 		}
3105 #endif
3106 
3107 		if (dircreate && (!is_posix || dblock.dbuf.typeflag == '5')) {
3108 			dir = 1;
3109 			if (vflag) {
3110 				(void) fprintf(vfile, "x %s, 0 bytes, ",
3111 				    &dirname[0]);
3112 				if (NotTape)
3113 					(void) fprintf(vfile, "0K\n");
3114 				else
3115 					(void) fprintf(vfile, gettext("%"
3116 					    FMT_blkcnt_t " tape blocks\n"),
3117 					    (blkcnt_t)0);
3118 			}
3119 			goto filedone;
3120 		}
3121 
3122 		if (dblock.dbuf.typeflag == '6') {	/* FIFO */
3123 			if (rmdir(namep) < 0) {
3124 				if (errno == ENOTDIR)
3125 					(void) unlink(namep);
3126 			}
3127 			linkp = templink;
3128 			if (*linkp !=  NULL) {
3129 				if (Aflag && *linkp == '/')
3130 					linkp++;
3131 				if (link(linkp, namep) < 0) {
3132 					(void) fprintf(stderr, gettext(
3133 					    "tar: %s: cannot link\n"), namep);
3134 					continue;
3135 				}
3136 				if (vflag)
3137 					(void) fprintf(vfile, gettext(
3138 					    "x %s linked to %s\n"), namep,
3139 					    linkp);
3140 				xcnt++;	 /* increment # files extracted */
3141 				continue;
3142 			}
3143 			if (mknod(namep, (int)(Gen.g_mode|S_IFIFO),
3144 			    (int)Gen.g_devmajor) < 0) {
3145 				vperror(0, gettext("%s: mknod failed"), namep);
3146 				continue;
3147 			}
3148 			bytes = stbuf.st_size;
3149 			blocks = TBLOCKS(bytes);
3150 			if (vflag) {
3151 				(void) fprintf(vfile, "x %s, %" FMT_off_t
3152 				    " bytes, ", namep, bytes);
3153 				if (NotTape)
3154 					(void) fprintf(vfile, "%" FMT_blkcnt_t
3155 					    "K\n", K(blocks));
3156 				else
3157 					(void) fprintf(vfile, gettext("%"
3158 					    FMT_blkcnt_t " tape blocks\n"),
3159 					    blocks);
3160 			}
3161 			goto filedone;
3162 		}
3163 		if (dblock.dbuf.typeflag == '3' && !Uid) { /* CHAR SPECIAL */
3164 			if (rmdir(namep) < 0) {
3165 				if (errno == ENOTDIR)
3166 					(void) unlink(namep);
3167 			}
3168 			linkp = templink;
3169 			if (*linkp != NULL) {
3170 				if (Aflag && *linkp == '/')
3171 					linkp++;
3172 				if (link(linkp, namep) < 0) {
3173 					(void) fprintf(stderr, gettext(
3174 					    "tar: %s: cannot link\n"), namep);
3175 					continue;
3176 				}
3177 				if (vflag)
3178 					(void) fprintf(vfile, gettext(
3179 					    "x %s linked to %s\n"), namep,
3180 					    linkp);
3181 				xcnt++;	 /* increment # files extracted */
3182 				continue;
3183 			}
3184 			if (mknod(namep, (int)(Gen.g_mode|S_IFCHR),
3185 			    (int)makedev(Gen.g_devmajor, Gen.g_devminor)) < 0) {
3186 				vperror(0, gettext(
3187 				    "%s: mknod failed"), namep);
3188 				continue;
3189 			}
3190 			bytes = stbuf.st_size;
3191 			blocks = TBLOCKS(bytes);
3192 			if (vflag) {
3193 				(void) fprintf(vfile, "x %s, %" FMT_off_t
3194 				    " bytes, ", namep, bytes);
3195 				if (NotTape)
3196 					(void) fprintf(vfile, "%" FMT_blkcnt_t
3197 					    "K\n", K(blocks));
3198 				else
3199 					(void) fprintf(vfile, gettext("%"
3200 					    FMT_blkcnt_t " tape blocks\n"),
3201 					    blocks);
3202 			}
3203 			goto filedone;
3204 		} else if (dblock.dbuf.typeflag == '3' && Uid) {
3205 			(void) fprintf(stderr, gettext(
3206 			    "Can't create special %s\n"), namep);
3207 			continue;
3208 		}
3209 
3210 		/* BLOCK SPECIAL */
3211 
3212 		if (dblock.dbuf.typeflag == '4' && !Uid) {
3213 			if (rmdir(namep) < 0) {
3214 				if (errno == ENOTDIR)
3215 					(void) unlink(namep);
3216 			}
3217 			linkp = templink;
3218 			if (*linkp != NULL) {
3219 				if (Aflag && *linkp == '/')
3220 					linkp++;
3221 				if (link(linkp, namep) < 0) {
3222 					(void) fprintf(stderr, gettext(
3223 					    "tar: %s: cannot link\n"), namep);
3224 					continue;
3225 				}
3226 				if (vflag)
3227 					(void) fprintf(vfile, gettext(
3228 					    "x %s linked to %s\n"), namep,
3229 					    linkp);
3230 				xcnt++;	 /* increment # files extracted */
3231 				continue;
3232 			}
3233 			if (mknod(namep, (int)(Gen.g_mode|S_IFBLK),
3234 			    (int)makedev(Gen.g_devmajor, Gen.g_devminor)) < 0) {
3235 				vperror(0, gettext("%s: mknod failed"), namep);
3236 				continue;
3237 			}
3238 			bytes = stbuf.st_size;
3239 			blocks = TBLOCKS(bytes);
3240 			if (vflag) {
3241 				(void) fprintf(vfile, gettext("x %s, %"
3242 				    FMT_off_t " bytes, "), namep, bytes);
3243 				if (NotTape)
3244 					(void) fprintf(vfile, "%" FMT_blkcnt_t
3245 					    "K\n", K(blocks));
3246 				else
3247 					(void) fprintf(vfile, gettext("%"
3248 					    FMT_blkcnt_t " tape blocks\n"),
3249 					    blocks);
3250 			}
3251 			goto filedone;
3252 		} else if (dblock.dbuf.typeflag == '4' && Uid) {
3253 			(void) fprintf(stderr,
3254 			    gettext("Can't create special %s\n"), namep);
3255 			continue;
3256 		}
3257 		if (dblock.dbuf.typeflag == '2') {	/* symlink */
3258 			if ((Tflag) && (lk_rpath_flag == 1))
3259 				linkp = lk_real_path;
3260 			else
3261 				linkp = templink;
3262 			if (Aflag && *linkp == '/')
3263 				linkp++;
3264 			if (rmdir(namep) < 0) {
3265 				if (errno == ENOTDIR)
3266 					(void) unlink(namep);
3267 			}
3268 			if (symlink(linkp, namep) < 0) {
3269 				vperror(0, gettext("%s: symbolic link failed"),
3270 				    namep);
3271 				continue;
3272 			}
3273 			if (vflag)
3274 				(void) fprintf(vfile, gettext(
3275 				    "x %s symbolic link to %s\n"),
3276 				    namep, linkp);
3277 
3278 			symflag = AT_SYMLINK_NOFOLLOW;
3279 			goto filedone;
3280 		}
3281 		if (dblock.dbuf.typeflag == '1') {
3282 			linkp = templink;
3283 			if (Aflag && *linkp == '/')
3284 				linkp++;
3285 			if (unlinkat(dirfd, comp, AT_REMOVEDIR) < 0) {
3286 				if (errno == ENOTDIR)
3287 					(void) unlinkat(dirfd, comp, 0);
3288 			}
3289 #if defined(O_XATTR)
3290 			if (xattrp && xattr_linkp) {
3291 				if (fchdir(dirfd) < 0) {
3292 					vperror(0, gettext(
3293 					    "Cannot fchdir to attribute "
3294 					    "directory %s"),
3295 					    (attrinfo->attr_parent == NULL) ?
3296 					    dirp : attrinfo->attr_parent);
3297 					exit(1);
3298 				}
3299 
3300 				error = link(xattr_linkaname, xattrapath);
3301 			} else {
3302 				error = link(linkp, namep);
3303 			}
3304 #else
3305 			error = link(linkp, namep);
3306 #endif
3307 
3308 			if (error < 0) {
3309 				(void) fprintf(stderr, gettext(
3310 				    "tar: %s%s%s: cannot link\n"),
3311 				    namep, (xattr_linkp != NULL) ?
3312 				    gettext(" attribute ") : "",
3313 				    (xattr_linkp != NULL) ?
3314 				    xattrapath : "");
3315 				continue;
3316 			}
3317 			if (vflag)
3318 				(void) fprintf(vfile, gettext(
3319 				    "x %s%s%s linked to %s%s%s\n"), namep,
3320 				    (xattr_linkp != NULL) ?
3321 				    gettext(" attribute ") : "",
3322 				    (xattr_linkp != NULL) ?
3323 				    xattr_linkaname : "",
3324 				    linkp,
3325 				    (xattr_linkp != NULL) ?
3326 				    gettext(" attribute ") : "",
3327 				    (xattr_linkp != NULL) ? xattrapath : "");
3328 			xcnt++;		/* increment # files extracted */
3329 #if defined(O_XATTR)
3330 			if (xattrp != NULL) {
3331 				free(xattrhead);
3332 				xattrp = NULL;
3333 				xattr_linkp = NULL;
3334 				xattrhead = NULL;
3335 			}
3336 #endif
3337 			continue;
3338 		}
3339 
3340 		/* REGULAR FILES */
3341 
3342 		if (convtoreg(stbuf.st_size)) {
3343 			convflag = 1;
3344 			if (errflag) {
3345 				(void) fprintf(stderr, gettext(
3346 				    "tar: %s: typeflag '%c' not recognized\n"),
3347 				    namep, dblock.dbuf.typeflag);
3348 				done(1);
3349 			} else {
3350 				(void) fprintf(stderr, gettext(
3351 				    "tar: %s: typeflag '%c' not recognized, "
3352 				    "converting to regular file\n"), namep,
3353 				    dblock.dbuf.typeflag);
3354 				Errflg = 1;
3355 			}
3356 		}
3357 		if (dblock.dbuf.typeflag == '0' ||
3358 		    dblock.dbuf.typeflag == NULL || convflag) {
3359 			delete_target(dirfd, comp, namep);
3360 			linkp = templink;
3361 			if (*linkp != NULL) {
3362 				if (Aflag && *linkp == '/')
3363 					linkp++;
3364 				if (link(linkp, comp) < 0) {
3365 					(void) fprintf(stderr, gettext(
3366 					    "tar: %s: cannot link\n"), namep);
3367 					continue;
3368 				}
3369 				if (vflag)
3370 					(void) fprintf(vfile, gettext(
3371 					    "x %s linked to %s\n"), comp,
3372 					    linkp);
3373 				xcnt++;	 /* increment # files extracted */
3374 #if defined(O_XATTR)
3375 				if (xattrp != NULL) {
3376 					free(xattrhead);
3377 					xattrp = NULL;
3378 					xattr_linkp = NULL;
3379 					xattrhead = NULL;
3380 				}
3381 #endif
3382 				continue;
3383 			}
3384 		newfile = ((fstatat(dirfd, comp,
3385 		    &xtractbuf, 0) == -1) ? TRUE : FALSE);
3386 		ofile = openat(dirfd, comp, O_RDWR|O_CREAT|O_TRUNC,
3387 		    stbuf.st_mode & MODEMASK);
3388 		saveerrno = errno;
3389 
3390 #if defined(O_XATTR)
3391 		if (xattrp != NULL) {
3392 			if (ofile < 0) {
3393 				ofile = retry_open_attr(dirfd, cwd,
3394 				    dirp, attrinfo->attr_parent, comp,
3395 				    O_RDWR|O_CREAT|O_TRUNC,
3396 				    stbuf.st_mode & MODEMASK);
3397 			}
3398 		}
3399 #endif
3400 		if (ofile < 0) {
3401 			errno = saveerrno;
3402 			(void) fprintf(stderr, gettext(
3403 			    "tar: %s%s%s%s - cannot create\n"),
3404 			    (xattrp == NULL) ? "" : (rw_sysattr ?
3405 			    gettext("system attribure ") :
3406 			    gettext("attribute ")),
3407 			    (xattrp == NULL) ? "" : xattrapath,
3408 			    (xattrp == NULL) ? "" : gettext(" of "),
3409 			    (xattrp == NULL) ? comp : namep);
3410 			if (errflag)
3411 				done(1);
3412 			else
3413 				Errflg = 1;
3414 #if defined(O_XATTR)
3415 			if (xattrp != NULL) {
3416 				dblock.dbuf.typeflag = _XATTR_HDRTYPE;
3417 				free(xattrhead);
3418 				xattrp = NULL;
3419 				xattr_linkp = NULL;
3420 				xattrhead = NULL;
3421 			}
3422 #endif
3423 			passtape();
3424 			continue;
3425 		}
3426 
3427 		if (Tflag && (check_ext_attr(namep) == 0)) {
3428 			if (errflag)
3429 				done(1);
3430 			else
3431 				Errflg = 1;
3432 			passtape();
3433 			continue;
3434 		}
3435 
3436 		if (extno != 0) {	/* file is in pieces */
3437 			if (extotal < 1 || extotal > MAXEXT)
3438 				(void) fprintf(stderr, gettext(
3439 				    "tar: ignoring bad extent info for "
3440 				    "%s%s%s%s\n"),
3441 				    (xattrp == NULL) ? "" : (rw_sysattr ?
3442 				    gettext("system attribute ") :
3443 				    gettext("attribute ")),
3444 				    (xattrp == NULL) ? "" : xattrapath,
3445 				    (xattrp == NULL) ? "" : gettext(" of "),
3446 				    (xattrp == NULL) ? comp : namep);
3447 			else {
3448 				/* extract it */
3449 				(void) xsfile(rw_sysattr, ofile);
3450 			}
3451 		}
3452 		extno = 0;	/* let everyone know file is not split */
3453 		bytes = stbuf.st_size;
3454 		blocks = TBLOCKS(bytes);
3455 		if (vflag) {
3456 			(void) fprintf(vfile,
3457 			    "x %s%s%s, %" FMT_off_t " bytes, ",
3458 			    (xattrp == NULL) ? "" : dirp,
3459 			    (xattrp == NULL) ? "" : (rw_sysattr ?
3460 			    gettext(" system attribute ") :
3461 			    gettext(" attribute ")),
3462 			    (xattrp == NULL) ? namep : xattrapath, bytes);
3463 			if (NotTape)
3464 				(void) fprintf(vfile, "%" FMT_blkcnt_t "K\n",
3465 				    K(blocks));
3466 			else
3467 				(void) fprintf(vfile, gettext("%"
3468 				    FMT_blkcnt_t " tape blocks\n"), blocks);
3469 		}
3470 
3471 		if (xblocks(rw_sysattr, bytes, ofile) != 0) {
3472 #if defined(O_XATTR)
3473 			if (xattrp != NULL) {
3474 				free(xattrhead);
3475 				xattrp = NULL;
3476 				xattr_linkp = NULL;
3477 				xattrhead = NULL;
3478 			}
3479 #endif
3480 			continue;
3481 		}
3482 filedone:
3483 		if (mflag == 0 && !symflag) {
3484 			if (dir)
3485 				doDirTimes(namep, stbuf.st_mtim);
3486 
3487 			else
3488 #if defined(O_XATTR)
3489 				if (xattrp != NULL) {
3490 					/*
3491 					 * Set the time on the attribute unless
3492 					 * the attribute is a system attribute
3493 					 * (can't successfully do this) or the
3494 					 * hidden attribute directory, "." (the
3495 					 * time on the hidden attribute
3496 					 * directory will be updated when
3497 					 * attributes are restored, otherwise
3498 					 * it's transient).
3499 					 */
3500 					if (!rw_sysattr && (Hiddendir == 0)) {
3501 						setPathTimes(dirfd, comp,
3502 						    stbuf.st_mtim);
3503 					}
3504 				} else
3505 					setPathTimes(dirfd, comp,
3506 					    stbuf.st_mtim);
3507 #else
3508 				setPathTimes(dirfd, comp, stbuf.st_mtim);
3509 #endif
3510 		}
3511 
3512 		/* moved this code from above */
3513 		if (pflag && !symflag && Hiddendir == 0) {
3514 			if (xattrp != NULL)
3515 				(void) fchmod(ofile, stbuf.st_mode & MODEMASK);
3516 			else
3517 				(void) chmod(namep, stbuf.st_mode & MODEMASK);
3518 		}
3519 
3520 
3521 		/*
3522 		 * Because ancillary file preceeds the normal file,
3523 		 * acl info may have been retrieved (in aclp).
3524 		 * All file types are directed here (go filedone).
3525 		 * Always restore ACLs if there are ACLs.
3526 		 */
3527 		if (aclp != NULL) {
3528 			int ret;
3529 
3530 #if defined(O_XATTR)
3531 			if (xattrp != NULL) {
3532 				if (Hiddendir)
3533 					ret = facl_set(dirfd, aclp);
3534 				else
3535 					ret = facl_set(ofile, aclp);
3536 			} else {
3537 				ret = acl_set(namep, aclp);
3538 			}
3539 #else
3540 			ret = acl_set(namep, aclp);
3541 #endif
3542 			if (ret < 0) {
3543 				if (pflag) {
3544 					(void) fprintf(stderr, gettext(
3545 					    "%s%s%s%s: failed to set acl "
3546 					    "entries\n"), namep,
3547 					    (xattrp == NULL) ? "" :
3548 					    (rw_sysattr ? gettext(
3549 					    " system attribute ") :
3550 					    gettext(" attribute ")),
3551 					    (xattrp == NULL) ? "" :
3552 					    xattrapath);
3553 				}
3554 				/* else: silent and continue */
3555 			}
3556 			acl_free(aclp);
3557 			aclp = NULL;
3558 		}
3559 
3560 		if (!oflag)
3561 		    resugname(dirfd, comp, symflag); /* set file ownership */
3562 
3563 		if (pflag && newfile == TRUE && !dir &&
3564 		    (dblock.dbuf.typeflag == '0' ||
3565 		    dblock.dbuf.typeflag == NULL ||
3566 		    convflag || dblock.dbuf.typeflag == '1')) {
3567 			if (fstat(ofile, &xtractbuf) == -1)
3568 				(void) fprintf(stderr, gettext(
3569 				    "tar: cannot stat extracted file "
3570 				    "%s%s%s%s\n"),
3571 				    (xattrp == NULL) ? "" : (rw_sysattr ?
3572 				    gettext("system attribute ") :
3573 				    gettext("attribute ")),
3574 				    (xattrp == NULL) ? "" : xattrapath,
3575 				    (xattrp == NULL) ? "" :
3576 				    gettext(" of "), namep);
3577 
3578 			else if ((xtractbuf.st_mode & (MODEMASK & ~S_IFMT))
3579 			    != (stbuf.st_mode & (MODEMASK & ~S_IFMT))) {
3580 				(void) fprintf(stderr, gettext(
3581 				    "tar: warning - file permissions have "
3582 				    "changed for %s%s%s%s (are 0%o, should be "
3583 				    "0%o)\n"),
3584 				    (xattrp == NULL) ? "" : (rw_sysattr ?
3585 				    gettext("system attribute ") :
3586 				    gettext("attribute ")),
3587 				    (xattrp == NULL) ? "" : xattrapath,
3588 				    (xattrp == NULL) ? "" :
3589 				    gettext(" of "), namep,
3590 				    xtractbuf.st_mode, stbuf.st_mode);
3591 
3592 			}
3593 		}
3594 #if defined(O_XATTR)
3595 		if (xattrp != NULL) {
3596 			free(xattrhead);
3597 			xattrp = NULL;
3598 			xattr_linkp = NULL;
3599 			xattrhead = NULL;
3600 		}
3601 #endif
3602 
3603 		if (ofile != -1) {
3604 			(void) close(dirfd);
3605 			dirfd = -1;
3606 			if (close(ofile) != 0)
3607 				vperror(2, gettext("close error"));
3608 			ofile = -1;
3609 		}
3610 		xcnt++;			/* increment # files extracted */
3611 		}
3612 
3613 		/*
3614 		 * Process ancillary file.
3615 		 *
3616 		 */
3617 
3618 		if (dblock.dbuf.typeflag == 'A') {	/* acl info */
3619 			char	buf[TBLOCK];
3620 			char	*secp;
3621 			char	*tp;
3622 			int	attrsize;
3623 			int	cnt;
3624 
3625 			/* reset Trusted Extensions flags */
3626 			dir_flag = 0;
3627 			mld_flag = 0;
3628 			lk_rpath_flag = 0;
3629 			rpath_flag = 0;
3630 
3631 			if (pflag) {
3632 				bytes = stbuf.st_size;
3633 				if ((secp = malloc((int)bytes)) == NULL) {
3634 					(void) fprintf(stderr, gettext(
3635 					    "Insufficient memory for acl\n"));
3636 					passtape();
3637 					continue;
3638 				}
3639 				tp = secp;
3640 				blocks = TBLOCKS(bytes);
3641 
3642 				/*
3643 				 * Display a line for each ancillary file.
3644 				 */
3645 				if (vflag && Tflag)
3646 					(void) fprintf(vfile, "x %s(A), %"
3647 					    FMT_blkcnt_t " bytes, %"
3648 					    FMT_blkcnt_t " tape blocks\n",
3649 					    namep, bytes, blocks);
3650 
3651 				while (blocks-- > 0) {
3652 					readtape(buf);
3653 					if (bytes <= TBLOCK) {
3654 						(void) memcpy(tp, buf,
3655 						    (size_t)bytes);
3656 						break;
3657 					} else {
3658 						(void) memcpy(tp, buf,
3659 						    TBLOCK);
3660 						tp += TBLOCK;
3661 					}
3662 					bytes -= TBLOCK;
3663 				}
3664 				bytes = stbuf.st_size;
3665 				/* got all attributes in secp */
3666 				tp = secp;
3667 				do {
3668 					attr = (struct sec_attr *)tp;
3669 					switch (attr->attr_type) {
3670 					case UFSD_ACL:
3671 					case ACE_ACL:
3672 						(void) sscanf(attr->attr_len,
3673 						    "%7o",
3674 						    (uint_t *)
3675 						    &cnt);
3676 						/* header is 8 */
3677 						attrsize = 8 + (int)strlen(
3678 						    &attr->attr_info[0]) + 1;
3679 						error =
3680 						    acl_fromtext(
3681 						    &attr->attr_info[0], &aclp);
3682 
3683 						if (error != 0) {
3684 							(void) fprintf(stderr,
3685 							    gettext(
3686 							    "aclfromtext "
3687 							    "failed: %s\n"),
3688 							    acl_strerror(
3689 							    error));
3690 							bytes -= attrsize;
3691 							break;
3692 						}
3693 						if (acl_cnt(aclp) != cnt) {
3694 							(void) fprintf(stderr,
3695 							    gettext(
3696 							    "aclcnt error\n"));
3697 							bytes -= attrsize;
3698 							break;
3699 						}
3700 						bytes -= attrsize;
3701 						break;
3702 
3703 					/* Trusted Extensions */
3704 
3705 					case DIR_TYPE:
3706 					case LBL_TYPE:
3707 					case APRIV_TYPE:
3708 					case FPRIV_TYPE:
3709 					case COMP_TYPE:
3710 					case LK_COMP_TYPE:
3711 					case ATTR_FLAG_TYPE:
3712 						attrsize =
3713 						    sizeof (struct sec_attr) +
3714 						    strlen(&attr->attr_info[0]);
3715 						bytes -= attrsize;
3716 						if (Tflag)
3717 							extract_attr(&namep,
3718 							    attr);
3719 						break;
3720 
3721 					default:
3722 						(void) fprintf(stderr, gettext(
3723 						    "unrecognized attr"
3724 						    " type\n"));
3725 						bytes = (off_t)0;
3726 						break;
3727 					}
3728 
3729 					/* next attributes */
3730 					tp += attrsize;
3731 				} while (bytes != 0);
3732 				free(secp);
3733 			} else {
3734 				passtape();
3735 			}
3736 		} /* acl */
3737 
3738 	} /* for */
3739 
3740 	/*
3741 	 *  Ensure that all the directories still on the directory stack
3742 	 *  get their modification times set correctly by flushing the
3743 	 *  stack.
3744 	 */
3745 
3746 	doDirTimes(NULL, time_zero);
3747 
3748 #if defined(O_XATTR)
3749 		if (xattrp != NULL) {
3750 			free(xattrhead);
3751 			xattrp = NULL;
3752 			xattr_linkp = NULL;
3753 			xattrhead = NULL;
3754 		}
3755 #endif
3756 
3757 	/*
3758 	 * Check if the number of files extracted is different from the
3759 	 * number of files listed on the command line
3760 	 */
3761 	if (fcnt > xcnt) {
3762 		(void) fprintf(stderr,
3763 		    gettext("tar: %d file(s) not extracted\n"),
3764 		fcnt-xcnt);
3765 		Errflg = 1;
3766 	}
3767 }
3768 
3769 /*
3770  *	xblocks		extract file/extent from tape to output file
3771  *
3772  *	xblocks(issysattr, bytes, ofile);
3773  *
3774  *	issysattr			flag set if the files being extracted
3775  *					is an extended system attribute file.
3776  *	unsigned long long bytes	size of extent or file to be extracted
3777  *	ofile				output file
3778  *
3779  *	called by doxtract() and xsfile()
3780  */
3781 
3782 static int
3783 xblocks(int issysattr, off_t bytes, int ofile)
3784 {
3785 	char *buf;
3786 	char tempname[NAMSIZ+1];
3787 	size_t maxwrite;
3788 	size_t bytesread;
3789 	size_t piosize;		/* preferred I/O size */
3790 	struct stat tsbuf;
3791 
3792 	/* Don't need to do anything if this is a zero size file */
3793 	if (bytes <= 0) {
3794 		return (0);
3795 	}
3796 
3797 	/*
3798 	 * To figure out the size of the buffer used to accumulate data
3799 	 * from readtape() and to write to the file, we need to determine
3800 	 * the largest chunk of data to be written to the file at one time.
3801 	 * This is determined based on the smallest of the following two
3802 	 * things:
3803 	 *	1) The size of the archived file.
3804 	 *	2) The preferred I/O size of the file.
3805 	 */
3806 	if (issysattr || (bytes <= TBLOCK)) {
3807 		/*
3808 		 * Writes to system attribute files must be
3809 		 * performed in one operation.
3810 		 */
3811 		maxwrite = bytes;
3812 	} else {
3813 		/*
3814 		 * fstat() the file to get the preferred I/O size.
3815 		 * If it fails, then resort back to just writing
3816 		 * one block at a time.
3817 		 */
3818 		if (fstat(ofile, &tsbuf) == 0) {
3819 			piosize = tsbuf.st_blksize;
3820 		} else {
3821 			piosize = TBLOCK;
3822 		}
3823 		maxwrite = min(bytes, piosize);
3824 	}
3825 
3826 	/*
3827 	 * The buffer used to accumulate the data for the write operation
3828 	 * needs to be the maximum number of bytes to be written rounded up
3829 	 * to the nearest TBLOCK since readtape reads one block at a time.
3830 	 */
3831 	if ((buf = malloc(TBLOCKS(maxwrite) * TBLOCK)) == NULL) {
3832 		fatal(gettext("cannot allocate buffer"));
3833 	}
3834 
3835 	while (bytes > 0) {
3836 
3837 		/*
3838 		 * readtape() obtains one block (TBLOCK) of data at a time.
3839 		 * Accumulate as many blocks of data in buf as we can write
3840 		 * in one operation.
3841 		 */
3842 		for (bytesread = 0; bytesread < maxwrite; bytesread += TBLOCK) {
3843 			readtape(buf + bytesread);
3844 		}
3845 
3846 		if (write(ofile, buf, maxwrite) < 0) {
3847 			int saveerrno = errno;
3848 
3849 			if (xhdr_flgs & _X_PATH)
3850 				(void) strlcpy(tempname, Xtarhdr.x_path,
3851 				    sizeof (tempname));
3852 			else
3853 				(void) sprintf(tempname, "%.*s", NAMSIZ,
3854 				    dblock.dbuf.name);
3855 			/*
3856 			 * If the extended system attribute being extracted
3857 			 * contains attributes that the user needs privileges
3858 			 * for, then just display a warning message, skip
3859 			 * the extraction of this file, and return.
3860 			 */
3861 			if ((saveerrno == EPERM) && issysattr) {
3862 				(void) fprintf(stderr, gettext(
3863 				    "tar: unable to extract system attribute "
3864 				    "%s: insufficient privileges\n"), tempname);
3865 				Errflg = 1;
3866 				(void) free(buf);
3867 				return (1);
3868 			} else {
3869 				(void) fprintf(stderr, gettext(
3870 				    "tar: %s: HELP - extract write error\n"),
3871 				    tempname);
3872 				done(2);
3873 			}
3874 		}
3875 		bytes -= maxwrite;
3876 
3877 		/*
3878 		 * If we've reached this point and there is still data
3879 		 * to be written, maxwrite had to have been determined
3880 		 * by the preferred I/O size.  If the number of bytes
3881 		 * left to write is smaller than the preferred I/O size,
3882 		 * then we're about to do our final write to the file, so
3883 		 * just set maxwrite to the number of bytes left to write.
3884 		 */
3885 		if ((bytes > 0) && (bytes < maxwrite)) {
3886 			maxwrite = bytes;
3887 		}
3888 	}
3889 	free(buf);
3890 
3891 	return (0);
3892 }
3893 
3894 /*
3895  * 	xsfile	extract split file
3896  *
3897  *	xsfile(ofd);	ofd = output file descriptor
3898  *
3899  *	file extracted and put in ofd via xblocks()
3900  *
3901  *	NOTE:  only called by doxtract() to extract one large file
3902  */
3903 
3904 static	union	hblock	savedblock;	/* to ensure same file across volumes */
3905 
3906 static int
3907 xsfile(int issysattr, int ofd)
3908 {
3909 	int i, c;
3910 	int sysattrerr = 0;
3911 	char name[PATH_MAX+1];	/* holds name for diagnostics */
3912 	int extents, totalext;
3913 	off_t bytes, totalbytes;
3914 
3915 	if (xhdr_flgs & _X_PATH)
3916 		(void) strcpy(name, Xtarhdr.x_path);
3917 	else
3918 		(void) sprintf(name, "%.*s", NAMSIZ, dblock.dbuf.name);
3919 
3920 	totalbytes = (off_t)0;		/* in case we read in half the file */
3921 	totalext = 0;		/* these keep count */
3922 
3923 	(void) fprintf(stderr, gettext(
3924 	    "tar: %s split across %d volumes\n"), name, extotal);
3925 
3926 	/* make sure we do extractions in order */
3927 	if (extno != 1) {	/* starting in middle of file? */
3928 		(void) printf(gettext(
3929 		    "tar: first extent read is not #1\n"
3930 		    "OK to read file beginning with extent #%d (%s/%s) ? "),
3931 		    extno, yesstr, nostr);
3932 		if (yes() == 0) {
3933 canit:
3934 			passtape();
3935 			if (close(ofd) != 0)
3936 				vperror(2, gettext("close error"));
3937 			if (sysattrerr) {
3938 				return (1);
3939 			} else {
3940 				return (0);
3941 			}
3942 		}
3943 	}
3944 	extents = extotal;
3945 	i = extno;
3946 	/*CONSTCOND*/
3947 	while (1) {
3948 		if (xhdr_flgs & _X_SIZE) {
3949 			bytes = extsize;
3950 		} else {
3951 			bytes = stbuf.st_size;
3952 		}
3953 
3954 		if (vflag)
3955 			(void) fprintf(vfile, "+++ x %s [extent #%d], %"
3956 			    FMT_off_t " bytes, %ldK\n", name, extno, bytes,
3957 			    (long)K(TBLOCKS(bytes)));
3958 		if (xblocks(issysattr, bytes, ofd) != 0) {
3959 			sysattrerr = 1;
3960 			goto canit;
3961 		}
3962 
3963 		totalbytes += bytes;
3964 		totalext++;
3965 		if (++i > extents)
3966 			break;
3967 
3968 		/* get next volume and verify it's the right one */
3969 		copy(&savedblock, &dblock);
3970 tryagain:
3971 		newvol();
3972 		xhdr_flgs = 0;
3973 		getdir();
3974 		if (Xhdrflag > 0)
3975 			(void) get_xdata();	/* Get x-header & regular hdr */
3976 		if ((dblock.dbuf.typeflag != 'A') && (xhdr_flgs != 0)) {
3977 			load_info_from_xtarhdr(xhdr_flgs, &Xtarhdr);
3978 			xhdr_flgs |= _X_XHDR;
3979 		}
3980 		if (endtape()) {	/* seemingly empty volume */
3981 			(void) fprintf(stderr, gettext(
3982 			    "tar: first record is null\n"));
3983 asknicely:
3984 			(void) fprintf(stderr, gettext(
3985 			    "tar: need volume with extent #%d of %s\n"),
3986 			    i, name);
3987 			goto tryagain;
3988 		}
3989 		if (notsame()) {
3990 			(void) fprintf(stderr, gettext(
3991 			    "tar: first file on that volume is not "
3992 			    "the same file\n"));
3993 			goto asknicely;
3994 		}
3995 		if (i != extno) {
3996 			(void) fprintf(stderr, gettext(
3997 			    "tar: extent #%d received out of order\ntar: "
3998 			    "should be #%d\n"), extno, i);
3999 			(void) fprintf(stderr, gettext(
4000 			    "Ignore error, Abort this file, or "
4001 			    "load New volume (i/a/n) ? "));
4002 			c = response();
4003 			if (c == 'a')
4004 				goto canit;
4005 			if (c != 'i')		/* default to new volume */
4006 				goto asknicely;
4007 			i = extno;		/* okay, start from there */
4008 		}
4009 	}
4010 	if (vflag)
4011 		(void) fprintf(vfile, gettext(
4012 		    "x %s (in %d extents), %" FMT_off_t " bytes, %ldK\n"),
4013 		    name, totalext, totalbytes, (long)K(TBLOCKS(totalbytes)));
4014 
4015 	return (0);
4016 }
4017 
4018 
4019 /*
4020  *	notsame()	check if extract file extent is invalid
4021  *
4022  *	returns true if anything differs between savedblock and dblock
4023  *	except extno (extent number), checksum, or size (extent size).
4024  *	Determines if this header belongs to the same file as the one we're
4025  *	extracting.
4026  *
4027  *	NOTE:	though rather bulky, it is only called once per file
4028  *		extension, and it can withstand changes in the definition
4029  *		of the header structure.
4030  *
4031  *	WARNING:	this routine is local to xsfile() above
4032  */
4033 
4034 static int
4035 notsame(void)
4036 {
4037 	return (
4038 	    (strncmp(savedblock.dbuf.name, dblock.dbuf.name, NAMSIZ)) ||
4039 	    (strcmp(savedblock.dbuf.mode, dblock.dbuf.mode)) ||
4040 	    (strcmp(savedblock.dbuf.uid, dblock.dbuf.uid)) ||
4041 	    (strcmp(savedblock.dbuf.gid, dblock.dbuf.gid)) ||
4042 	    (strcmp(savedblock.dbuf.mtime, dblock.dbuf.mtime)) ||
4043 	    (savedblock.dbuf.typeflag != dblock.dbuf.typeflag) ||
4044 	    (strncmp(savedblock.dbuf.linkname, dblock.dbuf.linkname, NAMSIZ)) ||
4045 	    (savedblock.dbuf.extotal != dblock.dbuf.extotal) ||
4046 	    (strcmp(savedblock.dbuf.efsize, dblock.dbuf.efsize)));
4047 }
4048 
4049 static void
4050 #ifdef	_iBCS2
4051 dotable(char *argv[], int tbl_cnt)
4052 #else
4053 dotable(char *argv[])
4054 #endif
4055 
4056 {
4057 	int tcnt;			/* count # files tabled */
4058 	int fcnt;			/* count # files in argv list */
4059 	char *namep, *dirp, *comp;
4060 	int want;
4061 	char aclchar = ' ';			/* either blank or '+' */
4062 	char templink[PATH_MAX+1];
4063 	attr_data_t *attrinfo = NULL;
4064 
4065 	dumping = 0;
4066 
4067 	/* if not on magtape, maximize seek speed */
4068 	if (NotTape && !bflag) {
4069 #if SYS_BLOCK > TBLOCK
4070 		nblock = SYS_BLOCK / TBLOCK;
4071 #else
4072 		nblock = 1;
4073 #endif
4074 	}
4075 	/*
4076 	 * Count the number of files that are to be tabled
4077 	 */
4078 	fcnt = tcnt = 0;
4079 
4080 #ifdef	_iBCS2
4081 	initarg(argv, Filefile);
4082 	while (nextarg() != NULL)
4083 		++fcnt;
4084 	fcnt += tbl_cnt;
4085 #endif	/*  _iBCS2 */
4086 
4087 	for (;;) {
4088 
4089 		/* namep is set by wantit to point to the full name */
4090 		if ((want = wantit(argv, &namep, &dirp, &comp, &attrinfo)) == 0)
4091 			continue;
4092 		if (want == -1)
4093 			break;
4094 		if (dblock.dbuf.typeflag != 'A')
4095 			++tcnt;
4096 
4097 		/*
4098 		 * ACL support:
4099 		 * aclchar is introduced to indicate if there are
4100 		 * acl entries. longt() now takes one extra argument.
4101 		 */
4102 		if (vflag) {
4103 			if (dblock.dbuf.typeflag == 'A') {
4104 				aclchar = '+';
4105 				passtape();
4106 				continue;
4107 			}
4108 			longt(&stbuf, aclchar);
4109 			aclchar = ' ';
4110 		}
4111 
4112 
4113 #if defined(O_XATTR)
4114 		if (xattrp != NULL) {
4115 			int	issysattr;
4116 			char	*bn = basename(attrinfo->attr_path);
4117 
4118 			/*
4119 			 * We could use sysattr_type() to test whether or not
4120 			 * the attribute we are processing is really an
4121 			 * extended system attribute, which as of this writing
4122 			 * just does a strcmp(), however, sysattr_type() may
4123 			 * be changed to issue a pathconf() call instead, which
4124 			 * would require being changed into the parent attribute
4125 			 * directory.  So instead, just do simple string
4126 			 * comparisons to see if we are processing an extended
4127 			 * system attribute.
4128 			 */
4129 			issysattr = is_sysattr(bn);
4130 
4131 			(void) printf(gettext("%s %sattribute %s"),
4132 			    xattrp->h_names,
4133 			    issysattr ? gettext("system ") : "",
4134 			    attrinfo->attr_path);
4135 		} else {
4136 			(void) printf("%s", namep);
4137 		}
4138 #else
4139 			(void) printf("%s", namep);
4140 #endif
4141 
4142 		if (extno != 0) {
4143 			if (vflag) {
4144 				/* keep the '\n' for backwards compatibility */
4145 				(void) fprintf(vfile, gettext(
4146 				    "\n [extent #%d of %d]"), extno, extotal);
4147 			} else {
4148 				(void) fprintf(vfile, gettext(
4149 				    " [extent #%d of %d]"), extno, extotal);
4150 			}
4151 		}
4152 		if (xhdr_flgs & _X_LINKPATH) {
4153 			(void) strcpy(templink, Xtarhdr.x_linkpath);
4154 		} else {
4155 #if defined(O_XATTR)
4156 			if (xattrp != NULL) {
4157 				(void) sprintf(templink,
4158 				    "file %.*s", NAMSIZ, xattrp->h_names);
4159 			} else {
4160 				(void) sprintf(templink, "%.*s", NAMSIZ,
4161 				    dblock.dbuf.linkname);
4162 			}
4163 #else
4164 			(void) sprintf(templink, "%.*s", NAMSIZ,
4165 			    dblock.dbuf.linkname);
4166 #endif
4167 			templink[NAMSIZ] = '\0';
4168 		}
4169 		if (dblock.dbuf.typeflag == '1') {
4170 			/*
4171 			 * TRANSLATION_NOTE
4172 			 *	Subject is omitted here.
4173 			 *	Translate this as if
4174 			 *		<subject> linked to %s
4175 			 */
4176 #if defined(O_XATTR)
4177 			if (xattrp != NULL) {
4178 				(void) printf(
4179 				    gettext(" linked to attribute %s"),
4180 				    xattr_linkp->h_names +
4181 				    strlen(xattr_linkp->h_names) + 1);
4182 			} else {
4183 				(void) printf(
4184 				    gettext(" linked to %s"), templink);
4185 			}
4186 #else
4187 				(void) printf(
4188 				    gettext(" linked to %s"), templink);
4189 
4190 #endif
4191 		}
4192 		if (dblock.dbuf.typeflag == '2')
4193 			(void) printf(gettext(
4194 			/*
4195 			 * TRANSLATION_NOTE
4196 			 *	Subject is omitted here.
4197 			 *	Translate this as if
4198 			 *		<subject> symbolic link to %s
4199 			 */
4200 			" symbolic link to %s"), templink);
4201 		(void) printf("\n");
4202 #if defined(O_XATTR)
4203 		if (xattrp != NULL) {
4204 			free(xattrhead);
4205 			xattrp = NULL;
4206 			xattrhead = NULL;
4207 		}
4208 #endif
4209 		passtape();
4210 	}
4211 	/*
4212 	 * Check if the number of files tabled is different from the
4213 	 * number of files listed on the command line
4214 	 */
4215 	if (fcnt > tcnt) {
4216 		(void) fprintf(stderr, gettext(
4217 		    "tar: %d file(s) not found\n"), fcnt-tcnt);
4218 		Errflg = 1;
4219 	}
4220 }
4221 
4222 static void
4223 putempty(blkcnt_t n)
4224 {
4225 	char buf[TBLOCK];
4226 	char *cp;
4227 
4228 	for (cp = buf; cp < &buf[TBLOCK]; )
4229 		*cp++ = '\0';
4230 	while (n-- > 0)
4231 		(void) writetbuf(buf, 1);
4232 }
4233 
4234 static	ushort_t	Ftype = S_IFMT;
4235 
4236 static	void
4237 verbose(struct stat *st, char aclchar)
4238 {
4239 	int i, j, temp;
4240 	mode_t mode;
4241 	char modestr[12];
4242 
4243 	for (i = 0; i < 11; i++)
4244 		modestr[i] = '-';
4245 	modestr[i] = '\0';
4246 
4247 	/* a '+' sign is printed if there is ACL */
4248 	modestr[i-1] = aclchar;
4249 
4250 	mode = st->st_mode;
4251 	for (i = 0; i < 3; i++) {
4252 		temp = (mode >> (6 - (i * 3)));
4253 		j = (i * 3) + 1;
4254 		if (S_IROTH & temp)
4255 			modestr[j] = 'r';
4256 		if (S_IWOTH & temp)
4257 			modestr[j + 1] = 'w';
4258 		if (S_IXOTH & temp)
4259 			modestr[j + 2] = 'x';
4260 	}
4261 	temp = st->st_mode & Ftype;
4262 	switch (temp) {
4263 	case (S_IFIFO):
4264 		modestr[0] = 'p';
4265 		break;
4266 	case (S_IFCHR):
4267 		modestr[0] = 'c';
4268 		break;
4269 	case (S_IFDIR):
4270 		modestr[0] = 'd';
4271 		break;
4272 	case (S_IFBLK):
4273 		modestr[0] = 'b';
4274 		break;
4275 	case (S_IFREG): /* was initialized to '-' */
4276 		break;
4277 	case (S_IFLNK):
4278 		modestr[0] = 'l';
4279 		break;
4280 	default:
4281 		/* This field may be zero in old archives. */
4282 		if (is_posix && dblock.dbuf.typeflag != '1') {
4283 			/*
4284 			 * For POSIX compliant archives, the mode field
4285 			 * consists of 12 bits, ie:  the file type bits
4286 			 * are not stored in dblock.dbuf.mode.
4287 			 * For files other than hard links, getdir() sets
4288 			 * the file type bits in the st_mode field of the
4289 			 * stat structure based upon dblock.dbuf.typeflag.
4290 			 */
4291 			(void) fprintf(stderr, gettext(
4292 			    "tar: impossible file type"));
4293 		}
4294 	}
4295 
4296 	if ((S_ISUID & Gen.g_mode) == S_ISUID)
4297 		modestr[3] = 's';
4298 	if ((S_ISVTX & Gen.g_mode) == S_ISVTX)
4299 		modestr[9] = 't';
4300 	if ((S_ISGID & Gen.g_mode) == S_ISGID && modestr[6] == 'x')
4301 		modestr[6] = 's';
4302 	else if ((S_ENFMT & Gen.g_mode) == S_ENFMT && modestr[6] != 'x')
4303 		modestr[6] = 'l';
4304 	(void) fprintf(vfile, "%s", modestr);
4305 }
4306 
4307 static void
4308 longt(struct stat *st, char aclchar)
4309 {
4310 	char fileDate[30];
4311 	struct tm *tm;
4312 
4313 	verbose(st, aclchar);
4314 	(void) fprintf(vfile, "%3ld/%-3ld", st->st_uid, st->st_gid);
4315 
4316 	if (dblock.dbuf.typeflag == '2') {
4317 		if (xhdr_flgs & _X_LINKPATH)
4318 			st->st_size = (off_t)strlen(Xtarhdr.x_linkpath);
4319 		else
4320 			st->st_size = (off_t)(memchr(dblock.dbuf.linkname,
4321 			    '\0', NAMSIZ) ?
4322 			    (strlen(dblock.dbuf.linkname)) : (NAMSIZ));
4323 	}
4324 	(void) fprintf(vfile, " %6" FMT_off_t, st->st_size);
4325 
4326 	tm = localtime(&(st->st_mtime));
4327 	(void) strftime(fileDate, sizeof (fileDate),
4328 	    dcgettext((const char *)0, "%b %e %R %Y", LC_TIME), tm);
4329 	(void) fprintf(vfile, " %s ", fileDate);
4330 }
4331 
4332 
4333 /*
4334  *  checkdir - Attempt to ensure that the path represented in name
4335  *             exists, and return 1 if this is true and name itself is a
4336  *             directory.
4337  *             Return 0 if this path cannot be created or if name is not
4338  *             a directory.
4339  */
4340 
4341 static int
4342 checkdir(char *name)
4343 {
4344 	char lastChar;		   /* the last character in name */
4345 	char *cp;		   /* scratch pointer into name */
4346 	char *firstSlash = NULL;   /* first slash in name */
4347 	char *lastSlash = NULL;	   /* last slash in name */
4348 	int  nameLen;		   /* length of name */
4349 	int  trailingSlash;	   /* true if name ends in slash */
4350 	int  leadingSlash;	   /* true if name begins with slash */
4351 	int  markedDir;		   /* true if name denotes a directory */
4352 	int  success;		   /* status of makeDir call */
4353 
4354 
4355 	/*
4356 	 *  Scan through the name, and locate first and last slashes.
4357 	 */
4358 
4359 	for (cp = name; *cp; cp++) {
4360 		if (*cp == '/') {
4361 			if (! firstSlash) {
4362 				firstSlash = cp;
4363 			}
4364 			lastSlash = cp;
4365 		}
4366 	}
4367 
4368 	/*
4369 	 *  Determine what you can from the proceeds of the scan.
4370 	 */
4371 
4372 	lastChar	= *(cp - 1);
4373 	nameLen		= (int)(cp - name);
4374 	trailingSlash	= (lastChar == '/');
4375 	leadingSlash	= (*name == '/');
4376 	markedDir	= (dblock.dbuf.typeflag == '5' || trailingSlash);
4377 
4378 	if (! lastSlash && ! markedDir) {
4379 		/*
4380 		 *  The named file does not have any subdrectory
4381 		 *  structure; just bail out.
4382 		 */
4383 
4384 		return (0);
4385 	}
4386 
4387 	/*
4388 	 *  Make sure that name doesn`t end with slash for the loop.
4389 	 *  This ensures that the makeDir attempt after the loop is
4390 	 *  meaningful.
4391 	 */
4392 
4393 	if (trailingSlash) {
4394 		name[nameLen-1] = '\0';
4395 	}
4396 
4397 	/*
4398 	 *  Make the path one component at a time.
4399 	 */
4400 
4401 	for (cp = strchr(leadingSlash ? name+1 : name, '/');
4402 	    cp;
4403 	    cp = strchr(cp+1, '/')) {
4404 		*cp = '\0';
4405 		success = makeDir(name);
4406 		*cp = '/';
4407 
4408 		if (!success) {
4409 			name[nameLen-1] = lastChar;
4410 			return (0);
4411 		}
4412 	}
4413 
4414 	/*
4415 	 *  This makes the last component of the name, if it is a
4416 	 *  directory.
4417 	 */
4418 
4419 	if (markedDir) {
4420 		if (! makeDir(name)) {
4421 			name[nameLen-1] = lastChar;
4422 			return (0);
4423 		}
4424 	}
4425 
4426 	name[nameLen-1] = (lastChar == '/') ? '\0' : lastChar;
4427 	return (markedDir);
4428 }
4429 
4430 /*
4431  * resugname - Restore the user name and group name.  Search the NIS
4432  *             before using the uid and gid.
4433  *             (It is presumed that an archive entry cannot be
4434  *	       simultaneously a symlink and some other type.)
4435  */
4436 
4437 static void
4438 resugname(int dirfd, 	/* dir fd file resides in */
4439 	char *name,	/* name of the file to be modified */
4440 	int symflag)	/* true if file is a symbolic link */
4441 {
4442 	uid_t duid;
4443 	gid_t dgid;
4444 	struct stat *sp = &stbuf;
4445 	char	*u_g_name;
4446 
4447 	if (checkflag == 1) { /* Extended tar format and euid == 0 */
4448 
4449 		/*
4450 		 * Try and extract the intended uid and gid from the name
4451 		 * service before believing the uid and gid in the header.
4452 		 *
4453 		 * In the case where we archived a setuid or setgid file
4454 		 * owned by someone with a large uid, then it will
4455 		 * have made it into the archive with a uid of nobody.  If
4456 		 * the corresponding username doesn't appear to exist, then we
4457 		 * want to make sure it *doesn't* end up as setuid nobody!
4458 		 *
4459 		 * Our caller will print an error message about the fact
4460 		 * that the restore didn't work out quite right ..
4461 		 */
4462 		if (xhdr_flgs & _X_UNAME)
4463 			u_g_name = Xtarhdr.x_uname;
4464 		else
4465 			u_g_name = dblock.dbuf.uname;
4466 		if ((duid = getuidbyname(u_g_name)) == -1) {
4467 			if (S_ISREG(sp->st_mode) && sp->st_uid == UID_NOBODY &&
4468 			    (sp->st_mode & S_ISUID) == S_ISUID)
4469 				(void) chmod(name,
4470 				    MODEMASK & sp->st_mode & ~S_ISUID);
4471 			duid = sp->st_uid;
4472 		}
4473 
4474 		/* (Ditto for gids) */
4475 
4476 		if (xhdr_flgs & _X_GNAME)
4477 			u_g_name = Xtarhdr.x_gname;
4478 		else
4479 			u_g_name = dblock.dbuf.gname;
4480 		if ((dgid = getgidbyname(u_g_name)) == -1) {
4481 			if (S_ISREG(sp->st_mode) && sp->st_gid == GID_NOBODY &&
4482 			    (sp->st_mode & S_ISGID) == S_ISGID)
4483 				(void) chmod(name,
4484 				    MODEMASK & sp->st_mode & ~S_ISGID);
4485 			dgid = sp->st_gid;
4486 		}
4487 	} else if (checkflag == 2) { /* tar format and euid == 0 */
4488 		duid = sp->st_uid;
4489 		dgid = sp->st_gid;
4490 	}
4491 	if ((checkflag == 1) || (checkflag == 2))
4492 		(void) fchownat(dirfd, name, duid, dgid, symflag);
4493 }
4494 
4495 /*ARGSUSED*/
4496 static void
4497 onintr(int sig)
4498 {
4499 	(void) signal(SIGINT, SIG_IGN);
4500 	term++;
4501 }
4502 
4503 /*ARGSUSED*/
4504 static void
4505 onquit(int sig)
4506 {
4507 	(void) signal(SIGQUIT, SIG_IGN);
4508 	term++;
4509 }
4510 
4511 /*ARGSUSED*/
4512 static void
4513 onhup(int sig)
4514 {
4515 	(void) signal(SIGHUP, SIG_IGN);
4516 	term++;
4517 }
4518 
4519 static void
4520 tomodes(struct stat *sp)
4521 {
4522 	uid_t uid;
4523 	gid_t gid;
4524 
4525 	bzero(dblock.dummy, TBLOCK);
4526 
4527 	/*
4528 	 * If the uid or gid is too large, we can't put it into
4529 	 * the archive.  We could fail to put anything in the
4530 	 * archive at all .. but most of the time the name service
4531 	 * will save the day when we do a lookup at restore time.
4532 	 *
4533 	 * Instead we choose a "safe" uid and gid, and fix up whether
4534 	 * or not the setuid and setgid bits are left set to extraction
4535 	 * time.
4536 	 */
4537 	if (Eflag) {
4538 		if ((ulong_t)(uid = sp->st_uid) > (ulong_t)OCTAL7CHAR) {
4539 			xhdr_flgs |= _X_UID;
4540 			Xtarhdr.x_uid = uid;
4541 		}
4542 		if ((ulong_t)(gid = sp->st_gid) > (ulong_t)OCTAL7CHAR) {
4543 			xhdr_flgs |= _X_GID;
4544 			Xtarhdr.x_gid = gid;
4545 		}
4546 		if (sp->st_size > TAR_OFFSET_MAX) {
4547 			xhdr_flgs |= _X_SIZE;
4548 			Xtarhdr.x_filesz = sp->st_size;
4549 			(void) sprintf(dblock.dbuf.size, "%011" FMT_off_t_o,
4550 			    (off_t)0);
4551 		} else
4552 			(void) sprintf(dblock.dbuf.size, "%011" FMT_off_t_o,
4553 			    sp->st_size);
4554 	} else {
4555 		(void) sprintf(dblock.dbuf.size, "%011" FMT_off_t_o,
4556 		    sp->st_size);
4557 	}
4558 	if ((ulong_t)(uid = sp->st_uid) > (ulong_t)OCTAL7CHAR)
4559 		uid = UID_NOBODY;
4560 	if ((ulong_t)(gid = sp->st_gid) > (ulong_t)OCTAL7CHAR)
4561 		gid = GID_NOBODY;
4562 	(void) sprintf(dblock.dbuf.gid, "%07lo", gid);
4563 	(void) sprintf(dblock.dbuf.uid, "%07lo", uid);
4564 	(void) sprintf(dblock.dbuf.mode, "%07lo", sp->st_mode & POSIXMODES);
4565 	(void) sprintf(dblock.dbuf.mtime, "%011lo", sp->st_mtime);
4566 }
4567 
4568 static	int
4569 #ifdef	EUC
4570 /*
4571  * Warning:  the result of this function depends whether 'char' is a
4572  * signed or unsigned data type.  This a source of potential
4573  * non-portability among heterogeneous systems.  It is retained here
4574  * for backward compatibility.
4575  */
4576 checksum_signed(union hblock *dblockp)
4577 #else
4578 checksum(union hblock *dblockp)
4579 #endif	/* EUC */
4580 {
4581 	int i;
4582 	char *cp;
4583 
4584 	for (cp = dblockp->dbuf.chksum;
4585 	    cp < &dblockp->dbuf.chksum[sizeof (dblockp->dbuf.chksum)]; cp++)
4586 		*cp = ' ';
4587 	i = 0;
4588 	for (cp = dblockp->dummy; cp < &(dblockp->dummy[TBLOCK]); cp++)
4589 		i += *cp;
4590 	return (i);
4591 }
4592 
4593 #ifdef	EUC
4594 /*
4595  * Generate unsigned checksum, regardless of what C compiler is
4596  * used.  Survives in the face of arbitrary 8-bit clean filenames,
4597  * e.g., internationalized filenames.
4598  */
4599 static int
4600 checksum(union hblock *dblockp)
4601 {
4602 	unsigned i;
4603 	unsigned char *cp;
4604 
4605 	for (cp = (unsigned char *) dblockp->dbuf.chksum;
4606 	    cp < (unsigned char *)
4607 	    &(dblockp->dbuf.chksum[sizeof (dblockp->dbuf.chksum)]); cp++)
4608 		*cp = ' ';
4609 	i = 0;
4610 	for (cp = (unsigned char *) dblockp->dummy;
4611 	    cp < (unsigned char *) &(dblockp->dummy[TBLOCK]); cp++)
4612 		i += *cp;
4613 
4614 	return (i);
4615 }
4616 #endif	/* EUC */
4617 
4618 /*
4619  * If the w flag is set, output the action to be taken and the name of the
4620  * file.  Perform the action if the user response is affirmative.
4621  */
4622 
4623 static int
4624 checkw(char c, char *name)
4625 {
4626 	if (wflag) {
4627 		(void) fprintf(vfile, "%c ", c);
4628 		if (vflag)
4629 			longt(&stbuf, ' ');	/* do we have acl info here */
4630 		(void) fprintf(vfile, "%s: ", name);
4631 		if (yes() == 1) {
4632 			return (1);
4633 		}
4634 		return (0);
4635 	}
4636 	return (1);
4637 }
4638 
4639 /*
4640  * When the F flag is set, exclude RCS and SCCS directories.  If F is set
4641  * twice, also exclude .o files, and files names errs, core, and a.out.
4642  */
4643 
4644 static int
4645 checkf(char *name, int mode, int howmuch)
4646 {
4647 	int l;
4648 
4649 	if ((mode & S_IFMT) == S_IFDIR) {
4650 		if ((strcmp(name, "SCCS") == 0) || (strcmp(name, "RCS") == 0))
4651 			return (0);
4652 		return (1);
4653 	}
4654 	if ((l = (int)strlen(name)) < 3)
4655 		return (1);
4656 	if (howmuch > 1 && name[l-2] == '.' && name[l-1] == 'o')
4657 		return (0);
4658 	if (howmuch > 1) {
4659 		if (strcmp(name, "core") == 0 || strcmp(name, "errs") == 0 ||
4660 		    strcmp(name, "a.out") == 0)
4661 			return (0);
4662 	}
4663 
4664 	/* SHOULD CHECK IF IT IS EXECUTABLE */
4665 	return (1);
4666 }
4667 
4668 static int
4669 response(void)
4670 {
4671 	int c;
4672 
4673 	c = getchar();
4674 	if (c != '\n')
4675 		while (getchar() != '\n')
4676 			;
4677 	else c = 'n';
4678 	return ((c >= 'A' && c <= 'Z') ? c + ('a'-'A') : c);
4679 }
4680 
4681 /* Has file been modified since being put into archive? If so, return > 0. */
4682 
4683 static int
4684 checkupdate(char *arg)
4685 {
4686 	char name[PATH_MAX+1];
4687 	time_t	mtime;
4688 	long nsecs;
4689 	off_t seekp;
4690 	static off_t	lookup(char *);
4691 
4692 	rewind(tfile);
4693 	if ((seekp = lookup(arg)) < 0)
4694 		return (1);
4695 	(void) fseek(tfile, seekp, 0);
4696 	(void) fscanf(tfile, "%s %ld.%ld", name, &mtime, &nsecs);
4697 
4698 	/*
4699 	 * Unless nanoseconds were stored in the file, only use seconds for
4700 	 * comparison of time.  Nanoseconds are stored when -E is specified.
4701 	 */
4702 	if (Eflag == 0)
4703 		return (stbuf.st_mtime > mtime);
4704 
4705 	if ((stbuf.st_mtime < mtime) ||
4706 	    ((stbuf.st_mtime == mtime) && (stbuf.st_mtim.tv_nsec <= nsecs)))
4707 		return (0);
4708 	return (1);
4709 }
4710 
4711 
4712 /*
4713  *	newvol	get new floppy (or tape) volume
4714  *
4715  *	newvol();		resets tapepos and first to TRUE, prompts for
4716  *				for new volume, and waits.
4717  *	if dumping, end-of-file is written onto the tape.
4718  */
4719 
4720 static void
4721 newvol(void)
4722 {
4723 	int c;
4724 
4725 	if (dumping) {
4726 #ifdef DEBUG
4727 		DEBUG("newvol called with 'dumping' set\n", 0, 0);
4728 #endif
4729 		putempty((blkcnt_t)2);	/* 2 EOT marks */
4730 		closevol();
4731 		flushtape();
4732 		sync();
4733 		tapepos = 0;
4734 	} else
4735 		first = TRUE;
4736 	if (close(mt) != 0)
4737 		vperror(2, gettext("close error"));
4738 	mt = 0;
4739 	(void) fprintf(stderr, gettext(
4740 	    "tar: \007please insert new volume, then press RETURN."));
4741 	(void) fseek(stdin, (off_t)0, 2);	/* scan over read-ahead */
4742 	while ((c = getchar()) != '\n' && ! term)
4743 		if (c == EOF)
4744 			done(Errflg);
4745 	if (term)
4746 		done(Errflg);
4747 
4748 	errno = 0;
4749 
4750 	if (strcmp(usefile, "-") == 0) {
4751 		mt = dup(1);
4752 	} else {
4753 		mt = open(usefile, dumping ? update : 0);
4754 	}
4755 
4756 	if (mt < 0) {
4757 		(void) fprintf(stderr, gettext(
4758 		    "tar: cannot reopen %s (%s)\n"),
4759 		    dumping ? gettext("output") : gettext("input"), usefile);
4760 
4761 		(void) fprintf(stderr, "update=%d, usefile=%s, mt=%d, [%s]\n",
4762 		    update, usefile, mt, strerror(errno));
4763 
4764 		done(2);
4765 	}
4766 }
4767 
4768 /*
4769  * Write a trailer portion to close out the current output volume.
4770  */
4771 
4772 static void
4773 closevol(void)
4774 {
4775 	if (mulvol) {
4776 		/*
4777 		 * blocklim does not count the 2 EOT marks;
4778 		 * tapepos  does count the 2 EOT marks;
4779 		 * therefore we need the +2 below.
4780 		 */
4781 		putempty(blocklim + (blkcnt_t)2 - tapepos);
4782 	}
4783 }
4784 
4785 static void
4786 done(int n)
4787 {
4788 	(void) unlink(tname);
4789 	if (mt > 0) {
4790 		if ((close(mt) != 0) || (fclose(stdout) != 0)) {
4791 			perror(gettext("tar: close error"));
4792 			exit(2);
4793 		}
4794 	}
4795 	exit(n);
4796 }
4797 
4798 /*
4799  * Determine if s1 is a prefix portion of s2 (or the same as s2).
4800  */
4801 
4802 static	int
4803 is_prefix(char *s1, char *s2)
4804 {
4805 	while (*s1)
4806 		if (*s1++ != *s2++)
4807 			return (0);
4808 	if (*s2)
4809 		return (*s2 == '/');
4810 	return (1);
4811 }
4812 
4813 /*
4814  * lookup and bsrch look through tfile entries to find a match for a name.
4815  * The name can be up to PATH_MAX bytes.  bsrch compares what it sees between
4816  * a pair of newline chars, so the buffer it uses must be long enough for
4817  * two lines:  name and modification time as well as period, newline and space.
4818  *
4819  * A kludge was added to bsrch to take care of matching on the first entry
4820  * in the file--there is no leading newline.  So, if we are reading from the
4821  * start of the file, read into byte two and set the first byte to a newline.
4822  * Otherwise, the first entry cannot be matched.
4823  *
4824  */
4825 
4826 #define	N	(2 * (PATH_MAX + TIME_MAX_DIGITS + LONG_MAX_DIGITS + 3))
4827 static	off_t
4828 lookup(char *s)
4829 {
4830 	int i;
4831 	off_t a;
4832 
4833 	for (i = 0; s[i]; i++)
4834 		if (s[i] == ' ')
4835 			break;
4836 	a = bsrch(s, i, low, high);
4837 	return (a);
4838 }
4839 
4840 static off_t
4841 bsrch(char *s, int n, off_t l, off_t h)
4842 {
4843 	int i, j;
4844 	char b[N];
4845 	off_t m, m1;
4846 
4847 
4848 loop:
4849 	if (l >= h)
4850 		return ((off_t)-1);
4851 	m = l + (h-l)/2 - N/2;
4852 	if (m < l)
4853 		m = l;
4854 	(void) fseek(tfile, m, 0);
4855 	if (m == 0) {
4856 		(void) fread(b+1, 1, N-1, tfile);
4857 		b[0] = '\n';
4858 		m--;
4859 	} else
4860 		(void) fread(b, 1, N, tfile);
4861 	for (i = 0; i < N; i++) {
4862 		if (b[i] == '\n')
4863 			break;
4864 		m++;
4865 	}
4866 	if (m >= h)
4867 		return ((off_t)-1);
4868 	m1 = m;
4869 	j = i;
4870 	for (i++; i < N; i++) {
4871 		m1++;
4872 		if (b[i] == '\n')
4873 			break;
4874 	}
4875 	i = cmp(b+j, s, n);
4876 	if (i < 0) {
4877 		h = m;
4878 		goto loop;
4879 	}
4880 	if (i > 0) {
4881 		l = m1;
4882 		goto loop;
4883 	}
4884 	if (m < 0)
4885 		m = 0;
4886 	return (m);
4887 }
4888 
4889 static int
4890 cmp(char *b, char *s, int n)
4891 {
4892 	int i;
4893 
4894 	assert(b[0] == '\n');
4895 
4896 	for (i = 0; i < n; i++) {
4897 		if (b[i+1] > s[i])
4898 			return (-1);
4899 		if (b[i+1] < s[i])
4900 			return (1);
4901 	}
4902 	return (b[i+1] == ' '? 0 : -1);
4903 }
4904 
4905 
4906 /*
4907  *	seekdisk	seek to next file on archive
4908  *
4909  *	called by passtape() only
4910  *
4911  *	WARNING: expects "nblock" to be set, that is, readtape() to have
4912  *		already been called.  Since passtape() is only called
4913  *		after a file header block has been read (why else would
4914  *		we skip to next file?), this is currently safe.
4915  *
4916  *	changed to guarantee SYS_BLOCK boundary
4917  */
4918 
4919 static void
4920 seekdisk(blkcnt_t blocks)
4921 {
4922 	off_t seekval;
4923 #if SYS_BLOCK > TBLOCK
4924 	/* handle non-multiple of SYS_BLOCK */
4925 	blkcnt_t nxb;	/* # extra blocks */
4926 #endif
4927 
4928 	tapepos += blocks;
4929 #ifdef DEBUG
4930 	DEBUG("seekdisk(%" FMT_blkcnt_t ") called\n", blocks, 0);
4931 #endif
4932 	if (recno + blocks <= nblock) {
4933 		recno += blocks;
4934 		return;
4935 	}
4936 	if (recno > nblock)
4937 		recno = nblock;
4938 	seekval = (off_t)blocks - (nblock - recno);
4939 	recno = nblock;	/* so readtape() reads next time through */
4940 #if SYS_BLOCK > TBLOCK
4941 	nxb = (blkcnt_t)(seekval % (off_t)(SYS_BLOCK / TBLOCK));
4942 #ifdef DEBUG
4943 	DEBUG("xtrablks=%" FMT_blkcnt_t " seekval=%" FMT_blkcnt_t " blks\n",
4944 	    nxb, seekval);
4945 #endif
4946 	if (nxb && nxb > seekval) /* don't seek--we'll read */
4947 		goto noseek;
4948 	seekval -=  nxb;	/* don't seek quite so far */
4949 #endif
4950 	if (lseek(mt, (off_t)(TBLOCK * seekval), 1) == (off_t)-1) {
4951 		(void) fprintf(stderr, gettext(
4952 		    "tar: device seek error\n"));
4953 		done(3);
4954 	}
4955 #if SYS_BLOCK > TBLOCK
4956 	/* read those extra blocks */
4957 noseek:
4958 	if (nxb) {
4959 #ifdef DEBUG
4960 		DEBUG("reading extra blocks\n", 0, 0);
4961 #endif
4962 		if (read(mt, tbuf, TBLOCK*nblock) < 0) {
4963 			(void) fprintf(stderr, gettext(
4964 			    "tar: read error while skipping file\n"));
4965 			done(8);
4966 		}
4967 		recno = nxb;	/* so we don't read in next readtape() */
4968 	}
4969 #endif
4970 }
4971 
4972 static void
4973 readtape(char *buffer)
4974 {
4975 	int i, j;
4976 
4977 	++tapepos;
4978 	if (recno >= nblock || first) {
4979 		if (first) {
4980 			/*
4981 			 * set the number of blocks to read initially, based on
4982 			 * the defined defaults for the device, or on the
4983 			 * explicit block factor given.
4984 			 */
4985 			if (bflag || defaults_used)
4986 				j = nblock;
4987 			else
4988 				j = NBLOCK;
4989 		} else
4990 			j = nblock;
4991 
4992 		if ((i = read(mt, tbuf, TBLOCK*j)) < 0) {
4993 			(void) fprintf(stderr, gettext(
4994 			    "tar: tape read error\n"));
4995 			done(3);
4996 		/*
4997 		 * i == 0 and !rflag means that EOF is reached and we are
4998 		 * trying to update or replace an empty tar file, so exit
4999 		 * with an error.
5000 		 *
5001 		 * If i == 0 and !first and NotTape, it means the pointer
5002 		 * has gone past the EOF. It could happen if two processes
5003 		 * try to update the same tar file simultaneously. So exit
5004 		 * with an error.
5005 		 */
5006 
5007 		} else if (i == 0) {
5008 			if (first && !rflag) {
5009 				(void) fprintf(stderr, gettext(
5010 				    "tar: blocksize = %d\n"), i);
5011 				done(Errflg);
5012 			} else if (!first && (!rflag || NotTape)) {
5013 				mterr("read", 0, 2);
5014 			}
5015 		} else if ((!first || Bflag) && i != TBLOCK*j) {
5016 			/*
5017 			 * Short read - try to get the remaining bytes.
5018 			 */
5019 
5020 			int remaining = (TBLOCK * j) - i;
5021 			char *b = (char *)tbuf + i;
5022 			int r;
5023 
5024 			do {
5025 				if ((r = read(mt, b, remaining)) < 0) {
5026 					(void) fprintf(stderr,
5027 					    gettext("tar: tape read error\n"));
5028 					done(3);
5029 				}
5030 				b += r;
5031 				remaining -= r;
5032 				i += r;
5033 			} while (remaining > 0 && r != 0);
5034 		}
5035 		if (first) {
5036 			if ((i % TBLOCK) != 0) {
5037 				(void) fprintf(stderr, gettext(
5038 				    "tar: tape blocksize error\n"));
5039 				done(3);
5040 			}
5041 			i /= TBLOCK;
5042 			if (vflag && i != nblock && i != 1) {
5043 				if (!NotTape)
5044 					(void) fprintf(stderr, gettext(
5045 					    "tar: blocksize = %d\n"), i);
5046 			}
5047 
5048 			/*
5049 			 * If we are reading a tape, then a short read is
5050 			 * understood to signify that the amount read is
5051 			 * the tape's actual blocking factor.  We adapt
5052 			 * nblock accordingly.  There is no reason to do
5053 			 * this when the device is not blocked.
5054 			 */
5055 
5056 			if (!NotTape)
5057 				nblock = i;
5058 		}
5059 		recno = 0;
5060 	}
5061 
5062 	first = FALSE;
5063 	copy(buffer, &tbuf[recno++]);
5064 }
5065 
5066 
5067 /*
5068  * replacement for writetape.
5069  */
5070 
5071 static int
5072 writetbuf(char *buffer, int n)
5073 {
5074 	int i;
5075 
5076 	tapepos += n;		/* output block count */
5077 
5078 	if (recno >= nblock) {
5079 		i = write(mt, (char *)tbuf, TBLOCK*nblock);
5080 		if (i != TBLOCK*nblock)
5081 			mterr("write", i, 2);
5082 		recno = 0;
5083 	}
5084 
5085 	/*
5086 	 *  Special case:  We have an empty tape buffer, and the
5087 	 *  users data size is >= the tape block size:  Avoid
5088 	 *  the bcopy and dma direct to tape.  BIG WIN.  Add the
5089 	 *  residual to the tape buffer.
5090 	 */
5091 	while (recno == 0 && n >= nblock) {
5092 		i = (int)write(mt, buffer, TBLOCK*nblock);
5093 		if (i != TBLOCK*nblock)
5094 			mterr("write", i, 2);
5095 		n -= nblock;
5096 		buffer += (nblock * TBLOCK);
5097 	}
5098 
5099 	while (n-- > 0) {
5100 		(void) memcpy((char *)&tbuf[recno++], buffer, TBLOCK);
5101 		buffer += TBLOCK;
5102 		if (recno >= nblock) {
5103 			i = (int)write(mt, (char *)tbuf, TBLOCK*nblock);
5104 			if (i != TBLOCK*nblock)
5105 				mterr("write", i, 2);
5106 			recno = 0;
5107 		}
5108 	}
5109 
5110 	/* Tell the user how much to write to get in sync */
5111 	return (nblock - recno);
5112 }
5113 
5114 /*
5115  *	backtape - reposition tape after reading soft "EOF" record
5116  *
5117  *	Backtape tries to reposition the tape back over the EOF
5118  *	record.  This is for the 'u' and 'r' function letters so that the
5119  *	tape can be extended.  This code is not well designed, but
5120  *	I'm confident that the only callers who care about the
5121  *	backspace-over-EOF feature are those involved in 'u' and 'r'.
5122  *
5123  *	The proper way to backup the tape is through the use of mtio.
5124  *	Earlier spins used lseek combined with reads in a confusing
5125  *	maneuver that only worked on 4.x, but shouldn't have, even
5126  *	there.  Lseeks are explicitly not supported for tape devices.
5127  */
5128 
5129 static void
5130 backtape(void)
5131 {
5132 	struct mtop mtcmd;
5133 #ifdef DEBUG
5134 	DEBUG("backtape() called, recno=%" FMT_blkcnt_t " nblock=%d\n", recno,
5135 	    nblock);
5136 #endif
5137 	/*
5138 	 * Backup to the position in the archive where the record
5139 	 * currently sitting in the tbuf buffer is situated.
5140 	 */
5141 
5142 	if (NotTape) {
5143 		/*
5144 		 * For non-tape devices, this means lseeking to the
5145 		 * correct position.  The absolute location tapepos-recno
5146 		 * should be the beginning of the current record.
5147 		 */
5148 
5149 		if (lseek(mt, (off_t)(TBLOCK*(tapepos-recno)), SEEK_SET) ==
5150 		    (off_t)-1) {
5151 			(void) fprintf(stderr,
5152 			    gettext("tar: lseek to end of archive failed\n"));
5153 			done(4);
5154 		}
5155 	} else {
5156 		/*
5157 		 * For tape devices, we backup over the most recently
5158 		 * read record.
5159 		 */
5160 
5161 		mtcmd.mt_op = MTBSR;
5162 		mtcmd.mt_count = 1;
5163 
5164 		if (ioctl(mt, MTIOCTOP, &mtcmd) < 0) {
5165 			(void) fprintf(stderr,
5166 			    gettext("tar: backspace over record failed\n"));
5167 			done(4);
5168 		}
5169 	}
5170 
5171 	/*
5172 	 * Decrement the tape and tbuf buffer indices to prepare for the
5173 	 * coming write to overwrite the soft EOF record.
5174 	 */
5175 
5176 	recno--;
5177 	tapepos--;
5178 }
5179 
5180 
5181 /*
5182  *	flushtape  write buffered block(s) onto tape
5183  *
5184  *      recno points to next free block in tbuf.  If nonzero, a write is done.
5185  *	Care is taken to write in multiples of SYS_BLOCK when device is
5186  *	non-magtape in case raw i/o is used.
5187  *
5188  *	NOTE: this is called by writetape() to do the actual writing
5189  */
5190 
5191 static void
5192 flushtape(void)
5193 {
5194 #ifdef DEBUG
5195 	DEBUG("flushtape() called, recno=%" FMT_blkcnt_t "\n", recno, 0);
5196 #endif
5197 	if (recno > 0) {	/* anything buffered? */
5198 		if (NotTape) {
5199 #if SYS_BLOCK > TBLOCK
5200 			int i;
5201 
5202 			/*
5203 			 * an odd-block write can only happen when
5204 			 * we are at the end of a volume that is not a tape.
5205 			 * Here we round recno up to an even SYS_BLOCK
5206 			 * boundary.
5207 			 */
5208 			if ((i = recno % (SYS_BLOCK / TBLOCK)) != 0) {
5209 #ifdef DEBUG
5210 				DEBUG("flushtape() %d rounding blocks\n", i, 0);
5211 #endif
5212 				recno += i;	/* round up to even SYS_BLOCK */
5213 			}
5214 #endif
5215 			if (recno > nblock)
5216 				recno = nblock;
5217 		}
5218 #ifdef DEBUG
5219 		DEBUG("writing out %" FMT_blkcnt_t " blocks of %" FMT_blkcnt_t
5220 		    " bytes\n", (blkcnt_t)(NotTape ? recno : nblock),
5221 		    (blkcnt_t)(NotTape ? recno : nblock) * TBLOCK);
5222 #endif
5223 		if (write(mt, tbuf,
5224 		    (size_t)(NotTape ? recno : nblock) * TBLOCK) < 0) {
5225 			(void) fprintf(stderr, gettext(
5226 			    "tar: tape write error\n"));
5227 			done(2);
5228 		}
5229 		recno = 0;
5230 	}
5231 }
5232 
5233 static void
5234 copy(void *dst, void *src)
5235 {
5236 	(void) memcpy(dst, src, TBLOCK);
5237 }
5238 
5239 #ifdef	_iBCS2
5240 /*
5241  *	initarg -- initialize things for nextarg.
5242  *
5243  *	argv		filename list, a la argv.
5244  *	filefile	name of file containing filenames.  Unless doing
5245  *		a create, seeks must be allowable (e.g. no named pipes).
5246  *
5247  *	- if filefile is non-NULL, it will be used first, and argv will
5248  *	be used when the data in filefile are exhausted.
5249  *	- otherwise argv will be used.
5250  */
5251 static char **Cmdargv = NULL;
5252 static FILE *FILEFile = NULL;
5253 static long seekFile = -1;
5254 static char *ptrtoFile, *begofFile, *endofFile;
5255 
5256 static	void
5257 initarg(char *argv[], char *filefile)
5258 {
5259 	struct stat statbuf;
5260 	char *p;
5261 	int nbytes;
5262 
5263 	Cmdargv = argv;
5264 	if (filefile == NULL)
5265 		return;		/* no -F file */
5266 	if (FILEFile != NULL) {
5267 		/*
5268 		 * need to REinitialize
5269 		 */
5270 		if (seekFile != -1)
5271 			(void) fseek(FILEFile, seekFile, 0);
5272 		ptrtoFile = begofFile;
5273 		return;
5274 	}
5275 	/*
5276 	 * first time initialization
5277 	 */
5278 	if ((FILEFile = fopen(filefile, "r")) == NULL)
5279 		fatal(gettext("cannot open (%s)"), filefile);
5280 	(void) fstat(fileno(FILEFile), &statbuf);
5281 	if ((statbuf.st_mode & S_IFMT) != S_IFREG) {
5282 		(void) fprintf(stderr, gettext(
5283 		    "tar: %s is not a regular file\n"), filefile);
5284 		(void) fclose(FILEFile);
5285 		done(1);
5286 	}
5287 	ptrtoFile = begofFile = endofFile;
5288 	seekFile = 0;
5289 	if (!xflag)
5290 		return;		/* the file will be read only once anyway */
5291 	nbytes = statbuf.st_size;
5292 	while ((begofFile = calloc(nbytes, sizeof (char))) == NULL)
5293 		nbytes -= 20;
5294 	if (nbytes < 50) {
5295 		free(begofFile);
5296 		begofFile = endofFile;
5297 		return;		/* no room so just do plain reads */
5298 	}
5299 	if (fread(begofFile, 1, nbytes, FILEFile) != nbytes)
5300 		fatal(gettext("could not read %s"), filefile);
5301 	ptrtoFile = begofFile;
5302 	endofFile = begofFile + nbytes;
5303 	for (p = begofFile; p < endofFile; ++p)
5304 		if (*p == '\n')
5305 			*p = '\0';
5306 	if (nbytes != statbuf.st_size)
5307 		seekFile = nbytes + 1;
5308 	else
5309 		(void) fclose(FILEFile);
5310 }
5311 
5312 /*
5313  *	nextarg -- get next argument of arglist.
5314  *
5315  *	The argument is taken from wherever is appropriate.
5316  *
5317  *	If the 'F file' function modifier has been specified, the argument
5318  *	will be taken from the file, unless EOF has been reached.
5319  *	Otherwise the argument will be taken from argv.
5320  *
5321  *	WARNING:
5322  *	  Return value may point to static data, whose contents are over-
5323  *	  written on each call.
5324  */
5325 static	char  *
5326 nextarg(void)
5327 {
5328 	static char nameFile[PATH_MAX + 1];
5329 	int n;
5330 	char *p;
5331 
5332 	if (FILEFile) {
5333 		if (ptrtoFile < endofFile) {
5334 			p = ptrtoFile;
5335 			while (*ptrtoFile)
5336 				++ptrtoFile;
5337 			++ptrtoFile;
5338 			return (p);
5339 		}
5340 		if (fgets(nameFile, PATH_MAX + 1, FILEFile) != NULL) {
5341 			n = strlen(nameFile);
5342 			if (n > 0 && nameFile[n-1] == '\n')
5343 				nameFile[n-1] = '\0';
5344 			return (nameFile);
5345 		}
5346 	}
5347 	return (*Cmdargv++);
5348 }
5349 #endif	/*  _iBCS2 */
5350 
5351 /*
5352  * kcheck()
5353  *	- checks the validity of size values for non-tape devices
5354  *	- if size is zero, mulvol tar is disabled and size is
5355  *	  assumed to be infinite.
5356  *	- returns volume size in TBLOCKS
5357  */
5358 
5359 static blkcnt_t
5360 kcheck(char *kstr)
5361 {
5362 	blkcnt_t kval;
5363 
5364 	kval = strtoll(kstr, NULL, 0);
5365 	if (kval == (blkcnt_t)0) {	/* no multi-volume; size is infinity. */
5366 		mulvol = 0;	/* definitely not mulvol, but we must  */
5367 		return (0);	/* took out setting of NotTape */
5368 	}
5369 	if (kval < (blkcnt_t)MINSIZE) {
5370 		(void) fprintf(stderr, gettext(
5371 		    "tar: sizes below %luK not supported (%" FMT_blkcnt_t
5372 		    ").\n"), (ulong_t)MINSIZE, kval);
5373 		if (!kflag)
5374 			(void) fprintf(stderr, gettext(
5375 			    "bad size entry for %s in %s.\n"),
5376 			    archive, DEF_FILE);
5377 		done(1);
5378 	}
5379 	mulvol++;
5380 	NotTape++;			/* implies non-tape */
5381 	return (kval * 1024 / TBLOCK);	/* convert to TBLOCKS */
5382 }
5383 
5384 
5385 /*
5386  * bcheck()
5387  *	- checks the validity of blocking factors
5388  *	- returns blocking factor
5389  */
5390 
5391 static int
5392 bcheck(char *bstr)
5393 {
5394 	blkcnt_t bval;
5395 
5396 	bval = strtoll(bstr, NULL, 0);
5397 	if ((bval <= 0) || (bval > INT_MAX / TBLOCK)) {
5398 		(void) fprintf(stderr, gettext(
5399 		    "tar: invalid blocksize \"%s\".\n"), bstr);
5400 		if (!bflag)
5401 			(void) fprintf(stderr, gettext(
5402 			    "bad blocksize entry for '%s' in %s.\n"),
5403 			    archive, DEF_FILE);
5404 		done(1);
5405 	}
5406 
5407 	return ((int)bval);
5408 }
5409 
5410 
5411 /*
5412  * defset()
5413  *	- reads DEF_FILE for the set of default values specified.
5414  *	- initializes 'usefile', 'nblock', and 'blocklim', and 'NotTape'.
5415  *	- 'usefile' points to static data, so will be overwritten
5416  *	  if this routine is called a second time.
5417  *	- the pattern specified by 'arch' must be followed by four
5418  *	  blank-separated fields (1) device (2) blocking,
5419  *				 (3) size(K), and (4) tape
5420  *	  for example: archive0=/dev/fd 1 400 n
5421  */
5422 
5423 static int
5424 defset(char *arch)
5425 {
5426 	char *bp;
5427 
5428 	if (defopen(DEF_FILE) != 0)
5429 		return (FALSE);
5430 	if (defcntl(DC_SETFLAGS, (DC_STD & ~(DC_CASE))) == -1) {
5431 		(void) fprintf(stderr, gettext(
5432 		    "tar: error setting parameters for %s.\n"), DEF_FILE);
5433 		return (FALSE);			/* & following ones too */
5434 	}
5435 	if ((bp = defread(arch)) == NULL) {
5436 		(void) fprintf(stderr, gettext(
5437 		    "tar: missing or invalid '%s' entry in %s.\n"),
5438 		    arch, DEF_FILE);
5439 		return (FALSE);
5440 	}
5441 	if ((usefile = strtok(bp, " \t")) == NULL) {
5442 		(void) fprintf(stderr, gettext(
5443 		    "tar: '%s' entry in %s is empty!\n"), arch, DEF_FILE);
5444 		return (FALSE);
5445 	}
5446 	if ((bp = strtok(NULL, " \t")) == NULL) {
5447 		(void) fprintf(stderr, gettext(
5448 		    "tar: block component missing in '%s' entry in %s.\n"),
5449 		    arch, DEF_FILE);
5450 		return (FALSE);
5451 	}
5452 	nblock = bcheck(bp);
5453 	if ((bp = strtok(NULL, " \t")) == NULL) {
5454 		(void) fprintf(stderr, gettext(
5455 		    "tar: size component missing in '%s' entry in %s.\n"),
5456 		    arch, DEF_FILE);
5457 		return (FALSE);
5458 	}
5459 	blocklim = kcheck(bp);
5460 	if ((bp = strtok(NULL, " \t")) != NULL)
5461 		NotTape = (*bp == 'n' || *bp == 'N');
5462 	else
5463 		NotTape = (blocklim != 0);
5464 	(void) defopen(NULL);
5465 #ifdef DEBUG
5466 	DEBUG("defset: archive='%s'; usefile='%s'\n", arch, usefile);
5467 	DEBUG("defset: nblock='%d'; blocklim='%" FMT_blkcnt_t "'\n",
5468 	    nblock, blocklim);
5469 	DEBUG("defset: not tape = %d\n", NotTape, 0);
5470 #endif
5471 	return (TRUE);
5472 }
5473 
5474 
5475 /*
5476  * Following code handles excluded and included files.
5477  * A hash table of file names to be {in,ex}cluded is built.
5478  * For excluded files, before writing or extracting a file
5479  * check to see if it is in the exclude_tbl.
5480  * For included files, the wantit() procedure will check to
5481  * see if the named file is in the include_tbl.
5482  */
5483 
5484 static void
5485 build_table(struct file_list *table[], char *file)
5486 {
5487 	FILE	*fp;
5488 	char	buf[PATH_MAX + 1];
5489 
5490 	if ((fp = fopen(file, "r")) == (FILE *)NULL)
5491 		vperror(1, gettext("could not open %s"), file);
5492 	while (fgets(buf, sizeof (buf), fp) != NULL) {
5493 		if (buf[strlen(buf) - 1] == '\n')
5494 			buf[strlen(buf) - 1] = '\0';
5495 		/* Only add to table if line has something in it */
5496 		if (strspn(buf, " \t") != strlen(buf))
5497 			add_file_to_table(table, buf);
5498 	}
5499 	(void) fclose(fp);
5500 }
5501 
5502 
5503 /*
5504  * Add a file name to the the specified table, if the file name has any
5505  * trailing '/'s then delete them before inserting into the table
5506  */
5507 
5508 static void
5509 add_file_to_table(struct file_list *table[], char *str)
5510 {
5511 	char	name[PATH_MAX + 1];
5512 	unsigned int h;
5513 	struct	file_list	*exp;
5514 
5515 	(void) strcpy(name, str);
5516 	while (name[strlen(name) - 1] == '/') {
5517 		name[strlen(name) - 1] = NULL;
5518 	}
5519 
5520 	h = hash(name);
5521 	if ((exp = (struct file_list *)calloc(sizeof (struct file_list),
5522 	    sizeof (char))) == NULL) {
5523 		(void) fprintf(stderr, gettext(
5524 		    "tar: out of memory, exclude/include table(entry)\n"));
5525 		exit(1);
5526 	}
5527 
5528 	if ((exp->name = strdup(name)) == NULL) {
5529 		(void) fprintf(stderr, gettext(
5530 		    "tar: out of memory, exclude/include table(file name)\n"));
5531 		exit(1);
5532 	}
5533 
5534 	exp->next = table[h];
5535 	table[h] = exp;
5536 }
5537 
5538 
5539 /*
5540  * See if a file name or any of the file's parent directories is in the
5541  * specified table, if the file name has any trailing '/'s then delete
5542  * them before searching the table
5543  */
5544 
5545 static int
5546 is_in_table(struct file_list *table[], char *str)
5547 {
5548 	char	name[PATH_MAX + 1];
5549 	unsigned int	h;
5550 	struct	file_list	*exp;
5551 	char	*ptr;
5552 
5553 	(void) strcpy(name, str);
5554 	while (name[strlen(name) - 1] == '/') {
5555 		name[strlen(name) - 1] = NULL;
5556 	}
5557 
5558 	/*
5559 	 * check for the file name in the passed list
5560 	 */
5561 	h = hash(name);
5562 	exp = table[h];
5563 	while (exp != NULL) {
5564 		if (strcmp(name, exp->name) == 0) {
5565 			return (1);
5566 		}
5567 		exp = exp->next;
5568 	}
5569 
5570 	/*
5571 	 * check for any parent directories in the file list
5572 	 */
5573 	while ((ptr = strrchr(name, '/'))) {
5574 		*ptr = NULL;
5575 		h = hash(name);
5576 		exp = table[h];
5577 		while (exp != NULL) {
5578 			if (strcmp(name, exp->name) == 0) {
5579 				return (1);
5580 			}
5581 			exp = exp->next;
5582 		}
5583 	}
5584 
5585 	return (0);
5586 }
5587 
5588 
5589 /*
5590  * Compute a hash from a string.
5591  */
5592 
5593 static unsigned int
5594 hash(char *str)
5595 {
5596 	char	*cp;
5597 	unsigned int	h;
5598 
5599 	h = 0;
5600 	for (cp = str; *cp; cp++) {
5601 		h += *cp;
5602 	}
5603 	return (h % TABLE_SIZE);
5604 }
5605 
5606 static	void *
5607 getmem(size_t size)
5608 {
5609 	void *p = calloc((unsigned)size, sizeof (char));
5610 
5611 	if (p == NULL && freemem) {
5612 		(void) fprintf(stderr, gettext(
5613 		    "tar: out of memory, link and directory modtime "
5614 		    "info lost\n"));
5615 		freemem = 0;
5616 		if (errflag)
5617 			done(1);
5618 		else
5619 			Errflg = 1;
5620 	}
5621 	return (p);
5622 }
5623 
5624 /*
5625  * vperror() --variable argument perror.
5626  * Takes 3 args: exit_status, formats, args.  If exit_status is 0, then
5627  * the errflag (exit on error) is checked -- if it is non-zero, tar exits
5628  * with the value of whatever "errno" is set to.  If exit_status is not
5629  * zero, then tar exits with that error status. If errflag and exit_status
5630  * are both zero, the routine returns to where it was called and sets Errflg
5631  * to errno.
5632  */
5633 
5634 static void
5635 vperror(int exit_status, char *fmt, ...)
5636 {
5637 	va_list	ap;
5638 
5639 	va_start(ap, fmt);
5640 	(void) fputs("tar: ", stderr);
5641 	(void) vfprintf(stderr, fmt, ap);
5642 	(void) fprintf(stderr, ": %s\n", strerror(errno));
5643 	va_end(ap);
5644 	if (exit_status)
5645 		done(exit_status);
5646 	else
5647 		if (errflag)
5648 			done(errno);
5649 		else
5650 			Errflg = errno;
5651 }
5652 
5653 
5654 static void
5655 fatal(char *format, ...)
5656 {
5657 	va_list	ap;
5658 
5659 	va_start(ap, format);
5660 	(void) fprintf(stderr, "tar: ");
5661 	(void) vfprintf(stderr, format, ap);
5662 	(void) fprintf(stderr, "\n");
5663 	va_end(ap);
5664 	done(1);
5665 }
5666 
5667 
5668 /*
5669  * Check to make sure that argument is a char * ptr.
5670  * Actually, we just check to see that it is non-null.
5671  * If it is null, print out the message and call usage(), bailing out.
5672  */
5673 
5674 static void
5675 assert_string(char *s, char *msg)
5676 {
5677 	if (s == NULL) {
5678 		(void) fprintf(stderr, msg);
5679 		usage();
5680 	}
5681 }
5682 
5683 
5684 static void
5685 mterr(char *operation, int i, int exitcode)
5686 {
5687 	(void) fprintf(stderr, gettext(
5688 	    "tar: %s error: "), operation);
5689 	if (i < 0)
5690 		perror("");
5691 	else
5692 		(void) fprintf(stderr, gettext("unexpected EOF\n"));
5693 	done(exitcode);
5694 }
5695 
5696 static int
5697 wantit(char *argv[], char **namep, char **dirp, char **component,
5698     attr_data_t **attrinfo)
5699 {
5700 	char **cp;
5701 	int gotit;		/* true if we've found a match */
5702 	int ret;
5703 
5704 top:
5705 	if (xhdr_flgs & _X_XHDR) {
5706 		xhdr_flgs = 0;
5707 	}
5708 	getdir();
5709 	if (Xhdrflag > 0) {
5710 		ret = get_xdata();
5711 		if (ret != 0) {	/* Xhdr items and regular header */
5712 			setbytes_to_skip(&stbuf, ret);
5713 			passtape();
5714 			return (0);	/* Error--don't want to extract  */
5715 		}
5716 	}
5717 
5718 	/*
5719 	 * If typeflag is not 'A' and xhdr_flgs is set, then processing
5720 	 * of ancillary file is either over or ancillary file
5721 	 * processing is not required, load info from Xtarhdr and set
5722 	 * _X_XHDR bit in xhdr_flgs.
5723 	 */
5724 	if ((dblock.dbuf.typeflag != 'A') && (xhdr_flgs != 0)) {
5725 		load_info_from_xtarhdr(xhdr_flgs, &Xtarhdr);
5726 		xhdr_flgs |= _X_XHDR;
5727 	}
5728 
5729 #if defined(O_XATTR)
5730 	if (dblock.dbuf.typeflag == _XATTR_HDRTYPE && xattrbadhead == 0) {
5731 		/*
5732 		 * Always needs to read the extended header.  If atflag, saflag,
5733 		 * or tflag isn't set, then we'll have the correct info for
5734 		 * passtape() later.
5735 		 */
5736 		(void) read_xattr_hdr(attrinfo);
5737 		goto top;
5738 	}
5739 	/*
5740 	 * Now that we've read the extended header, call passtape()
5741 	 * if we don't want to restore attributes or system attributes.
5742 	 * Don't restore the attribute if we are extracting
5743 	 * a file from an archive (as opposed to doing a table of
5744 	 * contents) and any of the following are true:
5745 	 * 1. neither -@ or -/ was specified.
5746 	 * 2. -@ was specified, -/ wasn't specified, and we're
5747 	 * processing a hidden attribute directory of an attribute
5748 	 * or we're processing a read-write system attribute file.
5749 	 * 3. -@ wasn't specified, -/ was specified, and the file
5750 	 * we're processing is not a read-write system attribute file,
5751 	 * or we're processing the hidden attribute directory of an
5752 	 * attribute.
5753 	 *
5754 	 * We always process the attributes if we're just generating
5755 	 * generating a table of contents, or if both -@ and -/ were
5756 	 * specified.
5757 	 */
5758 	if (xattrp != NULL) {
5759 		attr_data_t *ainfo = *attrinfo;
5760 
5761 		if (!tflag &&
5762 		    ((!atflag && !saflag) ||
5763 		    (atflag && !saflag && ((ainfo->attr_parent != NULL) ||
5764 		    ainfo->attr_rw_sysattr)) ||
5765 		    (!atflag && saflag && ((ainfo->attr_parent != NULL) ||
5766 		    !ainfo->attr_rw_sysattr)))) {
5767 			passtape();
5768 			return (0);
5769 		}
5770 	}
5771 #endif
5772 
5773 	/* sets *namep to point at the proper name */
5774 	if (check_prefix(namep, dirp, component) != 0) {
5775 		passtape();
5776 		return (0);
5777 	}
5778 
5779 	if (endtape()) {
5780 		if (Bflag) {
5781 			/*
5782 			 * Logically at EOT - consume any extra blocks
5783 			 * so that write to our stdin won't fail and
5784 			 * emit an error message; otherwise something
5785 			 * like "dd if=foo.tar | (cd bar; tar xvf -)"
5786 			 * will produce a bogus error message from "dd".
5787 			 */
5788 
5789 			while (read(mt, tbuf, TBLOCK*nblock) > 0) {
5790 				/* empty body */
5791 			}
5792 		}
5793 		return (-1);
5794 	}
5795 
5796 	gotit = 0;
5797 
5798 	if ((Iflag && is_in_table(include_tbl, *namep)) ||
5799 	    (! Iflag && *argv == NULL)) {
5800 		gotit = 1;
5801 	} else {
5802 		for (cp = argv; *cp; cp++) {
5803 			if (is_prefix(*cp, *namep)) {
5804 				gotit = 1;
5805 				break;
5806 			}
5807 		}
5808 	}
5809 
5810 	if (! gotit) {
5811 		passtape();
5812 		return (0);
5813 	}
5814 
5815 	if (Xflag && is_in_table(exclude_tbl, *namep)) {
5816 		if (vflag) {
5817 			(void) fprintf(stderr, gettext("%s excluded\n"),
5818 			    *namep);
5819 		}
5820 		passtape();
5821 		return (0);
5822 	}
5823 
5824 	return (1);
5825 }
5826 
5827 
5828 static void
5829 setbytes_to_skip(struct stat *st, int err)
5830 {
5831 	/*
5832 	 * In a scenario where a typeflag 'X' was followed by
5833 	 * a typeflag 'A' and typeflag 'O', then the number of
5834 	 * bytes to skip should be the size of ancillary file,
5835 	 * plus the dblock for regular file, and the size
5836 	 * from Xtarhdr. However, if the typeflag was just 'X'
5837 	 * followed by typeflag 'O', then the number of bytes
5838 	 * to skip should be the size from Xtarhdr.
5839 	 */
5840 	if ((err != 0) && (dblock.dbuf.typeflag == 'A') &&
5841 	    (Xhdrflag != 0)) {
5842 		st->st_size += TBLOCK + Xtarhdr.x_filesz;
5843 		xhdr_flgs |= _X_XHDR;
5844 	} else if ((dblock.dbuf.typeflag != 'A') &&
5845 	    (Xhdrflag != 0)) {
5846 		st->st_size = Xtarhdr.x_filesz;
5847 		xhdr_flgs |= _X_XHDR;
5848 	}
5849 }
5850 
5851 static int
5852 fill_in_attr_info(char *attr, char *longname, char *attrparent, int atparentfd,
5853     int rw_sysattr, attr_data_t **attrinfo)
5854 {
5855 	size_t	pathlen;
5856 	char	*tpath;
5857 	char	*tparent;
5858 
5859 	/* parent info */
5860 	if (attrparent != NULL) {
5861 		if ((tparent = strdup(attrparent)) == NULL) {
5862 			vperror(0, gettext(
5863 			    "unable to allocate memory for attribute parent "
5864 			    "name for %sattribute %s/%s of %s"),
5865 			    rw_sysattr ? gettext("system ") : "",
5866 			    attrparent, attr, longname);
5867 			return (1);
5868 		}
5869 	} else {
5870 		tparent = NULL;
5871 	}
5872 
5873 	/* path info */
5874 	pathlen = strlen(attr) + 1;
5875 	if (attrparent != NULL) {
5876 		pathlen += strlen(attrparent) + 1;	/* add 1 for '/' */
5877 	}
5878 	if ((tpath = calloc(1, pathlen)) == NULL) {
5879 		vperror(0, gettext(
5880 		    "unable to allocate memory for full "
5881 		    "attribute path name for %sattribute %s%s%s of %s"),
5882 		    rw_sysattr ? gettext("system ") : "",
5883 		    (attrparent == NULL) ? "" : attrparent,
5884 		    (attrparent == NULL) ? "" : "/",
5885 		    attr, longname);
5886 		if (tparent != NULL) {
5887 			free(tparent);
5888 		}
5889 		return (1);
5890 	}
5891 	(void) snprintf(tpath, pathlen, "%s%s%s",
5892 	    (attrparent == NULL) ? "" : attrparent,
5893 	    (attrparent == NULL) ? "" : "/",
5894 	    attr);
5895 
5896 	/* fill in the attribute info */
5897 	if (*attrinfo == NULL) {
5898 		if ((*attrinfo = malloc(sizeof (attr_data_t))) == NULL) {
5899 			vperror(0, gettext(
5900 			    "unable to allocate memory for attribute "
5901 			    "information for %sattribute %s%s%s of %s"),
5902 			    rw_sysattr ? gettext("system ") : "",
5903 			    (attrparent == NULL) ? "" : attrparent,
5904 			    (attrparent == NULL) ? "" : gettext("/"),
5905 			    attr, longname);
5906 			if (tparent != NULL) {
5907 				free(tparent);
5908 			}
5909 			free(tpath);
5910 			return (1);
5911 		}
5912 	} else {
5913 		if ((*attrinfo)->attr_parent != NULL) {
5914 			free((*attrinfo)->attr_parent);
5915 		}
5916 		if ((*attrinfo)->attr_path != NULL) {
5917 			free((*attrinfo)->attr_path);
5918 		}
5919 		/*
5920 		 * The parent file descriptor is passed in, so don't
5921 		 * close it here as it should be closed by the function
5922 		 * that opened it.
5923 		 */
5924 	}
5925 	(*attrinfo)->attr_parent = tparent;
5926 	(*attrinfo)->attr_path = tpath;
5927 	(*attrinfo)->attr_rw_sysattr = rw_sysattr;
5928 	(*attrinfo)->attr_parentfd = atparentfd;
5929 
5930 	return (0);
5931 }
5932 
5933 /*
5934  *  Return through *namep a pointer to the proper fullname (i.e  "<name> |
5935  *  <prefix>/<name>"), as represented in the header entry dblock.dbuf.
5936  *
5937  * Returns 0 if successful, otherwise returns 1.
5938  */
5939 
5940 static int
5941 check_prefix(char **namep, char **dirp, char **compp)
5942 {
5943 	static char fullname[PATH_MAX + 1];
5944 	static char dir[PATH_MAX + 1];
5945 	static char component[PATH_MAX + 1];
5946 	static char savename[PATH_MAX + 1];
5947 	char *s;
5948 
5949 	(void) memset(dir, 0, sizeof (dir));
5950 	(void) memset(component, 0, sizeof (component));
5951 
5952 	if (xhdr_flgs & _X_PATH) {
5953 		(void) strcpy(fullname, Xtarhdr.x_path);
5954 	} else {
5955 		if (dblock.dbuf.prefix[0] != '\0')
5956 			(void) sprintf(fullname, "%.*s/%.*s", PRESIZ,
5957 			    dblock.dbuf.prefix, NAMSIZ, dblock.dbuf.name);
5958 		else
5959 			(void) sprintf(fullname, "%.*s", NAMSIZ,
5960 			    dblock.dbuf.name);
5961 	}
5962 
5963 	/*
5964 	 * Set dir and component names
5965 	 */
5966 
5967 	get_parent(fullname, dir);
5968 
5969 #if defined(O_XATTR)
5970 	if (xattrp == NULL) {
5971 #endif
5972 		/*
5973 		 * Save of real name since were going to chop off the
5974 		 * trailing slashes.
5975 		 */
5976 		(void) strcpy(savename, fullname);
5977 		/*
5978 		 * first strip of trailing slashes.
5979 		 */
5980 		chop_endslashes(savename);
5981 		s = get_component(savename);
5982 		(void) strcpy(component, s);
5983 
5984 #if defined(O_XATTR)
5985 	} else {
5986 		(void) strcpy(fullname, xattrp->h_names);
5987 		(void) strcpy(dir, fullname);
5988 		(void) strcpy(component, basename(xattrp->h_names +
5989 		    strlen(xattrp->h_names) + 1));
5990 	}
5991 #endif
5992 	*namep = fullname;
5993 	*dirp = dir;
5994 	*compp = component;
5995 
5996 	return (0);
5997 }
5998 
5999 /*
6000  * Return true if the object indicated by the file descriptor and type
6001  * is a tape device, false otherwise
6002  */
6003 
6004 static int
6005 istape(int fd, int type)
6006 {
6007 	int result = 0;
6008 
6009 	if (S_ISCHR(type)) {
6010 		struct mtget mtg;
6011 
6012 		if (ioctl(fd, MTIOCGET, &mtg) != -1) {
6013 			result = 1;
6014 		}
6015 	}
6016 
6017 	return (result);
6018 }
6019 
6020 #include <utmpx.h>
6021 
6022 struct utmpx utmpx;
6023 
6024 #define	NMAX	(sizeof (utmpx.ut_name))
6025 
6026 typedef struct cachenode {	/* this struct must be zeroed before using */
6027 	struct cachenode *next;	/* next in hash chain */
6028 	int val;		/* the uid or gid of this entry */
6029 	int namehash;		/* name's hash signature */
6030 	char name[NMAX+1];	/* the string that val maps to */
6031 } cachenode_t;
6032 
6033 #define	HASHSIZE	256
6034 
6035 static cachenode_t *names[HASHSIZE];
6036 static cachenode_t *groups[HASHSIZE];
6037 static cachenode_t *uids[HASHSIZE];
6038 static cachenode_t *gids[HASHSIZE];
6039 
6040 static int
6041 hash_byname(char *name)
6042 {
6043 	int i, c, h = 0;
6044 
6045 	for (i = 0; i < NMAX; i++) {
6046 		c = name[i];
6047 		if (c == '\0')
6048 			break;
6049 		h = (h << 4) + h + c;
6050 	}
6051 	return (h);
6052 }
6053 
6054 static cachenode_t *
6055 hash_lookup_byval(cachenode_t *table[], int val)
6056 {
6057 	int h = val;
6058 	cachenode_t *c;
6059 
6060 	for (c = table[h & (HASHSIZE - 1)]; c != NULL; c = c->next) {
6061 		if (c->val == val)
6062 			return (c);
6063 	}
6064 	return (NULL);
6065 }
6066 
6067 static cachenode_t *
6068 hash_lookup_byname(cachenode_t *table[], char *name)
6069 {
6070 	int h = hash_byname(name);
6071 	cachenode_t *c;
6072 
6073 	for (c = table[h & (HASHSIZE - 1)]; c != NULL; c = c->next) {
6074 		if (c->namehash == h && strcmp(c->name, name) == 0)
6075 			return (c);
6076 	}
6077 	return (NULL);
6078 }
6079 
6080 static cachenode_t *
6081 hash_insert(cachenode_t *table[], char *name, int value)
6082 {
6083 	cachenode_t *c;
6084 	int signature;
6085 
6086 	c = calloc(1, sizeof (cachenode_t));
6087 	if (c == NULL) {
6088 		perror("malloc");
6089 		exit(1);
6090 	}
6091 	if (name != NULL) {
6092 		(void) strncpy(c->name, name, NMAX);
6093 		c->namehash = hash_byname(name);
6094 	}
6095 	c->val = value;
6096 	if (table == uids || table == gids)
6097 		signature = c->val;
6098 	else
6099 		signature = c->namehash;
6100 	c->next = table[signature & (HASHSIZE - 1)];
6101 	table[signature & (HASHSIZE - 1)] = c;
6102 	return (c);
6103 }
6104 
6105 static char *
6106 getname(uid_t uid)
6107 {
6108 	cachenode_t *c;
6109 
6110 	if ((c = hash_lookup_byval(uids, uid)) == NULL) {
6111 		struct passwd *pwent = getpwuid(uid);
6112 		c = hash_insert(uids, pwent ? pwent->pw_name : NULL, uid);
6113 	}
6114 	return (c->name);
6115 }
6116 
6117 static char *
6118 getgroup(gid_t gid)
6119 {
6120 	cachenode_t *c;
6121 
6122 	if ((c = hash_lookup_byval(gids, gid)) == NULL) {
6123 		struct group *grent = getgrgid(gid);
6124 		c = hash_insert(gids, grent ? grent->gr_name : NULL, gid);
6125 	}
6126 	return (c->name);
6127 }
6128 
6129 static uid_t
6130 getuidbyname(char *name)
6131 {
6132 	cachenode_t *c;
6133 
6134 	if ((c = hash_lookup_byname(names, name)) == NULL) {
6135 		struct passwd *pwent = getpwnam(name);
6136 		c = hash_insert(names, name, pwent ? (int)pwent->pw_uid : -1);
6137 	}
6138 	return ((uid_t)c->val);
6139 }
6140 
6141 static gid_t
6142 getgidbyname(char *group)
6143 {
6144 	cachenode_t *c;
6145 
6146 	if ((c = hash_lookup_byname(groups, group)) == NULL) {
6147 		struct group *grent = getgrnam(group);
6148 		c = hash_insert(groups, group, grent ? (int)grent->gr_gid : -1);
6149 	}
6150 	return ((gid_t)c->val);
6151 }
6152 
6153 /*
6154  * Build the header.
6155  * Determine whether or not an extended header is also needed.  If needed,
6156  * create and write the extended header and its data.
6157  * Writing of the extended header assumes that "tomodes" has been called and
6158  * the relevant information has been placed in the header block.
6159  */
6160 
6161 static int
6162 build_dblock(
6163 	const char		*name,
6164 	const char		*linkname,
6165 	const char		typeflag,
6166 	const int		filetype,
6167 	const struct stat	*sp,
6168 	const dev_t		device,
6169 	const char		*prefix)
6170 {
6171 	int nblks;
6172 	major_t		dev;
6173 	const char	*filename;
6174 	const char	*lastslash;
6175 
6176 	if (filetype == XATTR_FILE)
6177 		dblock.dbuf.typeflag = _XATTR_HDRTYPE;
6178 	else
6179 		dblock.dbuf.typeflag = typeflag;
6180 	(void) memset(dblock.dbuf.name, '\0', NAMSIZ);
6181 	(void) memset(dblock.dbuf.linkname, '\0', NAMSIZ);
6182 	(void) memset(dblock.dbuf.prefix, '\0', PRESIZ);
6183 
6184 	if (xhdr_flgs & _X_PATH)
6185 		filename = Xtarhdr.x_path;
6186 	else
6187 		filename = name;
6188 
6189 	if ((dev = major(device)) > OCTAL7CHAR) {
6190 		if (Eflag) {
6191 			xhdr_flgs |= _X_DEVMAJOR;
6192 			Xtarhdr.x_devmajor = dev;
6193 		} else {
6194 			(void) fprintf(stderr, gettext(
6195 			    "Device major too large for %s.  Use -E flag."),
6196 			    filename);
6197 			if (errflag)
6198 				done(1);
6199 			else
6200 				Errflg = 1;
6201 		}
6202 		dev = 0;
6203 	}
6204 	(void) sprintf(dblock.dbuf.devmajor, "%07lo", dev);
6205 	if ((dev = minor(device)) > OCTAL7CHAR) {
6206 		if (Eflag) {
6207 			xhdr_flgs |= _X_DEVMINOR;
6208 			Xtarhdr.x_devminor = dev;
6209 		} else {
6210 			(void) fprintf(stderr, gettext(
6211 			    "Device minor too large for %s.  Use -E flag."),
6212 			    filename);
6213 			if (errflag)
6214 				done(1);
6215 			else
6216 				Errflg = 1;
6217 		}
6218 		dev = 0;
6219 	}
6220 	(void) sprintf(dblock.dbuf.devminor, "%07lo", dev);
6221 
6222 	(void) strncpy(dblock.dbuf.name, name, NAMSIZ);
6223 	(void) strncpy(dblock.dbuf.linkname, linkname, NAMSIZ);
6224 	(void) sprintf(dblock.dbuf.magic, "%.5s", magic_type);
6225 	(void) sprintf(dblock.dbuf.version, "00");
6226 	(void) sprintf(dblock.dbuf.uname, "%.31s", getname(sp->st_uid));
6227 	(void) sprintf(dblock.dbuf.gname, "%.31s", getgroup(sp->st_gid));
6228 	(void) strncpy(dblock.dbuf.prefix, prefix, PRESIZ);
6229 	(void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock));
6230 
6231 	if (Eflag) {
6232 		(void) bcopy(dblock.dummy, xhdr_buf.dummy, TBLOCK);
6233 		(void) memset(xhdr_buf.dbuf.name, '\0', NAMSIZ);
6234 		lastslash = strrchr(name, '/');
6235 		if (lastslash == NULL)
6236 			lastslash = name;
6237 		else
6238 			lastslash++;
6239 		(void) strcpy(xhdr_buf.dbuf.name, lastslash);
6240 		(void) memset(xhdr_buf.dbuf.linkname, '\0', NAMSIZ);
6241 		(void) memset(xhdr_buf.dbuf.prefix, '\0', PRESIZ);
6242 		(void) strcpy(xhdr_buf.dbuf.prefix, xhdr_dirname);
6243 		xhdr_count++;
6244 		xrec_offset = 0;
6245 		gen_date("mtime", sp->st_mtim);
6246 		xhdr_buf.dbuf.typeflag = 'X';
6247 		if (gen_utf8_names(filename) != 0)
6248 			return (1);
6249 
6250 #ifdef XHDR_DEBUG
6251 		Xtarhdr.x_uname = dblock.dbuf.uname;
6252 		Xtarhdr.x_gname = dblock.dbuf.gname;
6253 		xhdr_flgs |= (_X_UNAME | _X_GNAME);
6254 #endif
6255 		if (xhdr_flgs) {
6256 			if (xhdr_flgs & _X_DEVMAJOR)
6257 				gen_num("SUN.devmajor", Xtarhdr.x_devmajor);
6258 			if (xhdr_flgs & _X_DEVMINOR)
6259 				gen_num("SUN.devminor", Xtarhdr.x_devminor);
6260 			if (xhdr_flgs & _X_GID)
6261 				gen_num("gid", Xtarhdr.x_gid);
6262 			if (xhdr_flgs & _X_UID)
6263 				gen_num("uid", Xtarhdr.x_uid);
6264 			if (xhdr_flgs & _X_SIZE)
6265 				gen_num("size", Xtarhdr.x_filesz);
6266 			if (xhdr_flgs & _X_PATH)
6267 				gen_string("path", Xtarhdr.x_path);
6268 			if (xhdr_flgs & _X_LINKPATH)
6269 				gen_string("linkpath", Xtarhdr.x_linkpath);
6270 			if (xhdr_flgs & _X_GNAME)
6271 				gen_string("gname", Xtarhdr.x_gname);
6272 			if (xhdr_flgs & _X_UNAME)
6273 				gen_string("uname", Xtarhdr.x_uname);
6274 		}
6275 		(void) sprintf(xhdr_buf.dbuf.size,
6276 		    "%011" FMT_off_t_o, xrec_offset);
6277 		(void) sprintf(xhdr_buf.dbuf.chksum, "%07o",
6278 		    checksum(&xhdr_buf));
6279 		(void) writetbuf((char *)&xhdr_buf, 1);
6280 		nblks = TBLOCKS(xrec_offset);
6281 		(void) writetbuf(xrec_ptr, nblks);
6282 	}
6283 	return (0);
6284 }
6285 
6286 
6287 /*
6288  *  makeDir - ensure that a directory with the pathname denoted by name
6289  *            exists, and return 1 on success, and 0 on failure (e.g.,
6290  *	      read-only file system, exists but not-a-directory).
6291  */
6292 
6293 static int
6294 makeDir(char *name)
6295 {
6296 	struct stat buf;
6297 
6298 	if (access(name, 0) < 0) {  /* name doesn't exist */
6299 		if (mkdir(name, 0777) < 0) {
6300 			vperror(0, "%s", name);
6301 			return (0);
6302 		}
6303 	} else {		   /* name exists */
6304 		if (stat(name, &buf) < 0) {
6305 			vperror(0, "%s", name);
6306 			return (0);
6307 		}
6308 
6309 		return ((buf.st_mode & S_IFMT) == S_IFDIR);
6310 	}
6311 
6312 	return (1);
6313 }
6314 
6315 
6316 /*
6317  * Save this directory and its mtime on the stack, popping and setting
6318  * the mtimes of any stacked dirs which aren't parents of this one.
6319  * A null name causes the entire stack to be unwound and set.
6320  *
6321  * Since all the elements of the directory "stack" share a common
6322  * prefix, we can make do with one string.  We keep only the current
6323  * directory path, with an associated array of mtime's. A negative
6324  * mtime means no mtime.
6325  *
6326  * This stack algorithm is not guaranteed to work for tapes created
6327  * with the 'r' function letter, but the vast majority of tapes with
6328  * directories are not.  This avoids saving every directory record on
6329  * the tape and setting all the times at the end.
6330  *
6331  * (This was borrowed from the 4.1.3 source, and adapted to the 5.x
6332  *  environment)
6333  */
6334 
6335 static void
6336 doDirTimes(char *name, timestruc_t modTime)
6337 {
6338 	static char dirstack[PATH_MAX+2];
6339 			/* Add spaces for the last slash and last NULL */
6340 	static timestruc_t	modtimes[PATH_MAX+1]; /* hash table */
6341 	char *p = dirstack;
6342 	char *q = name;
6343 	char *savp;
6344 
6345 	if (q) {
6346 		/*
6347 		 * Find common prefix
6348 		 */
6349 
6350 		while (*p == *q && *p) {
6351 			p++; q++;
6352 		}
6353 	}
6354 
6355 	savp = p;
6356 	while (*p) {
6357 		/*
6358 		 * Not a child: unwind the stack, setting the times.
6359 		 * The order we do this doesn't matter, so we go "forward."
6360 		 */
6361 
6362 		if (*p == '/')
6363 			if (modtimes[p - dirstack].tv_sec >= 0) {
6364 				*p = '\0';	 /* zap the slash */
6365 				setPathTimes(AT_FDCWD, dirstack,
6366 				    modtimes[p - dirstack]);
6367 				*p = '/';
6368 			}
6369 		++p;
6370 	}
6371 
6372 	p = savp;
6373 
6374 	/*
6375 	 *  Push this one on the "stack"
6376 	 */
6377 
6378 	if (q) {
6379 
6380 		/*
6381 		 * Since the name parameter points the dir pathname
6382 		 * which is limited only to contain PATH_MAX chars
6383 		 * at maximum, we can ignore the overflow case of p.
6384 		 */
6385 
6386 		while ((*p = *q++)) {	/* append the rest of the new dir */
6387 			modtimes[p - dirstack].tv_sec = -1;
6388 			p++;
6389 		}
6390 
6391 		/*
6392 		 * If the tar file had used 'P' or 'E' function modifier,
6393 		 * append the last slash.
6394 		 */
6395 		if (*(p - 1) != '/') {
6396 			*p++ = '/';
6397 			*p = '\0';
6398 		}
6399 		/* overwrite the last one */
6400 		modtimes[p - dirstack - 1] = modTime;
6401 	}
6402 }
6403 
6404 
6405 /*
6406  *  setPathTimes - set the modification time for given path.  Return 1 if
6407  *                 successful and 0 if not successful.
6408  */
6409 
6410 static void
6411 setPathTimes(int dirfd, char *path, timestruc_t modTime)
6412 
6413 {
6414 	struct timeval timebuf[2];
6415 
6416 	/*
6417 	 * futimesat takes an array of two timeval structs.
6418 	 * The first entry contains access time.
6419 	 * The second entry contains modification time.
6420 	 * Unlike a timestruc_t, which uses nanoseconds, timeval uses
6421 	 * microseconds.
6422 	 */
6423 	timebuf[0].tv_sec = time((time_t *)0);
6424 	timebuf[0].tv_usec = 0;
6425 	timebuf[1].tv_sec = modTime.tv_sec;
6426 
6427 	/* Extended header: use microseconds */
6428 	timebuf[1].tv_usec = (xhdr_flgs & _X_MTIME) ? modTime.tv_nsec/1000 : 0;
6429 
6430 	if (futimesat(dirfd, path, timebuf) < 0)
6431 		vperror(0, "can't set time on %s", path);
6432 }
6433 
6434 
6435 /*
6436  * If hflag is set then delete the symbolic link's target.
6437  * If !hflag then delete the target.
6438  */
6439 
6440 static void
6441 delete_target(int fd, char *comp, char *namep)
6442 {
6443 	struct	stat	xtractbuf;
6444 	char buf[PATH_MAX + 1];
6445 	int n;
6446 
6447 
6448 	if (unlinkat(fd, comp, AT_REMOVEDIR) < 0) {
6449 		if (errno == ENOTDIR && !hflag) {
6450 			(void) unlinkat(fd, comp, 0);
6451 		} else if (errno == ENOTDIR && hflag) {
6452 			if (!lstat(namep, &xtractbuf)) {
6453 				if ((xtractbuf.st_mode & S_IFMT) != S_IFLNK) {
6454 					(void) unlinkat(fd, comp, 0);
6455 				} else if ((n = readlink(namep, buf,
6456 				    PATH_MAX)) != -1) {
6457 					buf[n] = (char)NULL;
6458 					(void) unlinkat(fd, buf,
6459 					    AT_REMOVEDIR);
6460 					if (errno == ENOTDIR)
6461 						(void) unlinkat(fd, buf, 0);
6462 				} else {
6463 					(void) unlinkat(fd, comp, 0);
6464 				}
6465 			} else {
6466 				(void) unlinkat(fd, comp, 0);
6467 			}
6468 		}
6469 	}
6470 }
6471 
6472 
6473 /*
6474  * ACL changes:
6475  *	putfile():
6476  *		Get acl info after stat. Write out ancillary file
6477  *		before the normal file, i.e. directory, regular, FIFO,
6478  *		link, special. If acl count is less than 4, no need to
6479  *		create ancillary file. (i.e. standard permission is in
6480  *		use.
6481  *	doxtract():
6482  *		Process ancillary file. Read it in and set acl info.
6483  *		watch out for 'o' function modifier.
6484  *	't' function letter to display table
6485  */
6486 
6487 /*
6488  * New functions for ACLs and other security attributes
6489  */
6490 
6491 /*
6492  * The function appends the new security attribute info to the end of
6493  * existing secinfo.
6494  */
6495 int
6496 append_secattr(
6497 	char	 **secinfo,	/* existing security info */
6498 	int	 *secinfo_len,	/* length of existing security info */
6499 	int	 size,		/* new attribute size: unit depends on type */
6500 	char	*attrtext,	/* new attribute text */
6501 	char	 attr_type)	/* new attribute type */
6502 {
6503 	char	*new_secinfo;
6504 	int	newattrsize;
6505 	int	oldsize;
6506 	struct sec_attr	*attr;
6507 
6508 	/* no need to add */
6509 	if (attr_type != DIR_TYPE) {
6510 		if (attrtext == NULL)
6511 			return (0);
6512 	}
6513 
6514 	switch (attr_type) {
6515 	case UFSD_ACL:
6516 	case ACE_ACL:
6517 		if (attrtext == NULL) {
6518 			(void) fprintf(stderr, "acltotext failed\n");
6519 			return (-1);
6520 		}
6521 		/* header: type + size = 8 */
6522 		newattrsize = 8 + (int)strlen(attrtext) + 1;
6523 		attr = (struct sec_attr *)malloc(newattrsize);
6524 		if (attr == NULL) {
6525 			(void) fprintf(stderr, "can't allocate memory\n");
6526 			return (-1);
6527 		}
6528 		attr->attr_type = attr_type;
6529 		(void) sprintf(attr->attr_len,
6530 		    "%06o", size); /* acl entry count */
6531 		(void) strcpy((char *)&attr->attr_info[0], attrtext);
6532 		free(attrtext);
6533 		break;
6534 
6535 	/* Trusted Extensions */
6536 	case DIR_TYPE:
6537 	case LBL_TYPE:
6538 		newattrsize = sizeof (struct sec_attr) + strlen(attrtext);
6539 		attr = (struct sec_attr *)malloc(newattrsize);
6540 		if (attr == NULL) {
6541 			(void) fprintf(stderr,
6542 			gettext("can't allocate memory\n"));
6543 			return (-1);
6544 		}
6545 		attr->attr_type = attr_type;
6546 		(void) sprintf(attr->attr_len,
6547 		    "%06d", size); /* len of attr data */
6548 		(void) strcpy((char *)&attr->attr_info[0], attrtext);
6549 		break;
6550 
6551 	default:
6552 		(void) fprintf(stderr, "unrecognized attribute type\n");
6553 		return (-1);
6554 	}
6555 
6556 	/* old security info + new attr header(8) + new attr */
6557 	oldsize = *secinfo_len;
6558 	*secinfo_len += newattrsize;
6559 	new_secinfo = (char *)malloc(*secinfo_len);
6560 	if (new_secinfo == NULL) {
6561 		(void) fprintf(stderr, "can't allocate memory\n");
6562 		*secinfo_len -= newattrsize;
6563 		free(attr);
6564 		return (-1);
6565 	}
6566 
6567 	(void) memcpy(new_secinfo, *secinfo, oldsize);
6568 	(void) memcpy(new_secinfo + oldsize, attr, newattrsize);
6569 
6570 	free(*secinfo);
6571 	free(attr);
6572 	*secinfo = new_secinfo;
6573 	return (0);
6574 }
6575 
6576 /*
6577  * write_ancillary(): write out an ancillary file.
6578  *      The file has the same header as normal file except the type and size
6579  *      fields. The type is 'A' and size is the sum of all attributes
6580  *	in bytes.
6581  *	The body contains a list of attribute type, size and info. Currently,
6582  *	there is only ACL info.  This file is put before the normal file.
6583  */
6584 void
6585 write_ancillary(union hblock *dblockp, char *secinfo, int len, char hdrtype)
6586 {
6587 	long    blocks;
6588 	int	savflag;
6589 	int	savsize;
6590 
6591 	/* Just tranditional permissions or no security attribute info */
6592 	if (len == 0 || secinfo == NULL)
6593 		return;
6594 
6595 	/* save flag and size */
6596 	savflag = (dblockp->dbuf).typeflag;
6597 	(void) sscanf(dblockp->dbuf.size, "%12o", (uint_t *)&savsize);
6598 
6599 	/* special flag for ancillary file */
6600 	if (hdrtype == _XATTR_HDRTYPE)
6601 		dblockp->dbuf.typeflag = _XATTR_HDRTYPE;
6602 	else
6603 		dblockp->dbuf.typeflag = 'A';
6604 
6605 	/* for pre-2.5 versions of tar, need to make sure */
6606 	/* the ACL file is readable			  */
6607 	(void) sprintf(dblock.dbuf.mode, "%07lo",
6608 	    (stbuf.st_mode & POSIXMODES) | 0000200);
6609 	(void) sprintf(dblockp->dbuf.size, "%011o", len);
6610 	(void) sprintf(dblockp->dbuf.chksum, "%07o", checksum(dblockp));
6611 
6612 	/* write out the header */
6613 	(void) writetbuf((char *)dblockp, 1);
6614 
6615 	/* write out security info */
6616 	blocks = TBLOCKS(len);
6617 	(void) writetbuf((char *)secinfo, (int)blocks);
6618 
6619 	/* restore mode, flag and size */
6620 	(void) sprintf(dblock.dbuf.mode, "%07lo", stbuf.st_mode & POSIXMODES);
6621 	dblockp->dbuf.typeflag = savflag;
6622 	(void) sprintf(dblockp->dbuf.size, "%011o", savsize);
6623 }
6624 
6625 /*
6626  * Read the data record for extended headers and then the regular header.
6627  * The data are read into the buffer and then null-terminated.  Entries
6628  * are of the format:
6629  * 	"%d %s=%s\n"
6630  *
6631  * When an extended header record is found, the extended header must
6632  * be processed and its values used to override the values in the
6633  * normal header.  The way this is done is to process the extended
6634  * header data record and set the data values, then call getdir
6635  * to process the regular header, then then to reconcile the two
6636  * sets of data.
6637  */
6638 
6639 static int
6640 get_xdata(void)
6641 {
6642 	struct keylist_pair {
6643 		int keynum;
6644 		char *keylist;
6645 	}	keylist_pair[] = {	_X_DEVMAJOR, "SUN.devmajor",
6646 					_X_DEVMINOR, "SUN.devminor",
6647 					_X_GID, "gid",
6648 					_X_GNAME, "gname",
6649 					_X_LINKPATH, "linkpath",
6650 					_X_PATH, "path",
6651 					_X_SIZE, "size",
6652 					_X_UID, "uid",
6653 					_X_UNAME, "uname",
6654 					_X_MTIME, "mtime",
6655 					_X_LAST, "NULL" };
6656 	char		*lineloc;
6657 	int		length, i;
6658 	char		*keyword, *value;
6659 	blkcnt_t	nblocks;
6660 	int		bufneeded;
6661 	int		errors;
6662 
6663 	(void) memset(&Xtarhdr, 0, sizeof (Xtarhdr));
6664 	xhdr_count++;
6665 	errors = 0;
6666 
6667 	nblocks = TBLOCKS(stbuf.st_size);
6668 	bufneeded = nblocks * TBLOCK;
6669 	if (bufneeded >= xrec_size) {
6670 		free(xrec_ptr);
6671 		xrec_size = bufneeded + 1;
6672 		if ((xrec_ptr = malloc(xrec_size)) == NULL)
6673 			fatal(gettext("cannot allocate buffer"));
6674 	}
6675 
6676 	lineloc = xrec_ptr;
6677 
6678 	while (nblocks-- > 0) {
6679 		readtape(lineloc);
6680 		lineloc += TBLOCK;
6681 	}
6682 	lineloc = xrec_ptr;
6683 	xrec_ptr[stbuf.st_size] = '\0';
6684 	while (lineloc < xrec_ptr + stbuf.st_size) {
6685 		length = atoi(lineloc);
6686 		*(lineloc + length - 1) = '\0';
6687 		keyword = strchr(lineloc, ' ') + 1;
6688 		value = strchr(keyword, '=') + 1;
6689 		*(value - 1) = '\0';
6690 		i = 0;
6691 		lineloc += length;
6692 		while (keylist_pair[i].keynum != (int)_X_LAST) {
6693 			if (strcmp(keyword, keylist_pair[i].keylist) == 0)
6694 				break;
6695 			i++;
6696 		}
6697 		errno = 0;
6698 		switch (keylist_pair[i].keynum) {
6699 		case _X_DEVMAJOR:
6700 			Xtarhdr.x_devmajor = (major_t)strtoul(value, NULL, 0);
6701 			if (errno) {
6702 				(void) fprintf(stderr, gettext(
6703 				    "tar: Extended header major value error "
6704 				    "for file # %llu.\n"), xhdr_count);
6705 				errors++;
6706 			} else
6707 				xhdr_flgs |= _X_DEVMAJOR;
6708 			break;
6709 		case _X_DEVMINOR:
6710 			Xtarhdr.x_devminor = (minor_t)strtoul(value, NULL, 0);
6711 			if (errno) {
6712 				(void) fprintf(stderr, gettext(
6713 				    "tar: Extended header minor value error "
6714 				    "for file # %llu.\n"), xhdr_count);
6715 				errors++;
6716 			} else
6717 				xhdr_flgs |= _X_DEVMINOR;
6718 			break;
6719 		case _X_GID:
6720 			xhdr_flgs |= _X_GID;
6721 			Xtarhdr.x_gid = strtol(value, NULL, 0);
6722 			if ((errno) || (Xtarhdr.x_gid > UID_MAX)) {
6723 				(void) fprintf(stderr, gettext(
6724 				    "tar: Extended header gid value error "
6725 				    "for file # %llu.\n"), xhdr_count);
6726 				Xtarhdr.x_gid = GID_NOBODY;
6727 			}
6728 			break;
6729 		case _X_GNAME:
6730 			if (utf8_local("gname", &Xtarhdr.x_gname,
6731 			    local_gname, value, _POSIX_NAME_MAX) == 0)
6732 				xhdr_flgs |= _X_GNAME;
6733 			break;
6734 		case _X_LINKPATH:
6735 			if (utf8_local("linkpath", &Xtarhdr.x_linkpath,
6736 			    local_linkpath, value, PATH_MAX) == 0)
6737 				xhdr_flgs |= _X_LINKPATH;
6738 			else
6739 				errors++;
6740 			break;
6741 		case _X_PATH:
6742 			if (utf8_local("path", &Xtarhdr.x_path,
6743 			    local_path, value, PATH_MAX) == 0)
6744 				xhdr_flgs |= _X_PATH;
6745 			else
6746 				errors++;
6747 			break;
6748 		case _X_SIZE:
6749 			Xtarhdr.x_filesz = strtoull(value, NULL, 0);
6750 			if (errno) {
6751 				(void) fprintf(stderr, gettext(
6752 				    "tar: Extended header invalid filesize "
6753 				    "for file # %llu.\n"), xhdr_count);
6754 				errors++;
6755 			} else
6756 				xhdr_flgs |= _X_SIZE;
6757 			break;
6758 		case _X_UID:
6759 			xhdr_flgs |= _X_UID;
6760 			Xtarhdr.x_uid = strtol(value, NULL, 0);
6761 			if ((errno) || (Xtarhdr.x_uid > UID_MAX)) {
6762 				(void) fprintf(stderr, gettext(
6763 				    "tar: Extended header uid value error "
6764 				    "for file # %llu.\n"), xhdr_count);
6765 				Xtarhdr.x_uid = UID_NOBODY;
6766 			}
6767 			break;
6768 		case _X_UNAME:
6769 			if (utf8_local("uname", &Xtarhdr.x_uname,
6770 			    local_uname, value, _POSIX_NAME_MAX) == 0)
6771 				xhdr_flgs |= _X_UNAME;
6772 			break;
6773 		case _X_MTIME:
6774 			get_xtime(value, &(Xtarhdr.x_mtime));
6775 			if (errno)
6776 				(void) fprintf(stderr, gettext(
6777 				    "tar: Extended header modification time "
6778 				    "value error for file # %llu.\n"),
6779 				    xhdr_count);
6780 			else
6781 				xhdr_flgs |= _X_MTIME;
6782 			break;
6783 		default:
6784 			(void) fprintf(stderr,
6785 			    gettext("tar:  unrecognized extended"
6786 			    " header keyword '%s'.  Ignored.\n"), keyword);
6787 			break;
6788 		}
6789 	}
6790 
6791 	getdir();	/* get regular header */
6792 	if (errors && errflag)
6793 		done(1);
6794 	else
6795 		if (errors)
6796 			Errflg = 1;
6797 	return (errors);
6798 }
6799 
6800 /*
6801  * load_info_from_xtarhdr - sets Gen and stbuf variables from
6802  *	extended header
6803  *	load_info_from_xtarhdr(flag, xhdrp);
6804  *	u_longlong_t flag;	xhdr_flgs
6805  *	struct xtar_hdr *xhdrp; pointer to extended header
6806  *	NOTE:	called when typeflag is not 'A' and xhdr_flgs
6807  *		is set.
6808  */
6809 static void
6810 load_info_from_xtarhdr(u_longlong_t flag, struct xtar_hdr *xhdrp)
6811 {
6812 	if (flag & _X_DEVMAJOR) {
6813 		Gen.g_devmajor = xhdrp->x_devmajor;
6814 	}
6815 	if (flag & _X_DEVMINOR) {
6816 		Gen.g_devminor = xhdrp->x_devminor;
6817 	}
6818 	if (flag & _X_GID) {
6819 		Gen.g_gid = xhdrp->x_gid;
6820 		stbuf.st_gid = xhdrp->x_gid;
6821 	}
6822 	if (flag & _X_UID) {
6823 		Gen.g_uid = xhdrp->x_uid;
6824 		stbuf.st_uid  = xhdrp->x_uid;
6825 	}
6826 	if (flag & _X_SIZE) {
6827 		Gen.g_filesz = xhdrp->x_filesz;
6828 		stbuf.st_size = xhdrp->x_filesz;
6829 	}
6830 	if (flag & _X_MTIME) {
6831 		Gen.g_mtime = xhdrp->x_mtime.tv_sec;
6832 		stbuf.st_mtim.tv_sec = xhdrp->x_mtime.tv_sec;
6833 		stbuf.st_mtim.tv_nsec = xhdrp->x_mtime.tv_nsec;
6834 	}
6835 }
6836 
6837 /*
6838  * gen_num creates a string from a keyword and an usigned long long in the
6839  * format:  %d %s=%s\n
6840  * This is part of the extended header data record.
6841  */
6842 
6843 void
6844 gen_num(const char *keyword, const u_longlong_t number)
6845 {
6846 	char	save_val[ULONGLONG_MAX_DIGITS + 1];
6847 	int	len;
6848 	char	*curr_ptr;
6849 
6850 	(void) sprintf(save_val, "%llu", number);
6851 	/*
6852 	 * len = length of entire line, including itself.  len will be
6853 	 * two digits.  So, add the string lengths plus the length of len,
6854 	 * plus a blank, an equal sign, and a newline.
6855 	 */
6856 	len = strlen(save_val) + strlen(keyword) + 5;
6857 	if (xrec_offset + len > xrec_size) {
6858 		if (((curr_ptr = realloc(xrec_ptr, 2 * xrec_size)) == NULL))
6859 			fatal(gettext(
6860 			    "cannot allocate extended header buffer"));
6861 		xrec_ptr = curr_ptr;
6862 		xrec_size *= 2;
6863 	}
6864 	(void) sprintf(&xrec_ptr[xrec_offset],
6865 	    "%d %s=%s\n", len, keyword, save_val);
6866 	xrec_offset += len;
6867 }
6868 
6869 /*
6870  * gen_date creates a string from a keyword and a timestruc_t in the
6871  * format:  %d %s=%s\n
6872  * This is part of the extended header data record.
6873  * Currently, granularity is only microseconds, so the low-order three digits
6874  * will be truncated.
6875  */
6876 
6877 void
6878 gen_date(const char *keyword, const timestruc_t time_value)
6879 {
6880 	/* Allow for <seconds>.<nanoseconds>\n */
6881 	char	save_val[TIME_MAX_DIGITS + LONG_MAX_DIGITS + 2];
6882 	int	len;
6883 	char	*curr_ptr;
6884 
6885 	(void) sprintf(save_val, "%ld", time_value.tv_sec);
6886 	len = strlen(save_val);
6887 	save_val[len] = '.';
6888 	(void) sprintf(&save_val[len + 1], "%9.9ld", time_value.tv_nsec);
6889 
6890 	/*
6891 	 * len = length of entire line, including itself.  len will be
6892 	 * two digits.  So, add the string lengths plus the length of len,
6893 	 * plus a blank, an equal sign, and a newline.
6894 	 */
6895 	len = strlen(save_val) + strlen(keyword) + 5;
6896 	if (xrec_offset + len > xrec_size) {
6897 		if (((curr_ptr = realloc(xrec_ptr, 2 * xrec_size)) == NULL))
6898 			fatal(gettext(
6899 			    "cannot allocate extended header buffer"));
6900 		xrec_ptr = curr_ptr;
6901 		xrec_size *= 2;
6902 	}
6903 	(void) sprintf(&xrec_ptr[xrec_offset],
6904 	    "%d %s=%s\n", len, keyword, save_val);
6905 	xrec_offset += len;
6906 }
6907 
6908 /*
6909  * gen_string creates a string from a keyword and a char * in the
6910  * format:  %d %s=%s\n
6911  * This is part of the extended header data record.
6912  */
6913 
6914 void
6915 gen_string(const char *keyword, const char *value)
6916 {
6917 	int	len;
6918 	char	*curr_ptr;
6919 
6920 	/*
6921 	 * len = length of entire line, including itself.  The character length
6922 	 * of len must be 1-4 characters, because the maximum size of the path
6923 	 * or the name is PATH_MAX, which is 1024.  So, assume 1 character
6924 	 * for len, one for the space, one for the "=", and one for the newline.
6925 	 * Then adjust as needed.
6926 	 */
6927 	/* LINTED constant expression */
6928 	assert(PATH_MAX <= 9996);
6929 	len = strlen(value) + strlen(keyword) + 4;
6930 	if (len > 997)
6931 		len += 3;
6932 	else if (len > 98)
6933 		len += 2;
6934 	else if (len > 9)
6935 		len += 1;
6936 	if (xrec_offset + len > xrec_size) {
6937 		if (((curr_ptr = realloc(xrec_ptr, 2 * xrec_size)) == NULL))
6938 			fatal(gettext(
6939 			    "cannot allocate extended header buffer"));
6940 		xrec_ptr = curr_ptr;
6941 		xrec_size *= 2;
6942 	}
6943 #ifdef XHDR_DEBUG
6944 	if (strcmp(keyword+1, "name") != 0)
6945 #endif
6946 	(void) sprintf(&xrec_ptr[xrec_offset],
6947 	    "%d %s=%s\n", len, keyword, value);
6948 #ifdef XHDR_DEBUG
6949 	else {
6950 	len += 11;
6951 	(void) sprintf(&xrec_ptr[xrec_offset],
6952 	    "%d %s=%snametoolong\n", len, keyword, value);
6953 	}
6954 #endif
6955 	xrec_offset += len;
6956 }
6957 
6958 /*
6959  * Convert time found in the extended header data to seconds and nanoseconds.
6960  */
6961 
6962 void
6963 get_xtime(char *value, timestruc_t *xtime)
6964 {
6965 	char nanosec[10];
6966 	char *period;
6967 	int i;
6968 
6969 	(void) memset(nanosec, '0', 9);
6970 	nanosec[9] = '\0';
6971 
6972 	period = strchr(value, '.');
6973 	if (period != NULL)
6974 		period[0] = '\0';
6975 	xtime->tv_sec = strtol(value, NULL, 10);
6976 	if (period == NULL)
6977 		xtime->tv_nsec = 0;
6978 	else {
6979 		i = strlen(period +1);
6980 		(void) strncpy(nanosec, period + 1, min(i, 9));
6981 		xtime->tv_nsec = strtol(nanosec, NULL, 10);
6982 	}
6983 }
6984 
6985 /*
6986  *	Check linkpath for length.
6987  *	Emit an error message and return 1 if too long.
6988  */
6989 
6990 int
6991 chk_path_build(
6992 	char	*name,
6993 	char	*longname,
6994 	char	*linkname,
6995 	char	*prefix,
6996 	char	type,
6997 	int	filetype)
6998 {
6999 
7000 	if (strlen(linkname) > (size_t)NAMSIZ) {
7001 		if (Eflag > 0) {
7002 			xhdr_flgs |= _X_LINKPATH;
7003 			Xtarhdr.x_linkpath = linkname;
7004 		} else {
7005 			(void) fprintf(stderr, gettext(
7006 			    "tar: %s: linked to %s\n"), longname, linkname);
7007 			(void) fprintf(stderr, gettext(
7008 			    "tar: %s: linked name too long\n"), linkname);
7009 			if (errflag)
7010 				done(1);
7011 			else
7012 				Errflg = 1;
7013 			return (1);
7014 		}
7015 	}
7016 	if (xhdr_flgs & _X_LINKPATH)
7017 		return (build_dblock(name, tchar, type,
7018 		    filetype, &stbuf, stbuf.st_dev,
7019 		    prefix));
7020 	else
7021 		return (build_dblock(name, linkname, type,
7022 		    filetype, &stbuf, stbuf.st_dev, prefix));
7023 }
7024 
7025 /*
7026  * Convert from UTF-8 to local character set.
7027  */
7028 
7029 static int
7030 utf8_local(
7031 	char		*option,
7032 	char		**Xhdr_ptrptr,
7033 	char		*target,
7034 	const char	*source,
7035 	int		max_val)
7036 {
7037 	static	iconv_t	iconv_cd;
7038 	char		*nl_target;
7039 	const	char	*iconv_src;
7040 	char		*iconv_trg;
7041 	size_t		inlen;
7042 	size_t		outlen;
7043 
7044 	if (charset_type == -1) {	/* iconv_open failed in earlier try */
7045 		(void) fprintf(stderr, gettext(
7046 		    "tar:  file # %llu: (%s) UTF-8 conversion failed.\n"),
7047 		    xhdr_count, source);
7048 		return (1);
7049 	} else if (charset_type == 0) {	/* iconv_open has not yet been done */
7050 		nl_target = nl_langinfo(CODESET);
7051 		if (strlen(nl_target) == 0)	/* locale using 7-bit codeset */
7052 			nl_target = "646";
7053 		if (strcmp(nl_target, "646") == 0)
7054 			charset_type = 1;
7055 		else if (strcmp(nl_target, "UTF-8") == 0)
7056 			charset_type = 3;
7057 		else {
7058 			if (strncmp(nl_target, "ISO", 3) == 0)
7059 				nl_target += 3;
7060 			charset_type = 2;
7061 			errno = 0;
7062 			if ((iconv_cd = iconv_open(nl_target, "UTF-8")) ==
7063 			    (iconv_t)-1) {
7064 				if (errno == EINVAL)
7065 					(void) fprintf(stderr, gettext(
7066 					    "tar: conversion routines not "
7067 					    "available for current locale.  "));
7068 				(void) fprintf(stderr, gettext(
7069 				    "file # %llu: (%s) UTF-8 conversion"
7070 				    " failed.\n"), xhdr_count, source);
7071 				charset_type = -1;
7072 				return (1);
7073 			}
7074 		}
7075 	}
7076 
7077 	/* locale using 7-bit codeset or UTF-8 locale */
7078 	if (charset_type == 1 || charset_type == 3) {
7079 		if (strlen(source) > max_val) {
7080 			(void) fprintf(stderr, gettext(
7081 			    "tar: file # %llu: Extended header %s too long.\n"),
7082 			    xhdr_count, option);
7083 			return (1);
7084 		}
7085 		if (charset_type == 3)
7086 			(void) strcpy(target, source);
7087 		else if (c_utf8(target, source) != 0) {
7088 			(void) fprintf(stderr, gettext(
7089 			    "tar:  file # %llu: (%s) UTF-8 conversion"
7090 			    " failed.\n"), xhdr_count, source);
7091 			return (1);
7092 		}
7093 		*Xhdr_ptrptr = target;
7094 		return (0);
7095 	}
7096 
7097 	iconv_src = source;
7098 	iconv_trg = target;
7099 	inlen = strlen(source);
7100 	outlen = max_val * UTF_8_FACTOR;
7101 	if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) ==
7102 	    (size_t)-1) {	/* Error occurred:  didn't convert */
7103 		(void) fprintf(stderr, gettext(
7104 		    "tar:  file # %llu: (%s) UTF-8 conversion failed.\n"),
7105 		    xhdr_count, source);
7106 		/* Get remaining output; reinitialize conversion descriptor */
7107 		iconv_src = (const char *)NULL;
7108 		inlen = 0;
7109 		(void) iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen);
7110 		return (1);
7111 	}
7112 	/* Get remaining output; reinitialize conversion descriptor */
7113 	iconv_src = (const char *)NULL;
7114 	inlen = 0;
7115 	if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) ==
7116 	    (size_t)-1) {	/* Error occurred:  didn't convert */
7117 		(void) fprintf(stderr, gettext(
7118 		    "tar:  file # %llu: (%s) UTF-8 conversion failed.\n"),
7119 		    xhdr_count, source);
7120 		return (1);
7121 	}
7122 
7123 	*iconv_trg = '\0';	/* Null-terminate iconv output string */
7124 	if (strlen(target) > max_val) {
7125 		(void) fprintf(stderr, gettext(
7126 		    "tar: file # %llu: Extended header %s too long.\n"),
7127 		    xhdr_count, option);
7128 		return (1);
7129 	}
7130 	*Xhdr_ptrptr = target;
7131 	return (0);
7132 }
7133 
7134 /*
7135  * Check gname, uname, path, and linkpath to see if they need to go in an
7136  * extended header.  If they are already slated to be in an extended header,
7137  * or if they are not ascii, then they need to be in the extended header.
7138  * Then, convert all extended names to UTF-8.
7139  */
7140 
7141 int
7142 gen_utf8_names(const char *filename)
7143 {
7144 	static	iconv_t	iconv_cd;
7145 	char		*nl_target;
7146 	char		tempbuf[MAXNAM + 1];
7147 	int		nbytes;
7148 	int		errors;
7149 
7150 	if (charset_type == -1)	{	/* Previous failure to open. */
7151 		(void) fprintf(stderr, gettext(
7152 		    "tar: file # %llu: UTF-8 conversion failed.\n"),
7153 		    xhdr_count);
7154 		return (1);
7155 	}
7156 
7157 	if (charset_type == 0) {	/* Need to get conversion descriptor */
7158 		nl_target = nl_langinfo(CODESET);
7159 		if (strlen(nl_target) == 0)	/* locale using 7-bit codeset */
7160 			nl_target = "646";
7161 		if (strcmp(nl_target, "646") == 0)
7162 			charset_type = 1;
7163 		else if (strcmp(nl_target, "UTF-8") == 0)
7164 			charset_type = 3;
7165 		else {
7166 			if (strncmp(nl_target, "ISO", 3) == 0)
7167 				nl_target += 3;
7168 			charset_type = 2;
7169 			errno = 0;
7170 #ifdef ICONV_DEBUG
7171 			(void) fprintf(stderr,
7172 			    "Opening iconv_cd with target %s\n",
7173 			    nl_target);
7174 #endif
7175 			if ((iconv_cd = iconv_open("UTF-8", nl_target)) ==
7176 			    (iconv_t)-1) {
7177 				if (errno == EINVAL)
7178 					(void) fprintf(stderr, gettext(
7179 					    "tar: conversion routines not "
7180 					    "available for current locale.  "));
7181 				(void) fprintf(stderr, gettext(
7182 				    "file (%s): UTF-8 conversion failed.\n"),
7183 				    filename);
7184 				charset_type = -1;
7185 				return (1);
7186 			}
7187 		}
7188 	}
7189 
7190 	errors = 0;
7191 
7192 	errors += local_utf8(&Xtarhdr.x_gname, local_gname,
7193 	    dblock.dbuf.gname, iconv_cd, _X_GNAME, _POSIX_NAME_MAX);
7194 	errors += local_utf8(&Xtarhdr.x_uname, local_uname,
7195 	    dblock.dbuf.uname, iconv_cd, _X_UNAME,  _POSIX_NAME_MAX);
7196 	if ((xhdr_flgs & _X_LINKPATH) == 0) {	/* Need null-terminated str. */
7197 		(void) strncpy(tempbuf, dblock.dbuf.linkname, NAMSIZ);
7198 		tempbuf[NAMSIZ] = '\0';
7199 	}
7200 	errors += local_utf8(&Xtarhdr.x_linkpath, local_linkpath,
7201 	    tempbuf, iconv_cd, _X_LINKPATH, PATH_MAX);
7202 	if ((xhdr_flgs & _X_PATH) == 0) {	/* Concatenate prefix & name */
7203 		(void) strncpy(tempbuf, dblock.dbuf.prefix, PRESIZ);
7204 		tempbuf[PRESIZ] = '\0';
7205 		nbytes = strlen(tempbuf);
7206 		if (nbytes > 0) {
7207 			tempbuf[nbytes++] = '/';
7208 			tempbuf[nbytes] = '\0';
7209 		}
7210 		(void) strncat(tempbuf + nbytes, dblock.dbuf.name,
7211 		    (MAXNAM - nbytes));
7212 		tempbuf[MAXNAM] = '\0';
7213 	}
7214 	errors += local_utf8(&Xtarhdr.x_path, local_path,
7215 	    tempbuf, iconv_cd, _X_PATH, PATH_MAX);
7216 
7217 	if (errors > 0)
7218 		(void) fprintf(stderr, gettext(
7219 		    "tar: file (%s): UTF-8 conversion failed.\n"), filename);
7220 
7221 	if (errors && errflag)
7222 		done(1);
7223 	else
7224 		if (errors)
7225 			Errflg = 1;
7226 	return (errors);
7227 }
7228 
7229 static int
7230 local_utf8(
7231 		char	**Xhdr_ptrptr,
7232 		char	*target,
7233 		const	char	*source,
7234 		iconv_t	iconv_cd,
7235 		int	xhdrflg,
7236 		int	max_val)
7237 {
7238 	const	char	*iconv_src;
7239 	const	char	*starting_src;
7240 	char		*iconv_trg;
7241 	size_t		inlen;
7242 	size_t		outlen;
7243 #ifdef ICONV_DEBUG
7244 	unsigned char	c_to_hex;
7245 #endif
7246 
7247 	/*
7248 	 * If the item is already slated for extended format, get the string
7249 	 * to convert from the extended header record.  Otherwise, get it from
7250 	 * the regular (dblock) area.
7251 	 */
7252 	if (xhdr_flgs & xhdrflg) {
7253 		if (charset_type == 3) {	/* Already UTF-8, just copy */
7254 			(void) strcpy(target, *Xhdr_ptrptr);
7255 			*Xhdr_ptrptr = target;
7256 			return (0);
7257 		} else
7258 			iconv_src = (const char *) *Xhdr_ptrptr;
7259 	} else {
7260 		if (charset_type == 3)		/* Already in UTF-8 format */
7261 			return (0);		/* Don't create xhdr record */
7262 		iconv_src = source;
7263 	}
7264 	starting_src = iconv_src;
7265 	iconv_trg = target;
7266 	if ((inlen = strlen(iconv_src)) == 0)
7267 		return (0);
7268 
7269 	if (charset_type == 1) {	/* locale using 7-bit codeset */
7270 		if (c_utf8(target, starting_src) != 0) {
7271 			(void) fprintf(stderr,
7272 			    gettext("tar: invalid character in"
7273 			    " UTF-8 conversion of '%s'\n"), starting_src);
7274 			return (1);
7275 		}
7276 		return (0);
7277 	}
7278 
7279 	outlen = max_val * UTF_8_FACTOR;
7280 	errno = 0;
7281 	if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) ==
7282 	    (size_t)-1) {
7283 		/* An error occurred, or not all characters were converted */
7284 		if (errno == EILSEQ)
7285 			(void) fprintf(stderr,
7286 			    gettext("tar: invalid character in"
7287 			    " UTF-8 conversion of '%s'\n"), starting_src);
7288 		else
7289 			(void) fprintf(stderr, gettext(
7290 			    "tar: conversion to UTF-8 aborted for '%s'.\n"),
7291 			    starting_src);
7292 		/* Get remaining output; reinitialize conversion descriptor */
7293 		iconv_src = (const char *)NULL;
7294 		inlen = 0;
7295 		(void) iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen);
7296 		return (1);
7297 	}
7298 	/* Get remaining output; reinitialize conversion descriptor */
7299 	iconv_src = (const char *)NULL;
7300 	inlen = 0;
7301 	if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) ==
7302 	    (size_t)-1) {	/* Error occurred:  didn't convert */
7303 		if (errno == EILSEQ)
7304 			(void) fprintf(stderr,
7305 			    gettext("tar: invalid character in"
7306 			    " UTF-8 conversion of '%s'\n"), starting_src);
7307 		else
7308 			(void) fprintf(stderr, gettext(
7309 			    "tar: conversion to UTF-8 aborted for '%s'.\n"),
7310 			    starting_src);
7311 		return (1);
7312 	}
7313 
7314 	*iconv_trg = '\0';	/* Null-terminate iconv output string */
7315 	if (strcmp(starting_src, target) != 0) {
7316 		*Xhdr_ptrptr = target;
7317 		xhdr_flgs |= xhdrflg;
7318 #ifdef ICONV_DEBUG
7319 		(void) fprintf(stderr, "***  inlen: %d %d; outlen: %d %d\n",
7320 		    strlen(starting_src), inlen, max_val, outlen);
7321 		(void) fprintf(stderr, "Input string:\n  ");
7322 		for (inlen = 0; inlen < strlen(starting_src); inlen++) {
7323 			c_to_hex = (unsigned char)starting_src[inlen];
7324 			(void) fprintf(stderr, " %2.2x", c_to_hex);
7325 			if (inlen % 20 == 19)
7326 				(void) fprintf(stderr, "\n  ");
7327 		}
7328 		(void) fprintf(stderr, "\nOutput string:\n  ");
7329 		for (inlen = 0; inlen < strlen(target); inlen++) {
7330 			c_to_hex = (unsigned char)target[inlen];
7331 			(void) fprintf(stderr, " %2.2x", c_to_hex);
7332 			if (inlen % 20 == 19)
7333 				(void) fprintf(stderr, "\n  ");
7334 		}
7335 		(void) fprintf(stderr, "\n");
7336 #endif
7337 	}
7338 
7339 	return (0);
7340 }
7341 
7342 /*
7343  *	Function to test each byte of the source string to make sure it is
7344  *	in within bounds (value between 0 and 127).
7345  *	If valid, copy source to target.
7346  */
7347 
7348 int
7349 c_utf8(char *target, const char *source)
7350 {
7351 	size_t		len;
7352 	const char	*thischar;
7353 
7354 	len = strlen(source);
7355 	thischar = source;
7356 	while (len-- > 0) {
7357 		if (!isascii((int)(*thischar++)))
7358 			return (1);
7359 	}
7360 
7361 	(void) strcpy(target, source);
7362 	return (0);
7363 }
7364 
7365 
7366 #if defined(O_XATTR)
7367 #define	ROUNDTOTBLOCK(a)	((a + (TBLOCK -1)) & ~(TBLOCK -1))
7368 
7369 static void
7370 prepare_xattr(
7371 	char		**attrbuf,
7372 	char		*filename,
7373 	char		*attrpath,
7374 	char		typeflag,
7375 	struct linkbuf	*linkinfo,
7376 	int		*rlen)
7377 {
7378 	char			*bufhead;	/* ptr to full buffer */
7379 	char			*aptr;
7380 	struct xattr_hdr 	*hptr;		/* ptr to header in bufhead */
7381 	struct xattr_buf	*tptr;		/* ptr to pathing pieces */
7382 	int			totalen;	/* total buffer length */
7383 	int			len;		/* length returned to user */
7384 	int			stringlen;	/* length of filename + attr */
7385 						/*
7386 						 * length of filename + attr
7387 						 * in link section
7388 						 */
7389 	int			linkstringlen;
7390 	int			complen;	/* length of pathing section */
7391 	int			linklen;	/* length of link section */
7392 	int			attrnames_index; /* attrnames starting index */
7393 
7394 	/*
7395 	 * Release previous buffer
7396 	 */
7397 
7398 	if (*attrbuf != (char *)NULL) {
7399 		free(*attrbuf);
7400 		*attrbuf = NULL;
7401 	}
7402 
7403 	/*
7404 	 * First add in fixed size stuff
7405 	 */
7406 	len = sizeof (struct xattr_hdr) + sizeof (struct xattr_buf);
7407 
7408 	/*
7409 	 * Add space for two nulls
7410 	 */
7411 	stringlen = strlen(attrpath) + strlen(filename) + 2;
7412 	complen = stringlen + sizeof (struct xattr_buf);
7413 
7414 	len += stringlen;
7415 
7416 	/*
7417 	 * Now add on space for link info if any
7418 	 */
7419 
7420 	if (linkinfo != NULL) {
7421 		/*
7422 		 * Again add space for two nulls
7423 		 */
7424 		linkstringlen = strlen(linkinfo->pathname) +
7425 		    strlen(linkinfo->attrname) + 2;
7426 		linklen = linkstringlen + sizeof (struct xattr_buf);
7427 		len += linklen;
7428 	} else {
7429 		linklen = 0;
7430 	}
7431 
7432 	/*
7433 	 * Now add padding to end to fill out TBLOCK
7434 	 *
7435 	 * Function returns size of real data and not size + padding.
7436 	 */
7437 
7438 	totalen = ROUNDTOTBLOCK(len);
7439 
7440 	if ((bufhead = calloc(1, totalen)) == NULL) {
7441 		fatal(gettext("Out of memory."));
7442 	}
7443 
7444 
7445 	/*
7446 	 * Now we can fill in the necessary pieces
7447 	 */
7448 
7449 	/*
7450 	 * first fill in the fixed header
7451 	 */
7452 	hptr = (struct xattr_hdr *)bufhead;
7453 	(void) sprintf(hptr->h_version, "%s", XATTR_ARCH_VERS);
7454 	(void) sprintf(hptr->h_component_len, "%0*d",
7455 	    sizeof (hptr->h_component_len) - 1, complen);
7456 	(void) sprintf(hptr->h_link_component_len, "%0*d",
7457 	    sizeof (hptr->h_link_component_len) - 1, linklen);
7458 	(void) sprintf(hptr->h_size, "%0*d", sizeof (hptr->h_size) - 1, len);
7459 
7460 	/*
7461 	 * Now fill in the filename + attrnames section
7462 	 * The filename and attrnames section can be composed of two or more
7463 	 * path segments separated by a null character.  The first segment
7464 	 * is the path to the parent file that roots the entire sequence in
7465 	 * the normal name space. The remaining segments describes a path
7466 	 * rooted at the hidden extended attribute directory of the leaf file of
7467 	 * the previous segment, making it possible to name attributes on
7468 	 * attributes.  Thus, if we are just archiving an extended attribute,
7469 	 * the second segment will contain the attribute name.  If we are
7470 	 * archiving a system attribute of an extended attribute, then the
7471 	 * second segment will contain the attribute name, and a third segment
7472 	 * will contain the system attribute name.  The attribute pathing
7473 	 * information is obtained from 'attrpath'.
7474 	 */
7475 
7476 	tptr = (struct xattr_buf *)(bufhead + sizeof (struct xattr_hdr));
7477 	(void) sprintf(tptr->h_namesz, "%0*d", sizeof (tptr->h_namesz) - 1,
7478 	    stringlen);
7479 	(void) strcpy(tptr->h_names, filename);
7480 	attrnames_index = strlen(filename) + 1;
7481 	(void) strcpy(&tptr->h_names[attrnames_index], attrpath);
7482 	tptr->h_typeflag = typeflag;
7483 
7484 	/*
7485 	 * Split the attrnames section into two segments if 'attrpath'
7486 	 * contains pathing information for a system attribute of an
7487 	 * extended attribute.  We split them by replacing the '/' with
7488 	 * a '\0'.
7489 	 */
7490 	if ((aptr = strpbrk(&tptr->h_names[attrnames_index], "/")) != NULL) {
7491 		*aptr = '\0';
7492 	}
7493 
7494 	/*
7495 	 * Now fill in the optional link section if we have one
7496 	 */
7497 
7498 	if (linkinfo != (struct linkbuf *)NULL) {
7499 		tptr = (struct xattr_buf *)(bufhead +
7500 		    sizeof (struct xattr_hdr) + complen);
7501 
7502 		(void) sprintf(tptr->h_namesz, "%0*d",
7503 		    sizeof (tptr->h_namesz) - 1, linkstringlen);
7504 		(void) strcpy(tptr->h_names, linkinfo->pathname);
7505 		(void) strcpy(
7506 		    &tptr->h_names[strlen(linkinfo->pathname) + 1],
7507 		    linkinfo->attrname);
7508 		tptr->h_typeflag = typeflag;
7509 	}
7510 	*attrbuf = (char *)bufhead;
7511 	*rlen = len;
7512 }
7513 
7514 #else
7515 static void
7516 prepare_xattr(
7517 	char		**attrbuf,
7518 	char		*filename,
7519 	char		*attrname,
7520 	char		typeflag,
7521 	struct linkbuf	*linkinfo,
7522 	int		*rlen)
7523 {
7524 	*attrbuf = NULL;
7525 	*rlen = 0;
7526 }
7527 #endif
7528 
7529 int
7530 getstat(int dirfd, char *longname, char *shortname, char *attrparent)
7531 {
7532 
7533 	int i, j;
7534 	int	printerr;
7535 	int	slnkerr;
7536 	struct stat symlnbuf;
7537 
7538 	if (!hflag)
7539 		i = fstatat(dirfd, shortname, &stbuf, AT_SYMLINK_NOFOLLOW);
7540 	else
7541 		i = fstatat(dirfd, shortname, &stbuf, 0);
7542 
7543 	if (i < 0) {
7544 		/* Initialize flag to print error mesg. */
7545 		printerr = 1;
7546 		/*
7547 		 * If stat is done, then need to do lstat
7548 		 * to determine whether it's a sym link
7549 		 */
7550 		if (hflag) {
7551 			/* Save returned error */
7552 			slnkerr = errno;
7553 
7554 			j = fstatat(dirfd, shortname,
7555 			    &symlnbuf, AT_SYMLINK_NOFOLLOW);
7556 			/*
7557 			 * Suppress error message when file is a symbolic link
7558 			 * and function modifier 'l' is off.  Exception:  when
7559 			 * a symlink points to a symlink points to a
7560 			 * symlink ... and we get past MAXSYMLINKS.  That
7561 			 * error will cause a file not to be archived, and
7562 			 * needs to be printed.
7563 			 */
7564 			if ((j == 0) && (!linkerrok) && (slnkerr != ELOOP) &&
7565 			    (S_ISLNK(symlnbuf.st_mode)))
7566 				printerr = 0;
7567 
7568 			/*
7569 			 * Restore errno in case the lstat
7570 			 * on symbolic link change
7571 			 */
7572 			errno = slnkerr;
7573 		}
7574 
7575 		if (printerr) {
7576 			(void) fprintf(stderr, gettext(
7577 			    "tar: %s%s%s%s: %s\n"),
7578 			    (attrparent == NULL) ? "" : gettext("attribute "),
7579 			    (attrparent == NULL) ? "" : attrparent,
7580 			    (attrparent == NULL) ? "" : gettext(" of "),
7581 			    longname, strerror(errno));
7582 			Errflg = 1;
7583 		}
7584 		return (1);
7585 	}
7586 	return (0);
7587 }
7588 
7589 /*
7590  * Recursively archive the extended attributes and/or extended system attributes
7591  * of the base file, longname.  Note:  extended system attribute files will be
7592  * archived only if the extended system attributes are not transient (i.e. the
7593  * extended system attributes are other than the default values).
7594  *
7595  * If -@ was specified and the underlying file system supports it, archive the
7596  * extended attributes, and if there is a system attribute associated with the
7597  * extended attribute, then recursively call xattrs_put() to archive the
7598  * hidden attribute directory and the extended system attribute.  If -/ was
7599  * specified and the underlying file system supports it, archive the extended
7600  * system attributes.  Read-only extended system attributes are never archived.
7601  *
7602  * Currently, there cannot be attributes on attributes; only system
7603  * attributes on attributes.  In addition, there cannot be attributes on
7604  * system attributes.  A file and it's attribute directory hierarchy looks as
7605  * follows:
7606  *	longname ---->	.	("." is the hidden attribute directory)
7607  *			|
7608  *	     ----------------------------
7609  *	     |				|
7610  *	<sys_attr_name>		   <attr_name> ---->	.
7611  *							|
7612  *						  <sys_attr_name>
7613  *
7614  */
7615 #if defined(O_XATTR)
7616 static void
7617 xattrs_put(char *longname, char *shortname, char *parent, char *attrparent)
7618 {
7619 	char *filename = (attrparent == NULL) ? shortname : attrparent;
7620 	int arc_rwsysattr = 0;
7621 	int dirfd;
7622 	int fd = -1;
7623 	int rw_sysattr = 0;
7624 	int ext_attr = 0;
7625 	int rc;
7626 	DIR *dirp;
7627 	struct dirent *dp;
7628 	attr_data_t *attrinfo = NULL;
7629 
7630 	/*
7631 	 * If the underlying file system supports it, then archive the extended
7632 	 * attributes if -@ was specified, and the extended system attributes
7633 	 * if -/ was specified.
7634 	 */
7635 	if (verify_attr_support(filename, (attrparent == NULL), ARC_CREATE,
7636 	    &ext_attr) != ATTR_OK) {
7637 		return;
7638 	}
7639 
7640 	/*
7641 	 * Only want to archive a read-write extended system attribute file
7642 	 * if it contains extended system attribute settings that are not the
7643 	 * default values.
7644 	 */
7645 #if defined(_PC_SATTR_ENABLED)
7646 	if (saflag) {
7647 		int	filefd;
7648 		nvlist_t *slist = NULL;
7649 
7650 		/* Determine if there are non-transient system attributes */
7651 		errno = 0;
7652 		if ((filefd = open(filename, O_RDONLY)) == -1) {
7653 			if (attrparent == NULL) {
7654 				vperror(0, gettext(
7655 				    "unable to open file %s"), longname);
7656 			}
7657 			return;
7658 		}
7659 		if (((slist = sysattr_list(basename(myname), filefd,
7660 		    filename)) != NULL) || (errno != 0)) {
7661 			arc_rwsysattr = 1;
7662 		}
7663 		if (slist != NULL) {
7664 			(void) nvlist_free(slist);
7665 			slist = NULL;
7666 		}
7667 		(void) close(filefd);
7668 	}
7669 
7670 	/*
7671 	 * If we aren't archiving extended system attributes, and we are
7672 	 * processing an attribute, or if we are archiving extended system
7673 	 * attributes, and there are are no extended attributes, then there's
7674 	 * no need to open up the attribute directory of the file unless the
7675 	 * extended system attributes are not transient (i.e, the system
7676 	 * attributes are not the default values).
7677 	 */
7678 	if ((arc_rwsysattr == 0) && ((attrparent != NULL) ||
7679 	    (saflag && !ext_attr))) {
7680 		return;
7681 	}
7682 #endif	/* _PC_SATTR_ENABLED */
7683 
7684 	/* open the parent attribute directory */
7685 	fd = attropen(filename, ".", O_RDONLY);
7686 	if (fd < 0) {
7687 		vperror(0, gettext(
7688 		    "unable to open attribute directory for %s%s%sfile %s"),
7689 		    (attrparent == NULL) ? "" : gettext("attribute "),
7690 		    (attrparent == NULL) ? "" : attrparent,
7691 		    (attrparent == NULL) ? "" : gettext(" of "),
7692 		    longname);
7693 		return;
7694 	}
7695 
7696 	/*
7697 	 * We need to change into the parent's attribute directory to determine
7698 	 * if each of the attributes should be archived.
7699 	 */
7700 	if (fchdir(fd) < 0) {
7701 		vperror(0, gettext(
7702 		    "cannot change to attribute directory of %s%s%sfile %s"),
7703 		    (attrparent == NULL) ? "" : gettext("attribute "),
7704 		    (attrparent == NULL) ? "" : attrparent,
7705 		    (attrparent == NULL) ? "" : gettext(" of "),
7706 		    longname);
7707 		(void) close(fd);
7708 		return;
7709 	}
7710 
7711 	if (((dirfd = dup(fd)) == -1) ||
7712 	    ((dirp = fdopendir(dirfd)) == NULL)) {
7713 		(void) fprintf(stderr, gettext(
7714 		    "tar: unable to open dir pointer for %s%s%sfile %s\n"),
7715 		    (attrparent == NULL) ? "" : gettext("attribute "),
7716 		    (attrparent == NULL) ? "" : attrparent,
7717 		    (attrparent == NULL) ? "" : gettext(" of "),
7718 		    longname);
7719 		if (fd > 0) {
7720 			(void) close(fd);
7721 		}
7722 		return;
7723 	}
7724 
7725 	while (dp = readdir(dirp)) {
7726 		if (strcmp(dp->d_name, "..") == 0) {
7727 			continue;
7728 		} else if (strcmp(dp->d_name, ".") == 0) {
7729 			Hiddendir = 1;
7730 		} else {
7731 			Hiddendir = 0;
7732 		}
7733 
7734 		/* Determine if this attribute should be archived */
7735 		if (verify_attr(dp->d_name, attrparent, arc_rwsysattr,
7736 		    &rw_sysattr) != ATTR_OK) {
7737 			continue;
7738 		}
7739 
7740 		/* gather the attribute's information to pass to putfile() */
7741 		if ((fill_in_attr_info(dp->d_name, longname, attrparent,
7742 		    fd, rw_sysattr, &attrinfo)) == 1) {
7743 			continue;
7744 		}
7745 
7746 		/* add the attribute to the archive */
7747 		rc = putfile(longname, dp->d_name, parent, attrinfo,
7748 		    XATTR_FILE, LEV0, SYMLINK_LEV0);
7749 
7750 		if (exitflag) {
7751 			break;
7752 		}
7753 
7754 #if defined(_PC_SATTR_ENABLED)
7755 		/*
7756 		 * If both -/ and -@ were specified, then archive the
7757 		 * attribute's extended system attributes and hidden directory
7758 		 * by making a recursive call to xattrs_put().
7759 		 */
7760 		if (!rw_sysattr && saflag && atflag && (rc != PUT_AS_LINK) &&
7761 		    (Hiddendir == 0)) {
7762 
7763 			xattrs_put(longname, shortname, parent, dp->d_name);
7764 
7765 			/*
7766 			 * Change back to the parent's attribute directory
7767 			 * to process any further attributes.
7768 			 */
7769 			if (fchdir(fd) < 0) {
7770 				vperror(0, gettext(
7771 				    "cannot change back to attribute directory "
7772 				    "of file %s"), longname);
7773 				break;
7774 			}
7775 		}
7776 #endif	/* _PC_SATTR_ENABLED */
7777 	}
7778 
7779 	if (attrinfo != NULL) {
7780 		if (attrinfo->attr_parent != NULL) {
7781 			free(attrinfo->attr_parent);
7782 		}
7783 		free(attrinfo->attr_path);
7784 		free(attrinfo);
7785 	}
7786 	(void) closedir(dirp);
7787 	if (fd != -1) {
7788 		(void) close(fd);
7789 	}
7790 
7791 	/* Change back to the parent directory of the base file */
7792 	if (attrparent == NULL) {
7793 		(void) chdir(parent);
7794 	}
7795 	Hiddendir = 0;
7796 }
7797 #else
7798 static void
7799 xattrs_put(char *longname, char *shortname, char *parent, char *attrppath)
7800 {
7801 }
7802 #endif /* O_XATTR */
7803 
7804 static int
7805 put_link(char *name, char *longname, char *component, char *longattrname,
7806     char *prefix, int filetype, char type)
7807 {
7808 
7809 	if (stbuf.st_nlink > 1) {
7810 		struct linkbuf *lp;
7811 		int found = 0;
7812 
7813 		for (lp = ihead; lp != NULL; lp = lp->nextp)
7814 			if (lp->inum == stbuf.st_ino &&
7815 			    lp->devnum == stbuf.st_dev) {
7816 				found++;
7817 				break;
7818 			}
7819 		if (found) {
7820 #if defined(O_XATTR)
7821 			if (filetype == XATTR_FILE)
7822 				if (put_xattr_hdr(longname, component,
7823 				    longattrname, prefix, type, filetype, lp)) {
7824 					goto out;
7825 			}
7826 #endif
7827 			stbuf.st_size = (off_t)0;
7828 			if (filetype != XATTR_FILE) {
7829 				tomodes(&stbuf);
7830 				if (chk_path_build(name, longname, lp->pathname,
7831 				    prefix, type, filetype) > 0) {
7832 					goto out;
7833 				}
7834 			}
7835 
7836 			if (mulvol && tapepos + 1 >= blocklim)
7837 				newvol();
7838 			(void) writetbuf((char *)&dblock, 1);
7839 			/*
7840 			 * write_ancillary() is not needed here.
7841 			 * The first link is handled in the following
7842 			 * else statement. No need to process ACLs
7843 			 * for other hard links since they are the
7844 			 * same file.
7845 			 */
7846 
7847 			if (vflag) {
7848 #ifdef DEBUG
7849 				if (NotTape)
7850 					DEBUG("seek = %" FMT_blkcnt_t
7851 					    "K\t", K(tapepos), 0);
7852 #endif
7853 				if (filetype == XATTR_FILE) {
7854 					(void) fprintf(vfile, gettext(
7855 					    "a %s attribute %s link to "
7856 					    "%s attribute %s\n"),
7857 					    name, component, name,
7858 					    lp->attrname);
7859 				} else {
7860 					(void) fprintf(vfile, gettext(
7861 					    "a %s link to %s\n"),
7862 					    longname, lp->pathname);
7863 				}
7864 			}
7865 			lp->count--;
7866 			return (0);
7867 		} else {
7868 			lp = (struct linkbuf *)getmem(sizeof (*lp));
7869 			if (lp != (struct linkbuf *)NULL) {
7870 				lp->nextp = ihead;
7871 				ihead = lp;
7872 				lp->inum = stbuf.st_ino;
7873 				lp->devnum = stbuf.st_dev;
7874 				lp->count = stbuf.st_nlink - 1;
7875 				if (filetype == XATTR_FILE) {
7876 					(void) strcpy(lp->pathname, longname);
7877 					(void) strcpy(lp->attrname,
7878 					    component);
7879 				} else {
7880 					(void) strcpy(lp->pathname, longname);
7881 					(void) strcpy(lp->attrname, "");
7882 				}
7883 			}
7884 		}
7885 	}
7886 
7887 out:
7888 	return (1);
7889 }
7890 
7891 static int
7892 put_extra_attributes(char *longname, char *shortname, char *longattrname,
7893     char *prefix, int filetype, char typeflag)
7894 {
7895 	static acl_t *aclp = NULL;
7896 	int error;
7897 
7898 	if (aclp != NULL) {
7899 		acl_free(aclp);
7900 		aclp = NULL;
7901 	}
7902 #if defined(O_XATTR)
7903 	if ((atflag || saflag) && (filetype == XATTR_FILE)) {
7904 		if (put_xattr_hdr(longname, shortname, longattrname, prefix,
7905 		    typeflag, filetype, NULL)) {
7906 			return (1);
7907 		}
7908 	}
7909 #endif
7910 
7911 	/* ACL support */
7912 	if (pflag) {
7913 		char	*secinfo = NULL;
7914 		int	len = 0;
7915 
7916 		/* ACL support */
7917 		if (((stbuf.st_mode & S_IFMT) != S_IFLNK)) {
7918 			/*
7919 			 * Get ACL info: dont bother allocating space if
7920 			 * there is only a trivial ACL.
7921 			 */
7922 			if ((error = acl_get(shortname, ACL_NO_TRIVIAL,
7923 			    &aclp)) != 0) {
7924 				(void) fprintf(stderr, gettext(
7925 				    "%s: failed to retrieve acl : %s\n"),
7926 				    longname, acl_strerror(error));
7927 				return (1);
7928 			}
7929 		}
7930 
7931 		/* append security attributes if any */
7932 		if (aclp != NULL) {
7933 			(void) append_secattr(&secinfo, &len, acl_cnt(aclp),
7934 			    acl_totext(aclp, ACL_APPEND_ID | ACL_COMPACT_FMT),
7935 			    (acl_type(aclp) == ACLENT_T) ? UFSD_ACL : ACE_ACL);
7936 		}
7937 
7938 		if (Tflag) {
7939 			/* append Trusted Extensions extended attributes */
7940 			append_ext_attr(shortname, &secinfo, &len);
7941 			(void) write_ancillary(&dblock, secinfo, len, ACL_HDR);
7942 
7943 		} else if (aclp != NULL) {
7944 			(void) write_ancillary(&dblock, secinfo, len, ACL_HDR);
7945 		}
7946 	}
7947 	return (0);
7948 }
7949 
7950 #if defined(O_XATTR)
7951 static int
7952 put_xattr_hdr(char *longname, char *shortname, char *longattrname, char *prefix,
7953 	int typeflag, int filetype, struct linkbuf *lp)
7954 {
7955 	char *lname = NULL;
7956 	char *sname = NULL;
7957 	int  error = 0;
7958 	static char *attrbuf = NULL;
7959 	int attrlen;
7960 
7961 	lname = malloc(sizeof (char) * strlen("/dev/null") + 1 +
7962 	    strlen(shortname) + strlen(".hdr") + 1);
7963 
7964 	if (lname == NULL) {
7965 		fatal(gettext("Out of Memory."));
7966 	}
7967 	sname = malloc(sizeof (char) * strlen(shortname) +
7968 	    strlen(".hdr") + 1);
7969 	if (sname == NULL) {
7970 		fatal(gettext("Out of Memory."));
7971 	}
7972 
7973 	(void) sprintf(sname, "%s.hdr", shortname);
7974 	(void) sprintf(lname, "/dev/null/%s", sname);
7975 
7976 	if (strlcpy(dblock.dbuf.name, lname, sizeof (dblock.dbuf.name)) >=
7977 	    sizeof (dblock.dbuf.name)) {
7978 		fatal(gettext(
7979 		    "Buffer overflow writing extended attribute file name"));
7980 	}
7981 
7982 	/*
7983 	 * dump extended attr lookup info
7984 	 */
7985 	prepare_xattr(&attrbuf, longname, longattrname, typeflag, lp, &attrlen);
7986 	write_ancillary(&dblock, attrbuf, attrlen, _XATTR_HDRTYPE);
7987 
7988 	(void) sprintf(lname, "/dev/null/%s", shortname);
7989 	(void) strncpy(dblock.dbuf.name, sname, NAMSIZ);
7990 
7991 	/*
7992 	 * Set up filename for attribute
7993 	 */
7994 
7995 	error = build_dblock(lname, tchar, '0', filetype,
7996 	    &stbuf, stbuf.st_dev, prefix);
7997 	free(lname);
7998 	free(sname);
7999 
8000 	return (error);
8001 }
8002 #endif
8003 
8004 #if defined(O_XATTR)
8005 static int
8006 read_xattr_hdr(attr_data_t **attrinfo)
8007 {
8008 	char		buf[TBLOCK];
8009 	char		*attrparent = NULL;
8010 	blkcnt_t	blocks;
8011 	char		*tp;
8012 	off_t		bytes;
8013 	int		comp_len, link_len;
8014 	int		namelen;
8015 	int		attrparentlen;
8016 	int		parentfilelen;
8017 
8018 	if (dblock.dbuf.typeflag != _XATTR_HDRTYPE)
8019 		return (1);
8020 
8021 	bytes = stbuf.st_size;
8022 	if ((xattrhead = calloc(1, (int)bytes)) == NULL) {
8023 		(void) fprintf(stderr, gettext(
8024 		    "Insufficient memory for extended attribute\n"));
8025 		return (1);
8026 	}
8027 
8028 	tp = (char *)xattrhead;
8029 	blocks = TBLOCKS(bytes);
8030 	while (blocks-- > 0) {
8031 		readtape(buf);
8032 		if (bytes <= TBLOCK) {
8033 			(void) memcpy(tp, buf, (size_t)bytes);
8034 			break;
8035 		} else {
8036 			(void) memcpy(tp, buf, TBLOCK);
8037 			tp += TBLOCK;
8038 		}
8039 		bytes -= TBLOCK;
8040 	}
8041 
8042 	/*
8043 	 * Validate that we can handle header format
8044 	 */
8045 	if (strcmp(xattrhead->h_version, XATTR_ARCH_VERS) != 0) {
8046 		(void) fprintf(stderr,
8047 		    gettext("Unknown extended attribute format encountered\n"));
8048 		(void) fprintf(stderr,
8049 		    gettext("Disabling extended attribute parsing\n"));
8050 		xattrbadhead = 1;
8051 		return (0);
8052 	}
8053 	(void) sscanf(xattrhead->h_component_len, "%10d", &comp_len);
8054 	(void) sscanf(xattrhead->h_link_component_len,	"%10d", &link_len);
8055 	xattrp = (struct xattr_buf *)(((char *)xattrhead) +
8056 	    sizeof (struct xattr_hdr));
8057 	(void) sscanf(xattrp->h_namesz, "%7d", &namelen);
8058 	if (link_len > 0)
8059 		xattr_linkp = (struct xattr_buf *)
8060 		    ((int)xattrp + (int)comp_len);
8061 	else
8062 		xattr_linkp = NULL;
8063 
8064 	/*
8065 	 * Gather the attribute path from the filename and attrnames section.
8066 	 * The filename and attrnames section can be composed of two or more
8067 	 * path segments separated by a null character.  The first segment
8068 	 * is the path to the parent file that roots the entire sequence in
8069 	 * the normal name space. The remaining segments describes a path
8070 	 * rooted at the hidden extended attribute directory of the leaf file of
8071 	 * the previous segment, making it possible to name attributes on
8072 	 * attributes.
8073 	 */
8074 	parentfilelen = strlen(xattrp->h_names);
8075 	xattrapath = xattrp->h_names + parentfilelen + 1;
8076 	if ((strlen(xattrapath) + parentfilelen + 2) < namelen) {
8077 		/*
8078 		 * The attrnames section contains a system attribute on an
8079 		 * attribute.  Save the name of the attribute for use later,
8080 		 * and replace the null separating the attribute name from
8081 		 * the system attribute name with a '/' so that xattrapath can
8082 		 * be used to display messages with the full attribute path name
8083 		 * rooted at the hidden attribute directory of the base file
8084 		 * in normal name space.
8085 		 */
8086 		attrparent = strdup(xattrapath);
8087 		attrparentlen = strlen(attrparent);
8088 		xattrapath[attrparentlen] = '/';
8089 	}
8090 	if ((fill_in_attr_info((attrparent == NULL) ? xattrapath :
8091 	    xattrapath + attrparentlen + 1, xattrapath, attrparent,
8092 	    -1, 0, attrinfo)) == 1) {
8093 		free(attrparent);
8094 		return (1);
8095 	}
8096 
8097 	/* Gather link info */
8098 	if (xattr_linkp) {
8099 		xattr_linkaname = xattr_linkp->h_names +
8100 		    strlen(xattr_linkp->h_names) + 1;
8101 	} else {
8102 		xattr_linkaname = NULL;
8103 	}
8104 
8105 	return (0);
8106 }
8107 #else
8108 static int
8109 read_xattr_hdr(attr_data_t **attrinfo)
8110 {
8111 	return (0);
8112 }
8113 #endif
8114 
8115 /*
8116  * skip over extra slashes in string.
8117  *
8118  * For example:
8119  * /usr/tmp/////
8120  *
8121  * would return pointer at
8122  * /usr/tmp/////
8123  *         ^
8124  */
8125 static char *
8126 skipslashes(char *string, char *start)
8127 {
8128 	while ((string > start) && *(string - 1) == '/') {
8129 		string--;
8130 	}
8131 
8132 	return (string);
8133 }
8134 
8135 /*
8136  * Return the parent directory of a given path.
8137  *
8138  * Examples:
8139  * /usr/tmp return /usr
8140  * /usr/tmp/file return /usr/tmp
8141  * /  returns .
8142  * /usr returns /
8143  * file returns .
8144  *
8145  * dir is assumed to be at least as big as path.
8146  */
8147 static void
8148 get_parent(char *path, char *dir)
8149 {
8150 	char *s;
8151 	char tmpdir[PATH_MAX + 1];
8152 
8153 	if (strlen(path) > PATH_MAX) {
8154 		fatal(gettext("pathname is too long"));
8155 	}
8156 	(void) strcpy(tmpdir, path);
8157 	chop_endslashes(tmpdir);
8158 
8159 	if ((s = strrchr(tmpdir, '/')) == NULL) {
8160 		(void) strcpy(dir, ".");
8161 	} else {
8162 		s = skipslashes(s, tmpdir);
8163 		*s = '\0';
8164 		if (s == tmpdir)
8165 			(void) strcpy(dir, "/");
8166 		else
8167 			(void) strcpy(dir, tmpdir);
8168 	}
8169 }
8170 
8171 #if defined(O_XATTR)
8172 static char *
8173 get_component(char *path)
8174 {
8175 	char *ptr;
8176 
8177 	ptr = strrchr(path, '/');
8178 	if (ptr == NULL) {
8179 		return (path);
8180 	} else {
8181 		/*
8182 		 * Handle trailing slash
8183 		 */
8184 		if (*(ptr + 1) == '\0')
8185 			return (ptr);
8186 		else
8187 			return (ptr + 1);
8188 	}
8189 }
8190 #else
8191 static char *
8192 get_component(char *path)
8193 {
8194 	return (path);
8195 }
8196 #endif
8197 
8198 #if defined(O_XATTR)
8199 static int
8200 retry_open_attr(int pdirfd, int cwd, char *dirp, char *pattr, char *name,
8201     int oflag, mode_t mode)
8202 {
8203 	int dirfd;
8204 	int ofilefd = -1;
8205 	struct timeval times[2];
8206 	mode_t newmode;
8207 	struct stat parentstat;
8208 	acl_t *aclp = NULL;
8209 	int error;
8210 
8211 	/*
8212 	 * We couldn't get to attrdir. See if its
8213 	 * just a mode problem on the parent file.
8214 	 * for example: a mode such as r-xr--r--
8215 	 * on a ufs file system without extended
8216 	 * system attribute support won't let us
8217 	 * create an attribute dir if it doesn't
8218 	 * already exist, and on a ufs file system
8219 	 * with extended system attribute support
8220 	 * won't let us open the attribute for
8221 	 * write.
8222 	 *
8223 	 * If file has a non-trivial ACL, then save it
8224 	 * off so that we can place it back on after doing
8225 	 * chmod's.
8226 	 */
8227 	if ((dirfd = openat(cwd, (pattr == NULL) ? dirp : pattr,
8228 	    O_RDONLY)) == -1) {
8229 		return (-1);
8230 	}
8231 	if (fstat(dirfd, &parentstat) == -1) {
8232 		(void) fprintf(stderr, gettext(
8233 		    "tar: cannot stat %sfile %s: %s\n"),
8234 		    (pdirfd == -1) ? "" : gettext("parent of "),
8235 		    (pdirfd == -1) ? dirp : name, strerror(errno));
8236 			return (-1);
8237 	}
8238 	if ((error = facl_get(dirfd, ACL_NO_TRIVIAL, &aclp)) != 0) {
8239 		(void) fprintf(stderr, gettext(
8240 		    "tar: failed to retrieve ACL on %sfile %s: %s\n"),
8241 		    (pdirfd == -1) ? "" : gettext("parent of "),
8242 		    (pdirfd == -1) ? dirp : name, strerror(errno));
8243 			return (-1);
8244 	}
8245 
8246 	newmode = S_IWUSR | parentstat.st_mode;
8247 	if (fchmod(dirfd, newmode) == -1) {
8248 		(void) fprintf(stderr,
8249 		    gettext(
8250 		    "tar: cannot fchmod %sfile %s to %o: %s\n"),
8251 		    (pdirfd == -1) ? "" : gettext("parent of "),
8252 		    (pdirfd == -1) ? dirp : name, newmode, strerror(errno));
8253 		if (aclp)
8254 			acl_free(aclp);
8255 		return (-1);
8256 	}
8257 
8258 
8259 	if (pdirfd == -1) {
8260 		/*
8261 		 * We weren't able to create the attribute directory before.
8262 		 * Now try again.
8263 		 */
8264 		ofilefd = attropen(dirp, ".", oflag);
8265 	} else {
8266 		/*
8267 		 * We weren't able to create open the attribute before.
8268 		 * Now try again.
8269 		 */
8270 		ofilefd = openat(pdirfd, name, oflag, mode);
8271 	}
8272 
8273 	/*
8274 	 * Put mode back to original
8275 	 */
8276 	if (fchmod(dirfd, parentstat.st_mode) == -1) {
8277 		(void) fprintf(stderr,
8278 		    gettext("tar: cannot chmod %sfile %s to %o: %s\n"),
8279 		    (pdirfd == -1) ? "" : gettext("parent of "),
8280 		    (pdirfd == -1) ? dirp : name, newmode, strerror(errno));
8281 	}
8282 
8283 	if (aclp) {
8284 		error = facl_set(dirfd, aclp);
8285 		if (error) {
8286 			(void) fprintf(stderr,
8287 			    gettext("tar: failed to set acl entries on "
8288 			    "%sfile %s\n"),
8289 			    (pdirfd == -1) ? "" : gettext("parent of "),
8290 			    (pdirfd == -1) ? dirp : name);
8291 		}
8292 		acl_free(aclp);
8293 	}
8294 
8295 	/*
8296 	 * Put back time stamps
8297 	 */
8298 
8299 	times[0].tv_sec = parentstat.st_atime;
8300 	times[0].tv_usec = 0;
8301 	times[1].tv_sec = parentstat.st_mtime;
8302 	times[1].tv_usec = 0;
8303 
8304 	(void) futimesat(cwd, (pattr == NULL) ? dirp : pattr, times);
8305 
8306 	(void) close(dirfd);
8307 
8308 	return (ofilefd);
8309 }
8310 #endif
8311 
8312 #if !defined(O_XATTR)
8313 static int
8314 openat64(int fd, const char *name, int oflag, mode_t cmode)
8315 {
8316 	return (open64(name, oflag, cmode));
8317 }
8318 
8319 static int
8320 openat(int fd, const char *name, int oflag, mode_t cmode)
8321 {
8322 	return (open(name, oflag, cmode));
8323 }
8324 
8325 static int
8326 fchownat(int fd, const char *name, uid_t owner, gid_t group, int flag)
8327 {
8328 	if (flag == AT_SYMLINK_NOFOLLOW)
8329 		return (lchown(name, owner, group));
8330 	else
8331 		return (chown(name, owner, group));
8332 }
8333 
8334 static int
8335 renameat(int fromfd, char *old, int tofd, char *new)
8336 {
8337 	return (rename(old, new));
8338 }
8339 
8340 static int
8341 futimesat(int fd, char *path, struct timeval times[2])
8342 {
8343 	return (utimes(path, times));
8344 }
8345 
8346 static int
8347 unlinkat(int dirfd, char *path, int flag)
8348 {
8349 	if (flag == AT_REMOVEDIR)
8350 		return (rmdir(path));
8351 	else
8352 		return (unlink(path));
8353 }
8354 
8355 static int
8356 fstatat(int fd, char *path, struct stat *buf, int flag)
8357 {
8358 	if (flag == AT_SYMLINK_NOFOLLOW)
8359 		return (lstat(path, buf));
8360 	else
8361 		return (stat(path, buf));
8362 }
8363 
8364 static int
8365 attropen(char *file, char *attr, int omode, mode_t cmode)
8366 {
8367 	errno = ENOTSUP;
8368 	return (-1);
8369 }
8370 #endif
8371 
8372 static void
8373 chop_endslashes(char *path)
8374 {
8375 	char *end, *ptr;
8376 
8377 	/*
8378 	 * Chop of slashes, but not if all we have is slashes
8379 	 * for example: ////
8380 	 * should make no changes, otherwise it will screw up
8381 	 * checkdir
8382 	 */
8383 	end = &path[strlen(path) -1];
8384 	if (*end == '/' && end != path) {
8385 		ptr = skipslashes(end, path);
8386 		if (ptr != NULL && ptr != path) {
8387 			*ptr = '\0';
8388 		}
8389 	}
8390 }
8391 /* Trusted Extensions */
8392 
8393 /*
8394  * append_ext_attr():
8395  *
8396  * Append extended attributes and other information into the buffer
8397  * that gets written to the ancillary file.
8398  *
8399  * With option 'T', we create a tarfile which
8400  * has an ancillary file each corresponding archived file.
8401  * Each ancillary file contains 1 or more of the
8402  * following attributes:
8403  *
8404  *	attribute type        attribute		process procedure
8405  *	----------------      ----------------  --------------------------
8406  *   	DIR_TYPE       = 'D'   directory flag	append if a directory
8407  *    	LBL_TYPE       = 'L'   SL[IL] or SL	append ascii label
8408  *
8409  *
8410  */
8411 static void
8412 append_ext_attr(char *shortname, char **secinfo, int *len)
8413 {
8414 	bslabel_t	b_slabel;	/* binary sensitvity label */
8415 	char		*ascii = NULL;	/* ascii label */
8416 
8417 	/*
8418 	 * For each attribute type, append it if it is
8419 	 * relevant to the file type.
8420 	 */
8421 
8422 	/*
8423 	 * For attribute type DIR_TYPE,
8424 	 * append it to the following file type:
8425 	 *
8426 	 *	S_IFDIR: directories
8427 	 */
8428 
8429 	/*
8430 	 * For attribute type LBL_TYPE,
8431 	 * append it to the following file type:
8432 	 *
8433 	 *	S_IFDIR: directories (including mld, sld)
8434 	 *	S_IFLNK: symbolic link
8435 	 *	S_IFREG: regular file but not hard link
8436 	 *	S_IFIFO: FIFO file but not hard link
8437 	 *	S_IFCHR: char special file but not hard link
8438 	 *	S_IFBLK: block special file but not hard link
8439 	 */
8440 	switch (stbuf.st_mode & S_IFMT) {
8441 
8442 	case S_IFDIR:
8443 
8444 		/*
8445 		 * append DIR_TYPE
8446 		 */
8447 		(void) append_secattr(secinfo, len, 1,
8448 		    "\0", DIR_TYPE);
8449 
8450 		/*
8451 		 * Get and append attribute types LBL_TYPE.
8452 		 * For directories, LBL_TYPE contains SL.
8453 		 */
8454 		/* get binary sensitivity label */
8455 		if (getlabel(shortname, &b_slabel) != 0) {
8456 			(void) fprintf(stderr,
8457 			    gettext("tar: can't get sensitvity label for "
8458 			    " %s, getlabel() error: %s\n"),
8459 			    shortname, strerror(errno));
8460 		} else {
8461 			/* get ascii SL */
8462 			if (bsltos(&b_slabel, &ascii,
8463 			    0, 0) <= 0) {
8464 				(void) fprintf(stderr,
8465 				    gettext("tar: can't get ascii SL for"
8466 				    " %s\n"), shortname);
8467 			} else {
8468 				/* append LBL_TYPE */
8469 				(void) append_secattr(secinfo, len,
8470 				    strlen(ascii) + 1, ascii,
8471 				    LBL_TYPE);
8472 
8473 				/* free storage */
8474 				if (ascii != NULL) {
8475 					free(ascii);
8476 					ascii = (char *)0;
8477 				}
8478 			}
8479 
8480 		}
8481 		break;
8482 
8483 	case S_IFLNK:
8484 	case S_IFREG:
8485 	case S_IFIFO:
8486 	case S_IFCHR:
8487 	case S_IFBLK:
8488 
8489 		/* get binary sensitivity label */
8490 		if (getlabel(shortname, &b_slabel) != 0) {
8491 			(void) fprintf(stderr,
8492 			    gettext("tar: can't get sensitivty label for %s, "
8493 			    "getlabel() error: %s\n"),
8494 			    shortname, strerror(errno));
8495 		} else {
8496 			/* get ascii IL[SL] */
8497 			if (bsltos(&b_slabel, &ascii, 0, 0) <= 0) {
8498 				(void) fprintf(stderr,
8499 				    gettext("tar: can't translate sensitivity "
8500 				    " label for %s\n"), shortname);
8501 			} else {
8502 				char *cmw_label;
8503 				size_t  cmw_length;
8504 
8505 				cmw_length = strlen("ADMIN_LOW [] ") +
8506 				    strlen(ascii);
8507 				if ((cmw_label = malloc(cmw_length)) == NULL) {
8508 					(void) fprintf(stderr, gettext(
8509 					    "Insufficient memory for label\n"));
8510 					exit(1);
8511 				}
8512 				/* append LBL_TYPE */
8513 				(void) snprintf(cmw_label, cmw_length,
8514 				    "ADMIN_LOW [%s]", ascii);
8515 				(void) append_secattr(secinfo, len,
8516 				    strlen(cmw_label) + 1, cmw_label,
8517 				    LBL_TYPE);
8518 
8519 				/* free storage */
8520 				if (ascii != NULL) {
8521 					free(cmw_label);
8522 					free(ascii);
8523 					ascii = (char *)0;
8524 				}
8525 			}
8526 		}
8527 		break;
8528 
8529 	default:
8530 		break;
8531 	} /* end switch for LBL_TYPE */
8532 
8533 
8534 	/* DONE !! */
8535 	return;
8536 
8537 } /* end of append_ext_attr */
8538 
8539 
8540 /*
8541  *	Name: extract_attr()
8542  *
8543  *	Description:
8544  *		Process attributes from the ancillary file due to
8545  *		the T option.
8546  *
8547  *	Call by doxtract() as part of the switch case structure.
8548  *	Making this a separate routine because the nesting are too
8549  *	deep in doxtract, thus, leaving very little space
8550  *	on each line for instructions.
8551  *
8552  * With option 'T', we extract from a TS 8 or TS 2.5 ancillary file
8553  *
8554  * For option 'T', following are possible attributes in
8555  * a TS 8 ancillary file: (NOTE: No IL support)
8556  *
8557  *	attribute type        attribute		process procedure
8558  *	----------------      ----------------  -------------------------
8559  *    #	LBL_TYPE       = 'L'   SL               construct binary label
8560  *    #	APRIV_TYPE     = 'P'   allowed priv    	construct privileges
8561  *    #	FPRIV_TYPE     = 'p'   forced priv	construct privileges
8562  *    #	COMP_TYPE      = 'C'   path component	construct real path
8563  *    #	DIR_TYPE       = 'D'   directory flag	note it is a directory
8564  *    $	UFSD_ACL       = '1'   ACL data		construct ACL entries
8565  *	ATTR_FLAG_TYPE = 'F'   file attr flags  construct binary flags
8566  *	LK_COMP_TYPE   = 'K'   linked path comp construct linked real path
8567  *
8568  * note: # = attribute names common between TS 8 & TS 2.5 ancillary
8569  *           files.
8570  *       $ = ACL attribute is processed for the option 'p', it doesn't
8571  *           need option 'T'.
8572  *
8573  * Trusted Extensions ignores APRIV_TYPE, FPRIV_TYPE, and ATTR_FLAG_TYPE
8574  *
8575  */
8576 static void
8577 extract_attr(char **file_ptr, struct sec_attr *attr)
8578 {
8579 	int	reterr, err;
8580 	char	*dummy_buf;	/* for attribute extract */
8581 
8582 	dummy_buf = attr->attr_info;
8583 
8584 	switch (attr->attr_type) {
8585 
8586 	case DIR_TYPE:
8587 
8588 		dir_flag++;
8589 		break;
8590 
8591 	case LBL_TYPE:
8592 
8593 		/*
8594 		 * LBL_TYPE is used to indicate SL for directory, and
8595 		 * CMW label for other file types.
8596 		 */
8597 
8598 		if (!dir_flag) { /* not directory */
8599 			/* Skip over IL portion */
8600 			char *sl_ptr = strchr(dummy_buf, '[');
8601 
8602 			if (sl_ptr == NULL)
8603 				err = 0;
8604 			else
8605 				err = stobsl(sl_ptr, &bs_label,
8606 				    NEW_LABEL, &reterr);
8607 		} else { /* directory */
8608 			err = stobsl(dummy_buf, &bs_label,
8609 			    NEW_LABEL, &reterr);
8610 		}
8611 		if (err == 0) {
8612 			(void) fprintf(stderr, gettext("tar: "
8613 			    "can't convert %s to binary label\n"),
8614 			    dummy_buf);
8615 			bslundef(&bs_label);
8616 		} else if (!blequal(&bs_label, &admin_low) &&
8617 		    !blequal(&bs_label, &admin_high)) {
8618 			bslabel_t *from_label;
8619 			char *buf;
8620 			char tempbuf[MAXPATHLEN];
8621 
8622 			if (*orig_namep != '/') {
8623 				/* got relative linked to path */
8624 				(void) getcwd(tempbuf, (sizeof (tempbuf)));
8625 				(void) strncat(tempbuf, "/", MAXPATHLEN);
8626 			} else
8627 				*tempbuf = '\0';
8628 
8629 			buf = real_path;
8630 			(void) strncat(tempbuf, orig_namep, MAXPATHLEN);
8631 			from_label = getlabelbypath(tempbuf);
8632 			if (from_label != NULL) {
8633 				if (blequal(from_label, &admin_low)) {
8634 					if ((getpathbylabel(tempbuf, buf,
8635 					    MAXPATHLEN, &bs_label) == NULL)) {
8636 						(void) fprintf(stderr,
8637 						    gettext("tar: "
8638 						"can't get zone root path for "
8639 						"%s\n"), tempbuf);
8640 					} else
8641 						rpath_flag = 1;
8642 				}
8643 				free(from_label);
8644 			}
8645 		}
8646 		break;
8647 
8648 	case COMP_TYPE:
8649 
8650 		rebuild_comp_path(dummy_buf, file_ptr);
8651 		break;
8652 
8653 	case LK_COMP_TYPE:
8654 
8655 		if (rebuild_lk_comp_path(dummy_buf, file_ptr)
8656 		    == 0) {
8657 			lk_rpath_flag = 1;
8658 		} else {
8659 			(void) fprintf(stderr, gettext("tar: warning: link's "
8660 			    "target pathname might be invalid.\n"));
8661 			lk_rpath_flag = 0;
8662 		}
8663 		break;
8664 	case APRIV_TYPE:
8665 		ignored_aprivs++;
8666 		break;
8667 	case FPRIV_TYPE:
8668 		ignored_fprivs++;
8669 		break;
8670 	case ATTR_FLAG_TYPE:
8671 		ignored_fattrs++;
8672 		break;
8673 
8674 	default:
8675 
8676 		break;
8677 	}
8678 
8679 	/* done */
8680 	return;
8681 
8682 }	/* end extract_attr */
8683 
8684 
8685 
8686 /*
8687  *	Name:	rebuild_comp_path()
8688  *
8689  *	Description:
8690  *		Take the string of components passed down by the calling
8691  *		routine and parse the values and rebuild the path.
8692  *		This routine no longer needs to produce a new real_path
8693  *		string because it is produced when the 'L' LABEL_TYPE is
8694  *		interpreted. So the only thing done here is to distinguish
8695  *		between an SLD and an MLD entry. We only want one, so we
8696  *		ignore the MLD entry by setting the mld_flag.
8697  *
8698  *	return value:
8699  *		none
8700  */
8701 static void
8702 rebuild_comp_path(char *str, char **namep)
8703 {
8704 	char		*cp;
8705 
8706 	while (*str != '\0') {
8707 
8708 		switch (*str) {
8709 
8710 		case MLD_TYPE:
8711 
8712 			str++;
8713 			if ((cp = strstr(str, ";;")) != NULL) {
8714 				*cp = '\0';
8715 				str = cp + 2;
8716 				*cp = ';';
8717 			}
8718 			mld_flag = 1;
8719 			break;
8720 
8721 		case SLD_TYPE:
8722 
8723 			str++;
8724 			if ((cp = strstr(str, ";;")) != NULL) {
8725 				*cp = '\0';
8726 				str = cp + 2;
8727 				*cp = ';';
8728 			}
8729 			mld_flag = 0;
8730 			break;
8731 
8732 		case PATH_TYPE:
8733 
8734 			str++;
8735 			if ((cp = strstr(str, ";;")) != NULL) {
8736 				*cp = '\0';
8737 				str = cp + 2;
8738 				*cp = ';';
8739 			}
8740 			break;
8741 		}
8742 	}
8743 	if (rpath_flag)
8744 		*namep = real_path;
8745 	return;
8746 
8747 } /* end rebuild_comp_path() */
8748 
8749 /*
8750  *	Name:	rebuild_lk_comp_path()
8751  *
8752  *	Description:
8753  *		Take the string of components passed down by the calling
8754  *		routine and parse the values and rebuild the path.
8755  *
8756  *	return value:
8757  *		0 = succeeded
8758  *		-1 = failed
8759  */
8760 static int
8761 rebuild_lk_comp_path(char *str, char **namep)
8762 {
8763 	char		*cp;
8764 	int		reterr;
8765 	bslabel_t	bslabel;
8766 	char		*buf;
8767 	char		pbuf[MAXPATHLEN];
8768 	char		*ptr1, *ptr2;
8769 	int		plen;
8770 	int		use_pbuf;
8771 	char		tempbuf[MAXPATHLEN];
8772 	int		mismatch;
8773 	bslabel_t	*from_label;
8774 	char		zonename[ZONENAME_MAX];
8775 	zoneid_t	zoneid;
8776 
8777 	/* init stuff */
8778 	use_pbuf = 0;
8779 	mismatch = 0;
8780 
8781 	/*
8782 	 * For linked to pathname (LK_COMP_TYPE):
8783 	 *  - If the linked to pathname is absolute (start with /), we
8784 	 *    will use it as is.
8785 	 *  - If it is a relative pathname then it is relative to 1 of 2
8786 	 *    directories.  For a hardlink, it is relative to the current
8787 	 *    directory.  For a symbolic link, it is relative to the
8788 	 *    directory the symbolic link is in.  For the symbolic link
8789 	 *    case, set a flag to indicate we need to use the prefix of
8790 	 *    the restored file's pathname with the linked to pathname.
8791 	 *
8792 	 *    NOTE: At this point, we have no way to determine if we have
8793 	 *    a hardlink or a symbolic link.  We will compare the 1st
8794 	 *    component in the prefix portion of the restore file's
8795 	 *    pathname to the 1st component in the attribute data
8796 	 *    (the linked pathname).  If they are the same, we will assume
8797 	 *    the link pathname to reconstruct is relative to the current
8798 	 *    directory.  Otherwise, we will set a flag indicate we need
8799 	 *    to use a prefix with the reconstructed name.  Need to compare
8800 	 *    both the adorned and unadorned version before deciding a
8801 	 *    mismatch.
8802 	 */
8803 
8804 	buf = lk_real_path;
8805 	if (*(str + 1) != '/') { /* got relative linked to path */
8806 		ptr1 = orig_namep;
8807 		ptr2 = strrchr(ptr1, '/');
8808 		plen = ptr2 - ptr1;
8809 		if (plen > 0) {
8810 			pbuf[0] = '\0';
8811 			plen++;		/* include '/' */
8812 			(void) strncpy(pbuf, ptr1, plen);
8813 			*(pbuf + plen) = '\0';
8814 			ptr2 = strchr(pbuf, '/');
8815 			if (strncmp(pbuf, str + 1, ptr2 - pbuf) != 0)
8816 				mismatch = 1;
8817 		}
8818 
8819 		if (mismatch == 1)
8820 			use_pbuf = 1;
8821 	}
8822 
8823 	buf[0] = '\0';
8824 
8825 	while (*str != '\0') {
8826 
8827 		switch (*str) {
8828 
8829 		case MLD_TYPE:
8830 
8831 			str++;
8832 			if ((cp = strstr(str, ";;")) != NULL) {
8833 				*cp = '\0';
8834 
8835 				/*
8836 				 * Ignore attempts to backup over .MLD.
8837 				 */
8838 				if (strcmp(str, "../") != 0)
8839 					(void) strncat(buf, str, MAXPATHLEN);
8840 				str = cp + 2;
8841 				*cp = ';';
8842 			}
8843 			break;
8844 
8845 		case SLD_TYPE:
8846 
8847 			str++;
8848 			if ((cp = strstr(str, ";;")) != NULL) {
8849 				*cp = '\0';
8850 
8851 				/*
8852 				 * Use the path name in the header if
8853 				 * error occurs when processing the
8854 				 * SLD type.
8855 				 */
8856 
8857 				if (!stobsl(str, &bslabel,
8858 				    NO_CORRECTION, &reterr)) {
8859 					(void) fprintf(stderr, gettext(
8860 					    "tar: can't translate to binary"
8861 					    "SL for SLD, stobsl() error:"
8862 					    " %s\n"), strerror(errno));
8863 					return (-1);
8864 				}
8865 
8866 				str = cp + 2;
8867 				*cp = ';';
8868 
8869 				if (use_pbuf == 1) {
8870 					if (*pbuf != '/') {
8871 						/* relative linked to path */
8872 
8873 						(void) getcwd(tempbuf,
8874 						    (sizeof (tempbuf)));
8875 						(void) strncat(tempbuf, "/",
8876 						    MAXPATHLEN);
8877 						(void) strncat(tempbuf, pbuf,
8878 						    MAXPATHLEN);
8879 					}
8880 					else
8881 						(void) strcpy(tempbuf, pbuf);
8882 
8883 				} else if (*buf != '/') {
8884 					/* got relative linked to path */
8885 
8886 					(void) getcwd(tempbuf,
8887 					    (sizeof (tempbuf)));
8888 					(void) strncat(tempbuf, "/",
8889 					    MAXPATHLEN);
8890 				} else
8891 					*tempbuf = '\0';
8892 
8893 				(void) strncat(tempbuf, buf, MAXPATHLEN);
8894 				*buf = '\0';
8895 
8896 				if (blequal(&bslabel, &admin_high)) {
8897 					bslabel = admin_low;
8898 				}
8899 
8900 
8901 				/*
8902 				 * Check for cross-zone symbolic links
8903 				 */
8904 				from_label = getlabelbypath(real_path);
8905 				if (rpath_flag && (from_label != NULL) &&
8906 				    !blequal(&bslabel, from_label)) {
8907 					if ((zoneid =
8908 					    getzoneidbylabel(&bslabel)) == -1) {
8909 						(void) fprintf(stderr,
8910 						    gettext("tar: can't get "
8911 						    "zone ID for %s\n"),
8912 						    tempbuf);
8913 						return (-1);
8914 					}
8915 					if (zone_getattr(zoneid, ZONE_ATTR_NAME,
8916 					    &zonename, ZONENAME_MAX) == -1) {
8917 						/* Badly configured zone info */
8918 						(void) fprintf(stderr,
8919 						    gettext("tar: can't get "
8920 						    "zonename for %s\n"),
8921 						    tempbuf);
8922 						return (-1);
8923 					}
8924 					(void) strncpy(buf, AUTO_ZONE,
8925 					    MAXPATHLEN);
8926 					(void) strncat(buf, "/",
8927 					    MAXPATHLEN);
8928 					(void) strncat(buf, zonename,
8929 					    MAXPATHLEN);
8930 				}
8931 				if (from_label != NULL)
8932 					free(from_label);
8933 				(void) strncat(buf, tempbuf, MAXPATHLEN);
8934 				break;
8935 			}
8936 			mld_flag = 0;
8937 			break;
8938 
8939 		case PATH_TYPE:
8940 
8941 			str++;
8942 			if ((cp = strstr(str, ";;")) != NULL) {
8943 				*cp = '\0';
8944 				(void) strncat(buf, str, MAXPATHLEN);
8945 				str = cp + 2;
8946 				*cp = ';';
8947 			}
8948 			break;
8949 
8950 		default:
8951 
8952 			(void) fprintf(stderr, gettext(
8953 			    "tar: error rebuilding path %s\n"),
8954 			    *namep);
8955 			*buf = '\0';
8956 			str++;
8957 			return (-1);
8958 		}
8959 	}
8960 
8961 	/*
8962 	 * Done for LK_COMP_TYPE
8963 	 */
8964 
8965 	return (0);    /* component path is rebuilt successfully */
8966 
8967 } /* end rebuild_lk_comp_path() */
8968 
8969 /*
8970  *	Name: check_ext_attr()
8971  *
8972  *	Description:
8973  *		Check the extended attributes for a file being extracted.
8974  *		The attributes being checked here are CMW labels.
8975  *		ACLs are not set here because they are set by the
8976  *		pflag in doxtract().
8977  *
8978  *		If the label doesn't match, return 0
8979  *		else return 1
8980  */
8981 static int
8982 check_ext_attr(char *filename)
8983 {
8984 	bslabel_t	currentlabel;	/* label from zone */
8985 
8986 	if (bltype(&bs_label, SUN_SL_UN)) {
8987 		/* No label check possible */
8988 		return (0);
8989 	}
8990 	if (getlabel(filename, &currentlabel) != 0) {
8991 		(void) fprintf(stderr,
8992 		    gettext("tar: can't get label for "
8993 		    " %s, getlabel() error: %s\n"),
8994 		    filename, strerror(errno));
8995 		return (0);
8996 	} else if ((blequal(&currentlabel, &bs_label)) == 0) {
8997 		char	*src_label = NULL;	/* ascii label */
8998 
8999 		/* get current src SL */
9000 		if (bsltos(&bs_label, &src_label, 0, 0) <= 0) {
9001 			(void) fprintf(stderr,
9002 			    gettext("tar: can't interpret requested label for"
9003 			    " %s\n"), filename);
9004 		} else {
9005 			(void) fprintf(stderr,
9006 			    gettext("tar: can't apply label %s to %s\n"),
9007 			    src_label, filename);
9008 			free(src_label);
9009 		}
9010 		(void) fprintf(stderr,
9011 		    gettext("tar: %s not restored\n"), filename);
9012 		return (0);
9013 	}
9014 	return (1);
9015 
9016 }	/* end check_ext_attr */
9017