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.
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.
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]
22 * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2012 Milan Jurik. All rights reserved.
24 * Copyright 2015 Joyent, Inc.
27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
30 /* Copyright (c) 1987, 1988 Microsoft Corporation */
31 /* All Rights Reserved */
34 * Portions of this source code were derived from Berkeley 4.3 BSD
35 * under license from the Regents of the University of California.
39 #include <sys/types.h>
40 #include <sys/param.h>
42 #include <sys/mkdev.h>
72 #include <libnvpair.h>
75 #if defined(__SunOS_5_6) || defined(__SunOS_5_7)
78 #if defined(_PC_SATTR_ENABLED)
80 #include <libcmdutils.h>
83 #include "getresponse.h"
85 * Source compatibility
89 * These constants come from archives.h and sys/fcntl.h
90 * and were introduced by the extended attributes project
94 #define AT_SYMLINK_NOFOLLOW 0x1000
95 #define AT_REMOVEDIR 0x1
96 #define AT_FDCWD 0xffd19553
97 #define _XATTR_HDRTYPE 'E'
98 static int attropen();
100 static int renameat();
101 static int unlinkat();
103 static int fchownat();
104 static int futimesat();
108 * Compiling with -D_XPG4_2 gets this but produces other problems, so
109 * instead of including sys/time.h and compiling with -D_XPG4_2, I'm
110 * explicitly doing the declaration here.
112 int utimes(const char *path
, const struct timeval timeval_ptr
[]);
117 #define DEF_FILE "/etc/default/tar"
119 #define min(a, b) ((a) < (b) ? (a) : (b))
120 #define max(a, b) ((a) > (b) ? (a) : (b))
122 #define TBLOCK 512 /* tape block size--should be universal */
125 #define SYS_BLOCK BSIZE /* from sys/param.h: secondary block size */
127 #define SYS_BLOCK 512 /* default if no BSIZE in param.h */
134 #define MODEMASK 0777777 /* file creation mode mask */
135 #define POSIXMODES 07777 /* mask for POSIX mode bits */
136 #define MAXEXT 9 /* reasonable max # extents for a file */
137 #define EXTMIN 50 /* min blks left on floppy to split a file */
139 /* max value dblock.dbuf.efsize can store */
140 #define TAR_EFSIZE_MAX 0777777777
143 * Symbols which specify the values at which the use of the 'E' function
144 * modifier is required to properly store a file.
146 * TAR_OFFSET_MAX - the largest file size we can archive
147 * OCTAL7CHAR - the limit for ustar gid, uid, dev
151 /* tiny values which force the creation of extended header entries */
152 #define TAR_OFFSET_MAX 9
156 #define TAR_OFFSET_MAX 077777777777ULL
157 #define OCTAL7CHAR 07777777
160 #define TBLOCKS(bytes) (((bytes) + TBLOCK - 1) / TBLOCK)
161 #define K(tblocks) ((tblocks+1)/2) /* tblocks to Kbytes for printing */
163 #define MAXLEV (PATH_MAX / 2)
165 #define SYMLINK_LEV0 0
171 #define NORMAL_FILE 0
173 #define PUT_AS_LINK 1
174 #define PUT_NOTAS_LINK 0
176 #ifndef VIEW_READONLY
177 #define VIEW_READONLY "SUNWattr_ro"
180 #ifndef VIEW_READWRITE
181 #define VIEW_READWRITE "SUNWattr_rw"
184 #if _FILE_OFFSET_BITS == 64
185 #define FMT_off_t "lld"
186 #define FMT_off_t_o "llo"
187 #define FMT_blkcnt_t "lld"
189 #define FMT_off_t "ld"
190 #define FMT_off_t_o "lo"
191 #define FMT_blkcnt_t "ld"
221 typedef struct attr_data
{
230 * Tar has been changed to support extended attributes.
232 * As part of this change tar now uses the new *at() syscalls
233 * such as openat, fchownat(), unlinkat()...
235 * This was done so that attributes can be handled with as few code changes
238 * What this means is that tar now opens the directory that a file or directory
239 * resides in and then performs *at() functions to manipulate the entry.
241 * For example a new file is now created like this:
243 * dfd = open(<some dir path>)
244 * fd = openat(dfd, <name>,....);
246 * or in the case of an extended attribute
248 * dfd = attropen(<pathname>, ".", ....)
250 * Once we have a directory file descriptor all of the *at() functions can
253 * unlinkat(dfd, <component name>,...)
254 * fchownat(dfd, <component name>,..)
256 * This works for both normal namespace files and extended attribute file
262 * Extended attribute Format
264 * Extended attributes are stored in two pieces.
265 * 1. An attribute header which has information about
266 * what file the attribute is for and what the attribute
268 * 2. The attribute record itself. Stored as a normal file type
270 * Both the header and attribute record have special modes/typeflags
271 * associated with them.
273 * The names of the header in the archive look like:
276 * The name of the attribute looks like:
279 * This is done so that an archiver that doesn't understand these formats
280 * can just dispose of the attribute records.
282 * The format is composed of a fixed size header followed
283 * by a variable sized xattr_buf. If the attribute is a hard link
284 * to another attribute then another xattr_buf section is included
287 * The xattr_buf is used to define the necessary "pathing" steps
288 * to get to the extended attribute. This is necessary to support
289 * a fully recursive attribute model where an attribute may itself
292 * The basic layout looks like this.
294 * --------------------------------
298 * --------------------------------
299 * --------------------------------
303 * --------------------------------
304 * --------------------------------
306 * | (optional link info) |
308 * --------------------------------
309 * --------------------------------
311 * | attribute itself |
312 * | stored as normal tar |
313 * | or cpio data with |
314 * | special mode or |
317 * --------------------------------
322 * xattrhead is a pointer to the xattr_hdr
324 * xattrp is a pointer to the xattr_buf structure
325 * which contains the "pathing" steps to get to attributes
327 * xattr_linkp is a pointer to another xattr_buf structure that is
328 * only used when an attribute is actually linked to another attribute
332 static struct xattr_hdr
*xattrhead
;
333 static struct xattr_buf
*xattrp
;
334 static struct xattr_buf
*xattr_linkp
; /* pointer to link info, if any */
335 static char *xattrapath
; /* attribute name */
336 static char *xattr_linkaname
; /* attribute attribute is linked to */
337 static char Hiddendir
; /* are we processing hidden xattr dir */
338 static char xattrbadhead
;
340 /* Was statically allocated tbuf[NBLOCK] */
345 char name
[NAMSIZ
]; /* If non-null prefix, path is */
346 /* <prefix>/<name>; otherwise */
351 char size
[12]; /* size of this extent if file split */
355 char linkname
[NAMSIZ
];
362 char prefix
[PRESIZ
]; /* Together with "name", the path of */
363 /* the file: <prefix>/<name> */
364 char extno
; /* extent #, null if not split */
365 char extotal
; /* total extents */
366 char efsize
[10]; /* size of entire file */
368 } dblock
, *tbuf
, xhdr_buf
;
372 uid_t x_uid
, /* Uid of file */
373 x_gid
; /* Gid of file */
374 major_t x_devmajor
; /* Device major node */
375 minor_t x_devminor
; /* Device minor node */
376 off_t x_filesz
; /* Length of file */
377 char *x_uname
, /* Pointer to name of user */
378 *x_gname
, /* Pointer to gid of user */
379 *x_linkpath
, /* Path for a hard/symbolic link */
380 *x_path
; /* Path of file */
381 timestruc_t x_mtime
; /* Seconds and nanoseconds */
386 ulong_t g_mode
; /* Mode of file */
387 uid_t g_uid
, /* Uid of file */
388 g_gid
; /* Gid of file */
389 off_t g_filesz
; /* Length of file */
390 time_t g_mtime
; /* Modification time */
391 uint_t g_cksum
; /* Checksum of file */
392 ulong_t g_devmajor
, /* File system of file */
393 g_devminor
; /* Major/minor of special files */
401 char pathname
[MAXNAM
+1]; /* added 1 for last NULL */
402 char attrname
[MAXNAM
+1];
403 struct linkbuf
*nextp
;
406 /* see comments before build_table() */
407 #define TABLE_SIZE 512
408 typedef struct file_list
{
409 char *name
; /* Name of file to {in,ex}clude */
410 struct file_list
*next
; /* Linked list */
412 static file_list_t
*exclude_tbl
[TABLE_SIZE
],
413 *include_tbl
[TABLE_SIZE
];
415 static int append_secattr(char **, int *, int, char *, char);
416 static void write_ancillary(union hblock
*, char *, int, char);
418 static void add_file_to_table(file_list_t
*table
[], char *str
);
419 static void assert_string(char *s
, char *msg
);
420 static int istape(int fd
, int type
);
421 static void backtape(void);
422 static void build_table(file_list_t
*table
[], char *file
);
423 static int check_prefix(char **namep
, char **dirp
, char **compp
);
424 static void closevol(void);
425 static void copy(void *dst
, void *src
);
426 static int convtoreg(off_t
);
427 static void delete_target(int fd
, char *comp
, char *namep
);
428 static void doDirTimes(char *name
, timestruc_t modTime
);
429 static void done(int n
);
430 static void dorep(char *argv
[]);
431 static void dotable(char *argv
[]);
432 static void doxtract(char *argv
[]);
433 static int tar_chdir(const char *path
);
434 static int is_directory(char *name
);
435 static int has_dot_dot(char *name
);
436 static int is_absolute(char *name
);
437 static char *make_relative_name(char *name
, char **stripped_prefix
);
438 static void fatal(char *format
, ...);
439 static void vperror(int exit_status
, char *fmt
, ...);
440 static void flushtape(void);
441 static void getdir(void);
442 static void *getmem(size_t);
443 static void longt(struct stat
*st
, char aclchar
);
444 static void load_info_from_xtarhdr(u_longlong_t flag
, struct xtar_hdr
*xhdrp
);
445 static int makeDir(char *name
);
446 static void mterr(char *operation
, int i
, int exitcode
);
447 static void newvol(void);
448 static void passtape(void);
449 static void putempty(blkcnt_t n
);
450 static int putfile(char *longname
, char *shortname
, char *parent
,
451 attr_data_t
*attrinfo
, int filetype
, int lev
, int symlink_lev
);
452 static void readtape(char *buffer
);
453 static void seekdisk(blkcnt_t blocks
);
454 static void setPathTimes(int dirfd
, char *path
, timestruc_t modTime
);
455 static void setbytes_to_skip(struct stat
*st
, int err
);
456 static void splitfile(char *longname
, int ifd
, char *name
,
457 char *prefix
, int filetype
);
458 static void tomodes(struct stat
*sp
);
459 static void usage(void);
460 static int xblocks(int issysattr
, off_t bytes
, int ofile
);
461 static int xsfile(int issysattr
, int ofd
);
462 static void resugname(int dirfd
, char *name
, int symflag
);
463 static int bcheck(char *bstr
);
464 static int checkdir(char *name
);
465 static int checksum(union hblock
*dblockp
);
467 static int checksum_signed(union hblock
*dblockp
);
469 static int checkupdate(char *arg
);
470 static int checkw(char c
, char *name
);
471 static int cmp(char *b
, char *s
, int n
);
472 static int defset(char *arch
);
473 static boolean_t
endtape(void);
474 static int is_in_table(file_list_t
*table
[], char *str
);
475 static int notsame(void);
476 static int is_prefix(char *s1
, char *s2
);
477 static int response(void);
478 static int build_dblock(const char *, const char *, const char,
479 const int filetype
, const struct stat
*, const dev_t
, const char *);
480 static unsigned int hash(char *str
);
482 static blkcnt_t
kcheck(char *kstr
);
483 static off_t
bsrch(char *s
, int n
, off_t l
, off_t h
);
484 static void onintr(int sig
);
485 static void onquit(int sig
);
486 static void onhup(int sig
);
487 static uid_t
getuidbyname(char *);
488 static gid_t
getgidbyname(char *);
489 static char *getname(gid_t
);
490 static char *getgroup(gid_t
);
491 static int checkf(char *name
, int mode
, int howmuch
);
492 static int writetbuf(char *buffer
, int n
);
493 static int wantit(char *argv
[], char **namep
, char **dirp
, char **comp
,
494 attr_data_t
**attrinfo
);
495 static int get_xdata(void);
496 static void gen_num(const char *keyword
, const u_longlong_t number
);
497 static void gen_date(const char *keyword
, const timestruc_t time_value
);
498 static void gen_string(const char *keyword
, const char *value
);
499 static void get_xtime(char *value
, timestruc_t
*xtime
);
500 static int chk_path_build(char *name
, char *longname
, char *linkname
,
501 char *prefix
, char type
, int filetype
);
502 static int gen_utf8_names(const char *filename
);
503 static int utf8_local(char *option
, char **Xhdr_ptrptr
, char *target
,
504 const char *src
, int max_val
);
505 static int local_utf8(char **Xhdr_ptrptr
, char *target
, const char *src
,
506 iconv_t iconv_cd
, int xhdrflg
, int max_val
);
507 static int c_utf8(char *target
, const char *source
);
508 static int getstat(int dirfd
, char *longname
, char *shortname
,
510 static void xattrs_put(char *, char *, char *, char *);
511 static void prepare_xattr(char **, char *, char *,
512 char, struct linkbuf
*, int *);
513 static int put_link(char *name
, char *longname
, char *component
,
514 char *longattrname
, char *prefix
, int filetype
, char typeflag
);
515 static int put_extra_attributes(char *longname
, char *shortname
,
516 char *longattrname
, char *prefix
, int filetype
, char typeflag
);
517 static int put_xattr_hdr(char *longname
, char *shortname
, char *longattrname
,
518 char *prefix
, int typeflag
, int filetype
, struct linkbuf
*lp
);
519 static int read_xattr_hdr(attr_data_t
**attrinfo
);
521 static void get_parent(char *path
, char *dir
);
522 static char *get_component(char *path
);
523 static int retry_open_attr(int pdirfd
, int cwd
, char *dirp
, char *pattr
,
524 char *name
, int oflag
, mode_t mode
);
525 static char *skipslashes(char *string
, char *start
);
526 static void chop_endslashes(char *path
);
527 static pid_t
compress_file(void);
528 static void compress_back(void);
529 static void decompress_file(void);
530 static pid_t
uncompress_file(void);
531 static void *compress_malloc(size_t);
532 static void check_compression(void);
533 static char *bz_suffix(void);
534 static char *gz_suffix(void);
535 static char *xz_suffix(void);
536 static char *add_suffix();
537 static void wait_pid(pid_t
);
538 static void verify_compress_opt(const char *t
);
539 static void detect_compress(void);
540 static void dlog(const char *, ...);
541 static boolean_t
should_enable_debug(void);
543 static struct stat stbuf
;
546 static char *xtract_chdir
= NULL
;
547 static int checkflag
= 0;
548 static int Xflag
, Fflag
, iflag
, hflag
, Bflag
, Iflag
;
549 static int rflag
, xflag
, vflag
, tflag
, mt
, cflag
, mflag
, pflag
;
553 static int bflag
, Aflag
;
554 static int Pflag
; /* POSIX conformant archive */
555 static int Eflag
; /* Allow files greater than 8GB */
556 static int atflag
; /* traverse extended attributes */
557 static int saflag
; /* traverse extended sys attributes */
558 static int Dflag
; /* Data change flag */
559 static int jflag
; /* flag to use 'bzip2' */
560 static int zflag
; /* flag to use 'gzip' */
561 static int Zflag
; /* flag to use 'compress' */
562 static int Jflag
; /* flag to use 'xz' */
563 static int aflag
; /* flag to use autocompression */
565 static int term
, chksum
, wflag
,
566 first
= TRUE
, defaults_used
= FALSE
, linkerrok
;
567 static blkcnt_t recno
;
568 static int freemem
= 1;
569 static int nblock
= NBLOCK
;
570 static int Errflg
= 0;
571 static int exitflag
= 0;
573 static dev_t mt_dev
; /* device containing output file */
574 static ino_t mt_ino
; /* inode number of output file */
575 static int mt_devtype
; /* dev type of archive, from stat structure */
577 static int update
= 1; /* for `open' call */
583 static FILE *vfile
= stdout
;
585 static char *tmp_suffix
= "/tarXXXXXX";
587 static char archive
[] = "archive0=";
589 static char *usefile
;
590 static char tfname
[1024];
592 static int mulvol
; /* multi-volume option selected */
593 static blkcnt_t blocklim
; /* number of blocks to accept per volume */
594 static blkcnt_t tapepos
; /* current block number to be written */
595 static int NotTape
; /* true if tape is a disk */
596 static int dumping
; /* true if writing a tape or other archive */
597 static int extno
; /* number of extent: starts at 1 */
598 static int extotal
; /* total extents in this file */
599 static off_t extsize
; /* size of current extent during extraction */
600 static ushort_t Oumask
= 0; /* old umask value */
601 static boolean_t is_posix
; /* true if archive is POSIX-conformant */
602 static const char *magic_type
= "ustar";
603 static size_t xrec_size
= 8 * PATH_MAX
; /* extended rec initial size */
604 static char *xrec_ptr
;
605 static off_t xrec_offset
= 0;
607 static int charset_type
= 0;
609 static u_longlong_t xhdr_flgs
; /* Bits set determine which items */
610 /* need to be in extended header. */
611 static pid_t comp_pid
= 0;
613 static boolean_t debug_output
= B_FALSE
;
615 #define _X_DEVMAJOR 0x1
616 #define _X_DEVMINOR 0x2
619 #define _X_LINKPATH 0x10
623 #define _X_UNAME 0x100
624 #define _X_ATIME 0x200
625 #define _X_CTIME 0x400
626 #define _X_MTIME 0x800
627 #define _X_XHDR 0x1000 /* Bit flag that determines whether 'X' */
628 /* typeflag was followed by 'A' or non 'A' */
630 #define _X_LAST 0x40000000
632 #define PID_MAX_DIGITS (10 * sizeof (pid_t) / 4)
633 #define TIME_MAX_DIGITS (10 * sizeof (time_t) / 4)
634 #define LONG_MAX_DIGITS (10 * sizeof (long) / 4)
635 #define ULONGLONG_MAX_DIGITS (10 * sizeof (u_longlong_t) / 4)
637 * UTF_8 encoding requires more space than the current codeset equivalent.
638 * Currently a factor of 2-3 would suffice, but it is possible for a factor
639 * of 6 to be needed in the future, so for saftey, we use that here.
641 #define UTF_8_FACTOR 6
643 static u_longlong_t xhdr_count
= 0;
644 static char xhdr_dirname
[PRESIZ
+ 1];
645 static char pidchars
[PID_MAX_DIGITS
+ 1];
646 static char *tchar
= ""; /* null linkpath */
648 static char local_path
[UTF_8_FACTOR
* PATH_MAX
+ 1];
649 static char local_linkpath
[UTF_8_FACTOR
* PATH_MAX
+ 1];
650 static char local_gname
[UTF_8_FACTOR
* _POSIX_NAME_MAX
+ 1];
651 static char local_uname
[UTF_8_FACTOR
* _POSIX_NAME_MAX
+ 1];
654 * The following mechanism is provided to allow us to debug tar in complicated
655 * situations, like when it is part of a pipe. The idea is that you compile
656 * with -DWAITAROUND defined, and then add the 'D' function modifier to the
657 * target tar invocation, eg. "tar cDf tarfile file". If stderr is available,
658 * it will tell you to which pid to attach the debugger; otherwise, use ps to
659 * find it. Attach to the process from the debugger, and, *PRESTO*, you are
662 * Simply assign "waitaround = 0" once you attach to the process, and then
663 * proceed from there as usual.
667 int waitaround
= 0; /* wait for rendezvous with the debugger */
670 #define BZIP "/usr/bin/bzip2"
671 #define GZIP "/usr/bin/gzip"
672 #define COMPRESS "/usr/bin/compress"
673 #define XZ "/usr/bin/xz"
674 #define BZCAT "/usr/bin/bzcat"
675 #define GZCAT "/usr/bin/gzcat"
676 #define ZCAT "/usr/bin/zcat"
677 #define XZCAT "/usr/bin/xzcat"
678 #define GSUF 8 /* number of valid 'gzip' sufixes */
679 #define BSUF 4 /* number of valid 'bzip2' sufixes */
680 #define XSUF 1 /* number of valid 'xz' suffixes */
682 static char *compress_opt
; /* compression type */
684 static char *gsuffix
[] = {".gz", "-gz", ".z", "-z", "_z", ".Z",
686 static char *bsuffix
[] = {".bz2", ".bz", ".tbz2", ".tbz"};
687 static char *xsuffix
[] = {".xz"};
692 main(int argc
, char *argv
[])
698 (void) setlocale(LC_ALL
, "");
699 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
700 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
702 (void) textdomain(TEXT_DOMAIN
);
706 debug_output
= should_enable_debug();
709 if ((myname
= strdup(argv
[0])) == NULL
) {
710 (void) fprintf(stderr
, gettext(
711 "tar: cannot allocate program name\n"));
715 if (init_yes() < 0) {
716 (void) fprintf(stderr
, gettext(ERR_MSG_INIT_YES
),
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.
728 if (strcmp(argv
[1], "--") == 0) {
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'.
745 if ((usefile
= getenv("TAPE")) == (char *)NULL
) {
746 for (cp
= *argv
; *cp
; ++cp
)
747 if (isdigit(*cp
) || *cp
== 'f')
750 archive
[7] = (*cp
)? *cp
: '0';
751 if (!(defaults_used
= defset(archive
))) {
760 for (cp
= *argv
++; *cp
; cp
++)
764 /* rendezvous with the debugger */
769 assert_string(*argv
, gettext(
770 "tar: tarfile must be specified with 'f' "
771 "function modifier\n"));
787 #if defined(_PC_SATTR_ENABLED)
791 #endif /* _PC_SATTR_ENABLED */
793 uflag
++; /* moved code after signals caught */
811 assert_string(*argv
, gettext(
812 "tar: exclude file must be specified with 'X' "
813 "function modifier\n"));
816 build_table(exclude_tbl
, Xfile
);
831 /* ignore this silently */
833 case '0': /* numeric entries used only for defaults */
843 assert_string(*argv
, gettext(
844 "tar: blocking factor must be specified "
845 "with 'b' function modifier\n"));
847 nblock
= bcheck(*argv
++);
849 case 'n': /* not a magtape (instead of 'k') */
850 NotTape
++; /* assume non-magtape */
875 Pflag
++; /* Only POSIX archive made */
877 case 'j': /* compession "bzip2" */
880 case 'z': /* compression "gzip" */
883 case 'Z': /* compression "compress" */
886 case 'J': /* compression "xz" */
890 aflag
= 1; /* autocompression */
893 (void) fprintf(stderr
, gettext(
894 "tar: %c: unknown function modifier\n"), *cp
);
898 if (!rflag
&& !xflag
&& !tflag
)
900 if ((rflag
&& xflag
) || (xflag
&& tflag
) || (rflag
&& tflag
)) {
901 (void) fprintf(stderr
, gettext(
902 "tar: specify only one of [ctxru].\n"));
906 if ((jflag
+ zflag
+ Zflag
+ Jflag
+ aflag
) > 1) {
907 (void) fprintf(stderr
, gettext(
908 "tar: specify only one of [ajJzZ] to "
909 "create a compressed file.\n"));
913 if (cflag
&& *argv
== NULL
)
914 fatal(gettext("Missing filenames"));
916 fatal(gettext("device argument required"));
918 /* alloc a buffer of the right size */
919 if ((tbuf
= (union hblock
*)
920 calloc(sizeof (union hblock
) * nblock
, sizeof (char))) ==
921 (union hblock
*)NULL
) {
922 (void) fprintf(stderr
, gettext(
923 "tar: cannot allocate physio buffer\n"));
927 if ((xrec_ptr
= malloc(xrec_size
)) == NULL
) {
928 (void) fprintf(stderr
, gettext(
929 "tar: cannot allocate extended header buffer\n"));
935 (void) fprintf(stderr
, gettext("Rendezvous with tar on pid"
945 (void) sprintf(pidchars
, "%ld", thispid
);
946 thispid
= strlen(pidchars
);
948 if ((tmpdirp
= getenv("TMPDIR")) == (char *)NULL
)
949 (void) strcpy(xhdr_dirname
, "/tmp");
952 * Make sure that dir is no longer than what can
953 * fit in the prefix part of the header.
955 if (strlen(tmpdirp
) > (size_t)(PRESIZ
- thispid
- 12)) {
956 (void) strcpy(xhdr_dirname
, "/tmp");
957 if ((vflag
> 0) && (Eflag
> 0))
958 (void) fprintf(stderr
, gettext(
959 "Ignoring TMPDIR\n"));
961 (void) strcpy(xhdr_dirname
, tmpdirp
);
963 (void) strcat(xhdr_dirname
, "/PaxHeaders.");
964 (void) strcat(xhdr_dirname
, pidchars
);
967 if (cflag
&& usefile
!= NULL
) {
968 /* Set the compression type */
973 compress_opt
= compress_malloc(strlen(BZIP
)
975 (void) strcpy(compress_opt
, BZIP
);
977 compress_opt
= compress_malloc(strlen(GZIP
)
979 (void) strcpy(compress_opt
, GZIP
);
982 compress_malloc(strlen(COMPRESS
) + 1);
983 (void) strcpy(compress_opt
, COMPRESS
);
985 compress_opt
= compress_malloc(strlen(XZ
) + 1);
986 (void) strcpy(compress_opt
, XZ
);
990 * Decompress if the file is compressed for
991 * an update or replace.
993 if (strcmp(usefile
, "-") != 0) {
995 if (compress_opt
!= NULL
) {
1001 if (cflag
&& tfile
!= NULL
)
1003 if (signal(SIGINT
, SIG_IGN
) != SIG_IGN
)
1004 (void) signal(SIGINT
, onintr
);
1005 if (signal(SIGHUP
, SIG_IGN
) != SIG_IGN
)
1006 (void) signal(SIGHUP
, onhup
);
1007 if (signal(SIGQUIT
, SIG_IGN
) != SIG_IGN
)
1008 (void) signal(SIGQUIT
, onquit
);
1013 tmpdir
= getenv("TMPDIR");
1015 * If the name is invalid or this isn't a directory,
1016 * or the directory is not writable, then reset to
1017 * a default temporary directory.
1019 if (tmpdir
== NULL
|| *tmpdir
== '\0' ||
1020 (strlen(tmpdir
) + strlen(tmp_suffix
)) > PATH_MAX
) {
1022 } else if (stat(tmpdir
, &sbuf
) < 0 ||
1023 (sbuf
.st_mode
& S_IFMT
) != S_IFDIR
||
1024 (sbuf
.st_mode
& S_IWRITE
) == 0) {
1028 if ((tname
= calloc(1, strlen(tmpdir
) +
1029 strlen(tmp_suffix
) + 1)) == NULL
) {
1030 vperror(1, gettext("tar: out of memory, "
1031 "cannot create temporary file\n"));
1033 (void) strcpy(tname
, tmpdir
);
1034 (void) strcat(tname
, tmp_suffix
);
1036 if ((tnum
= mkstemp(tname
)) == -1)
1037 vperror(1, "%s", tname
);
1038 if ((tfile
= fdopen(tnum
, "w")) == NULL
)
1039 vperror(1, "%s", tname
);
1041 if (strcmp(usefile
, "-") == 0) {
1044 "can only create standard output archives."));
1051 O_RDWR
|O_CREAT
|O_TRUNC
, 0666);
1053 mt
= open(usefile
, O_RDWR
);
1056 if (cflag
== 0 || (mt
= creat(usefile
, 0666))
1058 vperror(1, "%s", usefile
);
1061 /* Get inode and device number of output file */
1062 (void) fstat(mt
, &stbuf
);
1063 mt_ino
= stbuf
.st_ino
;
1064 mt_dev
= stbuf
.st_dev
;
1065 mt_devtype
= stbuf
.st_mode
& S_IFMT
;
1066 NotTape
= !istape(mt
, mt_devtype
);
1068 if (rflag
&& !cflag
&& (mt_devtype
== S_IFIFO
))
1069 fatal(gettext("cannot append to pipe or FIFO."));
1073 gettext("Suppressing absolute pathnames\n"));
1074 if (cflag
&& compress_opt
!= NULL
)
1075 comp_pid
= compress_file();
1077 if (rflag
&& !cflag
&& (compress_opt
!= NULL
))
1079 } else if (xflag
|| tflag
) {
1081 * for each argument, check to see if there is a "-I file" pair.
1082 * if so, move the 3rd argument into "-I"'s place, build_table()
1083 * using "file"'s name and increment argc one (the second
1084 * increment appears in the for loop) which removes the two
1085 * args "-I" and "file" from the argument vector.
1087 for (argc
= 0; argv
[argc
]; argc
++) {
1088 if (strcmp(argv
[argc
], "-I") == 0) {
1089 if (!argv
[argc
+1]) {
1090 (void) fprintf(stderr
, gettext(
1091 "tar: missing argument for -I flag\n"));
1095 argv
[argc
] = argv
[argc
+2];
1096 build_table(include_tbl
, argv
[++argc
]);
1098 } else if (strcmp(argv
[argc
], "-C") == 0) {
1099 if (!argv
[argc
+1]) {
1100 (void) fprintf(stderr
, gettext("tar: "
1101 "missing argument for -C flag\n"));
1103 } else if (xtract_chdir
!= NULL
) {
1104 (void) fprintf(stderr
, gettext("tar: "
1105 "extract should have only one -C "
1109 argv
[argc
] = argv
[argc
+2];
1110 xtract_chdir
= argv
[++argc
];
1114 if (strcmp(usefile
, "-") == 0) {
1117 /* try to recover from short reads when reading stdin */
1119 } else if ((mt
= open(usefile
, 0)) < 0)
1120 vperror(1, "%s", usefile
);
1122 /* Decompress if the file is compressed */
1124 if (strcmp(usefile
, "-") != 0) {
1125 check_compression();
1126 if (compress_opt
!= NULL
)
1127 comp_pid
= uncompress_file();
1130 if (xtract_chdir
!= NULL
) {
1131 if (tar_chdir(xtract_chdir
) < 0) {
1132 vperror(1, gettext("can't change "
1133 "directories to %s"), xtract_chdir
);
1137 (void) printf(gettext(
1138 "Suppressing absolute pathnames.\n"));
1149 /* Not reached: keep compiler quiet */
1154 should_enable_debug(void)
1157 const char *truth
[] = {
1167 if ((val
= getenv("DEBUG_TAR")) == NULL
) {
1171 for (i
= 0; truth
[i
] != NULL
; i
++) {
1172 if (strcmp(val
, truth
[i
]) == 0) {
1182 dlog(const char *format
, ...)
1186 if (!debug_output
) {
1190 va_start(ap
, format
);
1191 (void) fprintf(stderr
, "tar: DEBUG: ");
1192 (void) vfprintf(stderr
, format
, ap
);
1199 (void) fprintf(stderr
, gettext(
1200 #if defined(O_XATTR)
1201 #if defined(_PC_SATTR_ENABLED)
1202 "Usage: tar {c|r|t|u|x}[BDeEFhilmnopPvw@/[0-7]][bf][X...] "
1204 "Usage: tar {c|r|t|u|x}[BDeEFhilmnopPvw@[0-7]][bf][X...] "
1205 #endif /* _PC_SATTR_ENABLED */
1207 "Usage: tar {c|r|t|u|x}[BDeEFhilmnopPvw[0-7]][bf][X...] "
1208 #endif /* O_XATTR */
1210 "[blocksize] [tarfile] [size] [exclude-file...] "
1211 "{file | -I include-file | -C directory file}...\n"));
1216 * dorep - do "replacements"
1218 * Dorep is responsible for creating ('c'), appending ('r')
1219 * and updating ('u');
1226 char wdir
[PATH_MAX
+2], tempdir
[PATH_MAX
+2], *parent
;
1227 char file
[PATH_MAX
*2], origdir
[PATH_MAX
+1];
1228 FILE *fp
= (FILE *)NULL
;
1235 getdir(); /* read header for next file */
1238 fatal(gettext("Archive contains extended"
1239 " header. -E flag required.\n"));
1240 ret
= get_xdata(); /* Get extended header items */
1241 /* and regular header */
1244 fatal(gettext("Archive contains no extended"
1245 " header. -E flag not allowed.\n"));
1247 while (!endtape()) { /* changed from a do while */
1248 setbytes_to_skip(&stbuf
, ret
);
1249 passtape(); /* skip the file data */
1251 done(Errflg
); /* received signal to stop */
1258 if ((dblock
.dbuf
.typeflag
!= 'A') &&
1260 load_info_from_xtarhdr(xhdr_flgs
,
1262 xhdr_flgs
|= _X_XHDR
;
1265 backtape(); /* was called by endtape */
1266 if (tfile
!= NULL
) {
1268 * Buffer size is calculated to be the size of the
1269 * tmpdir string, plus 6 times the size of the tname
1270 * string, plus a value that is known to be greater
1271 * than the command pipeline string.
1273 int buflen
= strlen(tmpdir
) + (6 * strlen(tname
)) + 100;
1276 if ((buf
= (char *)calloc(1, buflen
)) == NULL
) {
1277 vperror(1, gettext("tar: out of memory, "
1278 "cannot create sort command file\n"));
1281 (void) snprintf(buf
, buflen
, "env 'TMPDIR=%s' "
1282 "sort +0 -1 +1nr %s -o %s; awk '$1 "
1283 "!= prev {print; prev=$1}' %s >%sX;mv %sX %s",
1284 tmpdir
, tname
, tname
, tname
, tname
, tname
, tname
);
1285 (void) fflush(tfile
);
1288 (void) freopen(tname
, "r", tfile
);
1289 (void) fstat(fileno(tfile
), &stbuf
);
1290 high
= stbuf
.st_size
;
1295 if (mulvol
) { /* SP-1 */
1296 if (nblock
&& (blocklim
%nblock
) != 0)
1298 "Volume size not a multiple of block size."));
1299 blocklim
-= 2; /* for trailer records */
1301 (void) fprintf(vfile
, gettext("Volume ends at %"
1302 FMT_blkcnt_t
"K, blocking factor = %dK\n"),
1303 K((blocklim
- 1)), K(nblock
));
1307 * Save the original directory before it gets
1310 if (getcwd(origdir
, (PATH_MAX
+1)) == NULL
) {
1311 vperror(0, gettext("A parent directory cannot be read"));
1315 (void) strcpy(wdir
, origdir
);
1317 while ((*argv
|| fp
) && !term
) {
1318 if (fp
|| (strcmp(*argv
, "-I") == 0)) {
1320 if (*++argv
== NULL
)
1322 "missing file name for -I flag."));
1323 else if ((fp
= fopen(*argv
++, "r")) == NULL
)
1324 vperror(0, "%s", argv
[-1]);
1326 } else if ((fgets(file
, PATH_MAX
-1, fp
)) == NULL
) {
1332 if ((p
= strchr(cp2
, '\n')))
1335 } else if ((strcmp(*argv
, "-C") == 0) && argv
[1]) {
1336 if (tar_chdir(*++argv
) < 0)
1338 "can't change directories to %s"), *argv
);
1340 (void) getcwd(wdir
, (sizeof (wdir
)));
1344 cp
= cp2
= strcpy(file
, *argv
++);
1347 * point cp2 to the last '/' in file, but not
1352 while (*(cp
+1) == '/') {
1355 if (*(cp
+1) != '\0') {
1356 /* not trailing slash */
1363 if (tar_chdir(file
) < 0) {
1365 "can't change directories to %s"), file
);
1372 parent
= getcwd(tempdir
, (sizeof (tempdir
)));
1374 archtype
= putfile(file
, cp2
, parent
, NULL
, NORMAL_FILE
,
1375 LEV0
, SYMLINK_LEV0
);
1377 #if defined(O_XATTR)
1379 if ((atflag
|| saflag
) &&
1380 (archtype
== PUT_NOTAS_LINK
)) {
1381 xattrs_put(file
, cp2
, parent
, NULL
);
1386 if (tar_chdir(origdir
) < 0)
1387 vperror(0, gettext("cannot change back?: %s"), origdir
);
1391 * If e function modifier has been specified
1392 * write the files (that are listed before the
1393 * file causing the error) to tape. exitflag is
1394 * used because only some of the error conditions
1395 * in putfile() recognize the e function modifier.
1401 putempty((blkcnt_t
)2);
1403 closevol(); /* SP-1 */
1405 for (; ihead
!= NULL
; ihead
= ihead
->nextp
) {
1406 if (ihead
->count
== 0)
1408 (void) fprintf(stderr
, gettext(
1409 "tar: missing links to %s\n"), ihead
->pathname
);
1419 * endtape - check for tape at end
1421 * endtape checks the entry in dblock.dbuf to see if its the
1422 * special EOT entry. Endtape is usually called after getdir().
1424 * endtape used to call backtape; it no longer does, he who
1425 * wants it backed up must call backtape himself
1426 * RETURNS: 0 if not EOT, tape position unaffected
1427 * 1 if EOT, tape position unaffected
1433 if (dblock
.dbuf
.name
[0] != '\0') {
1435 * The name field is populated.
1440 if (is_posix
&& dblock
.dbuf
.prefix
[0] != '\0') {
1442 * This is a ustar/POSIX archive, and although the name
1443 * field is empty the prefix field is not.
1448 dlog("endtape(): found null header; EOT\n");
1453 * getdir - get directory entry from tar tape
1455 * getdir reads the next tarblock off the tape and cracks
1456 * it as a directory. The checksum must match properly.
1458 * If tfile is non-null getdir writes the file name and mod date
1467 static int warn_chksum_sign
= 0;
1471 readtape((char *)&dblock
);
1472 if (dblock
.dbuf
.name
[0] == '\0')
1475 (void) sscanf(dblock
.dbuf
.mode
, "%8lo", &Gen
.g_mode
);
1476 (void) sscanf(dblock
.dbuf
.uid
, "%8lo", (ulong_t
*)&Gen
.g_uid
);
1477 (void) sscanf(dblock
.dbuf
.gid
, "%8lo", (ulong_t
*)&Gen
.g_gid
);
1478 (void) sscanf(dblock
.dbuf
.size
, "%12" FMT_off_t_o
, &Gen
.g_filesz
);
1479 (void) sscanf(dblock
.dbuf
.mtime
, "%12lo", (ulong_t
*)&Gen
.g_mtime
);
1480 (void) sscanf(dblock
.dbuf
.chksum
, "%8o", &Gen
.g_cksum
);
1481 (void) sscanf(dblock
.dbuf
.devmajor
, "%8lo", &Gen
.g_devmajor
);
1482 (void) sscanf(dblock
.dbuf
.devminor
, "%8lo", &Gen
.g_devminor
);
1484 is_posix
= (strcmp(dblock
.dbuf
.magic
, magic_type
) == 0);
1486 sp
->st_mode
= Gen
.g_mode
;
1487 if (is_posix
&& (sp
->st_mode
& S_IFMT
) == 0) {
1488 switch (dblock
.dbuf
.typeflag
) {
1491 case _XATTR_HDRTYPE
:
1492 sp
->st_mode
|= S_IFREG
;
1494 case '1': /* hard link */
1497 sp
->st_mode
|= S_IFLNK
;
1500 sp
->st_mode
|= S_IFCHR
;
1503 sp
->st_mode
|= S_IFBLK
;
1506 sp
->st_mode
|= S_IFDIR
;
1509 sp
->st_mode
|= S_IFIFO
;
1512 if (convtoreg(Gen
.g_filesz
))
1513 sp
->st_mode
|= S_IFREG
;
1518 if ((dblock
.dbuf
.typeflag
== 'X') || (dblock
.dbuf
.typeflag
== 'L')) {
1519 Xhdrflag
= 1; /* Currently processing extended header */
1524 sp
->st_uid
= Gen
.g_uid
;
1525 sp
->st_gid
= Gen
.g_gid
;
1526 sp
->st_size
= Gen
.g_filesz
;
1527 sp
->st_mtime
= Gen
.g_mtime
;
1528 chksum
= Gen
.g_cksum
;
1530 if (dblock
.dbuf
.extno
!= '\0') { /* split file? */
1531 extno
= dblock
.dbuf
.extno
;
1532 extsize
= Gen
.g_filesz
;
1533 extotal
= dblock
.dbuf
.extotal
;
1535 extno
= 0; /* tell others file not split */
1541 if (chksum
!= checksum(&dblock
)) {
1542 if (chksum
!= checksum_signed(&dblock
)) {
1543 (void) fprintf(stderr
, gettext(
1544 "tar: directory checksum error\n"));
1551 if (! warn_chksum_sign
) {
1552 warn_chksum_sign
= 1;
1553 (void) fprintf(stderr
, gettext(
1554 "tar: warning: tar file made with signed checksum\n"));
1559 if (chksum
!= checksum(&dblock
)) {
1560 (void) fprintf(stderr
, gettext(
1561 "tar: directory checksum error\n"));
1569 if (tfile
!= NULL
&& Xhdrflag
== 0) {
1571 * If an extended header is present, then time is available
1572 * in nanoseconds in the extended header data, so set it.
1573 * Otherwise, give an invalid value so that checkupdate will
1574 * not test beyond seconds.
1576 if ((xhdr_flgs
& _X_MTIME
))
1577 sp
->st_mtim
.tv_nsec
= Xtarhdr
.x_mtime
.tv_nsec
;
1579 sp
->st_mtim
.tv_nsec
= -1;
1581 if (xhdr_flgs
& _X_PATH
)
1582 (void) fprintf(tfile
, "%s %10ld.%9.9ld\n",
1583 Xtarhdr
.x_path
, sp
->st_mtim
.tv_sec
,
1584 sp
->st_mtim
.tv_nsec
);
1586 (void) fprintf(tfile
, "%.*s %10ld.%9.9ld\n",
1587 NAMSIZ
, dblock
.dbuf
.name
, sp
->st_mtim
.tv_sec
,
1588 sp
->st_mtim
.tv_nsec
);
1591 #if defined(O_XATTR)
1593 if (xattrp
&& dblock
.dbuf
.typeflag
== _XATTR_HDRTYPE
) {
1600 char *aname
= basename(xattrapath
);
1601 size_t xindex
= aname
- xattrapath
;
1603 if (xattrapath
[xindex
] == '.' &&
1604 xattrapath
[xindex
+ 1] == '\0' &&
1605 xattrp
->h_typeflag
== '5') {
1608 (S_IFDIR
| (sp
->st_mode
& POSIXMODES
));
1610 dblock
.dbuf
.typeflag
= xattrp
->h_typeflag
;
1618 * passtape - skip over a file on the tape
1620 * passtape skips over the next data file on the tape.
1621 * The tape directory entry must be in dblock.dbuf. This
1622 * routine just eats the number of blocks computed from the
1623 * directory size entry; the tape must be (logically) positioned
1624 * right after the directory info.
1634 * Print some debugging information about the directory entry
1635 * we are skipping over:
1637 dlog("passtape: typeflag \"%c\"\n", dblock
.dbuf
.typeflag
);
1638 if (dblock
.dbuf
.name
[0] != '\0') {
1639 dlog("passtape: name \"%s\"\n", dblock
.dbuf
.name
);
1641 if (is_posix
&& dblock
.dbuf
.prefix
[0] != '\0') {
1642 dlog("passtape: prefix \"%s\"\n", dblock
.dbuf
.prefix
);
1646 * Types link(1), sym-link(2), char special(3), blk special(4),
1647 * directory(5), and FIFO(6) do not have data blocks associated
1648 * with them so just skip reading the data block.
1650 if (dblock
.dbuf
.typeflag
== '1' || dblock
.dbuf
.typeflag
== '2' ||
1651 dblock
.dbuf
.typeflag
== '3' || dblock
.dbuf
.typeflag
== '4' ||
1652 dblock
.dbuf
.typeflag
== '5' || dblock
.dbuf
.typeflag
== '6')
1654 blocks
= TBLOCKS(stbuf
.st_size
);
1656 dlog("passtape: block count %" FMT_blkcnt_t
"\n", blocks
);
1658 /* if operating on disk, seek instead of reading */
1662 while (blocks
-- > 0)
1666 #if defined(O_XATTR)
1668 is_sysattr(char *name
)
1670 return ((strcmp(name
, VIEW_READONLY
) == 0) ||
1671 (strcmp(name
, VIEW_READWRITE
) == 0));
1675 #if defined(O_XATTR)
1677 * Verify the attribute, attrname, is an attribute we want to restore.
1678 * Never restore read-only system attribute files. Only restore read-write
1679 * system attributes files when -/ was specified, and only traverse into
1680 * the 2nd level attribute directory containing only system attributes if
1681 * -@ was specified. This keeps us from archiving
1682 * <attribute name>/<read-write system attribute file>
1683 * when -/ was specified without -@.
1685 * attrname - attribute file name
1686 * attrparent - attribute's parent name within the base file's attribute
1687 * directory hierarchy
1689 static attr_status_t
1690 verify_attr(char *attrname
, char *attrparent
, int arc_rwsysattr
,
1693 #if defined(_PC_SATTR_ENABLED)
1696 /* Never restore read-only system attribute files */
1697 if ((attr_supported
= sysattr_type(attrname
)) == _RO_SATTR
) {
1701 *rw_sysattr
= (attr_supported
== _RW_SATTR
);
1705 * Only need to check if this attribute is an extended system
1708 if (*rw_sysattr
= is_sysattr(attrname
)) {
1713 #endif /* _PC_SATTR_ENABLED */
1716 * If the extended system attribute file is specified with the
1717 * arc_rwsysattr flag, as being transient (default extended
1718 * attributes), then don't archive it.
1720 if (*rw_sysattr
&& !arc_rwsysattr
) {
1725 * Only restore read-write system attribute files
1726 * when -/ was specified. Only restore extended
1727 * attributes when -@ was specified.
1732 * Only archive/restore the hidden directory "." if
1733 * we're processing the top level hidden attribute
1734 * directory. We don't want to process the
1735 * hidden attribute directory of the attribute
1736 * directory that contains only extended system
1739 if (*rw_sysattr
|| (Hiddendir
&&
1740 (attrparent
!= NULL
))) {
1744 } else if (saflag
) {
1746 * Only archive/restore read-write extended system attribute
1747 * files of the base file.
1749 if (!*rw_sysattr
|| (attrparent
!= NULL
)) {
1761 free_children(file_list_t
*children
)
1763 file_list_t
*child
= children
;
1766 while (child
!= NULL
) {
1768 if (child
->name
!= NULL
) {
1776 putfile(char *longname
, char *shortname
, char *parent
, attr_data_t
*attrinfo
,
1777 int filetype
, int lev
, int symlink_lev
)
1779 int infile
= -1; /* deliberately invalid */
1781 char buf
[PATH_MAX
+ 2]; /* Add trailing slash and null */
1784 int hint
; /* amount to write to get "in sync" */
1785 char filetmp
[PATH_MAX
+ 1];
1788 char *attrparent
= NULL
;
1789 char *longattrname
= NULL
;
1790 file_list_t
*child
= NULL
;
1791 file_list_t
*child_end
= NULL
;
1798 int rc
= PUT_NOTAS_LINK
;
1801 char newparent
[PATH_MAX
+ MAXNAMLEN
+ 1];
1804 char goodbuf
[PRESIZ
+ 2];
1805 char junkbuf
[MAXNAM
+1];
1811 (void) memset(goodbuf
, '\0', sizeof (goodbuf
));
1812 (void) memset(junkbuf
, '\0', sizeof (junkbuf
));
1816 if (filetype
== XATTR_FILE
) {
1817 attrparent
= attrinfo
->attr_parent
;
1818 longattrname
= attrinfo
->attr_path
;
1819 dirfd
= attrinfo
->attr_parentfd
;
1820 rw_sysattr
= attrinfo
->attr_rw_sysattr
;
1822 dirfd
= open(".", O_RDONLY
);
1826 (void) fprintf(stderr
, gettext(
1827 "tar: unable to open%sdirectory %s%s%s%s\n"),
1828 (filetype
== XATTR_FILE
) ? gettext(" attribute ") : " ",
1829 (attrparent
== NULL
) ? "" : gettext("of attribute "),
1830 (attrparent
== NULL
) ? "" : attrparent
,
1831 (attrparent
== NULL
) ? "" : gettext(" of "),
1832 (filetype
== XATTR_FILE
) ? longname
: parent
);
1837 (void) fprintf(stderr
,
1838 gettext("tar: directory nesting too deep, %s not dumped\n"),
1843 if (getstat(dirfd
, longname
, shortname
, attrparent
))
1848 * Catch nesting where a file is a symlink to its directory.
1850 j
= fstatat(dirfd
, shortname
, &sbuf
, AT_SYMLINK_NOFOLLOW
);
1851 if (S_ISLNK(sbuf
.st_mode
)) {
1852 if (symlink_lev
++ >= MAXSYMLINKS
) {
1853 (void) fprintf(stderr
, gettext(
1854 "tar: %s: Number of symbolic links "
1855 "encountered during path name traversal "
1856 "exceeds MAXSYMLINKS\n"), longname
);
1864 * Check if the input file is the same as the tar file we
1867 if ((mt_ino
== stbuf
.st_ino
) && (mt_dev
== stbuf
.st_dev
)) {
1868 (void) fprintf(stderr
, gettext(
1869 "tar: %s%s%s%s%s same as archive file\n"),
1870 rw_sysattr
? gettext("system ") : "",
1871 (longattrname
== NULL
) ? "" : gettext("attribute "),
1872 (longattrname
== NULL
) ? "" : longattrname
,
1873 (longattrname
== NULL
) ? "" : gettext(" of "),
1879 * Check size limit - we can't archive files that
1880 * exceed TAR_OFFSET_MAX bytes because of header
1881 * limitations. Exclude file types that set
1882 * st_size to zero below because they take no
1883 * archive space to represent contents.
1885 if ((stbuf
.st_size
> (off_t
)TAR_OFFSET_MAX
) &&
1886 !S_ISDIR(stbuf
.st_mode
) &&
1887 !S_ISCHR(stbuf
.st_mode
) &&
1888 !S_ISBLK(stbuf
.st_mode
) &&
1890 (void) fprintf(stderr
, gettext(
1891 "tar: %s%s%s%s%s too large to archive. "
1892 "Use E function modifier.\n"),
1893 rw_sysattr
? gettext("system ") : "",
1894 (longattrname
== NULL
) ? "" : gettext("attribute "),
1895 (longattrname
== NULL
) ? "" : longattrname
,
1896 (longattrname
== NULL
) ? "" : gettext(" of "),
1904 if (tfile
!= NULL
&& checkupdate(longname
) == 0) {
1907 if (checkw('r', longname
) == 0) {
1912 checkf(longname
, (stbuf
.st_mode
& S_IFMT
) == S_IFDIR
, Fflag
) == 0)
1916 if (is_in_table(exclude_tbl
, longname
)) {
1918 (void) fprintf(vfile
, gettext(
1919 "a %s excluded\n"), longname
);
1926 * If the length of the fullname is greater than MAXNAM,
1927 * print out a message and return (unless extended headers are used,
1928 * in which case fullname is limited to PATH_MAX).
1931 if ((((split
= (int)strlen(longname
)) > MAXNAM
) && (Eflag
== 0)) ||
1932 (split
> PATH_MAX
)) {
1933 (void) fprintf(stderr
, gettext(
1934 "tar: %s: file name too long\n"), longname
);
1942 * We split the fullname into prefix and name components if any one
1943 * of three conditions holds:
1944 * -- the length of the fullname exceeds NAMSIZ,
1945 * -- the length of the fullname equals NAMSIZ, and the shortname
1946 * is less than NAMSIZ, (splitting in this case preserves
1947 * compatibility with 5.6 and 5.5.1 tar), or
1948 * -- the length of the fullname equals NAMSIZ, the file is a
1949 * directory and we are not in POSIX-conformant mode (where
1950 * trailing slashes are removed from directories).
1952 if ((split
> NAMSIZ
) ||
1953 (split
== NAMSIZ
&& strlen(shortname
) < NAMSIZ
) ||
1954 (split
== NAMSIZ
&& S_ISDIR(stbuf
.st_mode
) && !Pflag
)) {
1956 * Since path is limited to PRESIZ characters, look for the
1957 * last slash within PRESIZ + 1 characters only.
1959 (void) strncpy(&goodbuf
[0], longname
, min(split
, PRESIZ
+ 1));
1961 lastslash
= strrchr(tmpbuf
, '/');
1962 if (lastslash
== NULL
) {
1963 i
= split
; /* Length of name */
1964 j
= 0; /* Length of prefix */
1967 *lastslash
= '\0'; /* Terminate the prefix */
1972 * If the filename is greater than NAMSIZ we can't
1973 * archive the file unless we are using extended headers.
1975 if ((i
> NAMSIZ
) || (i
== NAMSIZ
&& S_ISDIR(stbuf
.st_mode
) &&
1977 /* Determine which (filename or path) is too long. */
1978 lastslash
= strrchr(longname
, '/');
1979 if (lastslash
!= NULL
)
1980 i
= strlen(lastslash
+ 1);
1982 xhdr_flgs
|= _X_PATH
;
1983 Xtarhdr
.x_path
= longname
;
1985 (void) strcpy(junkbuf
, lastslash
+ 1);
1987 (void) sprintf(junkbuf
, "%llu",
1989 if (split
- i
- 1 > PRESIZ
)
1990 (void) strcpy(goodbuf
, xhdr_dirname
);
1992 if ((i
> NAMSIZ
) || (i
== NAMSIZ
&&
1993 S_ISDIR(stbuf
.st_mode
) && !Pflag
))
1994 (void) fprintf(stderr
, gettext(
1995 "tar: %s: filename is greater than "
1996 "%d\n"), lastslash
== NULL
?
1997 longname
: lastslash
+ 1, NAMSIZ
);
1999 (void) fprintf(stderr
, gettext(
2000 "tar: %s: prefix is greater than %d"
2001 "\n"), longname
, PRESIZ
);
2008 (void) strncpy(&junkbuf
[0], longname
+ j
+ 1,
2009 strlen(longname
+ j
+ 1));
2016 if ((prefix
!= NULL
) && (*prefix
!= '\0'))
2017 while (*prefix
== '/')
2020 while (*name
== '/')
2024 switch (stbuf
.st_mode
& S_IFMT
) {
2026 stbuf
.st_size
= (off_t
)0;
2027 blocks
= TBLOCKS(stbuf
.st_size
);
2029 if (filetype
!= XATTR_FILE
&& Hiddendir
== 0) {
2032 while ((*cp
++ = longname
[i
++]))
2039 if (build_dblock(name
, tchar
, '5', filetype
,
2040 &stbuf
, stbuf
.st_dev
, prefix
) != 0) {
2045 * Old archives require a slash at the end
2046 * of a directory name.
2049 * If directory name is too long, will
2050 * slash overfill field?
2052 if (strlen(name
) > (unsigned)NAMSIZ
-1) {
2053 (void) fprintf(stderr
, gettext(
2054 "tar: %s: filename is greater "
2055 "than %d\n"), name
, NAMSIZ
);
2061 if (strlen(name
) == (NAMSIZ
- 1)) {
2062 (void) memcpy(dblock
.dbuf
.name
,
2064 dblock
.dbuf
.name
[NAMSIZ
-1]
2067 (void) sprintf(dblock
.dbuf
.name
,
2071 * need to recalculate checksum
2072 * because the name changed.
2074 (void) sprintf(dblock
.dbuf
.chksum
,
2075 "%07o", checksum(&dblock
));
2079 if (put_extra_attributes(longname
, shortname
,
2080 longattrname
, prefix
, filetype
, '5') != 0)
2083 #if defined(O_XATTR)
2085 * Reset header typeflag when archiving directory, since
2086 * build_dblock changed it on us.
2088 if (filetype
== XATTR_FILE
) {
2089 dblock
.dbuf
.typeflag
= _XATTR_HDRTYPE
;
2091 dblock
.dbuf
.typeflag
= '5';
2094 dblock
.dbuf
.typeflag
= '5';
2097 (void) sprintf(dblock
.dbuf
.chksum
, "%07o",
2100 (void) writetbuf((char *)&dblock
, 1);
2104 dlog("seek = %" FMT_blkcnt_t
"K\n", K(tapepos
));
2106 if (filetype
== XATTR_FILE
&& Hiddendir
) {
2107 (void) fprintf(vfile
,
2108 gettext("a %s attribute %s "),
2109 longname
, longattrname
);
2112 (void) fprintf(vfile
, "a %s/ ", longname
);
2115 (void) fprintf(vfile
, "%" FMT_blkcnt_t
"K\n",
2118 (void) fprintf(vfile
, gettext("%" FMT_blkcnt_t
2119 " tape blocks\n"), blocks
);
2124 * If hidden dir then break now since xattrs_put() will do
2125 * the iterating of the directory.
2127 * At the moment, there can only be system attributes on
2128 * attributes. There can be no attributes on attributes or
2129 * directories within the attributes hidden directory hierarchy.
2131 if (filetype
== XATTR_FILE
)
2134 if (*shortname
!= '/')
2135 (void) sprintf(newparent
, "%s/%s", parent
, shortname
);
2137 (void) sprintf(newparent
, "%s", shortname
);
2139 if (tar_chdir(shortname
) < 0) {
2140 vperror(0, "%s", newparent
);
2144 if ((dirp
= opendir(".")) == NULL
) {
2146 "can't open directory %s"), longname
);
2147 if (tar_chdir(parent
) < 0)
2148 vperror(0, gettext("cannot change back?: %s"),
2154 * Create a list of files (children) in this directory to avoid
2155 * having to perform telldir()/seekdir().
2157 while ((dp
= readdir(dirp
)) != NULL
&& !term
) {
2158 if ((strcmp(".", dp
->d_name
) == 0) ||
2159 (strcmp("..", dp
->d_name
) == 0))
2161 if (((cptr
= (file_list_t
*)calloc(sizeof (char),
2162 sizeof (file_list_t
))) == NULL
) ||
2163 ((cptr
->name
= strdup(dp
->d_name
)) == NULL
)) {
2165 "Insufficient memory for directory "
2166 "list entry %s/%s\n"),
2167 newparent
, dp
->d_name
);
2170 /* Add the file to the list */
2171 if (child
== NULL
) {
2174 child_end
->next
= cptr
;
2178 (void) closedir(dirp
);
2181 * Archive each of the files in the current directory.
2182 * If a file is a directory, putfile() is called
2183 * recursively to archive the file hierarchy of the
2184 * directory before archiving the next file in the
2185 * current directory.
2187 while ((child
!= NULL
) && !term
) {
2188 (void) strcpy(cp
, child
->name
);
2189 archtype
= putfile(buf
, cp
, newparent
, NULL
,
2190 NORMAL_FILE
, lev
+ 1, symlink_lev
);
2193 if ((atflag
|| saflag
) &&
2194 (archtype
== PUT_NOTAS_LINK
)) {
2195 xattrs_put(buf
, cp
, newparent
, NULL
);
2201 /* Free each child as we are done processing it. */
2203 child
= child
->next
;
2207 if ((child
!= NULL
) && !term
) {
2208 free_children(child
);
2211 if (tar_chdir(parent
) < 0) {
2212 vperror(0, gettext("cannot change back?: %s"), parent
);
2218 readlink_max
= NAMSIZ
;
2219 if (stbuf
.st_size
> NAMSIZ
) {
2221 xhdr_flgs
|= _X_LINKPATH
;
2222 readlink_max
= PATH_MAX
;
2224 (void) fprintf(stderr
, gettext(
2225 "tar: %s: symbolic link too long\n"),
2234 * Sym-links need header size of zero since you
2235 * don't store any data for this type.
2237 stbuf
.st_size
= (off_t
)0;
2239 i
= readlink(shortname
, filetmp
, readlink_max
);
2242 "can't read symbolic link %s"), longname
);
2248 (void) fprintf(vfile
, gettext(
2249 "a %s symbolic link to %s\n"),
2251 if (xhdr_flgs
& _X_LINKPATH
) {
2252 Xtarhdr
.x_linkpath
= filetmp
;
2253 if (build_dblock(name
, tchar
, '2', filetype
, &stbuf
,
2254 stbuf
.st_dev
, prefix
) != 0)
2257 if (build_dblock(name
, filetmp
, '2', filetype
, &stbuf
,
2258 stbuf
.st_dev
, prefix
) != 0)
2260 (void) writetbuf((char *)&dblock
, 1);
2262 * No acls for symlinks: mode is always 777
2263 * dont call write ancillary
2268 if ((infile
= openat(dirfd
, shortname
, 0)) < 0) {
2269 vperror(0, gettext("unable to open %s%s%s%s"), longname
,
2270 rw_sysattr
? gettext(" system") : "",
2271 (filetype
== XATTR_FILE
) ?
2272 gettext(" attribute ") : "",
2273 (filetype
== XATTR_FILE
) ? (longattrname
== NULL
) ?
2274 shortname
: longattrname
: "");
2278 blocks
= TBLOCKS(stbuf
.st_size
);
2280 if (put_link(name
, longname
, shortname
, longattrname
,
2281 prefix
, filetype
, '1') == 0) {
2282 (void) close(infile
);
2289 /* correctly handle end of volume */
2290 while (mulvol
&& tapepos
+ blocks
+ 1 > blocklim
) {
2291 /* split if floppy has some room and file is large */
2292 if (((blocklim
- tapepos
) >= EXTMIN
) &&
2293 ((blocks
+ 1) >= blocklim
/10)) {
2294 splitfile(longname
, infile
,
2295 name
, prefix
, filetype
);
2296 (void) close(dirfd
);
2297 (void) close(infile
);
2300 newvol(); /* not worth it--just get new volume */
2302 dlog("putfile: %s wants %" FMT_blkcnt_t
" blocks\n", longname
,
2304 if (build_dblock(name
, tchar
, '0', filetype
,
2305 &stbuf
, stbuf
.st_dev
, prefix
) != 0) {
2310 dlog("seek = %" FMT_blkcnt_t
"K\n", K(tapepos
));
2312 (void) fprintf(vfile
, "a %s%s%s%s ", longname
,
2313 rw_sysattr
? gettext(" system") : "",
2314 (filetype
== XATTR_FILE
) ? gettext(
2315 " attribute ") : "",
2316 (filetype
== XATTR_FILE
) ?
2319 (void) fprintf(vfile
, "%" FMT_blkcnt_t
"K\n",
2322 (void) fprintf(vfile
,
2323 gettext("%" FMT_blkcnt_t
" tape blocks\n"),
2327 if (put_extra_attributes(longname
, shortname
, longattrname
,
2328 prefix
, filetype
, '0') != 0)
2332 * No need to reset typeflag for extended attribute here, since
2333 * put_extra_attributes already set it and we haven't called
2336 (void) sprintf(dblock
.dbuf
.chksum
, "%07o", checksum(&dblock
));
2337 hint
= writetbuf((char *)&dblock
, 1);
2338 maxread
= max(min(stbuf
.st_blksize
, stbuf
.st_size
),
2340 if ((bigbuf
= calloc((unsigned)maxread
, sizeof (char))) == 0) {
2346 read(infile
, bigbuf
, min((hint
*TBLOCK
), maxread
))) > 0) &&
2350 nblks
= ((i
-1)/TBLOCK
)+1;
2353 hint
= writetbuf(bigbuf
, nblks
);
2356 (void) close(infile
);
2360 vperror(0, gettext("Read error on %s"), longname
);
2361 else if (blocks
!= 0 || i
!= 0) {
2362 (void) fprintf(stderr
, gettext(
2363 "tar: %s: file changed size\n"), longname
);
2367 } else if (!Dflag
) {
2374 blocks
= TBLOCKS(stbuf
.st_size
);
2375 stbuf
.st_size
= (off_t
)0;
2377 if (put_link(name
, longname
, shortname
, longattrname
,
2378 prefix
, filetype
, '6') == 0) {
2384 while (mulvol
&& tapepos
+ blocks
+ 1 > blocklim
) {
2385 if (((blocklim
- tapepos
) >= EXTMIN
) &&
2386 ((blocks
+ 1) >= blocklim
/10)) {
2387 splitfile(longname
, infile
, name
,
2389 (void) close(dirfd
);
2390 (void) close(infile
);
2395 dlog("putfile: %s wants %" FMT_blkcnt_t
" blocks\n", longname
,
2399 dlog("seek = %" FMT_blkcnt_t
"K\n", K(tapepos
));
2401 (void) fprintf(vfile
, gettext("a %s %"
2402 FMT_blkcnt_t
"K\n "), longname
, K(blocks
));
2404 (void) fprintf(vfile
, gettext(
2405 "a %s %" FMT_blkcnt_t
" tape blocks\n"),
2409 if (build_dblock(name
, tchar
, '6', filetype
,
2410 &stbuf
, stbuf
.st_dev
, prefix
) != 0)
2413 if (put_extra_attributes(longname
, shortname
, longattrname
,
2414 prefix
, filetype
, '6') != 0)
2417 (void) sprintf(dblock
.dbuf
.chksum
, "%07o", checksum(&dblock
));
2418 dblock
.dbuf
.typeflag
= '6';
2420 (void) writetbuf((char *)&dblock
, 1);
2423 stbuf
.st_size
= (off_t
)0;
2424 blocks
= TBLOCKS(stbuf
.st_size
);
2425 if (put_link(name
, longname
, shortname
, longattrname
,
2426 prefix
, filetype
, '3') == 0) {
2432 while (mulvol
&& tapepos
+ blocks
+ 1 > blocklim
) {
2433 if (((blocklim
- tapepos
) >= EXTMIN
) &&
2434 ((blocks
+ 1) >= blocklim
/10)) {
2435 splitfile(longname
, infile
, name
,
2437 (void) close(dirfd
);
2442 dlog("putfile: %s wants %" FMT_blkcnt_t
" blocks\n", longname
,
2446 dlog("seek = %" FMT_blkcnt_t
"K\t", K(tapepos
));
2448 (void) fprintf(vfile
, gettext("a %s %"
2449 FMT_blkcnt_t
"K\n"), longname
, K(blocks
));
2451 (void) fprintf(vfile
, gettext("a %s %"
2452 FMT_blkcnt_t
" tape blocks\n"), longname
,
2456 if (build_dblock(name
, tchar
, '3',
2457 filetype
, &stbuf
, stbuf
.st_rdev
, prefix
) != 0)
2460 if (put_extra_attributes(longname
, shortname
, longattrname
,
2461 prefix
, filetype
, '3') != 0)
2464 (void) sprintf(dblock
.dbuf
.chksum
, "%07o", checksum(&dblock
));
2465 dblock
.dbuf
.typeflag
= '3';
2467 (void) writetbuf((char *)&dblock
, 1);
2470 stbuf
.st_size
= (off_t
)0;
2471 blocks
= TBLOCKS(stbuf
.st_size
);
2472 if (put_link(name
, longname
, shortname
, longattrname
,
2473 prefix
, filetype
, '4') == 0) {
2479 while (mulvol
&& tapepos
+ blocks
+ 1 > blocklim
) {
2480 if (((blocklim
- tapepos
) >= EXTMIN
) &&
2481 ((blocks
+ 1) >= blocklim
/10)) {
2482 splitfile(longname
, infile
,
2483 name
, prefix
, filetype
);
2484 (void) close(dirfd
);
2489 dlog("putfile: %s wants %" FMT_blkcnt_t
" blocks\n", longname
,
2493 dlog("seek = %" FMT_blkcnt_t
"K\n", K(tapepos
));
2496 (void) fprintf(vfile
, "a %s ", longname
);
2498 (void) fprintf(vfile
, "%" FMT_blkcnt_t
"K\n",
2501 (void) fprintf(vfile
, gettext("%"
2502 FMT_blkcnt_t
" tape blocks\n"), blocks
);
2504 if (build_dblock(name
, tchar
, '4',
2505 filetype
, &stbuf
, stbuf
.st_rdev
, prefix
) != 0)
2508 if (put_extra_attributes(longname
, shortname
, longattrname
,
2509 prefix
, filetype
, '4') != 0)
2512 (void) sprintf(dblock
.dbuf
.chksum
, "%07o", checksum(&dblock
));
2513 dblock
.dbuf
.typeflag
= '4';
2515 (void) writetbuf((char *)&dblock
, 1);
2518 (void) fprintf(stderr
, gettext(
2519 "tar: %s is not a file. Not dumped\n"), longname
);
2527 if ((dirfd
!= -1) && (filetype
!= XATTR_FILE
)) {
2528 (void) close(dirfd
);
2535 * splitfile dump a large file across volumes
2537 * splitfile(longname, fd);
2538 * char *longname; full name of file
2539 * int ifd; input file descriptor
2541 * NOTE: only called by putfile() to dump a large file.
2545 splitfile(char *longname
, int ifd
, char *name
, char *prefix
, int filetype
)
2552 blocks
= TBLOCKS(stbuf
.st_size
); /* blocks file needs */
2556 * size of file after using up rest of this floppy
2557 * blocks - (blocklim - tapepos) + 1 (for header)
2558 * plus roundup value before divide by blocklim-1
2559 * + (blocklim - 1) - 1
2560 * all divided by blocklim-1 (one block for each header).
2562 * (blocks - blocklim + tapepos + 1 + blocklim - 2)/(blocklim-1)
2563 * which reduces to the expression used.
2564 * one is added to account for this first extent.
2566 * When one is dealing with extremely large archives, one may want
2567 * to allow for a large number of extents. This code should be
2568 * revisited to determine if extents should be changed to something
2569 * larger than an int.
2571 extents
= (int)((blocks
+ tapepos
- 1ULL)/(blocklim
- 1ULL) + 1);
2573 if (extents
< 2 || extents
> MAXEXT
) { /* let's be reasonable */
2574 (void) fprintf(stderr
, gettext(
2575 "tar: %s needs unusual number of volumes to split\n"
2576 "tar: %s not dumped\n"), longname
, longname
);
2579 if (build_dblock(name
, tchar
, '0', filetype
,
2580 &stbuf
, stbuf
.st_dev
, prefix
) != 0)
2583 dblock
.dbuf
.extotal
= extents
;
2584 bytes
= stbuf
.st_size
;
2587 * The value contained in dblock.dbuf.efsize was formerly used when the
2588 * v flag was specified in conjunction with the t flag. Although it is
2589 * no longer used, older versions of tar will expect the former
2590 * behaviour, so we must continue to write it to the archive.
2592 * Since dblock.dbuf.efsize is 10 chars in size, the maximum value it
2593 * can store is TAR_EFSIZE_MAX. If bytes exceeds that value, simply
2596 if (bytes
<= TAR_EFSIZE_MAX
)
2597 (void) sprintf(dblock
.dbuf
.efsize
, "%9" FMT_off_t_o
, bytes
);
2599 (void) sprintf(dblock
.dbuf
.efsize
, "%9" FMT_off_t_o
, (off_t
)0);
2601 (void) fprintf(stderr
, gettext(
2602 "tar: large file %s needs %d extents.\n"
2603 "tar: current device seek position = %" FMT_blkcnt_t
"K\n"),
2604 longname
, extents
, K(tapepos
));
2606 s
= (off_t
)(blocklim
- tapepos
- 1) * TBLOCK
;
2607 for (i
= 1; i
<= extents
; i
++) {
2611 s
= bytes
; /* last ext. gets true bytes */
2613 s
= (off_t
)(blocklim
- 1)*TBLOCK
; /* all */
2616 blocks
= TBLOCKS(s
);
2618 (void) sprintf(dblock
.dbuf
.size
, "%011" FMT_off_t_o
, s
);
2619 dblock
.dbuf
.extno
= i
;
2620 (void) sprintf(dblock
.dbuf
.chksum
, "%07o", checksum(&dblock
));
2621 (void) writetbuf((char *)&dblock
, 1);
2624 (void) fprintf(vfile
,
2625 gettext("+++ a %s %" FMT_blkcnt_t
2626 "K [extent #%d of %d]\n"),
2627 longname
, K(blocks
), i
, extents
);
2628 while (blocks
&& read(ifd
, buf
, TBLOCK
) > 0) {
2630 (void) writetbuf(buf
, 1);
2633 (void) fprintf(stderr
, gettext(
2634 "tar: %s: file changed size\n"), longname
);
2635 (void) fprintf(stderr
, gettext(
2636 "tar: aborting split file %s\n"), longname
);
2643 (void) fprintf(vfile
, gettext("a %s %" FMT_off_t
"K (in %d "
2644 "extents)\n"), longname
, K(TBLOCKS(stbuf
.st_size
)),
2649 * convtoreg - determines whether the file should be converted to a
2650 * regular file when extracted
2652 * Returns 1 when file size > 0 and typeflag is not recognized
2653 * Otherwise returns 0
2656 convtoreg(off_t size
)
2658 if ((size
> 0) && (dblock
.dbuf
.typeflag
!= '0') &&
2659 (dblock
.dbuf
.typeflag
!= '\0') && (dblock
.dbuf
.typeflag
!= '1') &&
2660 (dblock
.dbuf
.typeflag
!= '2') && (dblock
.dbuf
.typeflag
!= '3') &&
2661 (dblock
.dbuf
.typeflag
!= '4') && (dblock
.dbuf
.typeflag
!= '5') &&
2662 (dblock
.dbuf
.typeflag
!= '6') && (dblock
.dbuf
.typeflag
!= 'A') &&
2663 (dblock
.dbuf
.typeflag
!= 'L') &&
2664 (dblock
.dbuf
.typeflag
!= _XATTR_HDRTYPE
) &&
2665 (dblock
.dbuf
.typeflag
!= 'X')) {
2671 #if defined(O_XATTR)
2675 return (open(".", O_RDONLY
));
2679 #if defined(O_XATTR)
2684 if (fchdir(*cwd
) < 0) {
2686 "Cannot fchdir to attribute directory"));
2696 * Verify the underlying file system supports the attribute type.
2697 * Only archive extended attribute files when '-@' was specified.
2698 * Only archive system extended attribute files if '-/' was specified.
2700 #if defined(O_XATTR)
2701 static attr_status_t
2702 verify_attr_support(char *filename
, int attrflg
, arc_action_t actflag
,
2706 * Verify extended attributes are supported/exist. We only
2707 * need to check if we are processing a base file, not an
2708 * extended attribute.
2711 *ext_attrflg
= (pathconf(filename
, (actflag
== ARC_CREATE
) ?
2712 _PC_XATTR_EXISTS
: _PC_XATTR_ENABLED
) == 1);
2716 if (!*ext_attrflg
) {
2717 #if defined(_PC_SATTR_ENABLED)
2719 /* Verify system attributes are supported */
2720 if (sysattr_support(filename
,
2721 (actflag
== ARC_CREATE
) ? _PC_SATTR_EXISTS
:
2722 _PC_SATTR_ENABLED
) != 1) {
2723 return (ATTR_SATTR_ERR
);
2726 return (ATTR_XATTR_ERR
);
2728 return (ATTR_XATTR_ERR
);
2729 #endif /* _PC_SATTR_ENABLED */
2732 #if defined(_PC_SATTR_ENABLED)
2733 } else if (saflag
) {
2734 /* Verify system attributes are supported */
2735 if (sysattr_support(filename
, (actflag
== ARC_CREATE
) ?
2736 _PC_SATTR_EXISTS
: _PC_SATTR_ENABLED
) != 1) {
2737 return (ATTR_SATTR_ERR
);
2739 #endif /* _PC_SATTR_ENABLED */
2748 #if defined(O_XATTR)
2750 * Recursively open attribute directories until the attribute directory
2751 * containing the specified attribute, attrname, is opened.
2753 * Currently, only 2 directory levels of attributes are supported, (i.e.,
2754 * extended system attributes on extended attributes). The following are
2755 * the possible input combinations:
2756 * 1. Open the attribute directory of the base file (don't change
2758 * attrinfo->parent = NULL
2760 * 2. Open the attribute directory of the base file and change into it.
2761 * attrinfo->parent = NULL
2762 * attrname = <attr> | <sys_attr>
2763 * 3. Open the attribute directory of the base file, change into it,
2764 * then recursively call open_attr_dir() to open the attribute's
2765 * parent directory (don't change into it).
2766 * attrinfo->parent = <attr>
2768 * 4. Open the attribute directory of the base file, change into it,
2769 * then recursively call open_attr_dir() to open the attribute's
2770 * parent directory and change into it.
2771 * attrinfo->parent = <attr>
2772 * attrname = <attr> | <sys_attr>
2774 * An attribute directory will be opened only if the underlying file system
2775 * supports the attribute type, and if the command line specifications (atflag
2776 * and saflag) enable the processing of the attribute type.
2778 * On succesful return, attrinfo->parentfd will be the file descriptor of the
2779 * opened attribute directory. In addition, if the attribute is a read-write
2780 * extended system attribute, attrinfo->rw_sysattr will be set to 1, otherwise
2781 * it will be set to 0.
2783 * Possible return values:
2784 * ATTR_OK Successfully opened and, if needed, changed into the
2785 * attribute directory containing attrname.
2786 * ATTR_SKIP The command line specifications don't enable the
2787 * processing of the attribute type.
2788 * ATTR_CHDIR_ERR An error occurred while trying to change into an
2789 * attribute directory.
2790 * ATTR_OPEN_ERR An error occurred while trying to open an
2791 * attribute directory.
2792 * ATTR_XATTR_ERR The underlying file system doesn't support extended
2794 * ATTR_SATTR_ERR The underlying file system doesn't support extended
2795 * system attributes.
2798 open_attr_dir(char *attrname
, char *dirp
, int cwd
, attr_data_t
*attrinfo
)
2801 int firsttime
= (attrinfo
->attr_parentfd
== -1);
2806 * open_attr_dir() was recursively called (input combination number 4),
2807 * close the previously opened file descriptor as we've already changed
2811 (void) close(attrinfo
->attr_parentfd
);
2812 attrinfo
->attr_parentfd
= -1;
2816 * Verify that the underlying file system supports the restoration
2819 if ((rc
= verify_attr_support(dirp
, firsttime
, ARC_RESTORE
,
2820 &ext_attr
)) != ATTR_OK
) {
2824 /* Open the base file's attribute directory */
2825 if ((attrinfo
->attr_parentfd
= attropen(dirp
, ".", O_RDONLY
)) == -1) {
2827 * Save the errno from the attropen so it can be reported
2828 * if the retry of the attropen fails.
2831 if ((attrinfo
->attr_parentfd
= retry_open_attr(-1, cwd
, dirp
,
2832 NULL
, ".", O_RDONLY
, 0)) == -1) {
2834 * Reset typeflag back to real value so passtape
2835 * will skip ahead correctly.
2837 dblock
.dbuf
.typeflag
= _XATTR_HDRTYPE
;
2838 (void) close(attrinfo
->attr_parentfd
);
2839 attrinfo
->attr_parentfd
= -1;
2841 return (ATTR_OPEN_ERR
);
2846 * Change into the parent attribute's directory unless we are
2847 * processing the hidden attribute directory of the base file itself.
2849 if ((Hiddendir
== 0) || (firsttime
&& attrinfo
->attr_parent
!= NULL
)) {
2850 if (fchdir(attrinfo
->attr_parentfd
) != 0) {
2852 (void) close(attrinfo
->attr_parentfd
);
2853 attrinfo
->attr_parentfd
= -1;
2855 return (ATTR_CHDIR_ERR
);
2859 /* Determine if the attribute should be processed */
2860 if ((rc
= verify_attr(attrname
, attrinfo
->attr_parent
, 1,
2861 &attrinfo
->attr_rw_sysattr
)) != ATTR_OK
) {
2863 (void) close(attrinfo
->attr_parentfd
);
2864 attrinfo
->attr_parentfd
= -1;
2870 * If the attribute is an extended attribute, or extended system
2871 * attribute, of an attribute (i.e., <attr>/<sys_attr>), then
2872 * recursively call open_attr_dir() to open the attribute directory
2873 * of the parent attribute.
2875 if (firsttime
&& (attrinfo
->attr_parent
!= NULL
)) {
2876 return (open_attr_dir(attrname
, attrinfo
->attr_parent
,
2877 attrinfo
->attr_parentfd
, attrinfo
));
2885 doxtract(char *argv
[])
2887 struct stat xtractbuf
; /* stat on file after extracting */
2891 int newfile
; /* Does the file already exist */
2892 int xcnt
= 0; /* count # files extracted */
2893 int fcnt
= 0; /* count # files in argv list */
2900 char *namep
, *dirp
, *comp
, *linkp
; /* for removing absolute paths */
2901 char dirname
[PATH_MAX
+1];
2902 char templink
[PATH_MAX
+1]; /* temp link with terminating NULL */
2907 attr_data_t
*attrinfo
= NULL
; /* attribute info */
2908 acl_t
*aclp
= NULL
; /* acl info */
2909 timestruc_t time_zero
; /* used for call to doDirTimes */
2912 time_zero
.tv_sec
= 0;
2913 time_zero
.tv_nsec
= 0;
2915 dumping
= 0; /* for newvol(), et al: we are not writing */
2928 (void) close(dirfd
);
2932 if (close(ofile
) != 0)
2933 vperror(2, gettext("close error"));
2936 #if defined(O_XATTR)
2942 /* namep is set by wantit to point to the full name */
2943 if ((want
= wantit(argv
, &namep
, &dirp
, &comp
,
2945 #if defined(O_XATTR)
2946 if (xattrp
!= NULL
) {
2959 (void) close(dirfd
);
2961 (void) strcpy(&dirname
[0], namep
);
2962 dircreate
= checkdir(&dirname
[0]);
2964 #if defined(O_XATTR)
2965 if (xattrp
!= NULL
) {
2968 if (((cwd
= save_cwd()) == -1) ||
2969 ((rc
= open_attr_dir(comp
, dirp
, cwd
,
2970 attrinfo
)) != ATTR_OK
)) {
2973 "unable to save current working "
2974 "directory while processing "
2975 "attribute %s of %s"),
2976 dirp
, attrinfo
->attr_path
);
2977 } else if (rc
!= ATTR_SKIP
) {
2978 (void) fprintf(vfile
,
2979 gettext("tar: cannot open "
2980 "%sattribute %s of file %s: %s\n"),
2981 attrinfo
->attr_rw_sysattr
? gettext(
2983 comp
, dirp
, strerror(errno
));
2993 dirfd
= attrinfo
->attr_parentfd
;
2994 rw_sysattr
= attrinfo
->attr_rw_sysattr
;
2997 dirfd
= open(dirp
, O_RDONLY
);
3000 dirfd
= open(dirp
, O_RDONLY
);
3003 (void) fprintf(vfile
, gettext(
3004 "tar: cannot open %s: %s\n"),
3005 dirp
, strerror(errno
));
3010 if (xhdr_flgs
& _X_LINKPATH
)
3011 (void) strcpy(templink
, Xtarhdr
.x_linkpath
);
3013 #if defined(O_XATTR)
3014 if (xattrp
&& dblock
.dbuf
.typeflag
== '1') {
3015 (void) sprintf(templink
, "%.*s", NAMSIZ
,
3018 (void) sprintf(templink
, "%.*s", NAMSIZ
,
3019 dblock
.dbuf
.linkname
);
3022 (void) sprintf(templink
, "%.*s", NAMSIZ
,
3023 dblock
.dbuf
.linkname
);
3028 if (checkf(namep
, is_directory(namep
), Fflag
) == 0) {
3034 if (checkw('x', namep
) == 0) {
3039 if (strcmp(dblock
.dbuf
.magic
, magic_type
) == 0) {
3040 if (geteuid() == (uid_t
)0) {
3044 /* get file creation mask */
3046 (void) umask(Oumask
);
3050 if (geteuid() == (uid_t
)0) {
3055 /* get file creation mask */
3057 (void) umask(Oumask
);
3063 #if defined(O_XATTR)
3065 * Handle extraction of hidden attr dir.
3066 * Dir is automatically created, we only
3067 * need to update mode and perm's.
3069 if ((xattrp
!= NULL
) && Hiddendir
== 1) {
3070 bytes
= stbuf
.st_size
;
3071 blocks
= TBLOCKS(bytes
);
3073 (void) fprintf(vfile
,
3074 "x %s%s%s, %" FMT_off_t
" %s, ", namep
,
3075 gettext(" attribute "),
3079 (void) fprintf(vfile
,
3080 "%" FMT_blkcnt_t
"K\n", K(blocks
));
3082 (void) fprintf(vfile
, gettext("%"
3083 FMT_blkcnt_t
" tape blocks\n"),
3088 * Set the permissions and mode of the attribute
3089 * unless the attribute is a system attribute (can't
3090 * successfully do this) or the hidden attribute
3091 * directory (".") of an attribute (when the attribute
3092 * is restored, the hidden attribute directory of an
3093 * attribute is transient). Note: when the permissions
3094 * and mode are set for the hidden attribute directory
3095 * of a file on a system supporting extended system
3096 * attributes, even though it returns successfully, it
3097 * will not have any affect since the attribute
3098 * directory is transient.
3100 if (attrinfo
->attr_parent
== NULL
) {
3101 if (fchownat(dirfd
, ".", stbuf
.st_uid
,
3102 stbuf
.st_gid
, 0) != 0) {
3104 "%s%s%s: failed to set ownership "
3105 "of attribute directory"), namep
,
3106 gettext(" attribute "), xattrapath
);
3109 if (fchmod(dirfd
, stbuf
.st_mode
) != 0) {
3111 "%s%s%s: failed to set permissions "
3112 "of attribute directory"), namep
,
3113 gettext(" attribute "), xattrapath
);
3120 if (dircreate
&& (!is_posix
|| dblock
.dbuf
.typeflag
== '5')) {
3123 (void) fprintf(vfile
, "x %s, 0 %s, ",
3124 &dirname
[0], gettext("bytes"));
3126 (void) fprintf(vfile
, "0K\n");
3128 (void) fprintf(vfile
, gettext("%"
3129 FMT_blkcnt_t
" tape blocks\n"),
3135 if (dblock
.dbuf
.typeflag
== '6') { /* FIFO */
3136 if (rmdir(namep
) < 0) {
3137 if (errno
== ENOTDIR
)
3138 (void) unlink(namep
);
3141 if (*linkp
!= '\0') {
3142 if (Aflag
&& *linkp
== '/')
3144 if (link(linkp
, namep
) < 0) {
3145 (void) fprintf(stderr
, gettext(
3146 "tar: %s: cannot link\n"), namep
);
3150 (void) fprintf(vfile
, gettext(
3151 "x %s linked to %s\n"), namep
,
3153 xcnt
++; /* increment # files extracted */
3156 if (mknod(namep
, (int)(Gen
.g_mode
|S_IFIFO
),
3157 (int)Gen
.g_devmajor
) < 0) {
3158 vperror(0, gettext("%s: mknod failed"), namep
);
3161 bytes
= stbuf
.st_size
;
3162 blocks
= TBLOCKS(bytes
);
3164 (void) fprintf(vfile
, "x %s, %" FMT_off_t
3165 " %s, ", namep
, bytes
, gettext("bytes"));
3167 (void) fprintf(vfile
, "%" FMT_blkcnt_t
3170 (void) fprintf(vfile
, gettext("%"
3171 FMT_blkcnt_t
" tape blocks\n"),
3176 if (dblock
.dbuf
.typeflag
== '3' && !Uid
) { /* CHAR SPECIAL */
3177 if (rmdir(namep
) < 0) {
3178 if (errno
== ENOTDIR
)
3179 (void) unlink(namep
);
3182 if (*linkp
!= '\0') {
3183 if (Aflag
&& *linkp
== '/')
3185 if (link(linkp
, namep
) < 0) {
3186 (void) fprintf(stderr
, gettext(
3187 "tar: %s: cannot link\n"), namep
);
3191 (void) fprintf(vfile
, gettext(
3192 "x %s linked to %s\n"), namep
,
3194 xcnt
++; /* increment # files extracted */
3197 if (mknod(namep
, (int)(Gen
.g_mode
|S_IFCHR
),
3198 (int)makedev(Gen
.g_devmajor
, Gen
.g_devminor
)) < 0) {
3200 "%s: mknod failed"), namep
);
3203 bytes
= stbuf
.st_size
;
3204 blocks
= TBLOCKS(bytes
);
3206 (void) fprintf(vfile
, "x %s, %" FMT_off_t
3207 " %s, ", namep
, bytes
, gettext("bytes"));
3209 (void) fprintf(vfile
, "%" FMT_blkcnt_t
3212 (void) fprintf(vfile
, gettext("%"
3213 FMT_blkcnt_t
" tape blocks\n"),
3217 } else if (dblock
.dbuf
.typeflag
== '3' && Uid
) {
3218 (void) fprintf(stderr
, gettext(
3219 "Can't create special %s\n"), namep
);
3225 if (dblock
.dbuf
.typeflag
== '4' && !Uid
) {
3226 if (rmdir(namep
) < 0) {
3227 if (errno
== ENOTDIR
)
3228 (void) unlink(namep
);
3231 if (*linkp
!= '\0') {
3232 if (Aflag
&& *linkp
== '/')
3234 if (link(linkp
, namep
) < 0) {
3235 (void) fprintf(stderr
, gettext(
3236 "tar: %s: cannot link\n"), namep
);
3240 (void) fprintf(vfile
, gettext(
3241 "x %s linked to %s\n"), namep
,
3243 xcnt
++; /* increment # files extracted */
3246 if (mknod(namep
, (int)(Gen
.g_mode
|S_IFBLK
),
3247 (int)makedev(Gen
.g_devmajor
, Gen
.g_devminor
)) < 0) {
3248 vperror(0, gettext("%s: mknod failed"), namep
);
3251 bytes
= stbuf
.st_size
;
3252 blocks
= TBLOCKS(bytes
);
3254 (void) fprintf(vfile
, gettext("x %s, %"
3255 FMT_off_t
" bytes, "), namep
, bytes
);
3257 (void) fprintf(vfile
, "%" FMT_blkcnt_t
3260 (void) fprintf(vfile
, gettext("%"
3261 FMT_blkcnt_t
" tape blocks\n"),
3265 } else if (dblock
.dbuf
.typeflag
== '4' && Uid
) {
3266 (void) fprintf(stderr
,
3267 gettext("Can't create special %s\n"), namep
);
3270 if (dblock
.dbuf
.typeflag
== '2') { /* symlink */
3272 if (Aflag
&& *linkp
== '/')
3274 if (rmdir(namep
) < 0) {
3275 if (errno
== ENOTDIR
)
3276 (void) unlink(namep
);
3278 if (symlink(linkp
, namep
) < 0) {
3279 vperror(0, gettext("%s: symbolic link failed"),
3284 (void) fprintf(vfile
, gettext(
3285 "x %s symbolic link to %s\n"),
3288 symflag
= AT_SYMLINK_NOFOLLOW
;
3291 if (dblock
.dbuf
.typeflag
== '1') {
3293 if (Aflag
&& *linkp
== '/')
3295 if (unlinkat(dirfd
, comp
, AT_REMOVEDIR
) < 0) {
3296 if (errno
== ENOTDIR
)
3297 (void) unlinkat(dirfd
, comp
, 0);
3299 #if defined(O_XATTR)
3300 if (xattrp
&& xattr_linkp
) {
3301 if (fchdir(dirfd
) < 0) {
3303 "Cannot fchdir to attribute "
3305 (attrinfo
->attr_parent
== NULL
) ?
3306 dirp
: attrinfo
->attr_parent
);
3310 error
= link(xattr_linkaname
, xattrapath
);
3312 error
= link(linkp
, namep
);
3315 error
= link(linkp
, namep
);
3319 (void) fprintf(stderr
, gettext(
3320 "tar: %s%s%s: cannot link\n"),
3321 namep
, (xattr_linkp
!= NULL
) ?
3322 gettext(" attribute ") : "",
3323 (xattr_linkp
!= NULL
) ?
3328 (void) fprintf(vfile
, gettext(
3329 "x %s%s%s linked to %s%s%s\n"), namep
,
3330 (xattr_linkp
!= NULL
) ?
3331 gettext(" attribute ") : "",
3332 (xattr_linkp
!= NULL
) ?
3333 xattr_linkaname
: "",
3335 (xattr_linkp
!= NULL
) ?
3336 gettext(" attribute ") : "",
3337 (xattr_linkp
!= NULL
) ? xattrapath
: "");
3338 xcnt
++; /* increment # files extracted */
3339 #if defined(O_XATTR)
3340 if (xattrp
!= NULL
) {
3352 if (convtoreg(stbuf
.st_size
)) {
3355 (void) fprintf(stderr
, gettext(
3356 "tar: %s: typeflag '%c' not recognized\n"),
3357 namep
, dblock
.dbuf
.typeflag
);
3360 (void) fprintf(stderr
, gettext(
3361 "tar: %s: typeflag '%c' not recognized, "
3362 "converting to regular file\n"), namep
,
3363 dblock
.dbuf
.typeflag
);
3367 if (dblock
.dbuf
.typeflag
== '0' ||
3368 dblock
.dbuf
.typeflag
== '\0' || convflag
) {
3369 delete_target(dirfd
, comp
, namep
);
3371 if (*linkp
!= '\0') {
3372 if (Aflag
&& *linkp
== '/')
3374 if (link(linkp
, comp
) < 0) {
3375 (void) fprintf(stderr
, gettext(
3376 "tar: %s: cannot link\n"), namep
);
3380 (void) fprintf(vfile
, gettext(
3381 "x %s linked to %s\n"), comp
,
3383 xcnt
++; /* increment # files extracted */
3384 #if defined(O_XATTR)
3385 if (xattrp
!= NULL
) {
3394 newfile
= ((fstatat(dirfd
, comp
,
3395 &xtractbuf
, 0) == -1) ? TRUE
: FALSE
);
3396 ofile
= openat(dirfd
, comp
, O_RDWR
|O_CREAT
|O_TRUNC
,
3397 stbuf
.st_mode
& MODEMASK
);
3400 #if defined(O_XATTR)
3401 if (xattrp
!= NULL
) {
3403 ofile
= retry_open_attr(dirfd
, cwd
,
3404 dirp
, attrinfo
->attr_parent
, comp
,
3405 O_RDWR
|O_CREAT
|O_TRUNC
,
3406 stbuf
.st_mode
& MODEMASK
);
3412 (void) fprintf(stderr
, gettext(
3413 "tar: %s%s%s%s - cannot create\n"),
3414 (xattrp
== NULL
) ? "" : (rw_sysattr
?
3415 gettext("system attribute ") :
3416 gettext("attribute ")),
3417 (xattrp
== NULL
) ? "" : xattrapath
,
3418 (xattrp
== NULL
) ? "" : gettext(" of "),
3419 (xattrp
== NULL
) ? comp
: namep
);
3424 #if defined(O_XATTR)
3425 if (xattrp
!= NULL
) {
3426 dblock
.dbuf
.typeflag
= _XATTR_HDRTYPE
;
3437 if (extno
!= 0) { /* file is in pieces */
3438 if (extotal
< 1 || extotal
> MAXEXT
)
3439 (void) fprintf(stderr
, gettext(
3440 "tar: ignoring bad extent info for "
3442 (xattrp
== NULL
) ? "" : (rw_sysattr
?
3443 gettext("system attribute ") :
3444 gettext("attribute ")),
3445 (xattrp
== NULL
) ? "" : xattrapath
,
3446 (xattrp
== NULL
) ? "" : gettext(" of "),
3447 (xattrp
== NULL
) ? comp
: namep
);
3450 (void) xsfile(rw_sysattr
, ofile
);
3453 extno
= 0; /* let everyone know file is not split */
3454 bytes
= stbuf
.st_size
;
3455 blocks
= TBLOCKS(bytes
);
3457 (void) fprintf(vfile
,
3458 "x %s%s%s, %" FMT_off_t
" %s, ",
3459 (xattrp
== NULL
) ? "" : dirp
,
3460 (xattrp
== NULL
) ? "" : (rw_sysattr
?
3461 gettext(" system attribute ") :
3462 gettext(" attribute ")),
3463 (xattrp
== NULL
) ? namep
: xattrapath
, bytes
,
3466 (void) fprintf(vfile
, "%" FMT_blkcnt_t
"K\n",
3469 (void) fprintf(vfile
, gettext("%"
3470 FMT_blkcnt_t
" tape blocks\n"), blocks
);
3473 if (xblocks(rw_sysattr
, bytes
, ofile
) != 0) {
3474 #if defined(O_XATTR)
3475 if (xattrp
!= NULL
) {
3485 if (mflag
== 0 && !symflag
) {
3487 doDirTimes(namep
, stbuf
.st_mtim
);
3490 #if defined(O_XATTR)
3491 if (xattrp
!= NULL
) {
3493 * Set the time on the attribute unless
3494 * the attribute is a system attribute
3495 * (can't successfully do this) or the
3496 * hidden attribute directory, "." (the
3497 * time on the hidden attribute
3498 * directory will be updated when
3499 * attributes are restored, otherwise
3502 if (!rw_sysattr
&& (Hiddendir
== 0)) {
3503 setPathTimes(dirfd
, comp
,
3507 setPathTimes(dirfd
, comp
,
3510 setPathTimes(dirfd
, comp
, stbuf
.st_mtim
);
3514 /* moved this code from above */
3515 if (pflag
&& !symflag
&& Hiddendir
== 0) {
3517 (void) fchmod(ofile
, stbuf
.st_mode
& MODEMASK
);
3519 (void) chmod(namep
, stbuf
.st_mode
& MODEMASK
);
3524 * Because ancillary file preceeds the normal file,
3525 * acl info may have been retrieved (in aclp).
3526 * All file types are directed here (go filedone).
3527 * Always restore ACLs if there are ACLs.
3532 #if defined(O_XATTR)
3533 if (xattrp
!= NULL
) {
3535 ret
= facl_set(dirfd
, aclp
);
3537 ret
= facl_set(ofile
, aclp
);
3539 ret
= acl_set(namep
, aclp
);
3542 ret
= acl_set(namep
, aclp
);
3546 (void) fprintf(stderr
, gettext(
3547 "%s%s%s%s: failed to set acl "
3548 "entries\n"), namep
,
3549 (xattrp
== NULL
) ? "" :
3550 (rw_sysattr
? gettext(
3551 " system attribute ") :
3552 gettext(" attribute ")),
3553 (xattrp
== NULL
) ? "" :
3556 /* else: silent and continue */
3563 /* set file ownership */
3564 resugname(dirfd
, comp
, symflag
);
3566 if (pflag
&& newfile
== TRUE
&& !dir
&&
3567 (dblock
.dbuf
.typeflag
== '0' ||
3568 dblock
.dbuf
.typeflag
== '\0' ||
3569 convflag
|| dblock
.dbuf
.typeflag
== '1')) {
3570 if (fstat(ofile
, &xtractbuf
) == -1)
3571 (void) fprintf(stderr
, gettext(
3572 "tar: cannot stat extracted file "
3574 (xattrp
== NULL
) ? "" : (rw_sysattr
?
3575 gettext("system attribute ") :
3576 gettext("attribute ")),
3577 (xattrp
== NULL
) ? "" : xattrapath
,
3578 (xattrp
== NULL
) ? "" :
3579 gettext(" of "), namep
);
3581 else if ((xtractbuf
.st_mode
& (MODEMASK
& ~S_IFMT
))
3582 != (stbuf
.st_mode
& (MODEMASK
& ~S_IFMT
))) {
3583 (void) fprintf(stderr
, gettext(
3584 "tar: warning - file permissions have "
3585 "changed for %s%s%s%s (are 0%o, should be "
3587 (xattrp
== NULL
) ? "" : (rw_sysattr
?
3588 gettext("system attribute ") :
3589 gettext("attribute ")),
3590 (xattrp
== NULL
) ? "" : xattrapath
,
3591 (xattrp
== NULL
) ? "" :
3592 gettext(" of "), namep
,
3593 xtractbuf
.st_mode
, stbuf
.st_mode
);
3597 #if defined(O_XATTR)
3598 if (xattrp
!= NULL
) {
3607 (void) close(dirfd
);
3609 if (close(ofile
) != 0)
3610 vperror(2, gettext("close error"));
3613 xcnt
++; /* increment # files extracted */
3617 * Process ancillary file.
3621 if (dblock
.dbuf
.typeflag
== 'A') { /* acl info */
3629 bytes
= stbuf
.st_size
;
3630 if ((secp
= malloc((int)bytes
)) == NULL
) {
3631 (void) fprintf(stderr
, gettext(
3632 "Insufficient memory for acl\n"));
3637 blocks
= TBLOCKS(bytes
);
3639 while (blocks
-- > 0) {
3641 if (bytes
<= TBLOCK
) {
3642 (void) memcpy(tp
, buf
,
3646 (void) memcpy(tp
, buf
,
3652 bytes
= stbuf
.st_size
;
3653 /* got all attributes in secp */
3656 attr
= (struct sec_attr
*)tp
;
3657 switch (attr
->attr_type
) {
3660 (void) sscanf(attr
->attr_len
,
3665 attrsize
= 8 + (int)strlen(
3666 &attr
->attr_info
[0]) + 1;
3669 &attr
->attr_info
[0], &aclp
);
3672 (void) fprintf(stderr
,
3681 if (acl_cnt(aclp
) != cnt
) {
3682 (void) fprintf(stderr
,
3692 (void) fprintf(stderr
, gettext(
3699 /* next attributes */
3701 } while (bytes
!= 0);
3711 * Ensure that all the directories still on the directory stack
3712 * get their modification times set correctly by flushing the
3716 doDirTimes(NULL
, time_zero
);
3718 #if defined(O_XATTR)
3719 if (xattrp
!= NULL
) {
3728 * Check if the number of files extracted is different from the
3729 * number of files listed on the command line
3732 (void) fprintf(stderr
,
3733 gettext("tar: %d file(s) not extracted\n"),
3740 * xblocks extract file/extent from tape to output file
3742 * xblocks(issysattr, bytes, ofile);
3744 * issysattr flag set if the files being extracted
3745 * is an extended system attribute file.
3746 * unsigned long long bytes size of extent or file to be extracted
3749 * called by doxtract() and xsfile()
3753 xblocks(int issysattr
, off_t bytes
, int ofile
)
3756 char tempname
[NAMSIZ
+1];
3759 size_t piosize
; /* preferred I/O size */
3762 /* Don't need to do anything if this is a zero size file */
3768 * To figure out the size of the buffer used to accumulate data
3769 * from readtape() and to write to the file, we need to determine
3770 * the largest chunk of data to be written to the file at one time.
3771 * This is determined based on the smallest of the following two
3773 * 1) The size of the archived file.
3774 * 2) The preferred I/O size of the file.
3776 if (issysattr
|| (bytes
<= TBLOCK
)) {
3778 * Writes to system attribute files must be
3779 * performed in one operation.
3784 * fstat() the file to get the preferred I/O size.
3785 * If it fails, then resort back to just writing
3786 * one block at a time.
3788 if (fstat(ofile
, &tsbuf
) == 0) {
3789 piosize
= tsbuf
.st_blksize
;
3793 maxwrite
= min(bytes
, piosize
);
3797 * The buffer used to accumulate the data for the write operation
3798 * needs to be the maximum number of bytes to be written rounded up
3799 * to the nearest TBLOCK since readtape reads one block at a time.
3801 if ((buf
= malloc(TBLOCKS(maxwrite
) * TBLOCK
)) == NULL
) {
3802 fatal(gettext("cannot allocate buffer"));
3808 * readtape() obtains one block (TBLOCK) of data at a time.
3809 * Accumulate as many blocks of data in buf as we can write
3812 for (bytesread
= 0; bytesread
< maxwrite
; bytesread
+= TBLOCK
) {
3813 readtape(buf
+ bytesread
);
3816 if (write(ofile
, buf
, maxwrite
) < 0) {
3817 int saveerrno
= errno
;
3819 if (xhdr_flgs
& _X_PATH
)
3820 (void) strlcpy(tempname
, Xtarhdr
.x_path
,
3823 (void) sprintf(tempname
, "%.*s", NAMSIZ
,
3826 * If the extended system attribute being extracted
3827 * contains attributes that the user needs privileges
3828 * for, then just display a warning message, skip
3829 * the extraction of this file, and return.
3831 if ((saveerrno
== EPERM
) && issysattr
) {
3832 (void) fprintf(stderr
, gettext(
3833 "tar: unable to extract system attribute "
3834 "%s: insufficient privileges\n"), tempname
);
3839 (void) fprintf(stderr
, gettext(
3840 "tar: %s: HELP - extract write error\n"),
3848 * If we've reached this point and there is still data
3849 * to be written, maxwrite had to have been determined
3850 * by the preferred I/O size. If the number of bytes
3851 * left to write is smaller than the preferred I/O size,
3852 * then we're about to do our final write to the file, so
3853 * just set maxwrite to the number of bytes left to write.
3855 if ((bytes
> 0) && (bytes
< maxwrite
)) {
3865 * xsfile extract split file
3867 * xsfile(ofd); ofd = output file descriptor
3869 * file extracted and put in ofd via xblocks()
3871 * NOTE: only called by doxtract() to extract one large file
3874 static union hblock savedblock
; /* to ensure same file across volumes */
3877 xsfile(int issysattr
, int ofd
)
3881 char name
[PATH_MAX
+1]; /* holds name for diagnostics */
3882 int extents
, totalext
;
3883 off_t bytes
, totalbytes
;
3885 if (xhdr_flgs
& _X_PATH
)
3886 (void) strcpy(name
, Xtarhdr
.x_path
);
3888 (void) sprintf(name
, "%.*s", NAMSIZ
, dblock
.dbuf
.name
);
3890 totalbytes
= (off_t
)0; /* in case we read in half the file */
3891 totalext
= 0; /* these keep count */
3893 (void) fprintf(stderr
, gettext(
3894 "tar: %s split across %d volumes\n"), name
, extotal
);
3896 /* make sure we do extractions in order */
3897 if (extno
!= 1) { /* starting in middle of file? */
3898 (void) printf(gettext(
3899 "tar: first extent read is not #1\n"
3900 "OK to read file beginning with extent #%d? "),
3905 if (close(ofd
) != 0)
3906 vperror(2, gettext("close error"));
3918 if (xhdr_flgs
& _X_SIZE
) {
3921 bytes
= stbuf
.st_size
;
3925 (void) fprintf(vfile
, "+++ x %s [%s #%d], %"
3926 FMT_off_t
" %s, %ldK\n",
3927 name
, gettext("extent"), extno
,
3928 bytes
, gettext("bytes"),
3929 (long)K(TBLOCKS(bytes
)));
3930 if (xblocks(issysattr
, bytes
, ofd
) != 0) {
3935 totalbytes
+= bytes
;
3940 /* get next volume and verify it's the right one */
3941 copy(&savedblock
, &dblock
);
3947 (void) get_xdata(); /* Get x-header & regular hdr */
3948 if ((dblock
.dbuf
.typeflag
!= 'A') && (xhdr_flgs
!= 0)) {
3949 load_info_from_xtarhdr(xhdr_flgs
, &Xtarhdr
);
3950 xhdr_flgs
|= _X_XHDR
;
3952 if (endtape()) { /* seemingly empty volume */
3953 (void) fprintf(stderr
, gettext(
3954 "tar: first record is null\n"));
3956 (void) fprintf(stderr
, gettext(
3957 "tar: need volume with extent #%d of %s\n"),
3962 (void) fprintf(stderr
, gettext(
3963 "tar: first file on that volume is not "
3964 "the same file\n"));
3968 (void) fprintf(stderr
, gettext(
3969 "tar: extent #%d received out of order\ntar: "
3970 "should be #%d\n"), extno
, i
);
3971 (void) fprintf(stderr
, gettext(
3972 "Ignore error, Abort this file, or "
3973 "load New volume (i/a/n) ? "));
3977 if (c
!= 'i') /* default to new volume */
3979 i
= extno
; /* okay, start from there */
3983 (void) fprintf(vfile
, gettext(
3984 "x %s (in %d extents), %" FMT_off_t
" bytes, %ldK\n"),
3985 name
, totalext
, totalbytes
, (long)K(TBLOCKS(totalbytes
)));
3992 * notsame() check if extract file extent is invalid
3994 * returns true if anything differs between savedblock and dblock
3995 * except extno (extent number), checksum, or size (extent size).
3996 * Determines if this header belongs to the same file as the one we're
3999 * NOTE: though rather bulky, it is only called once per file
4000 * extension, and it can withstand changes in the definition
4001 * of the header structure.
4003 * WARNING: this routine is local to xsfile() above
4010 (strncmp(savedblock
.dbuf
.name
, dblock
.dbuf
.name
, NAMSIZ
)) ||
4011 (strcmp(savedblock
.dbuf
.mode
, dblock
.dbuf
.mode
)) ||
4012 (strcmp(savedblock
.dbuf
.uid
, dblock
.dbuf
.uid
)) ||
4013 (strcmp(savedblock
.dbuf
.gid
, dblock
.dbuf
.gid
)) ||
4014 (strcmp(savedblock
.dbuf
.mtime
, dblock
.dbuf
.mtime
)) ||
4015 (savedblock
.dbuf
.typeflag
!= dblock
.dbuf
.typeflag
) ||
4016 (strncmp(savedblock
.dbuf
.linkname
, dblock
.dbuf
.linkname
, NAMSIZ
)) ||
4017 (savedblock
.dbuf
.extotal
!= dblock
.dbuf
.extotal
) ||
4018 (strcmp(savedblock
.dbuf
.efsize
, dblock
.dbuf
.efsize
)));
4022 dotable(char *argv
[])
4024 int tcnt
= 0; /* count # files tabled */
4025 int fcnt
= 0; /* count # files in argv list */
4026 char *namep
, *dirp
, *comp
;
4028 char aclchar
= ' '; /* either blank or '+' */
4029 char templink
[PATH_MAX
+1];
4030 attr_data_t
*attrinfo
= NULL
;
4034 /* if not on magtape, maximize seek speed */
4035 if (NotTape
&& !bflag
) {
4036 #if SYS_BLOCK > TBLOCK
4037 nblock
= SYS_BLOCK
/ TBLOCK
;
4045 /* namep is set by wantit to point to the full name */
4046 if ((want
= wantit(argv
, &namep
, &dirp
, &comp
, &attrinfo
)) == 0)
4050 if (dblock
.dbuf
.typeflag
!= 'A')
4054 if (checkf(namep
, is_directory(namep
), Fflag
) == 0) {
4061 * aclchar is introduced to indicate if there are
4062 * acl entries. longt() now takes one extra argument.
4065 if (dblock
.dbuf
.typeflag
== 'A') {
4070 longt(&stbuf
, aclchar
);
4075 #if defined(O_XATTR)
4076 if (xattrp
!= NULL
) {
4078 char *bn
= basename(attrinfo
->attr_path
);
4081 * We could use sysattr_type() to test whether or not
4082 * the attribute we are processing is really an
4083 * extended system attribute, which as of this writing
4084 * just does a strcmp(), however, sysattr_type() may
4085 * be changed to issue a pathconf() call instead, which
4086 * would require being changed into the parent attribute
4087 * directory. So instead, just do simple string
4088 * comparisons to see if we are processing an extended
4091 issysattr
= is_sysattr(bn
);
4093 (void) printf(gettext("%s %sattribute %s"),
4095 issysattr
? gettext("system ") : "",
4096 attrinfo
->attr_path
);
4098 (void) printf("%s", namep
);
4101 (void) printf("%s", namep
);
4106 /* keep the '\n' for backwards compatibility */
4107 (void) fprintf(vfile
, gettext(
4108 "\n [extent #%d of %d]"), extno
, extotal
);
4110 (void) fprintf(vfile
, gettext(
4111 " [extent #%d of %d]"), extno
, extotal
);
4114 if (xhdr_flgs
& _X_LINKPATH
) {
4115 (void) strcpy(templink
, Xtarhdr
.x_linkpath
);
4117 #if defined(O_XATTR)
4118 if (xattrp
!= NULL
) {
4119 (void) sprintf(templink
,
4120 "file %.*s", NAMSIZ
, xattrp
->h_names
);
4122 (void) sprintf(templink
, "%.*s", NAMSIZ
,
4123 dblock
.dbuf
.linkname
);
4126 (void) sprintf(templink
, "%.*s", NAMSIZ
,
4127 dblock
.dbuf
.linkname
);
4129 templink
[NAMSIZ
] = '\0';
4131 if (dblock
.dbuf
.typeflag
== '1') {
4134 * Subject is omitted here.
4135 * Translate this as if
4136 * <subject> linked to %s
4138 #if defined(O_XATTR)
4139 if (xattrp
!= NULL
) {
4141 gettext(" linked to attribute %s"),
4142 xattr_linkp
->h_names
+
4143 strlen(xattr_linkp
->h_names
) + 1);
4146 gettext(" linked to %s"), templink
);
4150 gettext(" linked to %s"), templink
);
4154 if (dblock
.dbuf
.typeflag
== '2')
4155 (void) printf(gettext(
4158 * Subject is omitted here.
4159 * Translate this as if
4160 * <subject> symbolic link to %s
4162 " symbolic link to %s"), templink
);
4163 (void) printf("\n");
4164 #if defined(O_XATTR)
4165 if (xattrp
!= NULL
) {
4174 * Check if the number of files tabled is different from the
4175 * number of files listed on the command line
4178 (void) fprintf(stderr
, gettext(
4179 "tar: %d file(s) not found\n"), fcnt
-tcnt
);
4185 putempty(blkcnt_t n
)
4190 for (cp
= buf
; cp
< &buf
[TBLOCK
]; )
4193 (void) writetbuf(buf
, 1);
4196 static ushort_t Ftype
= S_IFMT
;
4199 verbose(struct stat
*st
, char aclchar
)
4205 for (i
= 0; i
< 11; i
++)
4209 /* a '+' sign is printed if there is ACL */
4210 modestr
[i
-1] = aclchar
;
4213 for (i
= 0; i
< 3; i
++) {
4214 temp
= (mode
>> (6 - (i
* 3)));
4219 modestr
[j
+ 1] = 'w';
4221 modestr
[j
+ 2] = 'x';
4223 temp
= st
->st_mode
& Ftype
;
4237 case (S_IFREG
): /* was initialized to '-' */
4243 /* This field may be zero in old archives. */
4244 if (is_posix
&& dblock
.dbuf
.typeflag
!= '1') {
4246 * For POSIX compliant archives, the mode field
4247 * consists of 12 bits, ie: the file type bits
4248 * are not stored in dblock.dbuf.mode.
4249 * For files other than hard links, getdir() sets
4250 * the file type bits in the st_mode field of the
4251 * stat structure based upon dblock.dbuf.typeflag.
4253 (void) fprintf(stderr
, gettext(
4254 "tar: impossible file type"));
4258 if ((S_ISUID
& Gen
.g_mode
) == S_ISUID
)
4260 if ((S_ISVTX
& Gen
.g_mode
) == S_ISVTX
)
4262 if ((S_ISGID
& Gen
.g_mode
) == S_ISGID
&& modestr
[6] == 'x')
4264 else if ((S_ENFMT
& Gen
.g_mode
) == S_ENFMT
&& modestr
[6] != 'x')
4266 (void) fprintf(vfile
, "%s", modestr
);
4270 longt(struct stat
*st
, char aclchar
)
4275 verbose(st
, aclchar
);
4276 (void) fprintf(vfile
, "%3ld/%-3ld", st
->st_uid
, st
->st_gid
);
4278 if (dblock
.dbuf
.typeflag
== '2') {
4279 if (xhdr_flgs
& _X_LINKPATH
)
4280 st
->st_size
= (off_t
)strlen(Xtarhdr
.x_linkpath
);
4282 st
->st_size
= (off_t
)(memchr(dblock
.dbuf
.linkname
,
4284 (strlen(dblock
.dbuf
.linkname
)) : (NAMSIZ
));
4286 (void) fprintf(vfile
, " %6" FMT_off_t
, st
->st_size
);
4288 tm
= localtime(&(st
->st_mtime
));
4289 (void) strftime(fileDate
, sizeof (fileDate
),
4290 dcgettext((const char *)0, "%b %e %R %Y", LC_TIME
), tm
);
4291 (void) fprintf(vfile
, " %s ", fileDate
);
4296 * checkdir - Attempt to ensure that the path represented in name
4297 * exists, and return 1 if this is true and name itself is a
4299 * Return 0 if this path cannot be created or if name is not
4304 checkdir(char *name
)
4306 char lastChar
; /* the last character in name */
4307 char *cp
; /* scratch pointer into name */
4308 char *firstSlash
= NULL
; /* first slash in name */
4309 char *lastSlash
= NULL
; /* last slash in name */
4310 int nameLen
; /* length of name */
4311 int trailingSlash
; /* true if name ends in slash */
4312 int leadingSlash
; /* true if name begins with slash */
4313 int markedDir
; /* true if name denotes a directory */
4314 int success
; /* status of makeDir call */
4318 * Scan through the name, and locate first and last slashes.
4321 for (cp
= name
; *cp
; cp
++) {
4331 * Determine what you can from the proceeds of the scan.
4334 lastChar
= *(cp
- 1);
4335 nameLen
= (int)(cp
- name
);
4336 trailingSlash
= (lastChar
== '/');
4337 leadingSlash
= (*name
== '/');
4338 markedDir
= (dblock
.dbuf
.typeflag
== '5' || trailingSlash
);
4340 if (! lastSlash
&& ! markedDir
) {
4342 * The named file does not have any subdrectory
4343 * structure; just bail out.
4350 * Make sure that name doesn`t end with slash for the loop.
4351 * This ensures that the makeDir attempt after the loop is
4355 if (trailingSlash
) {
4356 name
[nameLen
-1] = '\0';
4360 * Make the path one component at a time.
4363 for (cp
= strchr(leadingSlash
? name
+1 : name
, '/');
4365 cp
= strchr(cp
+1, '/')) {
4367 success
= makeDir(name
);
4371 name
[nameLen
-1] = lastChar
;
4377 * This makes the last component of the name, if it is a
4382 if (! makeDir(name
)) {
4383 name
[nameLen
-1] = lastChar
;
4388 name
[nameLen
-1] = (lastChar
== '/') ? '\0' : lastChar
;
4393 * resugname - Restore the user name and group name. Search the NIS
4394 * before using the uid and gid.
4395 * (It is presumed that an archive entry cannot be
4396 * simultaneously a symlink and some other type.)
4400 resugname(int dirfd
, /* dir fd file resides in */
4401 char *name
, /* name of the file to be modified */
4402 int symflag
) /* true if file is a symbolic link */
4406 struct stat
*sp
= &stbuf
;
4409 if (checkflag
== 1) { /* Extended tar format and euid == 0 */
4412 * Try and extract the intended uid and gid from the name
4413 * service before believing the uid and gid in the header.
4415 * In the case where we archived a setuid or setgid file
4416 * owned by someone with a large uid, then it will
4417 * have made it into the archive with a uid of nobody. If
4418 * the corresponding username doesn't appear to exist, then we
4419 * want to make sure it *doesn't* end up as setuid nobody!
4421 * Our caller will print an error message about the fact
4422 * that the restore didn't work out quite right ..
4424 if (xhdr_flgs
& _X_UNAME
)
4425 u_g_name
= Xtarhdr
.x_uname
;
4427 u_g_name
= dblock
.dbuf
.uname
;
4428 if ((duid
= getuidbyname(u_g_name
)) == -1) {
4429 if (S_ISREG(sp
->st_mode
) && sp
->st_uid
== UID_NOBODY
&&
4430 (sp
->st_mode
& S_ISUID
) == S_ISUID
)
4432 MODEMASK
& sp
->st_mode
& ~S_ISUID
);
4436 /* (Ditto for gids) */
4438 if (xhdr_flgs
& _X_GNAME
)
4439 u_g_name
= Xtarhdr
.x_gname
;
4441 u_g_name
= dblock
.dbuf
.gname
;
4442 if ((dgid
= getgidbyname(u_g_name
)) == -1) {
4443 if (S_ISREG(sp
->st_mode
) && sp
->st_gid
== GID_NOBODY
&&
4444 (sp
->st_mode
& S_ISGID
) == S_ISGID
)
4446 MODEMASK
& sp
->st_mode
& ~S_ISGID
);
4449 } else if (checkflag
== 2) { /* tar format and euid == 0 */
4453 if ((checkflag
== 1) || (checkflag
== 2))
4454 (void) fchownat(dirfd
, name
, duid
, dgid
, symflag
);
4461 (void) signal(SIGINT
, SIG_IGN
);
4469 (void) signal(SIGQUIT
, SIG_IGN
);
4477 (void) signal(SIGHUP
, SIG_IGN
);
4482 tomodes(struct stat
*sp
)
4487 bzero(dblock
.dummy
, TBLOCK
);
4490 * If the uid or gid is too large, we can't put it into
4491 * the archive. We could fail to put anything in the
4492 * archive at all .. but most of the time the name service
4493 * will save the day when we do a lookup at restore time.
4495 * Instead we choose a "safe" uid and gid, and fix up whether
4496 * or not the setuid and setgid bits are left set to extraction
4500 if ((ulong_t
)(uid
= sp
->st_uid
) > (ulong_t
)OCTAL7CHAR
) {
4501 xhdr_flgs
|= _X_UID
;
4502 Xtarhdr
.x_uid
= uid
;
4504 if ((ulong_t
)(gid
= sp
->st_gid
) > (ulong_t
)OCTAL7CHAR
) {
4505 xhdr_flgs
|= _X_GID
;
4506 Xtarhdr
.x_gid
= gid
;
4508 if (sp
->st_size
> TAR_OFFSET_MAX
) {
4509 xhdr_flgs
|= _X_SIZE
;
4510 Xtarhdr
.x_filesz
= sp
->st_size
;
4511 (void) sprintf(dblock
.dbuf
.size
, "%011" FMT_off_t_o
,
4514 (void) sprintf(dblock
.dbuf
.size
, "%011" FMT_off_t_o
,
4517 (void) sprintf(dblock
.dbuf
.size
, "%011" FMT_off_t_o
,
4520 if ((ulong_t
)(uid
= sp
->st_uid
) > (ulong_t
)OCTAL7CHAR
)
4522 if ((ulong_t
)(gid
= sp
->st_gid
) > (ulong_t
)OCTAL7CHAR
)
4524 (void) sprintf(dblock
.dbuf
.gid
, "%07lo", gid
);
4525 (void) sprintf(dblock
.dbuf
.uid
, "%07lo", uid
);
4526 (void) sprintf(dblock
.dbuf
.mode
, "%07lo", sp
->st_mode
& POSIXMODES
);
4527 (void) sprintf(dblock
.dbuf
.mtime
, "%011lo", sp
->st_mtime
);
4533 * Warning: the result of this function depends whether 'char' is a
4534 * signed or unsigned data type. This a source of potential
4535 * non-portability among heterogeneous systems. It is retained here
4536 * for backward compatibility.
4538 checksum_signed(union hblock
*dblockp
)
4540 checksum(union hblock
*dblockp
)
4546 for (cp
= dblockp
->dbuf
.chksum
;
4547 cp
< &dblockp
->dbuf
.chksum
[sizeof (dblockp
->dbuf
.chksum
)]; cp
++)
4550 for (cp
= dblockp
->dummy
; cp
< &(dblockp
->dummy
[TBLOCK
]); cp
++)
4557 * Generate unsigned checksum, regardless of what C compiler is
4558 * used. Survives in the face of arbitrary 8-bit clean filenames,
4559 * e.g., internationalized filenames.
4562 checksum(union hblock
*dblockp
)
4567 for (cp
= (unsigned char *) dblockp
->dbuf
.chksum
;
4568 cp
< (unsigned char *)
4569 &(dblockp
->dbuf
.chksum
[sizeof (dblockp
->dbuf
.chksum
)]); cp
++)
4572 for (cp
= (unsigned char *) dblockp
->dummy
;
4573 cp
< (unsigned char *) &(dblockp
->dummy
[TBLOCK
]); cp
++)
4581 * If the w flag is set, output the action to be taken and the name of the
4582 * file. Perform the action if the user response is affirmative.
4586 checkw(char c
, char *name
)
4589 (void) fprintf(vfile
, "%c ", c
);
4591 longt(&stbuf
, ' '); /* do we have acl info here */
4592 (void) fprintf(vfile
, "%s: ", name
);
4602 * When the F flag is set, exclude RCS and SCCS directories (and any files
4603 * or directories under them). If F is set twice, also exclude .o files,
4604 * and files names errs, core, and a.out.
4606 * Return 0 if file should be excluded, 1 otherwise.
4610 checkf(char *longname
, int is_dir
, int howmuch
)
4612 static char fullname
[PATH_MAX
+ 1];
4615 #if defined(O_XATTR)
4617 * If there is an xattr_buf structure associated with this file,
4626 * First check to see if the base name is an RCS or SCCS directory.
4628 if (strlcpy(fullname
, longname
, sizeof (fullname
)) >= sizeof (fullname
))
4631 name
= basename(fullname
);
4633 if ((strcmp(name
, "SCCS") == 0) || (strcmp(name
, "RCS") == 0))
4638 * If two -F command line options were given then exclude .o files,
4639 * and files named errs, core, and a.out.
4641 if (howmuch
> 1 && !is_dir
) {
4642 size_t l
= strlen(name
);
4644 if (l
>= 3 && name
[l
- 2] == '.' && name
[l
- 1] == 'o')
4646 if (strcmp(name
, "core") == 0 || strcmp(name
, "errs") == 0 ||
4647 strcmp(name
, "a.out") == 0)
4652 * At this point, check to see if this file has a parent directory
4653 * named RCS or SCCS. If so, then this file should be excluded too.
4654 * The strcpy() operation is done again, because basename(3C) may
4655 * modify the path string passed to it.
4657 if (strlcpy(fullname
, longname
, sizeof (fullname
)) >= sizeof (fullname
))
4660 dir
= dirname(fullname
);
4661 while (strcmp(dir
, ".") != 0) {
4662 name
= basename(dir
);
4663 if ((strcmp(name
, "SCCS") == 0) || (strcmp(name
, "RCS") == 0))
4678 while (getchar() != '\n')
4681 return ((c
>= 'A' && c
<= 'Z') ? c
+ ('a'-'A') : c
);
4684 /* Has file been modified since being put into archive? If so, return > 0. */
4686 static off_t
lookup(char *);
4689 checkupdate(char *arg
)
4691 char name
[PATH_MAX
+1];
4697 if ((seekp
= lookup(arg
)) < 0)
4699 (void) fseek(tfile
, seekp
, 0);
4700 (void) fscanf(tfile
, "%s %ld.%ld", name
, &mtime
, &nsecs
);
4703 * Unless nanoseconds were stored in the file, only use seconds for
4704 * comparison of time. Nanoseconds are stored when -E is specified.
4707 return (stbuf
.st_mtime
> mtime
);
4709 if ((stbuf
.st_mtime
< mtime
) ||
4710 ((stbuf
.st_mtime
== mtime
) && (stbuf
.st_mtim
.tv_nsec
<= nsecs
)))
4717 * newvol get new floppy (or tape) volume
4719 * newvol(); resets tapepos and first to TRUE, prompts for
4720 * for new volume, and waits.
4721 * if dumping, end-of-file is written onto the tape.
4730 dlog("newvol called with 'dumping' set\n");
4731 putempty((blkcnt_t
)2); /* 2 EOT marks */
4739 vperror(2, gettext("close error"));
4741 (void) fprintf(stderr
, gettext(
4742 "tar: \007please insert new volume, then press RETURN."));
4743 (void) fseek(stdin
, (off_t
)0, 2); /* scan over read-ahead */
4744 while ((c
= getchar()) != '\n' && ! term
)
4752 if (strcmp(usefile
, "-") == 0) {
4755 mt
= open(usefile
, dumping
? update
: 0);
4759 (void) fprintf(stderr
, gettext(
4760 "tar: cannot reopen %s (%s)\n"),
4761 dumping
? gettext("output") : gettext("input"), usefile
);
4763 dlog("update=%d, usefile=%s ", update
, usefile
);
4764 dlog("mt=%d, [%s]\n", mt
, strerror(errno
));
4771 * Write a trailer portion to close out the current output volume.
4779 * blocklim does not count the 2 EOT marks;
4780 * tapepos does count the 2 EOT marks;
4781 * therefore we need the +2 below.
4783 putempty(blocklim
+ (blkcnt_t
)2 - tapepos
);
4791 * If we were terminated in some way, and we would otherwise have
4792 * exited with a value of 0, adjust to 1, so that external callers
4793 * can determine this by looking at the exit status.
4799 (void) unlink(tname
);
4800 if (compress_opt
!= NULL
)
4801 (void) free(compress_opt
);
4803 if ((close(mt
) != 0) || (fclose(stdout
) != 0)) {
4804 perror(gettext("tar: close error"));
4809 * If we have a compression child, we should have a child process that
4810 * we're waiting for to finish compressing or uncompressing the tar
4819 * Determine if s1 is a prefix portion of s2 (or the same as s2).
4823 is_prefix(char *s1
, char *s2
)
4829 return (*s2
== '/');
4834 * lookup and bsrch look through tfile entries to find a match for a name.
4835 * The name can be up to PATH_MAX bytes. bsrch compares what it sees between
4836 * a pair of newline chars, so the buffer it uses must be long enough for
4837 * two lines: name and modification time as well as period, newline and space.
4839 * A kludge was added to bsrch to take care of matching on the first entry
4840 * in the file--there is no leading newline. So, if we are reading from the
4841 * start of the file, read into byte two and set the first byte to a newline.
4842 * Otherwise, the first entry cannot be matched.
4846 #define N (2 * (PATH_MAX + TIME_MAX_DIGITS + LONG_MAX_DIGITS + 3))
4853 for (i
= 0; s
[i
]; i
++)
4856 a
= bsrch(s
, i
, low
, high
);
4861 bsrch(char *s
, int n
, off_t l
, off_t h
)
4871 m
= l
+ (h
-l
)/2 - N
/2;
4874 (void) fseek(tfile
, m
, 0);
4876 (void) fread(b
+1, 1, N
-1, tfile
);
4880 (void) fread(b
, 1, N
, tfile
);
4881 for (i
= 0; i
< N
; i
++) {
4890 for (i
++; i
< N
; i
++) {
4910 cmp(char *b
, char *s
, int n
)
4914 assert(b
[0] == '\n');
4916 for (i
= 0; i
< n
; i
++) {
4922 return (b
[i
+1] == ' '? 0 : -1);
4927 * seekdisk seek to next file on archive
4929 * called by passtape() only
4931 * WARNING: expects "nblock" to be set, that is, readtape() to have
4932 * already been called. Since passtape() is only called
4933 * after a file header block has been read (why else would
4934 * we skip to next file?), this is currently safe.
4936 * changed to guarantee SYS_BLOCK boundary
4940 seekdisk(blkcnt_t blocks
)
4943 #if SYS_BLOCK > TBLOCK
4944 /* handle non-multiple of SYS_BLOCK */
4945 blkcnt_t nxb
; /* # extra blocks */
4949 dlog("seekdisk(%" FMT_blkcnt_t
") called\n", blocks
);
4950 if (recno
+ blocks
<= nblock
) {
4956 seekval
= (off_t
)blocks
- (nblock
- recno
);
4957 recno
= nblock
; /* so readtape() reads next time through */
4958 #if SYS_BLOCK > TBLOCK
4959 nxb
= (blkcnt_t
)(seekval
% (off_t
)(SYS_BLOCK
/ TBLOCK
));
4960 dlog("xtrablks=%" FMT_blkcnt_t
" seekval=%" FMT_blkcnt_t
" blks\n",
4962 if (nxb
&& nxb
> seekval
) /* don't seek--we'll read */
4964 seekval
-= nxb
; /* don't seek quite so far */
4966 if (lseek(mt
, (off_t
)(TBLOCK
* seekval
), 1) == (off_t
)-1) {
4967 (void) fprintf(stderr
, gettext(
4968 "tar: device seek error\n"));
4971 #if SYS_BLOCK > TBLOCK
4972 /* read those extra blocks */
4975 dlog("reading extra blocks\n");
4976 if (read(mt
, tbuf
, TBLOCK
*nblock
) < 0) {
4977 (void) fprintf(stderr
, gettext(
4978 "tar: read error while skipping file\n"));
4981 recno
= nxb
; /* so we don't read in next readtape() */
4987 readtape(char *buffer
)
4992 if (recno
>= nblock
|| first
) {
4995 * set the number of blocks to read initially, based on
4996 * the defined defaults for the device, or on the
4997 * explicit block factor given.
4999 if (bflag
|| defaults_used
|| NotTape
)
5006 if ((i
= read(mt
, tbuf
, TBLOCK
*j
)) < 0) {
5007 (void) fprintf(stderr
, gettext(
5008 "tar: tape read error\n"));
5011 * i == 0 and !rflag means that EOF is reached and we are
5012 * trying to update or replace an empty tar file, so exit
5015 * If i == 0 and !first and NotTape, it means the pointer
5016 * has gone past the EOF. It could happen if two processes
5017 * try to update the same tar file simultaneously. So exit
5021 } else if (i
== 0) {
5022 if (first
&& !rflag
) {
5023 (void) fprintf(stderr
, gettext(
5024 "tar: blocksize = %d\n"), i
);
5026 } else if (!first
&& (!rflag
|| NotTape
)) {
5027 mterr("read", 0, 2);
5029 } else if ((!first
|| Bflag
) && i
!= TBLOCK
*j
) {
5031 * Short read - try to get the remaining bytes.
5034 int remaining
= (TBLOCK
* j
) - i
;
5035 char *b
= (char *)tbuf
+ i
;
5039 if ((r
= read(mt
, b
, remaining
)) < 0) {
5040 (void) fprintf(stderr
,
5041 gettext("tar: tape read error\n"));
5047 } while (remaining
> 0 && r
!= 0);
5050 if ((i
% TBLOCK
) != 0) {
5051 (void) fprintf(stderr
, gettext(
5052 "tar: tape blocksize error\n"));
5056 if (vflag
&& i
!= nblock
&& i
!= 1) {
5058 (void) fprintf(stderr
, gettext(
5059 "tar: blocksize = %d\n"), i
);
5063 * If we are reading a tape, then a short read is
5064 * understood to signify that the amount read is
5065 * the tape's actual blocking factor. We adapt
5066 * nblock accordingly. There is no reason to do
5067 * this when the device is not blocked.
5077 copy(buffer
, &tbuf
[recno
++]);
5082 * replacement for writetape.
5086 writetbuf(char *buffer
, int n
)
5090 tapepos
+= n
; /* output block count */
5092 if (recno
>= nblock
) {
5093 i
= write(mt
, (char *)tbuf
, TBLOCK
*nblock
);
5094 if (i
!= TBLOCK
*nblock
)
5095 mterr("write", i
, 2);
5100 * Special case: We have an empty tape buffer, and the
5101 * users data size is >= the tape block size: Avoid
5102 * the bcopy and dma direct to tape. BIG WIN. Add the
5103 * residual to the tape buffer.
5105 while (recno
== 0 && n
>= nblock
) {
5106 i
= (int)write(mt
, buffer
, TBLOCK
*nblock
);
5107 if (i
!= TBLOCK
*nblock
)
5108 mterr("write", i
, 2);
5110 buffer
+= (nblock
* TBLOCK
);
5114 (void) memcpy((char *)&tbuf
[recno
++], buffer
, TBLOCK
);
5116 if (recno
>= nblock
) {
5117 i
= (int)write(mt
, (char *)tbuf
, TBLOCK
*nblock
);
5118 if (i
!= TBLOCK
*nblock
)
5119 mterr("write", i
, 2);
5124 /* Tell the user how much to write to get in sync */
5125 return (nblock
- recno
);
5129 * backtape - reposition tape after reading soft "EOF" record
5131 * Backtape tries to reposition the tape back over the EOF
5132 * record. This is for the 'u' and 'r' function letters so that the
5133 * tape can be extended. This code is not well designed, but
5134 * I'm confident that the only callers who care about the
5135 * backspace-over-EOF feature are those involved in 'u' and 'r'.
5137 * The proper way to backup the tape is through the use of mtio.
5138 * Earlier spins used lseek combined with reads in a confusing
5139 * maneuver that only worked on 4.x, but shouldn't have, even
5140 * there. Lseeks are explicitly not supported for tape devices.
5147 dlog("backtape() called, recno=%" FMT_blkcnt_t
" nblock=%d\n", recno
,
5150 * Backup to the position in the archive where the record
5151 * currently sitting in the tbuf buffer is situated.
5156 * For non-tape devices, this means lseeking to the
5157 * correct position. The absolute location tapepos-recno
5158 * should be the beginning of the current record.
5161 if (lseek(mt
, (off_t
)(TBLOCK
*(tapepos
-recno
)), SEEK_SET
) ==
5163 (void) fprintf(stderr
,
5164 gettext("tar: lseek to end of archive failed\n"));
5169 * For tape devices, we backup over the most recently
5173 mtcmd
.mt_op
= MTBSR
;
5176 if (ioctl(mt
, MTIOCTOP
, &mtcmd
) < 0) {
5177 (void) fprintf(stderr
,
5178 gettext("tar: backspace over record failed\n"));
5184 * Decrement the tape and tbuf buffer indices to prepare for the
5185 * coming write to overwrite the soft EOF record.
5194 * flushtape write buffered block(s) onto tape
5196 * recno points to next free block in tbuf. If nonzero, a write is done.
5197 * Care is taken to write in multiples of SYS_BLOCK when device is
5198 * non-magtape in case raw i/o is used.
5200 * NOTE: this is called by writetape() to do the actual writing
5206 dlog("flushtape() called, recno=%" FMT_blkcnt_t
"\n", recno
);
5207 if (recno
> 0) { /* anything buffered? */
5209 #if SYS_BLOCK > TBLOCK
5213 * an odd-block write can only happen when
5214 * we are at the end of a volume that is not a tape.
5215 * Here we round recno up to an even SYS_BLOCK
5218 if ((i
= recno
% (SYS_BLOCK
/ TBLOCK
)) != 0) {
5219 dlog("flushtape() %d rounding blocks\n", i
);
5220 recno
+= i
; /* round up to even SYS_BLOCK */
5226 dlog("writing out %" FMT_blkcnt_t
" blocks of %" FMT_blkcnt_t
5227 " bytes\n", (blkcnt_t
)(NotTape
? recno
: nblock
),
5228 (blkcnt_t
)(NotTape
? recno
: nblock
) * TBLOCK
);
5230 (size_t)(NotTape
? recno
: nblock
) * TBLOCK
) < 0) {
5231 (void) fprintf(stderr
, gettext(
5232 "tar: tape write error\n"));
5240 copy(void *dst
, void *src
)
5242 (void) memcpy(dst
, src
, TBLOCK
);
5247 * - checks the validity of size values for non-tape devices
5248 * - if size is zero, mulvol tar is disabled and size is
5249 * assumed to be infinite.
5250 * - returns volume size in TBLOCKS
5258 kval
= strtoll(kstr
, NULL
, 0);
5259 if (kval
== (blkcnt_t
)0) { /* no multi-volume; size is infinity. */
5260 mulvol
= 0; /* definitely not mulvol, but we must */
5261 return (0); /* took out setting of NotTape */
5263 if (kval
< (blkcnt_t
)MINSIZE
) {
5264 (void) fprintf(stderr
, gettext(
5265 "tar: sizes below %luK not supported (%" FMT_blkcnt_t
5266 ").\n"), (ulong_t
)MINSIZE
, kval
);
5267 (void) fprintf(stderr
, gettext(
5268 "bad size entry for %s in %s.\n"),
5273 NotTape
++; /* implies non-tape */
5274 return (kval
* 1024 / TBLOCK
); /* convert to TBLOCKS */
5280 * - checks the validity of blocking factors
5281 * - returns blocking factor
5289 bval
= strtoll(bstr
, NULL
, 0);
5290 if ((bval
<= 0) || (bval
> INT_MAX
/ TBLOCK
)) {
5291 (void) fprintf(stderr
, gettext(
5292 "tar: invalid blocksize \"%s\".\n"), bstr
);
5294 (void) fprintf(stderr
, gettext(
5295 "bad blocksize entry for '%s' in %s.\n"),
5306 * - reads DEF_FILE for the set of default values specified.
5307 * - initializes 'usefile', 'nblock', and 'blocklim', and 'NotTape'.
5308 * - 'usefile' points to static data, so will be overwritten
5309 * if this routine is called a second time.
5310 * - the pattern specified by 'arch' must be followed by four
5311 * blank-separated fields (1) device (2) blocking,
5312 * (3) size(K), and (4) tape
5313 * for example: archive0=/dev/fd 1 400 n
5321 if (defopen(DEF_FILE
) != 0)
5323 if (defcntl(DC_SETFLAGS
, (DC_STD
& ~(DC_CASE
))) == -1) {
5324 (void) fprintf(stderr
, gettext(
5325 "tar: error setting parameters for %s.\n"), DEF_FILE
);
5326 return (FALSE
); /* & following ones too */
5328 if ((bp
= defread(arch
)) == NULL
) {
5329 (void) fprintf(stderr
, gettext(
5330 "tar: missing or invalid '%s' entry in %s.\n"),
5334 if ((usefile
= strtok(bp
, " \t")) == NULL
) {
5335 (void) fprintf(stderr
, gettext(
5336 "tar: '%s' entry in %s is empty!\n"), arch
, DEF_FILE
);
5339 if ((bp
= strtok(NULL
, " \t")) == NULL
) {
5340 (void) fprintf(stderr
, gettext(
5341 "tar: block component missing in '%s' entry in %s.\n"),
5345 nblock
= bcheck(bp
);
5346 if ((bp
= strtok(NULL
, " \t")) == NULL
) {
5347 (void) fprintf(stderr
, gettext(
5348 "tar: size component missing in '%s' entry in %s.\n"),
5352 blocklim
= kcheck(bp
);
5353 if ((bp
= strtok(NULL
, " \t")) != NULL
)
5354 NotTape
= (*bp
== 'n' || *bp
== 'N');
5356 NotTape
= (blocklim
!= 0);
5357 (void) defopen(NULL
);
5358 dlog("defset: archive='%s'; usefile='%s'\n", arch
, usefile
);
5359 dlog("defset: nblock='%d'; blocklim='%" FMT_blkcnt_t
"'\n",
5361 dlog("defset: not tape = %d\n", NotTape
);
5367 * Following code handles excluded and included files.
5368 * A hash table of file names to be {in,ex}cluded is built.
5369 * For excluded files, before writing or extracting a file
5370 * check to see if it is in the exclude_tbl.
5371 * For included files, the wantit() procedure will check to
5372 * see if the named file is in the include_tbl.
5376 build_table(file_list_t
*table
[], char *file
)
5379 char buf
[PATH_MAX
+ 1];
5381 if ((fp
= fopen(file
, "r")) == (FILE *)NULL
)
5382 vperror(1, gettext("could not open %s"), file
);
5383 while (fgets(buf
, sizeof (buf
), fp
) != NULL
) {
5384 if (buf
[strlen(buf
) - 1] == '\n')
5385 buf
[strlen(buf
) - 1] = '\0';
5386 /* Only add to table if line has something in it */
5387 if (strspn(buf
, " \t") != strlen(buf
))
5388 add_file_to_table(table
, buf
);
5395 * Add a file name to the the specified table, if the file name has any
5396 * trailing '/'s then delete them before inserting into the table
5400 add_file_to_table(file_list_t
*table
[], char *str
)
5402 char name
[PATH_MAX
+ 1];
5406 (void) strcpy(name
, str
);
5407 while (name
[strlen(name
) - 1] == '/') {
5408 name
[strlen(name
) - 1] = '\0';
5412 if ((exp
= (file_list_t
*)calloc(sizeof (file_list_t
),
5413 sizeof (char))) == NULL
) {
5414 (void) fprintf(stderr
, gettext(
5415 "tar: out of memory, exclude/include table(entry)\n"));
5419 if ((exp
->name
= strdup(name
)) == NULL
) {
5420 (void) fprintf(stderr
, gettext(
5421 "tar: out of memory, exclude/include table(file name)\n"));
5425 exp
->next
= table
[h
];
5431 * See if a file name or any of the file's parent directories is in the
5432 * specified table, if the file name has any trailing '/'s then delete
5433 * them before searching the table
5437 is_in_table(file_list_t
*table
[], char *str
)
5439 char name
[PATH_MAX
+ 1];
5444 (void) strcpy(name
, str
);
5445 while (name
[strlen(name
) - 1] == '/') {
5446 name
[strlen(name
) - 1] = '\0';
5450 * check for the file name in the passed list
5454 while (exp
!= NULL
) {
5455 if (strcmp(name
, exp
->name
) == 0) {
5462 * check for any parent directories in the file list
5464 while ((ptr
= strrchr(name
, '/'))) {
5468 while (exp
!= NULL
) {
5469 if (strcmp(name
, exp
->name
) == 0) {
5481 * Compute a hash from a string.
5491 for (cp
= str
; *cp
; cp
++) {
5494 return (h
% TABLE_SIZE
);
5500 void *p
= calloc((unsigned)size
, sizeof (char));
5502 if (p
== NULL
&& freemem
) {
5503 (void) fprintf(stderr
, gettext(
5504 "tar: out of memory, link and directory modtime "
5516 * vperror() --variable argument perror.
5517 * Takes 3 args: exit_status, formats, args. If exit_status is 0, then
5518 * the errflag (exit on error) is checked -- if it is non-zero, tar exits
5519 * with the value of whatever "errno" is set to. If exit_status is not
5520 * zero, then tar exits with that error status. If errflag and exit_status
5521 * are both zero, the routine returns to where it was called and sets Errflg
5526 vperror(int exit_status
, char *fmt
, ...)
5531 (void) fputs("tar: ", stderr
);
5532 (void) vfprintf(stderr
, fmt
, ap
);
5533 (void) fprintf(stderr
, ": %s\n", strerror(errno
));
5546 fatal(char *format
, ...)
5550 va_start(ap
, format
);
5551 (void) fprintf(stderr
, "tar: ");
5552 (void) vfprintf(stderr
, format
, ap
);
5553 (void) fprintf(stderr
, "\n");
5560 * Check to make sure that argument is a char * ptr.
5561 * Actually, we just check to see that it is non-null.
5562 * If it is null, print out the message and call usage(), bailing out.
5566 assert_string(char *s
, char *msg
)
5569 (void) fprintf(stderr
, msg
);
5576 mterr(char *operation
, int i
, int exitcode
)
5578 (void) fprintf(stderr
, gettext(
5579 "tar: %s error: "), operation
);
5583 (void) fprintf(stderr
, gettext("unexpected EOF\n"));
5588 wantit(char *argv
[], char **namep
, char **dirp
, char **component
,
5589 attr_data_t
**attrinfo
)
5592 int gotit
; /* true if we've found a match */
5596 if (xhdr_flgs
& _X_XHDR
) {
5602 if (ret
!= 0) { /* Xhdr items and regular header */
5603 setbytes_to_skip(&stbuf
, ret
);
5605 return (0); /* Error--don't want to extract */
5610 * If typeflag is not 'A' and xhdr_flgs is set, then processing
5611 * of ancillary file is either over or ancillary file
5612 * processing is not required, load info from Xtarhdr and set
5613 * _X_XHDR bit in xhdr_flgs.
5615 if ((dblock
.dbuf
.typeflag
!= 'A') && (xhdr_flgs
!= 0)) {
5616 load_info_from_xtarhdr(xhdr_flgs
, &Xtarhdr
);
5617 xhdr_flgs
|= _X_XHDR
;
5620 #if defined(O_XATTR)
5621 if (dblock
.dbuf
.typeflag
== _XATTR_HDRTYPE
&& xattrbadhead
== 0) {
5623 * Always needs to read the extended header. If atflag, saflag,
5624 * or tflag isn't set, then we'll have the correct info for
5627 (void) read_xattr_hdr(attrinfo
);
5631 * Now that we've read the extended header, call passtape()
5632 * if we don't want to restore attributes or system attributes.
5633 * Don't restore the attribute if we are extracting
5634 * a file from an archive (as opposed to doing a table of
5635 * contents) and any of the following are true:
5636 * 1. neither -@ or -/ was specified.
5637 * 2. -@ was specified, -/ wasn't specified, and we're
5638 * processing a hidden attribute directory of an attribute
5639 * or we're processing a read-write system attribute file.
5640 * 3. -@ wasn't specified, -/ was specified, and the file
5641 * we're processing is not a read-write system attribute file,
5642 * or we're processing the hidden attribute directory of an
5645 * We always process the attributes if we're just generating
5646 * generating a table of contents, or if both -@ and -/ were
5649 if (xattrp
!= NULL
) {
5650 attr_data_t
*ainfo
= *attrinfo
;
5653 ((!atflag
&& !saflag
) ||
5654 (atflag
&& !saflag
&& ((ainfo
->attr_parent
!= NULL
) ||
5655 ainfo
->attr_rw_sysattr
)) ||
5656 (!atflag
&& saflag
&& ((ainfo
->attr_parent
!= NULL
) ||
5657 !ainfo
->attr_rw_sysattr
)))) {
5664 /* sets *namep to point at the proper name */
5665 if (check_prefix(namep
, dirp
, component
) != 0) {
5673 size_t extra_blocks
= 0;
5676 * Logically at EOT - consume any extra blocks
5677 * so that write to our stdin won't fail and
5678 * emit an error message; otherwise something
5679 * like "dd if=foo.tar | (cd bar; tar xvf -)"
5680 * will produce a bogus error message from "dd".
5683 while ((sz
= read(mt
, tbuf
, TBLOCK
*nblock
)) > 0) {
5686 dlog("wantit(): %d bytes of extra blocks\n",
5689 dlog("wantit(): at end of tape.\n");
5695 if ((Iflag
&& is_in_table(include_tbl
, *namep
)) ||
5696 (! Iflag
&& *argv
== NULL
)) {
5699 for (cp
= argv
; *cp
; cp
++) {
5700 if (is_prefix(*cp
, *namep
)) {
5712 if (Xflag
&& is_in_table(exclude_tbl
, *namep
)) {
5714 (void) fprintf(stderr
, gettext("%s excluded\n"),
5726 setbytes_to_skip(struct stat
*st
, int err
)
5729 * In a scenario where a typeflag 'X' was followed by
5730 * a typeflag 'A' and typeflag 'O', then the number of
5731 * bytes to skip should be the size of ancillary file,
5732 * plus the dblock for regular file, and the size
5733 * from Xtarhdr. However, if the typeflag was just 'X'
5734 * followed by typeflag 'O', then the number of bytes
5735 * to skip should be the size from Xtarhdr.
5737 if ((err
!= 0) && (dblock
.dbuf
.typeflag
== 'A') &&
5738 (xhdr_flgs
& _X_SIZE
)) {
5739 st
->st_size
+= TBLOCK
+ Xtarhdr
.x_filesz
;
5740 xhdr_flgs
|= _X_XHDR
;
5741 } else if ((dblock
.dbuf
.typeflag
!= 'A') &&
5742 (xhdr_flgs
& _X_SIZE
)) {
5743 st
->st_size
+= Xtarhdr
.x_filesz
;
5744 xhdr_flgs
|= _X_XHDR
;
5749 fill_in_attr_info(char *attr
, char *longname
, char *attrparent
, int atparentfd
,
5750 int rw_sysattr
, attr_data_t
**attrinfo
)
5757 if (attrparent
!= NULL
) {
5758 if ((tparent
= strdup(attrparent
)) == NULL
) {
5760 "unable to allocate memory for attribute parent "
5761 "name for %sattribute %s/%s of %s"),
5762 rw_sysattr
? gettext("system ") : "",
5763 attrparent
, attr
, longname
);
5771 pathlen
= strlen(attr
) + 1;
5772 if (attrparent
!= NULL
) {
5773 pathlen
+= strlen(attrparent
) + 1; /* add 1 for '/' */
5775 if ((tpath
= calloc(1, pathlen
)) == NULL
) {
5777 "unable to allocate memory for full "
5778 "attribute path name for %sattribute %s%s%s of %s"),
5779 rw_sysattr
? gettext("system ") : "",
5780 (attrparent
== NULL
) ? "" : attrparent
,
5781 (attrparent
== NULL
) ? "" : "/",
5783 if (tparent
!= NULL
) {
5788 (void) snprintf(tpath
, pathlen
, "%s%s%s",
5789 (attrparent
== NULL
) ? "" : attrparent
,
5790 (attrparent
== NULL
) ? "" : "/",
5793 /* fill in the attribute info */
5794 if (*attrinfo
== NULL
) {
5795 if ((*attrinfo
= malloc(sizeof (attr_data_t
))) == NULL
) {
5797 "unable to allocate memory for attribute "
5798 "information for %sattribute %s%s%s of %s"),
5799 rw_sysattr
? gettext("system ") : "",
5800 (attrparent
== NULL
) ? "" : attrparent
,
5801 (attrparent
== NULL
) ? "" : gettext("/"),
5803 if (tparent
!= NULL
) {
5810 if ((*attrinfo
)->attr_parent
!= NULL
) {
5811 free((*attrinfo
)->attr_parent
);
5813 if ((*attrinfo
)->attr_path
!= NULL
) {
5814 free((*attrinfo
)->attr_path
);
5817 * The parent file descriptor is passed in, so don't
5818 * close it here as it should be closed by the function
5822 (*attrinfo
)->attr_parent
= tparent
;
5823 (*attrinfo
)->attr_path
= tpath
;
5824 (*attrinfo
)->attr_rw_sysattr
= rw_sysattr
;
5825 (*attrinfo
)->attr_parentfd
= atparentfd
;
5831 * Test to see if name is a directory.
5833 * Return 1 if true, 0 otherwise.
5837 is_directory(char *name
)
5839 #if defined(O_XATTR)
5841 * If there is an xattr_buf structure associated with this file,
5842 * then the directory test is based on whether the name has a
5846 return (name
[strlen(name
) - 1] == '/');
5849 return (dblock
.dbuf
.typeflag
== '5');
5851 return (name
[strlen(name
) - 1] == '/');
5855 * Version of chdir that handles directory pathnames of greater than PATH_MAX
5856 * length, by changing the working directory to manageable portions of the
5857 * complete directory pathname. If any of these attempts fail, then it exits
5860 * If a segment (i.e. a portion of "path" between two "/"'s) of the overall
5861 * pathname is greater than PATH_MAX, then this still won't work, and this
5862 * routine will return -1 with errno set to ENAMETOOLONG.
5864 * NOTE: this routine is semantically different to the system chdir in
5865 * that it is remotely possible for the currently working directory to be
5866 * changed to a different directory, if a chdir call fails when processing
5867 * one of the segments of a path that is greater than PATH_MAX. This isn't
5868 * a problem as this is tar's own specific version of chdir.
5872 tar_chdir(const char *path
)
5874 const char *sep
= "/";
5875 char *path_copy
= NULL
;
5878 /* The trivial case. */
5879 if (chdir(path
) == 0) {
5882 if (errno
== ENAMETOOLONG
) {
5883 if (path
[0] == '/' && chdir(sep
) != 0)
5886 /* strtok(3C) modifies the string, so make a copy. */
5887 if ((path_copy
= strdup(path
)) == NULL
) {
5891 /* chdir(2) for every path element. */
5892 for (ptr
= strtok(path_copy
, sep
);
5894 ptr
= strtok(NULL
, sep
)) {
5895 if (chdir(ptr
) != 0) {
5904 /* If chdir fails for any reason except ENAMETOOLONG. */
5909 * Test if name has a '..' sequence in it.
5911 * Return 1 if found, 0 otherwise.
5915 has_dot_dot(char *name
)
5918 size_t name_len
= strlen(name
);
5920 for (s
= name
; s
< (name
+ name_len
- 2); s
++) {
5921 if (s
[0] == '.' && s
[1] == '.' && ((s
[2] == '/') || !s
[2]))
5924 while (! (*s
== '/')) {
5934 * Test if name is an absolute path name.
5936 * Return 1 if true, 0 otherwise.
5940 is_absolute(char *name
)
5942 #if defined(O_XATTR)
5944 * If this is an extended attribute (whose name will begin with
5945 * "/dev/null/", always return 0 as they should be extracted with
5946 * the name intact, to allow other tar archiving programs that
5947 * don't understand extended attributes, to correctly throw them away.
5953 return (name
[0] == '/');
5957 * Adjust the pathname to make it a relative one. Strip off any leading
5958 * '/' characters and if the pathname contains any '..' sequences, strip
5959 * upto and including the last occurance of '../' (or '..' if found at
5960 * the very end of the pathname).
5962 * Return the relative pathname. stripped_prefix will also return the
5963 * portion of name that was stripped off and should be freed by the
5964 * calling routine when no longer needed.
5968 make_relative_name(char *name
, char **stripped_prefix
)
5971 size_t prefix_len
= 0;
5972 size_t name_len
= strlen(name
);
5974 for (s
= name
+ prefix_len
; s
< (name
+ name_len
- 2); ) {
5975 if (s
[0] == '.' && s
[1] == '.' && ((s
[2] == '/') || !s
[2]))
5976 prefix_len
= s
+ 2 - name
;
5986 for (s
= name
+ prefix_len
; *s
== '/'; s
++)
5988 prefix_len
= s
- name
;
5990 /* Create the portion of the name that was stripped off. */
5991 s
= malloc(prefix_len
+ 1);
5992 memcpy(s
, name
, prefix_len
);
5994 *stripped_prefix
= s
;
5995 s
= &name
[prefix_len
];
6001 * Return through *namep a pointer to the proper fullname (i.e "<name> |
6002 * <prefix>/<name>"), as represented in the header entry dblock.dbuf.
6004 * Returns 0 if successful, otherwise returns 1.
6008 check_prefix(char **namep
, char **dirp
, char **compp
)
6010 static char fullname
[PATH_MAX
+ 1];
6011 static char dir
[PATH_MAX
+ 1];
6012 static char component
[PATH_MAX
+ 1];
6013 static char savename
[PATH_MAX
+ 1];
6016 (void) memset(dir
, 0, sizeof (dir
));
6017 (void) memset(component
, 0, sizeof (component
));
6019 if (xhdr_flgs
& _X_PATH
) {
6020 (void) strcpy(fullname
, Xtarhdr
.x_path
);
6022 if (dblock
.dbuf
.prefix
[0] != '\0')
6023 (void) sprintf(fullname
, "%.*s/%.*s", PRESIZ
,
6024 dblock
.dbuf
.prefix
, NAMSIZ
, dblock
.dbuf
.name
);
6026 (void) sprintf(fullname
, "%.*s", NAMSIZ
,
6031 * If we are printing a table of contents or extracting an archive,
6032 * make absolute pathnames relative and prohibit the unpacking of
6033 * files contain ".." in their name (unless the user has supplied
6036 if ((tflag
|| xflag
) && !Pflag
) {
6037 if (is_absolute(fullname
) || has_dot_dot(fullname
)) {
6038 char *stripped_prefix
;
6040 (void) strcpy(savename
, fullname
);
6042 make_relative_name(savename
, &stripped_prefix
));
6043 (void) fprintf(stderr
,
6044 gettext("tar: Removing leading '%s' from '%s'\n"),
6045 stripped_prefix
, savename
);
6046 free(stripped_prefix
);
6051 * Set dir and component names
6054 get_parent(fullname
, dir
);
6056 #if defined(O_XATTR)
6057 if (xattrp
== NULL
) {
6060 * Save of real name since were going to chop off the
6063 (void) strcpy(savename
, fullname
);
6065 * first strip of trailing slashes.
6067 chop_endslashes(savename
);
6068 s
= get_component(savename
);
6069 (void) strcpy(component
, s
);
6071 #if defined(O_XATTR)
6073 (void) strcpy(fullname
, xattrp
->h_names
);
6074 (void) strcpy(dir
, fullname
);
6075 (void) strcpy(component
, basename(xattrp
->h_names
+
6076 strlen(xattrp
->h_names
) + 1));
6087 * Return true if the object indicated by the file descriptor and type
6088 * is a tape device, false otherwise
6092 istape(int fd
, int type
)
6096 if (S_ISCHR(type
)) {
6099 if (ioctl(fd
, MTIOCGET
, &mtg
) != -1) {
6111 #define NMAX (sizeof (utmpx.ut_name))
6113 typedef struct cachenode
{ /* this struct must be zeroed before using */
6114 struct cachenode
*next
; /* next in hash chain */
6115 int val
; /* the uid or gid of this entry */
6116 int namehash
; /* name's hash signature */
6117 char name
[NMAX
+1]; /* the string that val maps to */
6120 #define HASHSIZE 256
6122 static cachenode_t
*names
[HASHSIZE
];
6123 static cachenode_t
*groups
[HASHSIZE
];
6124 static cachenode_t
*uids
[HASHSIZE
];
6125 static cachenode_t
*gids
[HASHSIZE
];
6128 hash_byname(char *name
)
6132 for (i
= 0; i
< NMAX
; i
++) {
6136 h
= (h
<< 4) + h
+ c
;
6141 static cachenode_t
*
6142 hash_lookup_byval(cachenode_t
*table
[], int val
)
6147 for (c
= table
[h
& (HASHSIZE
- 1)]; c
!= NULL
; c
= c
->next
) {
6154 static cachenode_t
*
6155 hash_lookup_byname(cachenode_t
*table
[], char *name
)
6157 int h
= hash_byname(name
);
6160 for (c
= table
[h
& (HASHSIZE
- 1)]; c
!= NULL
; c
= c
->next
) {
6161 if (c
->namehash
== h
&& strcmp(c
->name
, name
) == 0)
6167 static cachenode_t
*
6168 hash_insert(cachenode_t
*table
[], char *name
, int value
)
6173 c
= calloc(1, sizeof (cachenode_t
));
6179 (void) strncpy(c
->name
, name
, NMAX
);
6180 c
->namehash
= hash_byname(name
);
6183 if (table
== uids
|| table
== gids
)
6186 signature
= c
->namehash
;
6187 c
->next
= table
[signature
& (HASHSIZE
- 1)];
6188 table
[signature
& (HASHSIZE
- 1)] = c
;
6197 if ((c
= hash_lookup_byval(uids
, uid
)) == NULL
) {
6198 struct passwd
*pwent
= getpwuid(uid
);
6199 c
= hash_insert(uids
, pwent
? pwent
->pw_name
: NULL
, uid
);
6209 if ((c
= hash_lookup_byval(gids
, gid
)) == NULL
) {
6210 struct group
*grent
= getgrgid(gid
);
6211 c
= hash_insert(gids
, grent
? grent
->gr_name
: NULL
, gid
);
6217 getuidbyname(char *name
)
6221 if ((c
= hash_lookup_byname(names
, name
)) == NULL
) {
6222 struct passwd
*pwent
= getpwnam(name
);
6223 c
= hash_insert(names
, name
, pwent
? (int)pwent
->pw_uid
: -1);
6225 return ((uid_t
)c
->val
);
6229 getgidbyname(char *group
)
6233 if ((c
= hash_lookup_byname(groups
, group
)) == NULL
) {
6234 struct group
*grent
= getgrnam(group
);
6235 c
= hash_insert(groups
, group
, grent
? (int)grent
->gr_gid
: -1);
6237 return ((gid_t
)c
->val
);
6242 * Determine whether or not an extended header is also needed. If needed,
6243 * create and write the extended header and its data.
6244 * Writing of the extended header assumes that "tomodes" has been called and
6245 * the relevant information has been placed in the header block.
6251 const char *linkname
,
6252 const char typeflag
,
6254 const struct stat
*sp
,
6260 const char *filename
;
6261 const char *lastslash
;
6263 if (filetype
== XATTR_FILE
)
6264 dblock
.dbuf
.typeflag
= _XATTR_HDRTYPE
;
6266 dblock
.dbuf
.typeflag
= typeflag
;
6267 (void) memset(dblock
.dbuf
.name
, '\0', NAMSIZ
);
6268 (void) memset(dblock
.dbuf
.linkname
, '\0', NAMSIZ
);
6269 (void) memset(dblock
.dbuf
.prefix
, '\0', PRESIZ
);
6271 if (xhdr_flgs
& _X_PATH
)
6272 filename
= Xtarhdr
.x_path
;
6276 if ((dev
= major(device
)) > OCTAL7CHAR
) {
6278 xhdr_flgs
|= _X_DEVMAJOR
;
6279 Xtarhdr
.x_devmajor
= dev
;
6281 (void) fprintf(stderr
, gettext(
6282 "Device major too large for %s. Use -E flag."),
6291 (void) sprintf(dblock
.dbuf
.devmajor
, "%07lo", dev
);
6292 if ((dev
= minor(device
)) > OCTAL7CHAR
) {
6294 xhdr_flgs
|= _X_DEVMINOR
;
6295 Xtarhdr
.x_devminor
= dev
;
6297 (void) fprintf(stderr
, gettext(
6298 "Device minor too large for %s. Use -E flag."),
6307 (void) sprintf(dblock
.dbuf
.devminor
, "%07lo", dev
);
6309 (void) strncpy(dblock
.dbuf
.name
, name
, NAMSIZ
);
6310 (void) strncpy(dblock
.dbuf
.linkname
, linkname
, NAMSIZ
);
6311 (void) sprintf(dblock
.dbuf
.magic
, "%.5s", magic_type
);
6312 (void) sprintf(dblock
.dbuf
.version
, "00");
6313 (void) sprintf(dblock
.dbuf
.uname
, "%.31s", getname(sp
->st_uid
));
6314 (void) sprintf(dblock
.dbuf
.gname
, "%.31s", getgroup(sp
->st_gid
));
6315 (void) strncpy(dblock
.dbuf
.prefix
, prefix
, PRESIZ
);
6316 (void) sprintf(dblock
.dbuf
.chksum
, "%07o", checksum(&dblock
));
6319 (void) bcopy(dblock
.dummy
, xhdr_buf
.dummy
, TBLOCK
);
6320 (void) memset(xhdr_buf
.dbuf
.name
, '\0', NAMSIZ
);
6321 lastslash
= strrchr(name
, '/');
6322 if (lastslash
== NULL
)
6326 (void) strcpy(xhdr_buf
.dbuf
.name
, lastslash
);
6327 (void) memset(xhdr_buf
.dbuf
.linkname
, '\0', NAMSIZ
);
6328 (void) memset(xhdr_buf
.dbuf
.prefix
, '\0', PRESIZ
);
6329 (void) strcpy(xhdr_buf
.dbuf
.prefix
, xhdr_dirname
);
6332 gen_date("mtime", sp
->st_mtim
);
6333 xhdr_buf
.dbuf
.typeflag
= 'X';
6334 if (gen_utf8_names(filename
) != 0)
6338 Xtarhdr
.x_uname
= dblock
.dbuf
.uname
;
6339 Xtarhdr
.x_gname
= dblock
.dbuf
.gname
;
6340 xhdr_flgs
|= (_X_UNAME
| _X_GNAME
);
6343 if (xhdr_flgs
& _X_DEVMAJOR
)
6344 gen_num("SUN.devmajor", Xtarhdr
.x_devmajor
);
6345 if (xhdr_flgs
& _X_DEVMINOR
)
6346 gen_num("SUN.devminor", Xtarhdr
.x_devminor
);
6347 if (xhdr_flgs
& _X_GID
)
6348 gen_num("gid", Xtarhdr
.x_gid
);
6349 if (xhdr_flgs
& _X_UID
)
6350 gen_num("uid", Xtarhdr
.x_uid
);
6351 if (xhdr_flgs
& _X_SIZE
)
6352 gen_num("size", Xtarhdr
.x_filesz
);
6353 if (xhdr_flgs
& _X_PATH
)
6354 gen_string("path", Xtarhdr
.x_path
);
6355 if (xhdr_flgs
& _X_LINKPATH
)
6356 gen_string("linkpath", Xtarhdr
.x_linkpath
);
6357 if (xhdr_flgs
& _X_GNAME
)
6358 gen_string("gname", Xtarhdr
.x_gname
);
6359 if (xhdr_flgs
& _X_UNAME
)
6360 gen_string("uname", Xtarhdr
.x_uname
);
6362 (void) sprintf(xhdr_buf
.dbuf
.size
,
6363 "%011" FMT_off_t_o
, xrec_offset
);
6364 (void) sprintf(xhdr_buf
.dbuf
.chksum
, "%07o",
6365 checksum(&xhdr_buf
));
6366 (void) writetbuf((char *)&xhdr_buf
, 1);
6367 nblks
= TBLOCKS(xrec_offset
);
6368 (void) writetbuf(xrec_ptr
, nblks
);
6375 * makeDir - ensure that a directory with the pathname denoted by name
6376 * exists, and return 1 on success, and 0 on failure (e.g.,
6377 * read-only file system, exists but not-a-directory).
6385 if (access(name
, 0) < 0) { /* name doesn't exist */
6386 if (mkdir(name
, 0777) < 0) {
6387 vperror(0, "%s", name
);
6390 } else { /* name exists */
6391 if (stat(name
, &buf
) < 0) {
6392 vperror(0, "%s", name
);
6396 return ((buf
.st_mode
& S_IFMT
) == S_IFDIR
);
6404 * Save this directory and its mtime on the stack, popping and setting
6405 * the mtimes of any stacked dirs which aren't parents of this one.
6406 * A null name causes the entire stack to be unwound and set.
6408 * Since all the elements of the directory "stack" share a common
6409 * prefix, we can make do with one string. We keep only the current
6410 * directory path, with an associated array of mtime's. A negative
6411 * mtime means no mtime.
6413 * This stack algorithm is not guaranteed to work for tapes created
6414 * with the 'r' function letter, but the vast majority of tapes with
6415 * directories are not. This avoids saving every directory record on
6416 * the tape and setting all the times at the end.
6418 * (This was borrowed from the 4.1.3 source, and adapted to the 5.x
6423 doDirTimes(char *name
, timestruc_t modTime
)
6425 static char dirstack
[PATH_MAX
+2];
6426 /* Add spaces for the last slash and last NULL */
6427 static timestruc_t modtimes
[PATH_MAX
+1]; /* hash table */
6434 * Find common prefix
6437 while (*p
== *q
&& *p
) {
6445 * Not a child: unwind the stack, setting the times.
6446 * The order we do this doesn't matter, so we go "forward."
6450 if (modtimes
[p
- dirstack
].tv_sec
>= 0) {
6451 *p
= '\0'; /* zap the slash */
6452 setPathTimes(AT_FDCWD
, dirstack
,
6453 modtimes
[p
- dirstack
]);
6462 * Push this one on the "stack"
6468 * Since the name parameter points the dir pathname
6469 * which is limited only to contain PATH_MAX chars
6470 * at maximum, we can ignore the overflow case of p.
6473 while ((*p
= *q
++)) { /* append the rest of the new dir */
6474 modtimes
[p
- dirstack
].tv_sec
= -1;
6479 * If the tar file had used 'P' or 'E' function modifier,
6480 * append the last slash.
6482 if (*(p
- 1) != '/') {
6486 /* overwrite the last one */
6487 modtimes
[p
- dirstack
- 1] = modTime
;
6493 * setPathTimes - set the modification time for given path. Return 1 if
6494 * successful and 0 if not successful.
6498 setPathTimes(int dirfd
, char *path
, timestruc_t modTime
)
6500 struct timeval timebuf
[2];
6503 * futimesat takes an array of two timeval structs.
6504 * The first entry contains access time.
6505 * The second entry contains modification time.
6506 * Unlike a timestruc_t, which uses nanoseconds, timeval uses
6509 timebuf
[0].tv_sec
= time((time_t *)0);
6510 timebuf
[0].tv_usec
= 0;
6511 timebuf
[1].tv_sec
= modTime
.tv_sec
;
6513 /* Extended header: use microseconds */
6514 timebuf
[1].tv_usec
= (xhdr_flgs
& _X_MTIME
) ? modTime
.tv_nsec
/1000 : 0;
6516 if (futimesat(dirfd
, path
, timebuf
) < 0)
6517 vperror(0, gettext("can't set time on %s"), path
);
6522 * If hflag is set then delete the symbolic link's target.
6523 * If !hflag then delete the target.
6527 delete_target(int fd
, char *comp
, char *namep
)
6529 struct stat xtractbuf
;
6530 char buf
[PATH_MAX
+ 1];
6534 if (unlinkat(fd
, comp
, AT_REMOVEDIR
) < 0) {
6535 if (errno
== ENOTDIR
&& !hflag
) {
6536 (void) unlinkat(fd
, comp
, 0);
6537 } else if (errno
== ENOTDIR
&& hflag
) {
6538 if (!lstat(namep
, &xtractbuf
)) {
6539 if ((xtractbuf
.st_mode
& S_IFMT
) != S_IFLNK
) {
6540 (void) unlinkat(fd
, comp
, 0);
6541 } else if ((n
= readlink(namep
, buf
,
6544 (void) unlinkat(fd
, buf
,
6546 if (errno
== ENOTDIR
)
6547 (void) unlinkat(fd
, buf
, 0);
6549 (void) unlinkat(fd
, comp
, 0);
6552 (void) unlinkat(fd
, comp
, 0);
6562 * Get acl info after stat. Write out ancillary file
6563 * before the normal file, i.e. directory, regular, FIFO,
6564 * link, special. If acl count is less than 4, no need to
6565 * create ancillary file. (i.e. standard permission is in
6568 * Process ancillary file. Read it in and set acl info.
6569 * watch out for 'o' function modifier.
6570 * 't' function letter to display table
6574 * New functions for ACLs and other security attributes
6578 * The function appends the new security attribute info to the end of
6583 char **secinfo
, /* existing security info */
6584 int *secinfo_len
, /* length of existing security info */
6585 int size
, /* new attribute size: unit depends on type */
6586 char *attrtext
, /* new attribute text */
6587 char attr_type
) /* new attribute type */
6592 struct sec_attr
*attr
;
6594 if (attrtext
== NULL
)
6597 switch (attr_type
) {
6600 if (attrtext
== NULL
) {
6601 (void) fprintf(stderr
, gettext("acltotext failed\n"));
6604 /* header: type + size = 8 */
6605 newattrsize
= 8 + (int)strlen(attrtext
) + 1;
6606 attr
= (struct sec_attr
*)malloc(newattrsize
);
6608 (void) fprintf(stderr
,
6609 gettext("can't allocate memory\n"));
6612 attr
->attr_type
= attr_type
;
6613 (void) sprintf(attr
->attr_len
,
6614 "%06o", size
); /* acl entry count */
6615 (void) strcpy((char *)&attr
->attr_info
[0], attrtext
);
6619 (void) fprintf(stderr
,
6620 gettext("unrecognized attribute type\n"));
6624 /* old security info + new attr header(8) + new attr */
6625 oldsize
= *secinfo_len
;
6626 *secinfo_len
+= newattrsize
;
6627 new_secinfo
= (char *)malloc(*secinfo_len
);
6628 if (new_secinfo
== NULL
) {
6629 (void) fprintf(stderr
, gettext("can't allocate memory\n"));
6630 *secinfo_len
-= newattrsize
;
6635 (void) memcpy(new_secinfo
, *secinfo
, oldsize
);
6636 (void) memcpy(new_secinfo
+ oldsize
, attr
, newattrsize
);
6640 *secinfo
= new_secinfo
;
6645 * write_ancillary(): write out an ancillary file.
6646 * The file has the same header as normal file except the type and size
6647 * fields. The type is 'A' and size is the sum of all attributes
6649 * The body contains a list of attribute type, size and info. Currently,
6650 * there is only ACL info. This file is put before the normal file.
6653 write_ancillary(union hblock
*dblockp
, char *secinfo
, int len
, char hdrtype
)
6659 /* Just tranditional permissions or no security attribute info */
6660 if (len
== 0 || secinfo
== NULL
)
6663 /* save flag and size */
6664 savflag
= (dblockp
->dbuf
).typeflag
;
6665 (void) sscanf(dblockp
->dbuf
.size
, "%12o", (uint_t
*)&savsize
);
6667 /* special flag for ancillary file */
6668 if (hdrtype
== _XATTR_HDRTYPE
)
6669 dblockp
->dbuf
.typeflag
= _XATTR_HDRTYPE
;
6671 dblockp
->dbuf
.typeflag
= 'A';
6673 /* for pre-2.5 versions of tar, need to make sure */
6674 /* the ACL file is readable */
6675 (void) sprintf(dblock
.dbuf
.mode
, "%07lo",
6676 (stbuf
.st_mode
& POSIXMODES
) | 0000200);
6677 (void) sprintf(dblockp
->dbuf
.size
, "%011o", len
);
6678 (void) sprintf(dblockp
->dbuf
.chksum
, "%07o", checksum(dblockp
));
6680 /* write out the header */
6681 (void) writetbuf((char *)dblockp
, 1);
6683 /* write out security info */
6684 blocks
= TBLOCKS(len
);
6685 (void) writetbuf((char *)secinfo
, (int)blocks
);
6687 /* restore mode, flag and size */
6688 (void) sprintf(dblock
.dbuf
.mode
, "%07lo", stbuf
.st_mode
& POSIXMODES
);
6689 dblockp
->dbuf
.typeflag
= savflag
;
6690 (void) sprintf(dblockp
->dbuf
.size
, "%011o", savsize
);
6694 * Read the data record for extended headers and then the regular header.
6695 * The data are read into the buffer and then null-terminated. Entries
6696 * for typeflag 'X' extended headers are of the format:
6699 * When an extended header record is found, the extended header must
6700 * be processed and its values used to override the values in the
6701 * normal header. The way this is done is to process the extended
6702 * header data record and set the data values, then call getdir
6703 * to process the regular header, then then to reconcile the two
6710 struct keylist_pair
{
6713 } keylist_pair
[] = { _X_DEVMAJOR
, "SUN.devmajor",
6714 _X_DEVMINOR
, "SUN.devminor",
6717 _X_LINKPATH
, "linkpath",
6726 char *keyword
, *value
;
6731 (void) memset(&Xtarhdr
, 0, sizeof (Xtarhdr
));
6735 nblocks
= TBLOCKS(stbuf
.st_size
);
6736 bufneeded
= nblocks
* TBLOCK
;
6737 if (bufneeded
>= xrec_size
) {
6739 xrec_size
= bufneeded
+ 1;
6740 if ((xrec_ptr
= malloc(xrec_size
)) == NULL
)
6741 fatal(gettext("cannot allocate buffer"));
6746 while (nblocks
-- > 0) {
6751 xrec_ptr
[stbuf
.st_size
] = '\0';
6752 while (lineloc
< xrec_ptr
+ stbuf
.st_size
) {
6753 if (dblock
.dbuf
.typeflag
== 'L') {
6758 length
= atoi(lineloc
);
6759 *(lineloc
+ length
- 1) = '\0';
6760 keyword
= strchr(lineloc
, ' ') + 1;
6761 value
= strchr(keyword
, '=') + 1;
6762 *(value
- 1) = '\0';
6766 while (keylist_pair
[i
].keynum
!= (int)_X_LAST
) {
6767 if (strcmp(keyword
, keylist_pair
[i
].keylist
) == 0)
6772 switch (keylist_pair
[i
].keynum
) {
6774 Xtarhdr
.x_devmajor
= (major_t
)strtoul(value
, NULL
, 0);
6776 (void) fprintf(stderr
, gettext(
6777 "tar: Extended header major value error "
6778 "for file # %llu.\n"), xhdr_count
);
6781 xhdr_flgs
|= _X_DEVMAJOR
;
6784 Xtarhdr
.x_devminor
= (minor_t
)strtoul(value
, NULL
, 0);
6786 (void) fprintf(stderr
, gettext(
6787 "tar: Extended header minor value error "
6788 "for file # %llu.\n"), xhdr_count
);
6791 xhdr_flgs
|= _X_DEVMINOR
;
6794 xhdr_flgs
|= _X_GID
;
6795 Xtarhdr
.x_gid
= strtol(value
, NULL
, 0);
6796 if ((errno
) || (Xtarhdr
.x_gid
> UID_MAX
)) {
6797 (void) fprintf(stderr
, gettext(
6798 "tar: Extended header gid value error "
6799 "for file # %llu.\n"), xhdr_count
);
6800 Xtarhdr
.x_gid
= GID_NOBODY
;
6804 if (utf8_local("gname", &Xtarhdr
.x_gname
,
6805 local_gname
, value
, _POSIX_NAME_MAX
) == 0)
6806 xhdr_flgs
|= _X_GNAME
;
6809 if (utf8_local("linkpath", &Xtarhdr
.x_linkpath
,
6810 local_linkpath
, value
, PATH_MAX
) == 0)
6811 xhdr_flgs
|= _X_LINKPATH
;
6816 if (utf8_local("path", &Xtarhdr
.x_path
,
6817 local_path
, value
, PATH_MAX
) == 0)
6818 xhdr_flgs
|= _X_PATH
;
6823 Xtarhdr
.x_filesz
= strtoull(value
, NULL
, 0);
6825 (void) fprintf(stderr
, gettext(
6826 "tar: Extended header invalid filesize "
6827 "for file # %llu.\n"), xhdr_count
);
6830 xhdr_flgs
|= _X_SIZE
;
6833 xhdr_flgs
|= _X_UID
;
6834 Xtarhdr
.x_uid
= strtol(value
, NULL
, 0);
6835 if ((errno
) || (Xtarhdr
.x_uid
> UID_MAX
)) {
6836 (void) fprintf(stderr
, gettext(
6837 "tar: Extended header uid value error "
6838 "for file # %llu.\n"), xhdr_count
);
6839 Xtarhdr
.x_uid
= UID_NOBODY
;
6843 if (utf8_local("uname", &Xtarhdr
.x_uname
,
6844 local_uname
, value
, _POSIX_NAME_MAX
) == 0)
6845 xhdr_flgs
|= _X_UNAME
;
6848 get_xtime(value
, &(Xtarhdr
.x_mtime
));
6850 (void) fprintf(stderr
, gettext(
6851 "tar: Extended header modification time "
6852 "value error for file # %llu.\n"),
6855 xhdr_flgs
|= _X_MTIME
;
6858 (void) fprintf(stderr
,
6859 gettext("tar: unrecognized extended"
6860 " header keyword '%s'. Ignored.\n"), keyword
);
6865 getdir(); /* get regular header */
6866 if (errors
&& errflag
)
6875 * load_info_from_xtarhdr - sets Gen and stbuf variables from
6877 * load_info_from_xtarhdr(flag, xhdrp);
6878 * u_longlong_t flag; xhdr_flgs
6879 * struct xtar_hdr *xhdrp; pointer to extended header
6880 * NOTE: called when typeflag is not 'A' and xhdr_flgs
6884 load_info_from_xtarhdr(u_longlong_t flag
, struct xtar_hdr
*xhdrp
)
6886 if (flag
& _X_DEVMAJOR
) {
6887 Gen
.g_devmajor
= xhdrp
->x_devmajor
;
6889 if (flag
& _X_DEVMINOR
) {
6890 Gen
.g_devminor
= xhdrp
->x_devminor
;
6892 if (flag
& _X_GID
) {
6893 Gen
.g_gid
= xhdrp
->x_gid
;
6894 stbuf
.st_gid
= xhdrp
->x_gid
;
6896 if (flag
& _X_UID
) {
6897 Gen
.g_uid
= xhdrp
->x_uid
;
6898 stbuf
.st_uid
= xhdrp
->x_uid
;
6900 if (flag
& _X_SIZE
) {
6901 Gen
.g_filesz
= xhdrp
->x_filesz
;
6902 stbuf
.st_size
= xhdrp
->x_filesz
;
6904 if (flag
& _X_MTIME
) {
6905 Gen
.g_mtime
= xhdrp
->x_mtime
.tv_sec
;
6906 stbuf
.st_mtim
.tv_sec
= xhdrp
->x_mtime
.tv_sec
;
6907 stbuf
.st_mtim
.tv_nsec
= xhdrp
->x_mtime
.tv_nsec
;
6912 * gen_num creates a string from a keyword and an usigned long long in the
6913 * format: %d %s=%s\n
6914 * This is part of the extended header data record.
6918 gen_num(const char *keyword
, const u_longlong_t number
)
6920 char save_val
[ULONGLONG_MAX_DIGITS
+ 1];
6924 (void) sprintf(save_val
, "%llu", number
);
6926 * len = length of entire line, including itself. len will be
6927 * two digits. So, add the string lengths plus the length of len,
6928 * plus a blank, an equal sign, and a newline.
6930 len
= strlen(save_val
) + strlen(keyword
) + 5;
6931 if (xrec_offset
+ len
> xrec_size
) {
6932 if (((curr_ptr
= realloc(xrec_ptr
, 2 * xrec_size
)) == NULL
))
6934 "cannot allocate extended header buffer"));
6935 xrec_ptr
= curr_ptr
;
6938 (void) sprintf(&xrec_ptr
[xrec_offset
],
6939 "%d %s=%s\n", len
, keyword
, save_val
);
6944 * gen_date creates a string from a keyword and a timestruc_t in the
6945 * format: %d %s=%s\n
6946 * This is part of the extended header data record.
6947 * Currently, granularity is only microseconds, so the low-order three digits
6948 * will be truncated.
6952 gen_date(const char *keyword
, const timestruc_t time_value
)
6954 /* Allow for <seconds>.<nanoseconds>\n */
6955 char save_val
[TIME_MAX_DIGITS
+ LONG_MAX_DIGITS
+ 2];
6959 (void) sprintf(save_val
, "%ld", time_value
.tv_sec
);
6960 len
= strlen(save_val
);
6961 save_val
[len
] = '.';
6962 (void) sprintf(&save_val
[len
+ 1], "%9.9ld", time_value
.tv_nsec
);
6965 * len = length of entire line, including itself. len will be
6966 * two digits. So, add the string lengths plus the length of len,
6967 * plus a blank, an equal sign, and a newline.
6969 len
= strlen(save_val
) + strlen(keyword
) + 5;
6970 if (xrec_offset
+ len
> xrec_size
) {
6971 if (((curr_ptr
= realloc(xrec_ptr
, 2 * xrec_size
)) == NULL
))
6973 "cannot allocate extended header buffer"));
6974 xrec_ptr
= curr_ptr
;
6977 (void) sprintf(&xrec_ptr
[xrec_offset
],
6978 "%d %s=%s\n", len
, keyword
, save_val
);
6983 * gen_string creates a string from a keyword and a char * in the
6984 * format: %d %s=%s\n
6985 * This is part of the extended header data record.
6989 gen_string(const char *keyword
, const char *value
)
6995 * len = length of entire line, including itself. The character length
6996 * of len must be 1-4 characters, because the maximum size of the path
6997 * or the name is PATH_MAX, which is 1024. So, assume 1 character
6998 * for len, one for the space, one for the "=", and one for the newline.
6999 * Then adjust as needed.
7001 /* LINTED constant expression */
7002 assert(PATH_MAX
<= 9996);
7003 len
= strlen(value
) + strlen(keyword
) + 4;
7010 if (xrec_offset
+ len
> xrec_size
) {
7011 if (((curr_ptr
= realloc(xrec_ptr
, 2 * xrec_size
)) == NULL
))
7013 "cannot allocate extended header buffer"));
7014 xrec_ptr
= curr_ptr
;
7018 if (strcmp(keyword
+1, "name") != 0)
7020 (void) sprintf(&xrec_ptr
[xrec_offset
],
7021 "%d %s=%s\n", len
, keyword
, value
);
7025 (void) sprintf(&xrec_ptr
[xrec_offset
],
7026 "%d %s=%snametoolong\n", len
, keyword
, value
);
7033 * Convert time found in the extended header data to seconds and nanoseconds.
7037 get_xtime(char *value
, timestruc_t
*xtime
)
7043 (void) memset(nanosec
, '0', 9);
7046 period
= strchr(value
, '.');
7049 xtime
->tv_sec
= strtol(value
, NULL
, 10);
7053 i
= strlen(period
+1);
7054 (void) strncpy(nanosec
, period
+ 1, min(i
, 9));
7055 xtime
->tv_nsec
= strtol(nanosec
, NULL
, 10);
7060 * Check linkpath for length.
7061 * Emit an error message and return 1 if too long.
7074 if (strlen(linkname
) > (size_t)NAMSIZ
) {
7076 xhdr_flgs
|= _X_LINKPATH
;
7077 Xtarhdr
.x_linkpath
= linkname
;
7079 (void) fprintf(stderr
, gettext(
7080 "tar: %s: linked to %s\n"), longname
, linkname
);
7081 (void) fprintf(stderr
, gettext(
7082 "tar: %s: linked name too long\n"), linkname
);
7090 if (xhdr_flgs
& _X_LINKPATH
)
7091 return (build_dblock(name
, tchar
, type
,
7092 filetype
, &stbuf
, stbuf
.st_dev
,
7095 return (build_dblock(name
, linkname
, type
,
7096 filetype
, &stbuf
, stbuf
.st_dev
, prefix
));
7100 * Convert from UTF-8 to local character set.
7111 static iconv_t iconv_cd
;
7113 const char *iconv_src
;
7118 if (charset_type
== -1) { /* iconv_open failed in earlier try */
7119 (void) fprintf(stderr
, gettext(
7120 "tar: file # %llu: (%s) UTF-8 conversion failed.\n"),
7121 xhdr_count
, source
);
7123 } else if (charset_type
== 0) { /* iconv_open has not yet been done */
7124 nl_target
= nl_langinfo(CODESET
);
7125 if (strlen(nl_target
) == 0) /* locale using 7-bit codeset */
7126 nl_target
= "US-ASCII";
7127 if (strcmp(nl_target
, "US-ASCII") == 0)
7129 else if (strcmp(nl_target
, "UTF-8") == 0)
7132 if (strncmp(nl_target
, "ISO", 3) == 0)
7136 if ((iconv_cd
= iconv_open(nl_target
, "UTF-8")) ==
7138 if (errno
== EINVAL
)
7139 (void) fprintf(stderr
, gettext(
7140 "tar: conversion routines not "
7141 "available for current locale. "));
7142 (void) fprintf(stderr
, gettext(
7143 "file # %llu: (%s) UTF-8 conversion"
7144 " failed.\n"), xhdr_count
, source
);
7151 /* locale using 7-bit codeset or UTF-8 locale */
7152 if (charset_type
== 1 || charset_type
== 3) {
7153 if (strlen(source
) > max_val
) {
7154 (void) fprintf(stderr
, gettext(
7155 "tar: file # %llu: Extended header %s too long.\n"),
7156 xhdr_count
, option
);
7159 if (charset_type
== 3)
7160 (void) strcpy(target
, source
);
7161 else if (c_utf8(target
, source
) != 0) {
7162 (void) fprintf(stderr
, gettext(
7163 "tar: file # %llu: (%s) UTF-8 conversion"
7164 " failed.\n"), xhdr_count
, source
);
7167 *Xhdr_ptrptr
= target
;
7173 inlen
= strlen(source
);
7174 outlen
= max_val
* UTF_8_FACTOR
;
7175 if (iconv(iconv_cd
, &iconv_src
, &inlen
, &iconv_trg
, &outlen
) ==
7176 (size_t)-1) { /* Error occurred: didn't convert */
7177 (void) fprintf(stderr
, gettext(
7178 "tar: file # %llu: (%s) UTF-8 conversion failed.\n"),
7179 xhdr_count
, source
);
7180 /* Get remaining output; reinitialize conversion descriptor */
7181 iconv_src
= (const char *)NULL
;
7183 (void) iconv(iconv_cd
, &iconv_src
, &inlen
, &iconv_trg
, &outlen
);
7186 /* Get remaining output; reinitialize conversion descriptor */
7187 iconv_src
= (const char *)NULL
;
7189 if (iconv(iconv_cd
, &iconv_src
, &inlen
, &iconv_trg
, &outlen
) ==
7190 (size_t)-1) { /* Error occurred: didn't convert */
7191 (void) fprintf(stderr
, gettext(
7192 "tar: file # %llu: (%s) UTF-8 conversion failed.\n"),
7193 xhdr_count
, source
);
7197 *iconv_trg
= '\0'; /* Null-terminate iconv output string */
7198 if (strlen(target
) > max_val
) {
7199 (void) fprintf(stderr
, gettext(
7200 "tar: file # %llu: Extended header %s too long.\n"),
7201 xhdr_count
, option
);
7204 *Xhdr_ptrptr
= target
;
7209 * Check gname, uname, path, and linkpath to see if they need to go in an
7210 * extended header. If they are already slated to be in an extended header,
7211 * or if they are not ascii, then they need to be in the extended header.
7212 * Then, convert all extended names to UTF-8.
7216 gen_utf8_names(const char *filename
)
7218 static iconv_t iconv_cd
;
7220 char tempbuf
[MAXNAM
+ 1];
7224 if (charset_type
== -1) { /* Previous failure to open. */
7225 (void) fprintf(stderr
, gettext(
7226 "tar: file # %llu: UTF-8 conversion failed.\n"),
7231 if (charset_type
== 0) { /* Need to get conversion descriptor */
7232 nl_target
= nl_langinfo(CODESET
);
7233 if (strlen(nl_target
) == 0) /* locale using 7-bit codeset */
7234 nl_target
= "US-ASCII";
7235 if (strcmp(nl_target
, "US-ASCII") == 0)
7237 else if (strcmp(nl_target
, "UTF-8") == 0)
7240 if (strncmp(nl_target
, "ISO", 3) == 0)
7245 (void) fprintf(stderr
,
7246 gettext("Opening iconv_cd with target %s\n"),
7249 if ((iconv_cd
= iconv_open("UTF-8", nl_target
)) ==
7251 if (errno
== EINVAL
)
7252 (void) fprintf(stderr
, gettext(
7253 "tar: conversion routines not "
7254 "available for current locale. "));
7255 (void) fprintf(stderr
, gettext(
7256 "file (%s): UTF-8 conversion failed.\n"),
7266 errors
+= local_utf8(&Xtarhdr
.x_gname
, local_gname
,
7267 dblock
.dbuf
.gname
, iconv_cd
, _X_GNAME
, _POSIX_NAME_MAX
);
7268 errors
+= local_utf8(&Xtarhdr
.x_uname
, local_uname
,
7269 dblock
.dbuf
.uname
, iconv_cd
, _X_UNAME
, _POSIX_NAME_MAX
);
7270 if ((xhdr_flgs
& _X_LINKPATH
) == 0) { /* Need null-terminated str. */
7271 (void) strncpy(tempbuf
, dblock
.dbuf
.linkname
, NAMSIZ
);
7272 tempbuf
[NAMSIZ
] = '\0';
7274 errors
+= local_utf8(&Xtarhdr
.x_linkpath
, local_linkpath
,
7275 tempbuf
, iconv_cd
, _X_LINKPATH
, PATH_MAX
);
7276 if ((xhdr_flgs
& _X_PATH
) == 0) { /* Concatenate prefix & name */
7277 (void) strncpy(tempbuf
, dblock
.dbuf
.prefix
, PRESIZ
);
7278 tempbuf
[PRESIZ
] = '\0';
7279 nbytes
= strlen(tempbuf
);
7281 tempbuf
[nbytes
++] = '/';
7282 tempbuf
[nbytes
] = '\0';
7284 (void) strncat(tempbuf
+ nbytes
, dblock
.dbuf
.name
,
7286 tempbuf
[MAXNAM
] = '\0';
7288 errors
+= local_utf8(&Xtarhdr
.x_path
, local_path
,
7289 tempbuf
, iconv_cd
, _X_PATH
, PATH_MAX
);
7292 (void) fprintf(stderr
, gettext(
7293 "tar: file (%s): UTF-8 conversion failed.\n"), filename
);
7295 if (errors
&& errflag
)
7312 const char *iconv_src
;
7313 const char *starting_src
;
7318 unsigned char c_to_hex
;
7322 * If the item is already slated for extended format, get the string
7323 * to convert from the extended header record. Otherwise, get it from
7324 * the regular (dblock) area.
7326 if (xhdr_flgs
& xhdrflg
) {
7327 if (charset_type
== 3) { /* Already UTF-8, just copy */
7328 (void) strcpy(target
, *Xhdr_ptrptr
);
7329 *Xhdr_ptrptr
= target
;
7332 iconv_src
= (const char *) *Xhdr_ptrptr
;
7334 if (charset_type
== 3) /* Already in UTF-8 format */
7335 return (0); /* Don't create xhdr record */
7338 starting_src
= iconv_src
;
7340 if ((inlen
= strlen(iconv_src
)) == 0)
7343 if (charset_type
== 1) { /* locale using 7-bit codeset */
7344 if (c_utf8(target
, starting_src
) != 0) {
7345 (void) fprintf(stderr
,
7346 gettext("tar: invalid character in"
7347 " UTF-8 conversion of '%s'\n"), starting_src
);
7353 outlen
= max_val
* UTF_8_FACTOR
;
7355 if (iconv(iconv_cd
, &iconv_src
, &inlen
, &iconv_trg
, &outlen
) ==
7357 /* An error occurred, or not all characters were converted */
7358 if (errno
== EILSEQ
)
7359 (void) fprintf(stderr
,
7360 gettext("tar: invalid character in"
7361 " UTF-8 conversion of '%s'\n"), starting_src
);
7363 (void) fprintf(stderr
, gettext(
7364 "tar: conversion to UTF-8 aborted for '%s'.\n"),
7366 /* Get remaining output; reinitialize conversion descriptor */
7367 iconv_src
= (const char *)NULL
;
7369 (void) iconv(iconv_cd
, &iconv_src
, &inlen
, &iconv_trg
, &outlen
);
7372 /* Get remaining output; reinitialize conversion descriptor */
7373 iconv_src
= (const char *)NULL
;
7375 if (iconv(iconv_cd
, &iconv_src
, &inlen
, &iconv_trg
, &outlen
) ==
7376 (size_t)-1) { /* Error occurred: didn't convert */
7377 if (errno
== EILSEQ
)
7378 (void) fprintf(stderr
,
7379 gettext("tar: invalid character in"
7380 " UTF-8 conversion of '%s'\n"), starting_src
);
7382 (void) fprintf(stderr
, gettext(
7383 "tar: conversion to UTF-8 aborted for '%s'.\n"),
7388 *iconv_trg
= '\0'; /* Null-terminate iconv output string */
7389 if (strcmp(starting_src
, target
) != 0) {
7390 *Xhdr_ptrptr
= target
;
7391 xhdr_flgs
|= xhdrflg
;
7393 (void) fprintf(stderr
, "*** inlen: %d %d; outlen: %d %d\n",
7394 strlen(starting_src
), inlen
, max_val
, outlen
);
7395 (void) fprintf(stderr
, "Input string:\n ");
7396 for (inlen
= 0; inlen
< strlen(starting_src
); inlen
++) {
7397 c_to_hex
= (unsigned char)starting_src
[inlen
];
7398 (void) fprintf(stderr
, " %2.2x", c_to_hex
);
7399 if (inlen
% 20 == 19)
7400 (void) fprintf(stderr
, "\n ");
7402 (void) fprintf(stderr
, "\nOutput string:\n ");
7403 for (inlen
= 0; inlen
< strlen(target
); inlen
++) {
7404 c_to_hex
= (unsigned char)target
[inlen
];
7405 (void) fprintf(stderr
, " %2.2x", c_to_hex
);
7406 if (inlen
% 20 == 19)
7407 (void) fprintf(stderr
, "\n ");
7409 (void) fprintf(stderr
, "\n");
7417 * Function to test each byte of the source string to make sure it is
7418 * in within bounds (value between 0 and 127).
7419 * If valid, copy source to target.
7423 c_utf8(char *target
, const char *source
)
7426 const char *thischar
;
7428 len
= strlen(source
);
7431 if (!isascii((int)(*thischar
++)))
7435 (void) strcpy(target
, source
);
7440 #if defined(O_XATTR)
7441 #define ROUNDTOTBLOCK(a) ((a + (TBLOCK -1)) & ~(TBLOCK -1))
7449 struct linkbuf
*linkinfo
,
7452 char *bufhead
; /* ptr to full buffer */
7454 struct xattr_hdr
*hptr
; /* ptr to header in bufhead */
7455 struct xattr_buf
*tptr
; /* ptr to pathing pieces */
7456 int totalen
; /* total buffer length */
7457 int len
; /* length returned to user */
7458 int stringlen
; /* length of filename + attr */
7460 * length of filename + attr
7464 int complen
; /* length of pathing section */
7465 int linklen
; /* length of link section */
7466 int attrnames_index
; /* attrnames starting index */
7469 * Release previous buffer
7472 if (*attrbuf
!= (char *)NULL
) {
7478 * First add in fixed size stuff
7480 len
= sizeof (struct xattr_hdr
) + sizeof (struct xattr_buf
);
7483 * Add space for two nulls
7485 stringlen
= strlen(attrpath
) + strlen(filename
) + 2;
7486 complen
= stringlen
+ sizeof (struct xattr_buf
);
7491 * Now add on space for link info if any
7494 if (linkinfo
!= NULL
) {
7496 * Again add space for two nulls
7498 linkstringlen
= strlen(linkinfo
->pathname
) +
7499 strlen(linkinfo
->attrname
) + 2;
7500 linklen
= linkstringlen
+ sizeof (struct xattr_buf
);
7507 * Now add padding to end to fill out TBLOCK
7509 * Function returns size of real data and not size + padding.
7512 totalen
= ROUNDTOTBLOCK(len
);
7514 if ((bufhead
= calloc(1, totalen
)) == NULL
) {
7515 fatal(gettext("Out of memory."));
7520 * Now we can fill in the necessary pieces
7524 * first fill in the fixed header
7526 hptr
= (struct xattr_hdr
*)bufhead
;
7527 (void) sprintf(hptr
->h_version
, "%s", XATTR_ARCH_VERS
);
7528 (void) sprintf(hptr
->h_component_len
, "%0*d",
7529 sizeof (hptr
->h_component_len
) - 1, complen
);
7530 (void) sprintf(hptr
->h_link_component_len
, "%0*d",
7531 sizeof (hptr
->h_link_component_len
) - 1, linklen
);
7532 (void) sprintf(hptr
->h_size
, "%0*d", sizeof (hptr
->h_size
) - 1, len
);
7535 * Now fill in the filename + attrnames section
7536 * The filename and attrnames section can be composed of two or more
7537 * path segments separated by a null character. The first segment
7538 * is the path to the parent file that roots the entire sequence in
7539 * the normal name space. The remaining segments describes a path
7540 * rooted at the hidden extended attribute directory of the leaf file of
7541 * the previous segment, making it possible to name attributes on
7542 * attributes. Thus, if we are just archiving an extended attribute,
7543 * the second segment will contain the attribute name. If we are
7544 * archiving a system attribute of an extended attribute, then the
7545 * second segment will contain the attribute name, and a third segment
7546 * will contain the system attribute name. The attribute pathing
7547 * information is obtained from 'attrpath'.
7550 tptr
= (struct xattr_buf
*)(bufhead
+ sizeof (struct xattr_hdr
));
7551 (void) sprintf(tptr
->h_namesz
, "%0*d", sizeof (tptr
->h_namesz
) - 1,
7553 (void) strcpy(tptr
->h_names
, filename
);
7554 attrnames_index
= strlen(filename
) + 1;
7555 (void) strcpy(&tptr
->h_names
[attrnames_index
], attrpath
);
7556 tptr
->h_typeflag
= typeflag
;
7559 * Split the attrnames section into two segments if 'attrpath'
7560 * contains pathing information for a system attribute of an
7561 * extended attribute. We split them by replacing the '/' with
7564 if ((aptr
= strpbrk(&tptr
->h_names
[attrnames_index
], "/")) != NULL
) {
7569 * Now fill in the optional link section if we have one
7572 if (linkinfo
!= (struct linkbuf
*)NULL
) {
7573 tptr
= (struct xattr_buf
*)(bufhead
+
7574 sizeof (struct xattr_hdr
) + complen
);
7576 (void) sprintf(tptr
->h_namesz
, "%0*d",
7577 sizeof (tptr
->h_namesz
) - 1, linkstringlen
);
7578 (void) strcpy(tptr
->h_names
, linkinfo
->pathname
);
7580 &tptr
->h_names
[strlen(linkinfo
->pathname
) + 1],
7581 linkinfo
->attrname
);
7582 tptr
->h_typeflag
= typeflag
;
7584 *attrbuf
= (char *)bufhead
;
7595 struct linkbuf
*linkinfo
,
7604 getstat(int dirfd
, char *longname
, char *shortname
, char *attrparent
)
7610 struct stat symlnbuf
;
7613 i
= fstatat(dirfd
, shortname
, &stbuf
, AT_SYMLINK_NOFOLLOW
);
7615 i
= fstatat(dirfd
, shortname
, &stbuf
, 0);
7618 /* Initialize flag to print error mesg. */
7621 * If stat is done, then need to do lstat
7622 * to determine whether it's a sym link
7625 /* Save returned error */
7628 j
= fstatat(dirfd
, shortname
,
7629 &symlnbuf
, AT_SYMLINK_NOFOLLOW
);
7631 * Suppress error message when file is a symbolic link
7632 * and function modifier 'l' is off. Exception: when
7633 * a symlink points to a symlink points to a
7634 * symlink ... and we get past MAXSYMLINKS. That
7635 * error will cause a file not to be archived, and
7636 * needs to be printed.
7638 if ((j
== 0) && (!linkerrok
) && (slnkerr
!= ELOOP
) &&
7639 (S_ISLNK(symlnbuf
.st_mode
)))
7643 * Restore errno in case the lstat
7644 * on symbolic link change
7650 (void) fprintf(stderr
, gettext(
7651 "tar: %s%s%s%s: %s\n"),
7652 (attrparent
== NULL
) ? "" : gettext("attribute "),
7653 (attrparent
== NULL
) ? "" : attrparent
,
7654 (attrparent
== NULL
) ? "" : gettext(" of "),
7655 longname
, strerror(errno
));
7664 * Recursively archive the extended attributes and/or extended system attributes
7665 * of the base file, longname. Note: extended system attribute files will be
7666 * archived only if the extended system attributes are not transient (i.e. the
7667 * extended system attributes are other than the default values).
7669 * If -@ was specified and the underlying file system supports it, archive the
7670 * extended attributes, and if there is a system attribute associated with the
7671 * extended attribute, then recursively call xattrs_put() to archive the
7672 * hidden attribute directory and the extended system attribute. If -/ was
7673 * specified and the underlying file system supports it, archive the extended
7674 * system attributes. Read-only extended system attributes are never archived.
7676 * Currently, there cannot be attributes on attributes; only system
7677 * attributes on attributes. In addition, there cannot be attributes on
7678 * system attributes. A file and it's attribute directory hierarchy looks as
7680 * longname ----> . ("." is the hidden attribute directory)
7682 * ----------------------------
7684 * <sys_attr_name> <attr_name> ----> .
7689 #if defined(O_XATTR)
7691 xattrs_put(char *longname
, char *shortname
, char *parent
, char *attrparent
)
7693 char *filename
= (attrparent
== NULL
) ? shortname
: attrparent
;
7694 int arc_rwsysattr
= 0;
7702 attr_data_t
*attrinfo
= NULL
;
7705 * If the underlying file system supports it, then archive the extended
7706 * attributes if -@ was specified, and the extended system attributes
7707 * if -/ was specified.
7709 if (verify_attr_support(filename
, (attrparent
== NULL
), ARC_CREATE
,
7710 &ext_attr
) != ATTR_OK
) {
7715 * Only want to archive a read-write extended system attribute file
7716 * if it contains extended system attribute settings that are not the
7719 #if defined(_PC_SATTR_ENABLED)
7722 nvlist_t
*slist
= NULL
;
7724 /* Determine if there are non-transient system attributes */
7726 if ((filefd
= open(filename
, O_RDONLY
)) == -1) {
7727 if (attrparent
== NULL
) {
7729 "unable to open file %s"), longname
);
7733 if (((slist
= sysattr_list(basename(myname
), filefd
,
7734 filename
)) != NULL
) || (errno
!= 0)) {
7737 if (slist
!= NULL
) {
7738 (void) nvlist_free(slist
);
7741 (void) close(filefd
);
7745 * If we aren't archiving extended system attributes, and we are
7746 * processing an attribute, or if we are archiving extended system
7747 * attributes, and there are are no extended attributes, then there's
7748 * no need to open up the attribute directory of the file unless the
7749 * extended system attributes are not transient (i.e, the system
7750 * attributes are not the default values).
7752 if ((arc_rwsysattr
== 0) && ((attrparent
!= NULL
) ||
7753 (saflag
&& !ext_attr
))) {
7756 #endif /* _PC_SATTR_ENABLED */
7758 /* open the parent attribute directory */
7759 fd
= attropen(filename
, ".", O_RDONLY
);
7762 "unable to open attribute directory for %s%s%sfile %s"),
7763 (attrparent
== NULL
) ? "" : gettext("attribute "),
7764 (attrparent
== NULL
) ? "" : attrparent
,
7765 (attrparent
== NULL
) ? "" : gettext(" of "),
7771 * We need to change into the parent's attribute directory to determine
7772 * if each of the attributes should be archived.
7774 if (fchdir(fd
) < 0) {
7776 "cannot change to attribute directory of %s%s%sfile %s"),
7777 (attrparent
== NULL
) ? "" : gettext("attribute "),
7778 (attrparent
== NULL
) ? "" : attrparent
,
7779 (attrparent
== NULL
) ? "" : gettext(" of "),
7785 if (((dirfd
= dup(fd
)) == -1) ||
7786 ((dirp
= fdopendir(dirfd
)) == NULL
)) {
7787 (void) fprintf(stderr
, gettext(
7788 "tar: unable to open dir pointer for %s%s%sfile %s\n"),
7789 (attrparent
== NULL
) ? "" : gettext("attribute "),
7790 (attrparent
== NULL
) ? "" : attrparent
,
7791 (attrparent
== NULL
) ? "" : gettext(" of "),
7799 while ((dp
= readdir(dirp
)) != NULL
) {
7800 if (strcmp(dp
->d_name
, "..") == 0) {
7802 } else if (strcmp(dp
->d_name
, ".") == 0) {
7808 /* Determine if this attribute should be archived */
7809 if (verify_attr(dp
->d_name
, attrparent
, arc_rwsysattr
,
7810 &rw_sysattr
) != ATTR_OK
) {
7814 /* gather the attribute's information to pass to putfile() */
7815 if ((fill_in_attr_info(dp
->d_name
, longname
, attrparent
,
7816 fd
, rw_sysattr
, &attrinfo
)) == 1) {
7820 /* add the attribute to the archive */
7821 rc
= putfile(longname
, dp
->d_name
, parent
, attrinfo
,
7822 XATTR_FILE
, LEV0
, SYMLINK_LEV0
);
7828 #if defined(_PC_SATTR_ENABLED)
7830 * If both -/ and -@ were specified, then archive the
7831 * attribute's extended system attributes and hidden directory
7832 * by making a recursive call to xattrs_put().
7834 if (!rw_sysattr
&& saflag
&& atflag
&& (rc
!= PUT_AS_LINK
) &&
7837 xattrs_put(longname
, shortname
, parent
, dp
->d_name
);
7840 * Change back to the parent's attribute directory
7841 * to process any further attributes.
7843 if (fchdir(fd
) < 0) {
7845 "cannot change back to attribute directory "
7846 "of file %s"), longname
);
7850 #endif /* _PC_SATTR_ENABLED */
7853 if (attrinfo
!= NULL
) {
7854 if (attrinfo
->attr_parent
!= NULL
) {
7855 free(attrinfo
->attr_parent
);
7857 free(attrinfo
->attr_path
);
7860 (void) closedir(dirp
);
7865 /* Change back to the parent directory of the base file */
7866 if (attrparent
== NULL
) {
7867 (void) tar_chdir(parent
);
7873 xattrs_put(char *longname
, char *shortname
, char *parent
, char *attrppath
)
7876 #endif /* O_XATTR */
7879 put_link(char *name
, char *longname
, char *component
, char *longattrname
,
7880 char *prefix
, int filetype
, char type
)
7883 if (stbuf
.st_nlink
> 1) {
7887 for (lp
= ihead
; lp
!= NULL
; lp
= lp
->nextp
)
7888 if (lp
->inum
== stbuf
.st_ino
&&
7889 lp
->devnum
== stbuf
.st_dev
) {
7894 #if defined(O_XATTR)
7895 if (filetype
== XATTR_FILE
)
7896 if (put_xattr_hdr(longname
, component
,
7897 longattrname
, prefix
, type
, filetype
, lp
)) {
7901 stbuf
.st_size
= (off_t
)0;
7902 if (filetype
!= XATTR_FILE
) {
7904 if (chk_path_build(name
, longname
, lp
->pathname
,
7905 prefix
, type
, filetype
) > 0) {
7910 if (mulvol
&& tapepos
+ 1 >= blocklim
)
7912 (void) writetbuf((char *)&dblock
, 1);
7914 * write_ancillary() is not needed here.
7915 * The first link is handled in the following
7916 * else statement. No need to process ACLs
7917 * for other hard links since they are the
7923 dlog("seek = %" FMT_blkcnt_t
7925 if (filetype
== XATTR_FILE
) {
7926 (void) fprintf(vfile
, gettext(
7927 "a %s attribute %s link to "
7928 "%s attribute %s\n"),
7929 name
, component
, name
,
7932 (void) fprintf(vfile
, gettext(
7933 "a %s link to %s\n"),
7934 longname
, lp
->pathname
);
7940 lp
= (struct linkbuf
*)getmem(sizeof (*lp
));
7941 if (lp
!= (struct linkbuf
*)NULL
) {
7944 lp
->inum
= stbuf
.st_ino
;
7945 lp
->devnum
= stbuf
.st_dev
;
7946 lp
->count
= stbuf
.st_nlink
- 1;
7947 if (filetype
== XATTR_FILE
) {
7948 (void) strcpy(lp
->pathname
, longname
);
7949 (void) strcpy(lp
->attrname
,
7952 (void) strcpy(lp
->pathname
, longname
);
7953 (void) strcpy(lp
->attrname
, "");
7964 put_extra_attributes(char *longname
, char *shortname
, char *longattrname
,
7965 char *prefix
, int filetype
, char typeflag
)
7967 static acl_t
*aclp
= NULL
;
7974 #if defined(O_XATTR)
7975 if ((atflag
|| saflag
) && (filetype
== XATTR_FILE
)) {
7976 if (put_xattr_hdr(longname
, shortname
, longattrname
, prefix
,
7977 typeflag
, filetype
, NULL
)) {
7985 char *secinfo
= NULL
;
7989 if (((stbuf
.st_mode
& S_IFMT
) != S_IFLNK
)) {
7991 * Get ACL info: dont bother allocating space if
7992 * there is only a trivial ACL.
7994 if ((error
= acl_get(shortname
, ACL_NO_TRIVIAL
,
7996 (void) fprintf(stderr
, gettext(
7997 "%s: failed to retrieve acl : %s\n"),
7998 longname
, acl_strerror(error
));
8003 /* append security attributes if any */
8005 (void) append_secattr(&secinfo
, &len
, acl_cnt(aclp
),
8006 acl_totext(aclp
, ACL_APPEND_ID
| ACL_COMPACT_FMT
|
8007 ACL_SID_FMT
), (acl_type(aclp
) == ACLENT_T
) ?
8008 UFSD_ACL
: ACE_ACL
);
8012 (void) write_ancillary(&dblock
, secinfo
, len
, ACL_HDR
);
8018 #if defined(O_XATTR)
8020 put_xattr_hdr(char *longname
, char *shortname
, char *longattrname
, char *prefix
,
8021 int typeflag
, int filetype
, struct linkbuf
*lp
)
8026 static char *attrbuf
= NULL
;
8029 lname
= malloc(sizeof (char) * strlen("/dev/null") + 1 +
8030 strlen(shortname
) + strlen(".hdr") + 1);
8032 if (lname
== NULL
) {
8033 fatal(gettext("Out of Memory."));
8035 sname
= malloc(sizeof (char) * strlen(shortname
) +
8036 strlen(".hdr") + 1);
8037 if (sname
== NULL
) {
8038 fatal(gettext("Out of Memory."));
8041 (void) sprintf(sname
, "%s.hdr", shortname
);
8042 (void) sprintf(lname
, "/dev/null/%s", sname
);
8044 if (strlcpy(dblock
.dbuf
.name
, lname
, sizeof (dblock
.dbuf
.name
)) >=
8045 sizeof (dblock
.dbuf
.name
)) {
8047 "Buffer overflow writing extended attribute file name"));
8051 * dump extended attr lookup info
8053 prepare_xattr(&attrbuf
, longname
, longattrname
, typeflag
, lp
, &attrlen
);
8054 write_ancillary(&dblock
, attrbuf
, attrlen
, _XATTR_HDRTYPE
);
8056 (void) sprintf(lname
, "/dev/null/%s", shortname
);
8057 (void) strncpy(dblock
.dbuf
.name
, sname
, NAMSIZ
);
8060 * Set up filename for attribute
8063 error
= build_dblock(lname
, tchar
, '0', filetype
,
8064 &stbuf
, stbuf
.st_dev
, prefix
);
8072 #if defined(O_XATTR)
8074 read_xattr_hdr(attr_data_t
**attrinfo
)
8077 char *attrparent
= NULL
;
8081 int comp_len
, link_len
;
8086 if (dblock
.dbuf
.typeflag
!= _XATTR_HDRTYPE
)
8089 bytes
= stbuf
.st_size
;
8090 if ((xattrhead
= calloc(1, (int)bytes
)) == NULL
) {
8091 (void) fprintf(stderr
, gettext(
8092 "Insufficient memory for extended attribute\n"));
8096 tp
= (char *)xattrhead
;
8097 blocks
= TBLOCKS(bytes
);
8098 while (blocks
-- > 0) {
8100 if (bytes
<= TBLOCK
) {
8101 (void) memcpy(tp
, buf
, (size_t)bytes
);
8104 (void) memcpy(tp
, buf
, TBLOCK
);
8111 * Validate that we can handle header format
8113 if (strcmp(xattrhead
->h_version
, XATTR_ARCH_VERS
) != 0) {
8114 (void) fprintf(stderr
,
8115 gettext("Unknown extended attribute format encountered\n"));
8116 (void) fprintf(stderr
,
8117 gettext("Disabling extended attribute parsing\n"));
8121 (void) sscanf(xattrhead
->h_component_len
, "%10d", &comp_len
);
8122 (void) sscanf(xattrhead
->h_link_component_len
, "%10d", &link_len
);
8123 xattrp
= (struct xattr_buf
*)(((char *)xattrhead
) +
8124 sizeof (struct xattr_hdr
));
8125 (void) sscanf(xattrp
->h_namesz
, "%7d", &namelen
);
8127 xattr_linkp
= (struct xattr_buf
*)
8128 ((int)xattrp
+ (int)comp_len
);
8133 * Gather the attribute path from the filename and attrnames section.
8134 * The filename and attrnames section can be composed of two or more
8135 * path segments separated by a null character. The first segment
8136 * is the path to the parent file that roots the entire sequence in
8137 * the normal name space. The remaining segments describes a path
8138 * rooted at the hidden extended attribute directory of the leaf file of
8139 * the previous segment, making it possible to name attributes on
8142 parentfilelen
= strlen(xattrp
->h_names
);
8143 xattrapath
= xattrp
->h_names
+ parentfilelen
+ 1;
8144 if ((strlen(xattrapath
) + parentfilelen
+ 2) < namelen
) {
8146 * The attrnames section contains a system attribute on an
8147 * attribute. Save the name of the attribute for use later,
8148 * and replace the null separating the attribute name from
8149 * the system attribute name with a '/' so that xattrapath can
8150 * be used to display messages with the full attribute path name
8151 * rooted at the hidden attribute directory of the base file
8152 * in normal name space.
8154 attrparent
= strdup(xattrapath
);
8155 attrparentlen
= strlen(attrparent
);
8156 xattrapath
[attrparentlen
] = '/';
8158 if ((fill_in_attr_info((attrparent
== NULL
) ? xattrapath
:
8159 xattrapath
+ attrparentlen
+ 1, xattrapath
, attrparent
,
8160 -1, 0, attrinfo
)) == 1) {
8165 /* Gather link info */
8167 xattr_linkaname
= xattr_linkp
->h_names
+
8168 strlen(xattr_linkp
->h_names
) + 1;
8170 xattr_linkaname
= NULL
;
8177 read_xattr_hdr(attr_data_t
**attrinfo
)
8184 * skip over extra slashes in string.
8189 * would return pointer at
8194 skipslashes(char *string
, char *start
)
8196 while ((string
> start
) && *(string
- 1) == '/') {
8204 * Return the parent directory of a given path.
8207 * /usr/tmp return /usr
8208 * /usr/tmp/file return /usr/tmp
8213 * dir is assumed to be at least as big as path.
8216 get_parent(char *path
, char *dir
)
8219 char tmpdir
[PATH_MAX
+ 1];
8221 if (strlen(path
) > PATH_MAX
) {
8222 fatal(gettext("pathname is too long"));
8224 (void) strcpy(tmpdir
, path
);
8225 chop_endslashes(tmpdir
);
8227 if ((s
= strrchr(tmpdir
, '/')) == NULL
) {
8228 (void) strcpy(dir
, ".");
8230 s
= skipslashes(s
, tmpdir
);
8233 (void) strcpy(dir
, "/");
8235 (void) strcpy(dir
, tmpdir
);
8239 #if defined(O_XATTR)
8241 get_component(char *path
)
8245 ptr
= strrchr(path
, '/');
8250 * Handle trailing slash
8252 if (*(ptr
+ 1) == '\0')
8260 get_component(char *path
)
8266 #if defined(O_XATTR)
8268 retry_open_attr(int pdirfd
, int cwd
, char *dirp
, char *pattr
, char *name
,
8269 int oflag
, mode_t mode
)
8273 struct timeval times
[2];
8275 struct stat parentstat
;
8280 * We couldn't get to attrdir. See if its
8281 * just a mode problem on the parent file.
8282 * for example: a mode such as r-xr--r--
8283 * on a ufs file system without extended
8284 * system attribute support won't let us
8285 * create an attribute dir if it doesn't
8286 * already exist, and on a ufs file system
8287 * with extended system attribute support
8288 * won't let us open the attribute for
8291 * If file has a non-trivial ACL, then save it
8292 * off so that we can place it back on after doing
8295 if ((dirfd
= openat(cwd
, (pattr
== NULL
) ? dirp
: pattr
,
8299 if (fstat(dirfd
, &parentstat
) == -1) {
8300 (void) fprintf(stderr
, gettext(
8301 "tar: cannot stat %sfile %s: %s\n"),
8302 (pdirfd
== -1) ? "" : gettext("parent of "),
8303 (pdirfd
== -1) ? dirp
: name
, strerror(errno
));
8306 if ((error
= facl_get(dirfd
, ACL_NO_TRIVIAL
, &aclp
)) != 0) {
8307 (void) fprintf(stderr
, gettext(
8308 "tar: failed to retrieve ACL on %sfile %s: %s\n"),
8309 (pdirfd
== -1) ? "" : gettext("parent of "),
8310 (pdirfd
== -1) ? dirp
: name
, strerror(errno
));
8314 newmode
= S_IWUSR
| parentstat
.st_mode
;
8315 if (fchmod(dirfd
, newmode
) == -1) {
8316 (void) fprintf(stderr
,
8318 "tar: cannot fchmod %sfile %s to %o: %s\n"),
8319 (pdirfd
== -1) ? "" : gettext("parent of "),
8320 (pdirfd
== -1) ? dirp
: name
, newmode
, strerror(errno
));
8329 * We weren't able to create the attribute directory before.
8332 ofilefd
= attropen(dirp
, ".", oflag
);
8335 * We weren't able to create open the attribute before.
8338 ofilefd
= openat(pdirfd
, name
, oflag
, mode
);
8342 * Put mode back to original
8344 if (fchmod(dirfd
, parentstat
.st_mode
) == -1) {
8345 (void) fprintf(stderr
,
8346 gettext("tar: cannot chmod %sfile %s to %o: %s\n"),
8347 (pdirfd
== -1) ? "" : gettext("parent of "),
8348 (pdirfd
== -1) ? dirp
: name
, newmode
, strerror(errno
));
8352 error
= facl_set(dirfd
, aclp
);
8354 (void) fprintf(stderr
,
8355 gettext("tar: failed to set acl entries on "
8357 (pdirfd
== -1) ? "" : gettext("parent of "),
8358 (pdirfd
== -1) ? dirp
: name
);
8364 * Put back time stamps
8367 times
[0].tv_sec
= parentstat
.st_atime
;
8368 times
[0].tv_usec
= 0;
8369 times
[1].tv_sec
= parentstat
.st_mtime
;
8370 times
[1].tv_usec
= 0;
8372 (void) futimesat(cwd
, (pattr
== NULL
) ? dirp
: pattr
, times
);
8374 (void) close(dirfd
);
8380 #if !defined(O_XATTR)
8382 openat64(int fd
, const char *name
, int oflag
, mode_t cmode
)
8384 return (open64(name
, oflag
, cmode
));
8388 openat(int fd
, const char *name
, int oflag
, mode_t cmode
)
8390 return (open(name
, oflag
, cmode
));
8394 fchownat(int fd
, const char *name
, uid_t owner
, gid_t group
, int flag
)
8396 if (flag
== AT_SYMLINK_NOFOLLOW
)
8397 return (lchown(name
, owner
, group
));
8399 return (chown(name
, owner
, group
));
8403 renameat(int fromfd
, char *old
, int tofd
, char *new)
8405 return (rename(old
, new));
8409 futimesat(int fd
, char *path
, struct timeval times
[2])
8411 return (utimes(path
, times
));
8415 unlinkat(int dirfd
, char *path
, int flag
)
8417 if (flag
== AT_REMOVEDIR
)
8418 return (rmdir(path
));
8420 return (unlink(path
));
8424 fstatat(int fd
, char *path
, struct stat
*buf
, int flag
)
8426 if (flag
== AT_SYMLINK_NOFOLLOW
)
8427 return (lstat(path
, buf
));
8429 return (stat(path
, buf
));
8433 attropen(char *file
, char *attr
, int omode
, mode_t cmode
)
8441 chop_endslashes(char *path
)
8446 * Chop of slashes, but not if all we have is slashes
8448 * should make no changes, otherwise it will screw up
8451 end
= &path
[strlen(path
) -1];
8452 if (*end
== '/' && end
!= path
) {
8453 ptr
= skipslashes(end
, path
);
8454 if (ptr
!= NULL
&& ptr
!= path
) {
8460 /* Compressing a tar file using compression method provided in 'opt' */
8468 (void) fprintf(vfile
,
8469 gettext("Compressing '%s' with '%s'...\n"),
8470 usefile
, compress_opt
);
8472 if ((pid
= fork()) == 0) {
8473 verify_compress_opt(compress_opt
);
8474 (void) execlp(compress_opt
, compress_opt
,
8476 } else if (pid
== -1) {
8477 vperror(1, "%s", gettext("Could not fork"));
8481 (void) rename(tfname
, usefile
);
8485 /* The magic numbers from /etc/magic */
8487 #define GZIP_MAGIC "\037\213"
8488 #define BZIP_MAGIC "BZh"
8489 #define COMP_MAGIC "\037\235"
8490 #define XZ_MAGIC "\375\067\172\130\132\000"
8493 check_compression(void)
8498 if ((fp
= fopen(usefile
, "r")) != NULL
) {
8499 (void) fread(magic
, sizeof (char), 6, fp
);
8503 if (memcmp(magic
, GZIP_MAGIC
, 2) == 0) {
8504 if (xflag
|| tflag
) {
8505 compress_opt
= compress_malloc(strlen(GZCAT
) + 1);
8506 (void) strcpy(compress_opt
, GZCAT
);
8507 } else if (uflag
|| rflag
) {
8508 compress_opt
= compress_malloc(strlen(GZIP
) + 1);
8509 (void) strcpy(compress_opt
, GZIP
);
8511 } else if (memcmp(magic
, BZIP_MAGIC
, 2) == 0) {
8512 if (xflag
|| tflag
) {
8513 compress_opt
= compress_malloc(strlen(BZCAT
) + 1);
8514 (void) strcpy(compress_opt
, BZCAT
);
8515 } else if (uflag
|| rflag
) {
8516 compress_opt
= compress_malloc(strlen(BZIP
) + 1);
8517 (void) strcpy(compress_opt
, BZIP
);
8519 } else if (memcmp(magic
, COMP_MAGIC
, 2) == 0) {
8520 if (xflag
|| tflag
) {
8521 compress_opt
= compress_malloc(strlen(ZCAT
) + 1);
8522 (void) strcpy(compress_opt
, ZCAT
);
8523 } else if (uflag
|| rflag
) {
8524 compress_opt
= compress_malloc(strlen(COMPRESS
) + 1);
8525 (void) strcpy(compress_opt
, COMPRESS
);
8527 } else if (memcmp(magic
, XZ_MAGIC
, 6) == 0) {
8528 if (xflag
|| tflag
) {
8529 compress_opt
= compress_malloc(strlen(XZCAT
) + 1);
8530 (void) strcpy(compress_opt
, XZCAT
);
8531 } else if (uflag
|| rflag
) {
8532 compress_opt
= compress_malloc(strlen(XZ
) + 1);
8533 (void) strcpy(compress_opt
, XZ
);
8541 (void) strcpy(tfname
, usefile
);
8542 if (strcmp(compress_opt
, GZIP
) == 0) {
8543 if ((suffix
= gz_suffix()) == NULL
) {
8544 strlcat(tfname
, gsuffix
[0], sizeof (tfname
));
8545 return (gsuffix
[0]);
8547 } else if (strcmp(compress_opt
, COMPRESS
) == 0) {
8548 if ((suffix
= gz_suffix()) == NULL
) {
8549 strlcat(tfname
, gsuffix
[6], sizeof (tfname
));
8550 return (gsuffix
[6]);
8552 } else if (strcmp(compress_opt
, BZIP
) == 0) {
8553 if ((suffix
= bz_suffix()) == NULL
) {
8554 strlcat(tfname
, bsuffix
[0], sizeof (tfname
));
8555 return (bsuffix
[0]);
8557 } else if (strcmp(compress_opt
, XZ
) == 0) {
8558 if ((suffix
= xz_suffix()) == NULL
) {
8559 strlcat(tfname
, xsuffix
[0], sizeof (tfname
));
8560 return (xsuffix
[0]);
8566 /* Decompressing a tar file using compression method from the file type */
8568 decompress_file(void)
8574 added_suffix
= add_suffix();
8575 if (added_suffix
!= NULL
) {
8576 (void) rename(usefile
, tfname
);
8578 if ((pid
= fork()) == 0) {
8580 (void) fprintf(vfile
,
8581 gettext("Decompressing '%s' with "
8582 "'%s'...\n"), usefile
, compress_opt
);
8584 verify_compress_opt(compress_opt
);
8585 (void) execlp(compress_opt
, compress_opt
, "-df",
8587 vperror(1, gettext("Could not exec %s"), compress_opt
);
8588 } else if (pid
== -1) {
8589 vperror(1, gettext("Could not fork"));
8592 if (suffix
!= NULL
) {
8593 /* restore the file name - original file was without suffix */
8594 *(usefile
+ strlen(usefile
) - strlen(suffix
)) = '\0';
8598 /* Set the archive for writing and then compress the archive */
8606 (void) fprintf(vfile
, gettext("Compressing '%s' with "
8607 "'%s'...\n"), usefile
, compress_opt
);
8611 vperror(1, gettext("Could not create pipe"));
8613 if ((pid
= fork()) > 0) {
8615 (void) close(fd
[0]);
8619 (void) dup2(fd
[0], STDIN_FILENO
);
8620 (void) close(fd
[1]);
8621 (void) dup2(mt
, STDOUT_FILENO
);
8622 verify_compress_opt(compress_opt
);
8623 (void) execlp(compress_opt
, compress_opt
, NULL
);
8624 vperror(1, gettext("Could not exec %s"), compress_opt
);
8625 return (0); /*NOTREACHED*/
8629 uncompress_file(void)
8635 (void) fprintf(vfile
, gettext("Decompressing '%s' with "
8636 "'%s'...\n"), usefile
, compress_opt
);
8640 vperror(1, gettext("Could not create pipe"));
8642 if ((pid
= fork()) > 0) {
8644 (void) close(fd
[1]);
8648 (void) dup2(fd
[1], STDOUT_FILENO
);
8649 (void) close(fd
[0]);
8650 (void) dup2(mt
, STDIN_FILENO
);
8651 verify_compress_opt(compress_opt
);
8652 (void) execlp(compress_opt
, compress_opt
, NULL
);
8653 vperror(1, gettext("Could not exec %s"), compress_opt
);
8654 return (0); /*NOTREACHED*/
8657 /* Checking suffix validity */
8659 check_suffix(char **suf
, int size
)
8663 int nlen
= strlen(usefile
);
8665 for (i
= 0; i
< size
; i
++) {
8666 slen
= strlen(suf
[i
]);
8669 if (strcmp(usefile
+ nlen
- slen
, suf
[i
]) == 0)
8675 /* Checking valid 'bzip2' suffix */
8679 return (check_suffix(bsuffix
, BSUF
));
8682 /* Checking valid 'gzip' suffix */
8686 return (check_suffix(gsuffix
, GSUF
));
8689 /* Checking valid 'xz' suffix */
8693 return (check_suffix(xsuffix
, XSUF
));
8697 compress_malloc(size_t size
)
8701 if ((opt
= malloc(size
)) == NULL
) {
8703 gettext("Could not allocate compress buffer\n"));
8713 while (waitpid(pid
, &status
, 0) == -1 && errno
== EINTR
)
8718 verify_compress_opt(const char *t
)
8720 struct stat statbuf
;
8722 if (stat(t
, &statbuf
) == -1)
8723 vperror(1, "%s %s: %s\n", gettext("Could not stat"),
8724 t
, strerror(errno
));
8728 detect_compress(void)
8730 char *zsuf
[] = {".Z"};
8731 if (check_suffix(zsuf
, 1) != NULL
) {
8733 } else if (check_suffix(bsuffix
, BSUF
) != NULL
) {
8735 } else if (check_suffix(gsuffix
, GSUF
) != NULL
) {
8737 } else if (check_suffix(xsuffix
, XSUF
) != NULL
) {
8740 vperror(1, "%s\n", gettext("No compression method detected"));