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