1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 1676 jpk * Common Development and Distribution License (the "License"). 6 1676 jpk * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* 22 9694 Scott * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 0 stevel * Use is subject to license terms. 24 0 stevel */ 25 0 stevel 26 0 stevel /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 27 0 stevel /* All Rights Reserved */ 28 0 stevel 29 0 stevel /* Copyright (c) 1987, 1988 Microsoft Corporation */ 30 0 stevel /* All Rights Reserved */ 31 0 stevel 32 0 stevel /* 33 0 stevel * Portions of this source code were derived from Berkeley 4.3 BSD 34 0 stevel * under license from the Regents of the University of California. 35 0 stevel */ 36 0 stevel 37 0 stevel #include <unistd.h> 38 0 stevel #include <sys/types.h> 39 0 stevel #include <sys/param.h> 40 0 stevel #include <sys/stat.h> 41 0 stevel #include <sys/mkdev.h> 42 0 stevel #include <sys/wait.h> 43 0 stevel #include <dirent.h> 44 0 stevel #include <errno.h> 45 0 stevel #include <stdio.h> 46 0 stevel #include <signal.h> 47 0 stevel #include <ctype.h> 48 0 stevel #include <locale.h> 49 0 stevel #include <nl_types.h> 50 0 stevel #include <langinfo.h> 51 0 stevel #include <pwd.h> 52 0 stevel #include <grp.h> 53 0 stevel #include <fcntl.h> 54 0 stevel #include <string.h> 55 0 stevel #include <malloc.h> 56 0 stevel #include <time.h> 57 0 stevel #include <utime.h> 58 0 stevel #include <stdlib.h> 59 0 stevel #include <stdarg.h> 60 0 stevel #include <widec.h> 61 0 stevel #include <sys/mtio.h> 62 0 stevel #include <sys/acl.h> 63 0 stevel #include <strings.h> 64 0 stevel #include <deflt.h> 65 0 stevel #include <limits.h> 66 0 stevel #include <iconv.h> 67 0 stevel #include <assert.h> 68 5331 amw #include <libgen.h> 69 5331 amw #include <libintl.h> 70 789 ahrens #include <aclutils.h> 71 5331 amw #include <libnvpair.h> 72 5331 amw #include <archives.h> 73 4774 as145665 74 0 stevel #if defined(__SunOS_5_6) || defined(__SunOS_5_7) 75 0 stevel extern int defcntl(); 76 0 stevel #endif 77 5331 amw #if defined(_PC_SATTR_ENABLED) 78 5331 amw #include <attr.h> 79 5331 amw #include <libcmdutils.h> 80 5331 amw #endif 81 0 stevel 82 1676 jpk /* Trusted Extensions */ 83 1676 jpk #include <zone.h> 84 1676 jpk #include <tsol/label.h> 85 1676 jpk #include <sys/tsol/label_macro.h> 86 1676 jpk 87 5331 amw #include "getresponse.h" 88 0 stevel /* 89 0 stevel * Source compatibility 90 0 stevel */ 91 0 stevel 92 0 stevel /* 93 0 stevel * These constants come from archives.h and sys/fcntl.h 94 0 stevel * and were introduced by the extended attributes project 95 0 stevel * in Solaris 9. 96 0 stevel */ 97 0 stevel #if !defined(O_XATTR) 98 0 stevel #define AT_SYMLINK_NOFOLLOW 0x1000 99 0 stevel #define AT_REMOVEDIR 0x1 100 0 stevel #define AT_FDCWD 0xffd19553 101 0 stevel #define _XATTR_HDRTYPE 'E' 102 0 stevel static int attropen(); 103 0 stevel static int fstatat(); 104 0 stevel static int renameat(); 105 0 stevel static int unlinkat(); 106 0 stevel static int openat(); 107 0 stevel static int fchownat(); 108 0 stevel static int futimesat(); 109 0 stevel #endif 110 0 stevel 111 0 stevel /* 112 0 stevel * Compiling with -D_XPG4_2 gets this but produces other problems, so 113 0 stevel * instead of including sys/time.h and compiling with -D_XPG4_2, I'm 114 0 stevel * explicitly doing the declaration here. 115 0 stevel */ 116 0 stevel int utimes(const char *path, const struct timeval timeval_ptr[]); 117 0 stevel 118 0 stevel #ifndef MINSIZE 119 0 stevel #define MINSIZE 250 120 0 stevel #endif 121 0 stevel #define DEF_FILE "/etc/default/tar" 122 0 stevel 123 0 stevel #define min(a, b) ((a) < (b) ? (a) : (b)) 124 0 stevel #define max(a, b) ((a) > (b) ? (a) : (b)) 125 0 stevel 126 0 stevel /* -DDEBUG ONLY for debugging */ 127 0 stevel #ifdef DEBUG 128 0 stevel #undef DEBUG 129 0 stevel #define DEBUG(a, b, c)\ 130 0 stevel (void) fprintf(stderr, "DEBUG - "), (void) fprintf(stderr, a, b, c) 131 0 stevel #endif 132 0 stevel 133 0 stevel #define TBLOCK 512 /* tape block size--should be universal */ 134 0 stevel 135 0 stevel #ifdef BSIZE 136 0 stevel #define SYS_BLOCK BSIZE /* from sys/param.h: secondary block size */ 137 0 stevel #else /* BSIZE */ 138 0 stevel #define SYS_BLOCK 512 /* default if no BSIZE in param.h */ 139 0 stevel #endif /* BSIZE */ 140 0 stevel 141 0 stevel #define NBLOCK 20 142 0 stevel #define NAMSIZ 100 143 0 stevel #define PRESIZ 155 144 0 stevel #define MAXNAM 256 145 0 stevel #define MODEMASK 0777777 /* file creation mode mask */ 146 0 stevel #define POSIXMODES 07777 /* mask for POSIX mode bits */ 147 0 stevel #define MAXEXT 9 /* reasonable max # extents for a file */ 148 0 stevel #define EXTMIN 50 /* min blks left on floppy to split a file */ 149 0 stevel 150 0 stevel /* max value dblock.dbuf.efsize can store */ 151 0 stevel #define TAR_EFSIZE_MAX 0777777777 152 0 stevel 153 0 stevel /* 154 0 stevel * Symbols which specify the values at which the use of the 'E' function 155 0 stevel * modifier is required to properly store a file. 156 0 stevel * 157 0 stevel * TAR_OFFSET_MAX - the largest file size we can archive 158 0 stevel * OCTAL7CHAR - the limit for ustar gid, uid, dev 159 0 stevel */ 160 0 stevel 161 0 stevel #ifdef XHDR_DEBUG 162 0 stevel /* tiny values which force the creation of extended header entries */ 163 0 stevel #define TAR_OFFSET_MAX 9 164 0 stevel #define OCTAL7CHAR 2 165 0 stevel #else 166 0 stevel /* normal values */ 167 373 ceastha #define TAR_OFFSET_MAX 077777777777ULL 168 0 stevel #define OCTAL7CHAR 07777777 169 0 stevel #endif 170 0 stevel 171 0 stevel #define TBLOCKS(bytes) (((bytes) + TBLOCK - 1) / TBLOCK) 172 0 stevel #define K(tblocks) ((tblocks+1)/2) /* tblocks to Kbytes for printing */ 173 0 stevel 174 0 stevel #define MAXLEV (PATH_MAX / 2) 175 0 stevel #define LEV0 1 176 0 stevel #define SYMLINK_LEV0 0 177 0 stevel 178 0 stevel #define TRUE 1 179 0 stevel #define FALSE 0 180 0 stevel 181 0 stevel #define XATTR_FILE 1 182 0 stevel #define NORMAL_FILE 0 183 0 stevel 184 0 stevel #define PUT_AS_LINK 1 185 0 stevel #define PUT_NOTAS_LINK 0 186 0 stevel 187 5331 amw #ifndef VIEW_READONLY 188 5331 amw #define VIEW_READONLY "SUNWattr_ro" 189 5331 amw #endif 190 5331 amw 191 5331 amw #ifndef VIEW_READWRITE 192 5331 amw #define VIEW_READWRITE "SUNWattr_rw" 193 5331 amw #endif 194 5331 amw 195 0 stevel #if _FILE_OFFSET_BITS == 64 196 0 stevel #define FMT_off_t "lld" 197 0 stevel #define FMT_off_t_o "llo" 198 0 stevel #define FMT_blkcnt_t "lld" 199 0 stevel #else 200 0 stevel #define FMT_off_t "ld" 201 0 stevel #define FMT_off_t_o "lo" 202 0 stevel #define FMT_blkcnt_t "ld" 203 0 stevel #endif 204 0 stevel 205 0 stevel /* ACL support */ 206 0 stevel 207 0 stevel static 208 0 stevel struct sec_attr { 209 0 stevel char attr_type; 210 0 stevel char attr_len[7]; 211 0 stevel char attr_info[1]; 212 0 stevel } *attr; 213 5331 amw 214 5331 amw #if defined(O_XATTR) 215 5331 amw typedef enum { 216 5331 amw ATTR_OK, 217 5331 amw ATTR_SKIP, 218 5331 amw ATTR_CHDIR_ERR, 219 5331 amw ATTR_OPEN_ERR, 220 5331 amw ATTR_XATTR_ERR, 221 5331 amw ATTR_SATTR_ERR 222 5331 amw } attr_status_t; 223 5331 amw #endif 224 5331 amw 225 5331 amw #if defined(O_XATTR) 226 5331 amw typedef enum { 227 5331 amw ARC_CREATE, 228 5331 amw ARC_RESTORE 229 5331 amw } arc_action_t; 230 5331 amw #endif 231 5331 amw 232 5331 amw typedef struct attr_data { 233 5331 amw char *attr_parent; 234 5331 amw char *attr_path; 235 5331 amw int attr_parentfd; 236 5331 amw int attr_rw_sysattr; 237 5331 amw } attr_data_t; 238 0 stevel 239 0 stevel /* 240 0 stevel * 241 0 stevel * Tar has been changed to support extended attributes. 242 0 stevel * 243 0 stevel * As part of this change tar now uses the new *at() syscalls 244 0 stevel * such as openat, fchownat(), unlinkat()... 245 0 stevel * 246 0 stevel * This was done so that attributes can be handled with as few code changes 247 0 stevel * as possible. 248 0 stevel * 249 0 stevel * What this means is that tar now opens the directory that a file or directory 250 0 stevel * resides in and then performs *at() functions to manipulate the entry. 251 0 stevel * 252 0 stevel * For example a new file is now created like this: 253 0 stevel * 254 0 stevel * dfd = open(<some dir path>) 255 0 stevel * fd = openat(dfd, <name>,....); 256 0 stevel * 257 0 stevel * or in the case of an extended attribute 258 0 stevel * 259 0 stevel * dfd = attropen(<pathname>, ".", ....) 260 0 stevel * 261 0 stevel * Once we have a directory file descriptor all of the *at() functions can 262 0 stevel * be applied to it. 263 0 stevel * 264 0 stevel * unlinkat(dfd, <component name>,...) 265 0 stevel * fchownat(dfd, <component name>,..) 266 0 stevel * 267 0 stevel * This works for both normal namespace files and extended attribute file 268 0 stevel * 269 0 stevel */ 270 0 stevel 271 0 stevel /* 272 0 stevel * 273 0 stevel * Extended attribute Format 274 0 stevel * 275 0 stevel * Extended attributes are stored in two pieces. 276 0 stevel * 1. An attribute header which has information about 277 0 stevel * what file the attribute is for and what the attribute 278 0 stevel * is named. 279 0 stevel * 2. The attribute record itself. Stored as a normal file type 280 0 stevel * of entry. 281 0 stevel * Both the header and attribute record have special modes/typeflags 282 0 stevel * associated with them. 283 0 stevel * 284 0 stevel * The names of the header in the archive look like: 285 0 stevel * /dev/null/attr.hdr 286 0 stevel * 287 0 stevel * The name of the attribute looks like: 288 0 stevel * /dev/null/attr 289 0 stevel * 290 0 stevel * This is done so that an archiver that doesn't understand these formats 291 0 stevel * can just dispose of the attribute records. 292 0 stevel * 293 0 stevel * The format is composed of a fixed size header followed 294 0 stevel * by a variable sized xattr_buf. If the attribute is a hard link 295 0 stevel * to another attribute then another xattr_buf section is included 296 0 stevel * for the link. 297 0 stevel * 298 0 stevel * The xattr_buf is used to define the necessary "pathing" steps 299 0 stevel * to get to the extended attribute. This is necessary to support 300 0 stevel * a fully recursive attribute model where an attribute may itself 301 0 stevel * have an attribute. 302 0 stevel * 303 0 stevel * The basic layout looks like this. 304 0 stevel * 305 0 stevel * -------------------------------- 306 0 stevel * | | 307 0 stevel * | xattr_hdr | 308 0 stevel * | | 309 0 stevel * -------------------------------- 310 0 stevel * -------------------------------- 311 0 stevel * | | 312 0 stevel * | xattr_buf | 313 0 stevel * | | 314 0 stevel * -------------------------------- 315 0 stevel * -------------------------------- 316 0 stevel * | | 317 0 stevel * | (optional link info) | 318 0 stevel * | | 319 0 stevel * -------------------------------- 320 0 stevel * -------------------------------- 321 0 stevel * | | 322 0 stevel * | attribute itself | 323 0 stevel * | stored as normal tar | 324 0 stevel * | or cpio data with | 325 0 stevel * | special mode or | 326 0 stevel * | typeflag | 327 0 stevel * | | 328 0 stevel * -------------------------------- 329 0 stevel * 330 0 stevel */ 331 0 stevel 332 0 stevel /* 333 0 stevel * xattrhead is a pointer to the xattr_hdr 334 0 stevel * 335 0 stevel * xattrp is a pointer to the xattr_buf structure 336 0 stevel * which contains the "pathing" steps to get to attributes 337 0 stevel * 338 0 stevel * xattr_linkp is a pointer to another xattr_buf structure that is 339 0 stevel * only used when an attribute is actually linked to another attribute 340 0 stevel * 341 0 stevel */ 342 0 stevel 343 0 stevel static struct xattr_hdr *xattrhead; 344 0 stevel static struct xattr_buf *xattrp; 345 0 stevel static struct xattr_buf *xattr_linkp; /* pointer to link info, if any */ 346 5331 amw static char *xattrapath; /* attribute name */ 347 0 stevel static char *xattr_linkaname; /* attribute attribute is linked to */ 348 0 stevel static char Hiddendir; /* are we processing hidden xattr dir */ 349 0 stevel static char xattrbadhead; 350 0 stevel 351 0 stevel /* Was statically allocated tbuf[NBLOCK] */ 352 0 stevel static 353 0 stevel union hblock { 354 0 stevel char dummy[TBLOCK]; 355 0 stevel struct header { 356 0 stevel char name[NAMSIZ]; /* If non-null prefix, path is */ 357 0 stevel /* <prefix>/<name>; otherwise */ 358 0 stevel /* <name> */ 359 0 stevel char mode[8]; 360 0 stevel char uid[8]; 361 0 stevel char gid[8]; 362 0 stevel char size[12]; /* size of this extent if file split */ 363 0 stevel char mtime[12]; 364 0 stevel char chksum[8]; 365 0 stevel char typeflag; 366 0 stevel char linkname[NAMSIZ]; 367 0 stevel char magic[6]; 368 0 stevel char version[2]; 369 0 stevel char uname[32]; 370 0 stevel char gname[32]; 371 0 stevel char devmajor[8]; 372 0 stevel char devminor[8]; 373 0 stevel char prefix[PRESIZ]; /* Together with "name", the path of */ 374 0 stevel /* the file: <prefix>/<name> */ 375 0 stevel char extno; /* extent #, null if not split */ 376 0 stevel char extotal; /* total extents */ 377 0 stevel char efsize[10]; /* size of entire file */ 378 0 stevel } dbuf; 379 0 stevel } dblock, *tbuf, xhdr_buf; 380 0 stevel 381 0 stevel static 382 0 stevel struct xtar_hdr { 383 0 stevel uid_t x_uid, /* Uid of file */ 384 0 stevel x_gid; /* Gid of file */ 385 0 stevel major_t x_devmajor; /* Device major node */ 386 0 stevel minor_t x_devminor; /* Device minor node */ 387 0 stevel off_t x_filesz; /* Length of file */ 388 0 stevel char *x_uname, /* Pointer to name of user */ 389 0 stevel *x_gname, /* Pointer to gid of user */ 390 0 stevel *x_linkpath, /* Path for a hard/symbolic link */ 391 0 stevel *x_path; /* Path of file */ 392 0 stevel timestruc_t x_mtime; /* Seconds and nanoseconds */ 393 0 stevel } Xtarhdr; 394 0 stevel 395 0 stevel static 396 0 stevel struct gen_hdr { 397 0 stevel ulong_t g_mode; /* Mode of file */ 398 0 stevel uid_t g_uid, /* Uid of file */ 399 0 stevel g_gid; /* Gid of file */ 400 0 stevel off_t g_filesz; /* Length of file */ 401 0 stevel time_t g_mtime; /* Modification time */ 402 0 stevel uint_t g_cksum; /* Checksum of file */ 403 0 stevel ulong_t g_devmajor, /* File system of file */ 404 0 stevel g_devminor; /* Major/minor of special files */ 405 0 stevel } Gen; 406 0 stevel 407 0 stevel static 408 0 stevel struct linkbuf { 409 0 stevel ino_t inum; 410 0 stevel dev_t devnum; 411 0 stevel int count; 412 0 stevel char pathname[MAXNAM+1]; /* added 1 for last NULL */ 413 0 stevel char attrname[MAXNAM+1]; 414 0 stevel struct linkbuf *nextp; 415 0 stevel } *ihead; 416 0 stevel 417 0 stevel /* see comments before build_table() */ 418 0 stevel #define TABLE_SIZE 512 419 6525 ceastha typedef struct file_list { 420 0 stevel char *name; /* Name of file to {in,ex}clude */ 421 0 stevel struct file_list *next; /* Linked list */ 422 6525 ceastha } file_list_t; 423 6525 ceastha static file_list_t *exclude_tbl[TABLE_SIZE], 424 6525 ceastha *include_tbl[TABLE_SIZE]; 425 0 stevel 426 1676 jpk static int append_secattr(char **, int *, int, char *, char); 427 0 stevel static void write_ancillary(union hblock *, char *, int, char); 428 0 stevel 429 6525 ceastha static void add_file_to_table(file_list_t *table[], char *str); 430 0 stevel static void assert_string(char *s, char *msg); 431 0 stevel static int istape(int fd, int type); 432 0 stevel static void backtape(void); 433 6525 ceastha static void build_table(file_list_t *table[], char *file); 434 5331 amw static int check_prefix(char **namep, char **dirp, char **compp); 435 0 stevel static void closevol(void); 436 0 stevel static void copy(void *dst, void *src); 437 0 stevel static int convtoreg(off_t); 438 3805 lovely static void delete_target(int fd, char *comp, char *namep); 439 0 stevel static void doDirTimes(char *name, timestruc_t modTime); 440 0 stevel static void done(int n); 441 0 stevel static void dorep(char *argv[]); 442 0 stevel #ifdef _iBCS2 443 0 stevel static void dotable(char *argv[], int cnt); 444 0 stevel static void doxtract(char *argv[], int cnt); 445 0 stevel #else 446 0 stevel static void dotable(char *argv[]); 447 0 stevel static void doxtract(char *argv[]); 448 0 stevel #endif 449 0 stevel static void fatal(char *format, ...); 450 0 stevel static void vperror(int exit_status, char *fmt, ...); 451 0 stevel static void flushtape(void); 452 0 stevel static void getdir(void); 453 0 stevel static void *getmem(size_t); 454 0 stevel static void longt(struct stat *st, char aclchar); 455 5482 as158974 static void load_info_from_xtarhdr(u_longlong_t flag, struct xtar_hdr *xhdrp); 456 0 stevel static int makeDir(char *name); 457 0 stevel static void mterr(char *operation, int i, int exitcode); 458 0 stevel static void newvol(void); 459 0 stevel static void passtape(void); 460 0 stevel static void putempty(blkcnt_t n); 461 0 stevel static int putfile(char *longname, char *shortname, char *parent, 462 5331 amw attr_data_t *attrinfo, int filetype, int lev, int symlink_lev); 463 0 stevel static void readtape(char *buffer); 464 0 stevel static void seekdisk(blkcnt_t blocks); 465 0 stevel static void setPathTimes(int dirfd, char *path, timestruc_t modTime); 466 5482 as158974 static void setbytes_to_skip(struct stat *st, int err); 467 0 stevel static void splitfile(char *longname, int ifd, char *name, 468 0 stevel char *prefix, int filetype); 469 0 stevel static void tomodes(struct stat *sp); 470 0 stevel static void usage(void); 471 5331 amw static int xblocks(int issysattr, off_t bytes, int ofile); 472 5331 amw static int xsfile(int issysattr, int ofd); 473 0 stevel static void resugname(int dirfd, char *name, int symflag); 474 0 stevel static int bcheck(char *bstr); 475 0 stevel static int checkdir(char *name); 476 0 stevel static int checksum(union hblock *dblockp); 477 0 stevel #ifdef EUC 478 0 stevel static int checksum_signed(union hblock *dblockp); 479 0 stevel #endif /* EUC */ 480 0 stevel static int checkupdate(char *arg); 481 0 stevel static int checkw(char c, char *name); 482 0 stevel static int cmp(char *b, char *s, int n); 483 0 stevel static int defset(char *arch); 484 0 stevel static int endtape(void); 485 6525 ceastha static int is_in_table(file_list_t *table[], char *str); 486 0 stevel static int notsame(void); 487 0 stevel static int is_prefix(char *s1, char *s2); 488 0 stevel static int response(void); 489 0 stevel static int build_dblock(const char *, const char *, const char, 490 0 stevel const int filetype, const struct stat *, const dev_t, const char *); 491 0 stevel static unsigned int hash(char *str); 492 0 stevel 493 0 stevel #ifdef _iBCS2 494 0 stevel static void initarg(char *argv[], char *file); 495 0 stevel static char *nextarg(); 496 0 stevel #endif 497 0 stevel static blkcnt_t kcheck(char *kstr); 498 0 stevel static off_t bsrch(char *s, int n, off_t l, off_t h); 499 0 stevel static void onintr(int sig); 500 0 stevel static void onquit(int sig); 501 0 stevel static void onhup(int sig); 502 0 stevel static uid_t getuidbyname(char *); 503 0 stevel static gid_t getgidbyname(char *); 504 0 stevel static char *getname(gid_t); 505 0 stevel static char *getgroup(gid_t); 506 0 stevel static int checkf(char *name, int mode, int howmuch); 507 0 stevel static int writetbuf(char *buffer, int n); 508 5331 amw static int wantit(char *argv[], char **namep, char **dirp, char **comp, 509 5331 amw attr_data_t **attrinfo); 510 1676 jpk static void append_ext_attr(char *shortname, char **secinfo, int *len); 511 0 stevel static int get_xdata(void); 512 0 stevel static void gen_num(const char *keyword, const u_longlong_t number); 513 0 stevel static void gen_date(const char *keyword, const timestruc_t time_value); 514 0 stevel static void gen_string(const char *keyword, const char *value); 515 0 stevel static void get_xtime(char *value, timestruc_t *xtime); 516 0 stevel static int chk_path_build(char *name, char *longname, char *linkname, 517 0 stevel char *prefix, char type, int filetype); 518 0 stevel static int gen_utf8_names(const char *filename); 519 0 stevel static int utf8_local(char *option, char **Xhdr_ptrptr, char *target, 520 0 stevel const char *src, int max_val); 521 0 stevel static int local_utf8(char **Xhdr_ptrptr, char *target, const char *src, 522 0 stevel iconv_t iconv_cd, int xhdrflg, int max_val); 523 0 stevel static int c_utf8(char *target, const char *source); 524 5331 amw static int getstat(int dirfd, char *longname, char *shortname, 525 5331 amw char *attrparent); 526 5331 amw static void xattrs_put(char *, char *, char *, char *); 527 0 stevel static void prepare_xattr(char **, char *, char *, 528 0 stevel char, struct linkbuf *, int *); 529 5331 amw static int put_link(char *name, char *longname, char *component, 530 5331 amw char *longattrname, char *prefix, int filetype, char typeflag); 531 0 stevel static int put_extra_attributes(char *longname, char *shortname, 532 5331 amw char *longattrname, char *prefix, int filetype, char typeflag); 533 5331 amw static int put_xattr_hdr(char *longname, char *shortname, char *longattrname, 534 5331 amw char *prefix, int typeflag, int filetype, struct linkbuf *lp); 535 5331 amw static int read_xattr_hdr(attr_data_t **attrinfo); 536 1676 jpk 537 1676 jpk /* Trusted Extensions */ 538 1676 jpk #define AUTO_ZONE "/zone" 539 1676 jpk 540 1676 jpk static void extract_attr(char **file_ptr, struct sec_attr *); 541 1676 jpk static int check_ext_attr(char *filename); 542 1676 jpk static void rebuild_comp_path(char *str, char **namep); 543 1676 jpk static int rebuild_lk_comp_path(char *str, char **namep); 544 1676 jpk 545 0 stevel static void get_parent(char *path, char *dir); 546 0 stevel static char *get_component(char *path); 547 5331 amw static int retry_open_attr(int pdirfd, int cwd, char *dirp, char *pattr, 548 5331 amw char *name, int oflag, mode_t mode); 549 0 stevel static char *skipslashes(char *string, char *start); 550 0 stevel static void chop_endslashes(char *path); 551 789 ahrens 552 0 stevel static struct stat stbuf; 553 0 stevel 554 5331 amw static char *myname; 555 0 stevel static int checkflag = 0; 556 0 stevel #ifdef _iBCS2 557 0 stevel static int Fileflag; 558 0 stevel char *sysv3_env; 559 0 stevel #endif 560 0 stevel static int Xflag, Fflag, iflag, hflag, Bflag, Iflag; 561 0 stevel static int rflag, xflag, vflag, tflag, mt, cflag, mflag, pflag; 562 0 stevel static int uflag; 563 0 stevel static int eflag, errflag, qflag; 564 0 stevel static int oflag; 565 0 stevel static int bflag, kflag, Aflag; 566 0 stevel static int Pflag; /* POSIX conformant archive */ 567 0 stevel static int Eflag; /* Allow files greater than 8GB */ 568 0 stevel static int atflag; /* traverse extended attributes */ 569 5331 amw static int saflag; /* traverse extended sys attributes */ 570 0 stevel static int Dflag; /* Data change flag */ 571 1676 jpk /* Trusted Extensions */ 572 1676 jpk static int Tflag; /* Trusted Extensions attr flags */ 573 1676 jpk static int dir_flag; /* for attribute extract */ 574 1676 jpk static int mld_flag; /* for attribute extract */ 575 1676 jpk static char *orig_namep; /* original namep - unadorned */ 576 1676 jpk static int rpath_flag; /* MLD real path is rebuilt */ 577 1676 jpk static char real_path[MAXPATHLEN]; /* MLD real path */ 578 1676 jpk static int lk_rpath_flag; /* linked to real path is rebuilt */ 579 1676 jpk static char lk_real_path[MAXPATHLEN]; /* linked real path */ 580 1676 jpk static bslabel_t bs_label; /* for attribute extract */ 581 1676 jpk static bslabel_t admin_low; 582 1676 jpk static bslabel_t admin_high; 583 1676 jpk static int ignored_aprivs = 0; 584 1676 jpk static int ignored_fprivs = 0; 585 1676 jpk static int ignored_fattrs = 0; 586 1676 jpk 587 0 stevel static int term, chksum, wflag, 588 0 stevel first = TRUE, defaults_used = FALSE, linkerrok; 589 0 stevel static blkcnt_t recno; 590 0 stevel static int freemem = 1; 591 0 stevel static int nblock = NBLOCK; 592 0 stevel static int Errflg = 0; 593 0 stevel static int exitflag = 0; 594 0 stevel 595 0 stevel static dev_t mt_dev; /* device containing output file */ 596 0 stevel static ino_t mt_ino; /* inode number of output file */ 597 0 stevel static int mt_devtype; /* dev type of archive, from stat structure */ 598 0 stevel 599 0 stevel static int update = 1; /* for `open' call */ 600 0 stevel 601 0 stevel static off_t low; 602 0 stevel static off_t high; 603 0 stevel 604 0 stevel static FILE *tfile; 605 0 stevel static FILE *vfile = stdout; 606 0 stevel static char tname[] = "/tmp/tarXXXXXX"; 607 0 stevel static char archive[] = "archive0="; 608 0 stevel static char *Xfile; 609 0 stevel static char *usefile; 610 0 stevel static char *Filefile; 611 0 stevel 612 0 stevel static int mulvol; /* multi-volume option selected */ 613 0 stevel static blkcnt_t blocklim; /* number of blocks to accept per volume */ 614 0 stevel static blkcnt_t tapepos; /* current block number to be written */ 615 0 stevel static int NotTape; /* true if tape is a disk */ 616 0 stevel static int dumping; /* true if writing a tape or other archive */ 617 0 stevel static int extno; /* number of extent: starts at 1 */ 618 0 stevel static int extotal; /* total extents in this file */ 619 0 stevel static off_t extsize; /* size of current extent during extraction */ 620 0 stevel static ushort_t Oumask = 0; /* old umask value */ 621 0 stevel static int is_posix; /* true if archive we're reading is POSIX-conformant */ 622 0 stevel static const char *magic_type = "ustar"; 623 0 stevel static size_t xrec_size = 8 * PATH_MAX; /* extended rec initial size */ 624 0 stevel static char *xrec_ptr; 625 0 stevel static off_t xrec_offset = 0; 626 0 stevel static int Xhdrflag; 627 0 stevel static int charset_type = 0; 628 0 stevel 629 0 stevel static u_longlong_t xhdr_flgs; /* Bits set determine which items */ 630 0 stevel /* need to be in extended header. */ 631 0 stevel #define _X_DEVMAJOR 0x1 632 0 stevel #define _X_DEVMINOR 0x2 633 0 stevel #define _X_GID 0x4 634 0 stevel #define _X_GNAME 0x8 635 0 stevel #define _X_LINKPATH 0x10 636 0 stevel #define _X_PATH 0x20 637 0 stevel #define _X_SIZE 0x40 638 0 stevel #define _X_UID 0x80 639 0 stevel #define _X_UNAME 0x100 640 0 stevel #define _X_ATIME 0x200 641 0 stevel #define _X_CTIME 0x400 642 0 stevel #define _X_MTIME 0x800 643 5482 as158974 #define _X_XHDR 0x1000 /* Bit flag that determines whether 'X' */ 644 5482 as158974 /* typeflag was followed by 'A' or non 'A' */ 645 5482 as158974 /* typeflag. */ 646 0 stevel #define _X_LAST 0x40000000 647 0 stevel 648 0 stevel #define PID_MAX_DIGITS (10 * sizeof (pid_t) / 4) 649 0 stevel #define TIME_MAX_DIGITS (10 * sizeof (time_t) / 4) 650 0 stevel #define LONG_MAX_DIGITS (10 * sizeof (long) / 4) 651 0 stevel #define ULONGLONG_MAX_DIGITS (10 * sizeof (u_longlong_t) / 4) 652 0 stevel /* 653 0 stevel * UTF_8 encoding requires more space than the current codeset equivalent. 654 0 stevel * Currently a factor of 2-3 would suffice, but it is possible for a factor 655 0 stevel * of 6 to be needed in the future, so for saftey, we use that here. 656 0 stevel */ 657 0 stevel #define UTF_8_FACTOR 6 658 0 stevel 659 0 stevel static u_longlong_t xhdr_count = 0; 660 0 stevel static char xhdr_dirname[PRESIZ + 1]; 661 0 stevel static char pidchars[PID_MAX_DIGITS + 1]; 662 0 stevel static char *tchar = ""; /* null linkpath */ 663 0 stevel 664 0 stevel static char local_path[UTF_8_FACTOR * PATH_MAX + 1]; 665 0 stevel static char local_linkpath[UTF_8_FACTOR * PATH_MAX + 1]; 666 0 stevel static char local_gname[UTF_8_FACTOR * _POSIX_NAME_MAX + 1]; 667 0 stevel static char local_uname[UTF_8_FACTOR * _POSIX_NAME_MAX + 1]; 668 0 stevel 669 0 stevel /* 670 0 stevel * The following mechanism is provided to allow us to debug tar in complicated 671 0 stevel * situations, like when it is part of a pipe. The idea is that you compile 672 0 stevel * with -DWAITAROUND defined, and then add the 'z' function modifier to the 673 0 stevel * target tar invocation, eg. "tar czf tarfile file". If stderr is available, 674 0 stevel * it will tell you to which pid to attach the debugger; otherwise, use ps to 675 0 stevel * find it. Attach to the process from the debugger, and, *PRESTO*, you are 676 0 stevel * there! 677 0 stevel * 678 0 stevel * Simply assign "waitaround = 0" once you attach to the process, and then 679 0 stevel * proceed from there as usual. 680 0 stevel */ 681 0 stevel 682 0 stevel #ifdef WAITAROUND 683 0 stevel int waitaround = 0; /* wait for rendezvous with the debugger */ 684 0 stevel #endif 685 0 stevel 686 0 stevel 687 0 stevel int 688 0 stevel main(int argc, char *argv[]) 689 0 stevel { 690 0 stevel char *cp; 691 0 stevel char *tmpdirp; 692 0 stevel pid_t thispid; 693 0 stevel 694 0 stevel #ifdef _iBCS2 695 0 stevel int tbl_cnt = 0; 696 0 stevel sysv3_env = getenv("SYSV3"); 697 0 stevel #endif 698 0 stevel (void) setlocale(LC_ALL, ""); 699 0 stevel #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 700 0 stevel #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 701 0 stevel #endif 702 0 stevel (void) textdomain(TEXT_DOMAIN); 703 0 stevel if (argc < 2) 704 0 stevel usage(); 705 0 stevel 706 0 stevel tfile = NULL; 707 5331 amw if ((myname = strdup(argv[0])) == NULL) { 708 5331 amw (void) fprintf(stderr, gettext( 709 5331 amw "tar: cannot allocate program name\n")); 710 5331 amw exit(1); 711 5331 amw } 712 0 stevel 713 4774 as145665 if (init_yes() < 0) { 714 4774 as145665 (void) fprintf(stderr, gettext(ERR_MSG_INIT_YES), 715 4774 as145665 strerror(errno)); 716 4774 as145665 exit(2); 717 4774 as145665 } 718 4774 as145665 719 0 stevel /* 720 0 stevel * For XPG4 compatibility, we must be able to accept the "--" 721 0 stevel * argument normally recognized by getopt; it is used to delimit 722 0 stevel * the end opt the options section, and so can only appear in 723 0 stevel * the position of the first argument. We simply skip it. 724 0 stevel */ 725 0 stevel 726 0 stevel if (strcmp(argv[1], "--") == 0) { 727 0 stevel argv++; 728 0 stevel argc--; 729 0 stevel if (argc < 3) 730 0 stevel usage(); 731 0 stevel } 732 0 stevel 733 0 stevel argv[argc] = NULL; 734 0 stevel argv++; 735 0 stevel 736 0 stevel /* 737 0 stevel * Set up default values. 738 0 stevel * Search the operand string looking for the first digit or an 'f'. 739 0 stevel * If you find a digit, use the 'archive#' entry in DEF_FILE. 740 0 stevel * If 'f' is given, bypass looking in DEF_FILE altogether. 741 0 stevel * If no digit or 'f' is given, still look in DEF_FILE but use '0'. 742 0 stevel */ 743 0 stevel if ((usefile = getenv("TAPE")) == (char *)NULL) { 744 0 stevel for (cp = *argv; *cp; ++cp) 745 0 stevel if (isdigit(*cp) || *cp == 'f') 746 0 stevel break; 747 0 stevel if (*cp != 'f') { 748 0 stevel archive[7] = (*cp)? *cp: '0'; 749 0 stevel if (!(defaults_used = defset(archive))) { 750 0 stevel usefile = NULL; 751 0 stevel nblock = 1; 752 0 stevel blocklim = 0; 753 0 stevel NotTape = 0; 754 0 stevel } 755 0 stevel } 756 0 stevel } 757 0 stevel 758 0 stevel for (cp = *argv++; *cp; cp++) 759 0 stevel switch (*cp) { 760 0 stevel #ifdef WAITAROUND 761 0 stevel case 'z': 762 0 stevel /* rendezvous with the debugger */ 763 0 stevel waitaround = 1; 764 0 stevel break; 765 0 stevel #endif 766 0 stevel case 'f': 767 0 stevel assert_string(*argv, gettext( 768 0 stevel "tar: tarfile must be specified with 'f' " 769 0 stevel "function modifier\n")); 770 0 stevel usefile = *argv++; 771 0 stevel break; 772 0 stevel case 'F': 773 0 stevel #ifdef _iBCS2 774 0 stevel if (sysv3_env) { 775 0 stevel assert_string(*argv, gettext( 776 1266 ceastha "tar: 'F' requires a file name\n")); 777 0 stevel Filefile = *argv++; 778 0 stevel Fileflag++; 779 0 stevel } else 780 0 stevel #endif /* _iBCS2 */ 781 0 stevel Fflag++; 782 0 stevel break; 783 0 stevel case 'c': 784 0 stevel cflag++; 785 0 stevel rflag++; 786 0 stevel update = 1; 787 0 stevel break; 788 0 stevel #if defined(O_XATTR) 789 0 stevel case '@': 790 0 stevel atflag++; 791 0 stevel break; 792 5331 amw #endif /* O_XATTR */ 793 5331 amw #if defined(_PC_SATTR_ENABLED) 794 5331 amw case '/': 795 5331 amw saflag++; 796 5331 amw break; 797 5331 amw #endif /* _PC_SATTR_ENABLED */ 798 0 stevel case 'u': 799 0 stevel uflag++; /* moved code after signals caught */ 800 0 stevel rflag++; 801 0 stevel update = 2; 802 0 stevel break; 803 0 stevel case 'r': 804 0 stevel rflag++; 805 0 stevel update = 2; 806 0 stevel break; 807 0 stevel case 'v': 808 0 stevel vflag++; 809 0 stevel break; 810 0 stevel case 'w': 811 0 stevel wflag++; 812 0 stevel break; 813 0 stevel case 'x': 814 0 stevel xflag++; 815 0 stevel break; 816 0 stevel case 'X': 817 0 stevel assert_string(*argv, gettext( 818 0 stevel "tar: exclude file must be specified with 'X' " 819 0 stevel "function modifier\n")); 820 0 stevel Xflag = 1; 821 0 stevel Xfile = *argv++; 822 0 stevel build_table(exclude_tbl, Xfile); 823 0 stevel break; 824 0 stevel case 't': 825 0 stevel tflag++; 826 0 stevel break; 827 0 stevel case 'm': 828 0 stevel mflag++; 829 0 stevel break; 830 0 stevel case 'p': 831 0 stevel pflag++; 832 0 stevel break; 833 0 stevel case 'D': 834 0 stevel Dflag++; 835 0 stevel break; 836 0 stevel case '-': 837 0 stevel /* ignore this silently */ 838 0 stevel break; 839 0 stevel case '0': /* numeric entries used only for defaults */ 840 0 stevel case '1': 841 0 stevel case '2': 842 0 stevel case '3': 843 0 stevel case '4': 844 0 stevel case '5': 845 0 stevel case '6': 846 0 stevel case '7': 847 0 stevel break; 848 0 stevel case 'b': 849 0 stevel assert_string(*argv, gettext( 850 0 stevel "tar: blocking factor must be specified " 851 0 stevel "with 'b' function modifier\n")); 852 0 stevel bflag++; 853 0 stevel nblock = bcheck(*argv++); 854 0 stevel break; 855 0 stevel case 'q': 856 0 stevel qflag++; 857 0 stevel break; 858 0 stevel case 'k': 859 0 stevel assert_string(*argv, gettext( 860 0 stevel "tar: size value must be specified with 'k' " 861 0 stevel "function modifier\n")); 862 0 stevel kflag++; 863 0 stevel blocklim = kcheck(*argv++); 864 0 stevel break; 865 0 stevel case 'n': /* not a magtape (instead of 'k') */ 866 0 stevel NotTape++; /* assume non-magtape */ 867 0 stevel break; 868 0 stevel case 'l': 869 0 stevel linkerrok++; 870 0 stevel break; 871 0 stevel case 'e': 872 0 stevel #ifdef _iBCS2 873 0 stevel /* If sysv3 IS set, don't be as verbose */ 874 0 stevel if (!sysv3_env) 875 0 stevel #endif /* _iBCS2 */ 876 0 stevel errflag++; 877 0 stevel eflag++; 878 0 stevel break; 879 0 stevel case 'o': 880 0 stevel oflag++; 881 0 stevel break; 882 0 stevel case 'h': 883 0 stevel hflag++; 884 0 stevel break; 885 0 stevel case 'i': 886 0 stevel iflag++; 887 0 stevel break; 888 0 stevel case 'B': 889 0 stevel Bflag++; 890 0 stevel break; 891 0 stevel case 'P': 892 0 stevel Pflag++; 893 0 stevel break; 894 0 stevel case 'E': 895 0 stevel Eflag++; 896 0 stevel Pflag++; /* Only POSIX archive made */ 897 0 stevel break; 898 1676 jpk case 'T': 899 1676 jpk Tflag++; /* Handle Trusted Extensions attrs */ 900 1676 jpk pflag++; /* also set flag for ACL */ 901 1676 jpk break; 902 0 stevel default: 903 0 stevel (void) fprintf(stderr, gettext( 904 0 stevel "tar: %c: unknown function modifier\n"), *cp); 905 0 stevel usage(); 906 0 stevel } 907 0 stevel 908 0 stevel #ifdef _iBCS2 909 0 stevel if (Xflag && Fileflag) { 910 0 stevel (void) fprintf(stderr, gettext( 911 0 stevel "tar: specify only one of X or F.\n")); 912 0 stevel usage(); 913 0 stevel } 914 0 stevel #endif /* _iBCS2 */ 915 0 stevel 916 0 stevel if (!rflag && !xflag && !tflag) 917 0 stevel usage(); 918 0 stevel if ((rflag && xflag) || (xflag && tflag) || (rflag && tflag)) { 919 0 stevel (void) fprintf(stderr, gettext( 920 0 stevel "tar: specify only one of [ctxru].\n")); 921 1676 jpk usage(); 922 1676 jpk } 923 1676 jpk /* Trusted Extensions attribute handling */ 924 1676 jpk if (Tflag && ((getzoneid() != GLOBAL_ZONEID) || 925 1676 jpk !is_system_labeled())) { 926 1676 jpk (void) fprintf(stderr, gettext( 927 1676 jpk "tar: the 'T' option is only available with " 928 1676 jpk "Trusted Extensions\nand must be run from " 929 1676 jpk "the global zone.\n")); 930 0 stevel usage(); 931 0 stevel } 932 0 stevel if (cflag && *argv == NULL && Filefile == NULL) 933 0 stevel fatal(gettext("Missing filenames")); 934 0 stevel if (usefile == NULL) 935 0 stevel fatal(gettext("device argument required")); 936 0 stevel 937 0 stevel /* alloc a buffer of the right size */ 938 0 stevel if ((tbuf = (union hblock *) 939 1266 ceastha calloc(sizeof (union hblock) * nblock, sizeof (char))) == 940 1266 ceastha (union hblock *)NULL) { 941 0 stevel (void) fprintf(stderr, gettext( 942 0 stevel "tar: cannot allocate physio buffer\n")); 943 0 stevel exit(1); 944 0 stevel } 945 0 stevel 946 0 stevel if ((xrec_ptr = malloc(xrec_size)) == NULL) { 947 0 stevel (void) fprintf(stderr, gettext( 948 0 stevel "tar: cannot allocate extended header buffer\n")); 949 0 stevel exit(1); 950 0 stevel } 951 0 stevel 952 0 stevel #ifdef WAITAROUND 953 0 stevel if (waitaround) { 954 0 stevel (void) fprintf(stderr, gettext("Rendezvous with tar on pid" 955 0 stevel " %d\n"), getpid()); 956 0 stevel 957 0 stevel while (waitaround) { 958 0 stevel (void) sleep(10); 959 0 stevel } 960 0 stevel } 961 0 stevel #endif 962 0 stevel 963 0 stevel thispid = getpid(); 964 0 stevel (void) sprintf(pidchars, "%ld", thispid); 965 0 stevel thispid = strlen(pidchars); 966 0 stevel 967 0 stevel if ((tmpdirp = getenv("TMPDIR")) == (char *)NULL) 968 0 stevel (void) strcpy(xhdr_dirname, "/tmp"); 969 0 stevel else { 970 0 stevel /* 971 0 stevel * Make sure that dir is no longer than what can 972 0 stevel * fit in the prefix part of the header. 973 0 stevel */ 974 0 stevel if (strlen(tmpdirp) > (size_t)(PRESIZ - thispid - 12)) { 975 0 stevel (void) strcpy(xhdr_dirname, "/tmp"); 976 0 stevel if ((vflag > 0) && (Eflag > 0)) 977 0 stevel (void) fprintf(stderr, gettext( 978 0 stevel "Ignoring TMPDIR\n")); 979 0 stevel } else 980 0 stevel (void) strcpy(xhdr_dirname, tmpdirp); 981 0 stevel } 982 0 stevel (void) strcat(xhdr_dirname, "/PaxHeaders."); 983 0 stevel (void) strcat(xhdr_dirname, pidchars); 984 0 stevel 985 0 stevel if (rflag) { 986 0 stevel if (cflag && tfile != NULL) 987 0 stevel usage(); 988 0 stevel if (signal(SIGINT, SIG_IGN) != SIG_IGN) 989 0 stevel (void) signal(SIGINT, onintr); 990 0 stevel if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 991 0 stevel (void) signal(SIGHUP, onhup); 992 0 stevel if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) 993 0 stevel (void) signal(SIGQUIT, onquit); 994 0 stevel if (uflag) { 995 0 stevel int tnum; 996 0 stevel if ((tnum = mkstemp(tname)) == -1) 997 0 stevel vperror(1, "%s", tname); 998 0 stevel if ((tfile = fdopen(tnum, "w")) == NULL) 999 0 stevel vperror(1, "%s", tname); 1000 0 stevel } 1001 0 stevel if (strcmp(usefile, "-") == 0) { 1002 0 stevel if (cflag == 0) 1003 0 stevel fatal(gettext( 1004 0 stevel "can only create standard output archives.")); 1005 0 stevel vfile = stderr; 1006 0 stevel mt = dup(1); 1007 0 stevel ++bflag; 1008 0 stevel } else { 1009 0 stevel if (cflag) 1010 0 stevel mt = open(usefile, 1011 0 stevel O_RDWR|O_CREAT|O_TRUNC, 0666); 1012 0 stevel else 1013 0 stevel mt = open(usefile, O_RDWR); 1014 0 stevel 1015 0 stevel if (mt < 0) { 1016 0 stevel if (cflag == 0 || (mt = creat(usefile, 0666)) 1017 1266 ceastha < 0) 1018 0 stevel vperror(1, "%s", usefile); 1019 0 stevel } 1020 0 stevel } 1021 0 stevel /* Get inode and device number of output file */ 1022 0 stevel (void) fstat(mt, &stbuf); 1023 0 stevel mt_ino = stbuf.st_ino; 1024 0 stevel mt_dev = stbuf.st_dev; 1025 0 stevel mt_devtype = stbuf.st_mode & S_IFMT; 1026 0 stevel NotTape = !istape(mt, mt_devtype); 1027 0 stevel 1028 0 stevel if (rflag && !cflag && (mt_devtype == S_IFIFO)) 1029 0 stevel fatal(gettext("cannot append to pipe or FIFO.")); 1030 0 stevel 1031 0 stevel if (Aflag && vflag) 1032 0 stevel (void) printf( 1033 0 stevel gettext("Suppressing absolute pathnames\n")); 1034 0 stevel dorep(argv); 1035 0 stevel } else if (xflag || tflag) { 1036 0 stevel /* 1037 0 stevel * for each argument, check to see if there is a "-I file" pair. 1038 0 stevel * if so, move the 3rd argument into "-I"'s place, build_table() 1039 0 stevel * using "file"'s name and increment argc one (the second 1040 0 stevel * increment appears in the for loop) which removes the two 1041 0 stevel * args "-I" and "file" from the argument vector. 1042 0 stevel */ 1043 0 stevel for (argc = 0; argv[argc]; argc++) { 1044 0 stevel if (strcmp(argv[argc], "-I") == 0) { 1045 0 stevel if (!argv[argc+1]) { 1046 0 stevel (void) fprintf(stderr, gettext( 1047 0 stevel "tar: missing argument for -I flag\n")); 1048 0 stevel done(2); 1049 0 stevel } else { 1050 0 stevel Iflag = 1; 1051 0 stevel argv[argc] = argv[argc+2]; 1052 0 stevel build_table(include_tbl, argv[++argc]); 1053 0 stevel #ifdef _iBCS2 1054 0 stevel if (Fileflag) { 1055 0 stevel (void) fprintf(stderr, gettext( 1056 0 stevel "tar: only one of I or F.\n")); 1057 0 stevel usage(); 1058 0 stevel } 1059 0 stevel #endif /* _iBCS2 */ 1060 0 stevel 1061 0 stevel } 1062 0 stevel } 1063 0 stevel } 1064 0 stevel if (strcmp(usefile, "-") == 0) { 1065 0 stevel mt = dup(0); 1066 0 stevel ++bflag; 1067 0 stevel /* try to recover from short reads when reading stdin */ 1068 0 stevel ++Bflag; 1069 0 stevel } else if ((mt = open(usefile, 0)) < 0) 1070 0 stevel vperror(1, "%s", usefile); 1071 0 stevel 1072 0 stevel if (xflag) { 1073 0 stevel if (Aflag && vflag) 1074 1266 ceastha (void) printf(gettext( 1075 1266 ceastha "Suppressing absolute pathnames.\n")); 1076 0 stevel 1077 0 stevel #ifdef _iBCS2 1078 0 stevel doxtract(argv, tbl_cnt); 1079 0 stevel #else 1080 0 stevel doxtract(argv); 1081 0 stevel #endif 1082 0 stevel } else if (tflag) 1083 0 stevel 1084 0 stevel #ifdef _iBCS2 1085 0 stevel dotable(argv, tbl_cnt); 1086 0 stevel #else 1087 0 stevel dotable(argv); 1088 0 stevel #endif 1089 0 stevel } 1090 0 stevel else 1091 0 stevel usage(); 1092 0 stevel 1093 0 stevel done(Errflg); 1094 0 stevel 1095 0 stevel /* Not reached: keep compiler quiet */ 1096 0 stevel return (1); 1097 0 stevel } 1098 0 stevel 1099 0 stevel static void 1100 0 stevel usage(void) 1101 0 stevel { 1102 0 stevel 1103 0 stevel #ifdef _iBCS2 1104 0 stevel if (sysv3_env) { 1105 0 stevel (void) fprintf(stderr, gettext( 1106 0 stevel #if defined(O_XATTR) 1107 5331 amw #if defined(_PC_SATTR_ENABLED) 1108 5331 amw "Usage: tar {c|r|t|u|x}[BDeEhilmnopPqTvw@/[0-7]][bfFk][X...] " 1109 5331 amw #else 1110 1676 jpk "Usage: tar {c|r|t|u|x}[BDeEhilmnopPqTvw@[0-7]][bfFk][X...] " 1111 5331 amw #endif /* _PC_SATTR_ENABLED */ 1112 1676 jpk #else 1113 1676 jpk "Usage: tar {c|r|t|u|x}[BDeEhilmnopPqTvw[0-7]][bfFk][X...] " 1114 5331 amw #endif /* O_XATTR */ 1115 0 stevel "[blocksize] [tarfile] [filename] [size] [exclude-file...] " 1116 0 stevel "{file | -I include-file | -C directory file}...\n")); 1117 0 stevel } else 1118 0 stevel #endif /* _iBCS2 */ 1119 0 stevel { 1120 0 stevel (void) fprintf(stderr, gettext( 1121 0 stevel #if defined(O_XATTR) 1122 5331 amw #if defined(_PC_SATTR_ENABLED) 1123 5331 amw "Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqTvw@/[0-7]][bfk][X...] " 1124 5331 amw #else 1125 1676 jpk "Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqTvw@[0-7]][bfk][X...] " 1126 5331 amw #endif /* _PC_SATTR_ENABLED */ 1127 1676 jpk #else 1128 1676 jpk "Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqTvw[0-7]][bfk][X...] " 1129 5331 amw #endif /* O_XATTR */ 1130 0 stevel "[blocksize] [tarfile] [size] [exclude-file...] " 1131 0 stevel "{file | -I include-file | -C directory file}...\n")); 1132 0 stevel } 1133 0 stevel done(1); 1134 0 stevel } 1135 0 stevel 1136 0 stevel /* 1137 0 stevel * dorep - do "replacements" 1138 0 stevel * 1139 0 stevel * Dorep is responsible for creating ('c'), appending ('r') 1140 0 stevel * and updating ('u'); 1141 0 stevel */ 1142 0 stevel 1143 0 stevel static void 1144 0 stevel dorep(char *argv[]) 1145 0 stevel { 1146 0 stevel char *cp, *cp2, *p; 1147 0 stevel char wdir[PATH_MAX+2], tempdir[PATH_MAX+2], *parent; 1148 0 stevel char file[PATH_MAX*2], origdir[PATH_MAX+1]; 1149 0 stevel FILE *fp = (FILE *)NULL; 1150 0 stevel FILE *ff = (FILE *)NULL; 1151 0 stevel int archtype; 1152 5482 as158974 int ret; 1153 0 stevel 1154 0 stevel 1155 0 stevel if (!cflag) { 1156 0 stevel xhdr_flgs = 0; 1157 0 stevel getdir(); /* read header for next file */ 1158 0 stevel if (Xhdrflag > 0) { 1159 0 stevel if (!Eflag) 1160 0 stevel fatal(gettext("Archive contains extended" 1161 0 stevel " header. -E flag required.\n")); 1162 5482 as158974 ret = get_xdata(); /* Get extended header items */ 1163 0 stevel /* and regular header */ 1164 0 stevel } else { 1165 0 stevel if (Eflag) 1166 0 stevel fatal(gettext("Archive contains no extended" 1167 0 stevel " header. -E flag not allowed.\n")); 1168 0 stevel } 1169 0 stevel while (!endtape()) { /* changed from a do while */ 1170 5482 as158974 setbytes_to_skip(&stbuf, ret); 1171 0 stevel passtape(); /* skip the file data */ 1172 0 stevel if (term) 1173 0 stevel done(Errflg); /* received signal to stop */ 1174 0 stevel xhdr_flgs = 0; 1175 0 stevel getdir(); 1176 0 stevel if (Xhdrflag > 0) 1177 5482 as158974 ret = get_xdata(); 1178 5482 as158974 } 1179 5482 as158974 if (ret == 0) { 1180 5482 as158974 if ((dblock.dbuf.typeflag != 'A') && 1181 5482 as158974 (xhdr_flgs != 0)) { 1182 5482 as158974 load_info_from_xtarhdr(xhdr_flgs, 1183 5482 as158974 &Xtarhdr); 1184 5482 as158974 xhdr_flgs |= _X_XHDR; 1185 5482 as158974 } 1186 0 stevel } 1187 0 stevel backtape(); /* was called by endtape */ 1188 0 stevel if (tfile != NULL) { 1189 0 stevel char buf[200]; 1190 0 stevel 1191 0 stevel (void) sprintf(buf, "sort +0 -1 +1nr %s -o %s; awk '$1 " 1192 0 stevel "!= prev {print; prev=$1}' %s >%sX;mv %sX %s", 1193 1266 ceastha tname, tname, tname, tname, tname, tname); 1194 0 stevel (void) fflush(tfile); 1195 0 stevel (void) system(buf); 1196 0 stevel (void) freopen(tname, "r", tfile); 1197 0 stevel (void) fstat(fileno(tfile), &stbuf); 1198 0 stevel high = stbuf.st_size; 1199 0 stevel } 1200 0 stevel } 1201 0 stevel 1202 0 stevel dumping = 1; 1203 0 stevel if (mulvol) { /* SP-1 */ 1204 0 stevel if (nblock && (blocklim%nblock) != 0) 1205 0 stevel fatal(gettext( 1206 0 stevel "Volume size not a multiple of block size.")); 1207 0 stevel blocklim -= 2; /* for trailer records */ 1208 0 stevel if (vflag) 1209 0 stevel (void) fprintf(vfile, gettext("Volume ends at %" 1210 0 stevel FMT_blkcnt_t "K, blocking factor = %dK\n"), 1211 0 stevel K((blocklim - 1)), K(nblock)); 1212 0 stevel } 1213 0 stevel 1214 0 stevel #ifdef _iBCS2 1215 0 stevel if (Fileflag) { 1216 0 stevel if (Filefile != NULL) { 1217 0 stevel if ((ff = fopen(Filefile, "r")) == NULL) 1218 0 stevel vperror(0, "%s", Filefile); 1219 0 stevel } else { 1220 0 stevel (void) fprintf(stderr, gettext( 1221 0 stevel "tar: F requires a file name.\n")); 1222 0 stevel usage(); 1223 0 stevel } 1224 0 stevel } 1225 0 stevel #endif /* _iBCS2 */ 1226 0 stevel 1227 0 stevel /* 1228 0 stevel * Save the original directory before it gets 1229 0 stevel * changed. 1230 0 stevel */ 1231 0 stevel if (getcwd(origdir, (PATH_MAX+1)) == NULL) { 1232 0 stevel vperror(0, gettext("A parent directory cannot be read")); 1233 0 stevel exit(1); 1234 0 stevel } 1235 0 stevel 1236 0 stevel (void) strcpy(wdir, origdir); 1237 0 stevel 1238 0 stevel while ((*argv || fp || ff) && !term) { 1239 0 stevel if (fp || (strcmp(*argv, "-I") == 0)) { 1240 0 stevel #ifdef _iBCS2 1241 0 stevel if (Fileflag) { 1242 0 stevel (void) fprintf(stderr, gettext( 1243 0 stevel "tar: only one of I or F.\n")); 1244 0 stevel usage(); 1245 0 stevel } 1246 0 stevel #endif /* _iBCS2 */ 1247 0 stevel if (fp == NULL) { 1248 0 stevel if (*++argv == NULL) 1249 0 stevel fatal(gettext( 1250 0 stevel "missing file name for -I flag.")); 1251 0 stevel else if ((fp = fopen(*argv++, "r")) == NULL) 1252 0 stevel vperror(0, "%s", argv[-1]); 1253 0 stevel continue; 1254 0 stevel } else if ((fgets(file, PATH_MAX-1, fp)) == NULL) { 1255 0 stevel (void) fclose(fp); 1256 0 stevel fp = NULL; 1257 0 stevel continue; 1258 0 stevel } else { 1259 0 stevel cp = cp2 = file; 1260 0 stevel if ((p = strchr(cp2, '\n'))) 1261 0 stevel *p = 0; 1262 0 stevel } 1263 0 stevel } else if ((strcmp(*argv, "-C") == 0) && argv[1]) { 1264 0 stevel #ifdef _iBCS2 1265 0 stevel if (Fileflag) { 1266 0 stevel (void) fprintf(stderr, gettext( 1267 0 stevel "tar: only one of F or C\n")); 1268 0 stevel usage(); 1269 0 stevel } 1270 0 stevel #endif /* _iBCS2 */ 1271 0 stevel 1272 0 stevel if (chdir(*++argv) < 0) 1273 0 stevel vperror(0, gettext( 1274 5331 amw "can't change directories to %s"), *argv); 1275 0 stevel else 1276 0 stevel (void) getcwd(wdir, (sizeof (wdir))); 1277 0 stevel argv++; 1278 0 stevel continue; 1279 0 stevel #ifdef _iBCS2 1280 0 stevel } else if (Fileflag && (ff != NULL)) { 1281 0 stevel if ((fgets(file, PATH_MAX-1, ff)) == NULL) { 1282 0 stevel (void) fclose(ff); 1283 0 stevel ff = NULL; 1284 0 stevel continue; 1285 0 stevel } else { 1286 0 stevel cp = cp2 = file; 1287 0 stevel if (p = strchr(cp2, '\n')) 1288 0 stevel *p = 0; 1289 0 stevel } 1290 0 stevel #endif /* _iBCS2 */ 1291 0 stevel } else 1292 0 stevel cp = cp2 = strcpy(file, *argv++); 1293 0 stevel 1294 0 stevel /* 1295 0 stevel * point cp2 to the last '/' in file, but not 1296 0 stevel * to a trailing '/' 1297 0 stevel */ 1298 0 stevel for (; *cp; cp++) { 1299 0 stevel if (*cp == '/') { 1300 0 stevel while (*(cp+1) == '/') { 1301 0 stevel ++cp; 1302 0 stevel } 1303 0 stevel if (*(cp+1) != '\0') { 1304 0 stevel /* not trailing slash */ 1305 0 stevel cp2 = cp; 1306 0 stevel } 1307 0 stevel } 1308 0 stevel } 1309 0 stevel if (cp2 != file) { 1310 0 stevel *cp2 = '\0'; 1311 0 stevel if (chdir(file) < 0) { 1312 0 stevel vperror(0, gettext( 1313 5331 amw "can't change directories to %s"), file); 1314 0 stevel continue; 1315 0 stevel } 1316 0 stevel *cp2 = '/'; 1317 0 stevel cp2++; 1318 0 stevel } 1319 0 stevel 1320 0 stevel parent = getcwd(tempdir, (sizeof (tempdir))); 1321 5331 amw 1322 5331 amw archtype = putfile(file, cp2, parent, NULL, NORMAL_FILE, 1323 0 stevel LEV0, SYMLINK_LEV0); 1324 0 stevel 1325 0 stevel #if defined(O_XATTR) 1326 0 stevel if (!exitflag) { 1327 5331 amw if ((atflag || saflag) && 1328 5331 amw (archtype == PUT_NOTAS_LINK)) { 1329 5331 amw xattrs_put(file, cp2, parent, NULL); 1330 0 stevel } 1331 0 stevel } 1332 0 stevel #endif 1333 0 stevel 1334 0 stevel if (chdir(origdir) < 0) 1335 0 stevel vperror(0, gettext("cannot change back?: %s"), origdir); 1336 0 stevel 1337 0 stevel if (exitflag) { 1338 0 stevel /* 1339 0 stevel * If e function modifier has been specified 1340 0 stevel * write the files (that are listed before the 1341 0 stevel * file causing the error) to tape. exitflag is 1342 0 stevel * used because only some of the error conditions 1343 0 stevel * in putfile() recognize the e function modifier. 1344 0 stevel */ 1345 0 stevel break; 1346 0 stevel } 1347 0 stevel } 1348 0 stevel 1349 0 stevel putempty((blkcnt_t)2); 1350 0 stevel flushtape(); 1351 0 stevel closevol(); /* SP-1 */ 1352 0 stevel if (linkerrok == 1) 1353 0 stevel for (; ihead != NULL; ihead = ihead->nextp) { 1354 0 stevel if (ihead->count == 0) 1355 0 stevel continue; 1356 0 stevel (void) fprintf(stderr, gettext( 1357 0 stevel "tar: missing links to %s\n"), ihead->pathname); 1358 0 stevel if (errflag) 1359 0 stevel done(1); 1360 0 stevel else 1361 0 stevel Errflg = 1; 1362 0 stevel } 1363 0 stevel } 1364 0 stevel 1365 0 stevel 1366 0 stevel /* 1367 0 stevel * endtape - check for tape at end 1368 0 stevel * 1369 0 stevel * endtape checks the entry in dblock.dbuf to see if its the 1370 0 stevel * special EOT entry. Endtape is usually called after getdir(). 1371 0 stevel * 1372 0 stevel * endtape used to call backtape; it no longer does, he who 1373 0 stevel * wants it backed up must call backtape himself 1374 0 stevel * RETURNS: 0 if not EOT, tape position unaffected 1375 0 stevel * 1 if EOT, tape position unaffected 1376 0 stevel */ 1377 0 stevel 1378 0 stevel static int 1379 0 stevel endtape(void) 1380 0 stevel { 1381 0 stevel if (dblock.dbuf.name[0] == '\0') { /* null header = EOT */ 1382 0 stevel return (1); 1383 0 stevel } else 1384 0 stevel return (0); 1385 0 stevel } 1386 0 stevel 1387 0 stevel /* 1388 0 stevel * getdir - get directory entry from tar tape 1389 0 stevel * 1390 0 stevel * getdir reads the next tarblock off the tape and cracks 1391 0 stevel * it as a directory. The checksum must match properly. 1392 0 stevel * 1393 0 stevel * If tfile is non-null getdir writes the file name and mod date 1394 0 stevel * to tfile. 1395 0 stevel */ 1396 0 stevel 1397 0 stevel static void 1398 0 stevel getdir(void) 1399 0 stevel { 1400 0 stevel struct stat *sp; 1401 0 stevel #ifdef EUC 1402 0 stevel static int warn_chksum_sign = 0; 1403 0 stevel #endif /* EUC */ 1404 0 stevel 1405 0 stevel top: 1406 0 stevel readtape((char *)&dblock); 1407 0 stevel if (dblock.dbuf.name[0] == '\0') 1408 0 stevel return; 1409 0 stevel sp = &stbuf; 1410 0 stevel (void) sscanf(dblock.dbuf.mode, "%8lo", &Gen.g_mode); 1411 0 stevel (void) sscanf(dblock.dbuf.uid, "%8lo", (ulong_t *)&Gen.g_uid); 1412 0 stevel (void) sscanf(dblock.dbuf.gid, "%8lo", (ulong_t *)&Gen.g_gid); 1413 0 stevel (void) sscanf(dblock.dbuf.size, "%12" FMT_off_t_o, &Gen.g_filesz); 1414 0 stevel (void) sscanf(dblock.dbuf.mtime, "%12lo", (ulong_t *)&Gen.g_mtime); 1415 0 stevel (void) sscanf(dblock.dbuf.chksum, "%8o", &Gen.g_cksum); 1416 0 stevel (void) sscanf(dblock.dbuf.devmajor, "%8lo", &Gen.g_devmajor); 1417 0 stevel (void) sscanf(dblock.dbuf.devminor, "%8lo", &Gen.g_devminor); 1418 0 stevel 1419 0 stevel is_posix = (strcmp(dblock.dbuf.magic, magic_type) == 0); 1420 0 stevel 1421 0 stevel sp->st_mode = Gen.g_mode; 1422 0 stevel if (is_posix && (sp->st_mode & S_IFMT) == 0) 1423 0 stevel switch (dblock.dbuf.typeflag) { 1424 0 stevel case '0': case 0: case _XATTR_HDRTYPE: 1425 0 stevel sp->st_mode |= S_IFREG; 1426 0 stevel break; 1427 0 stevel case '1': /* hard link */ 1428 0 stevel break; 1429 0 stevel case '2': 1430 0 stevel sp->st_mode |= S_IFLNK; 1431 0 stevel break; 1432 0 stevel case '3': 1433 0 stevel sp->st_mode |= S_IFCHR; 1434 0 stevel break; 1435 0 stevel case '4': 1436 0 stevel sp->st_mode |= S_IFBLK; 1437 0 stevel break; 1438 0 stevel case '5': 1439 0 stevel sp->st_mode |= S_IFDIR; 1440 0 stevel break; 1441 0 stevel case '6': 1442 0 stevel sp->st_mode |= S_IFIFO; 1443 0 stevel break; 1444 0 stevel default: 1445 0 stevel if (convtoreg(Gen.g_filesz)) 1446 0 stevel sp->st_mode |= S_IFREG; 1447 0 stevel break; 1448 0 stevel } 1449 0 stevel 1450 0 stevel if (dblock.dbuf.typeflag == 'X') 1451 0 stevel Xhdrflag = 1; /* Currently processing extended header */ 1452 0 stevel else 1453 0 stevel Xhdrflag = 0; 1454 0 stevel 1455 0 stevel sp->st_uid = Gen.g_uid; 1456 0 stevel sp->st_gid = Gen.g_gid; 1457 0 stevel sp->st_size = Gen.g_filesz; 1458 0 stevel sp->st_mtime = Gen.g_mtime; 1459 0 stevel chksum = Gen.g_cksum; 1460 0 stevel 1461 0 stevel if (dblock.dbuf.extno != '\0') { /* split file? */ 1462 0 stevel extno = dblock.dbuf.extno; 1463 0 stevel extsize = Gen.g_filesz; 1464 0 stevel extotal = dblock.dbuf.extotal; 1465 0 stevel } else { 1466 0 stevel extno = 0; /* tell others file not split */ 1467 0 stevel extsize = 0; 1468 0 stevel extotal = 0; 1469 0 stevel } 1470 0 stevel 1471 0 stevel #ifdef EUC 1472 0 stevel if (chksum != checksum(&dblock)) { 1473 0 stevel if (chksum != checksum_signed(&dblock)) { 1474 0 stevel (void) fprintf(stderr, gettext( 1475 0 stevel "tar: directory checksum error\n")); 1476 0 stevel if (iflag) 1477 0 stevel goto top; 1478 0 stevel done(2); 1479 0 stevel } else { 1480 0 stevel if (! warn_chksum_sign) { 1481 0 stevel warn_chksum_sign = 1; 1482 0 stevel (void) fprintf(stderr, gettext( 1483 0 stevel "tar: warning: tar file made with signed checksum\n")); 1484 0 stevel } 1485 0 stevel } 1486 0 stevel } 1487 0 stevel #else 1488 0 stevel if (chksum != checksum(&dblock)) { 1489 0 stevel (void) fprintf(stderr, gettext( 1490 0 stevel "tar: directory checksum error\n")); 1491 0 stevel if (iflag) 1492 0 stevel goto top; 1493 0 stevel done(2); 1494 0 stevel } 1495 0 stevel #endif /* EUC */ 1496 0 stevel if (tfile != NULL && Xhdrflag == 0) { 1497 0 stevel /* 1498 0 stevel * If an extended header is present, then time is available 1499 0 stevel * in nanoseconds in the extended header data, so set it. 1500 0 stevel * Otherwise, give an invalid value so that checkupdate will 1501 0 stevel * not test beyond seconds. 1502 0 stevel */ 1503 0 stevel if ((xhdr_flgs & _X_MTIME)) 1504 0 stevel sp->st_mtim.tv_nsec = Xtarhdr.x_mtime.tv_nsec; 1505 0 stevel else 1506 0 stevel sp->st_mtim.tv_nsec = -1; 1507 0 stevel 1508 0 stevel if (xhdr_flgs & _X_PATH) 1509 0 stevel (void) fprintf(tfile, "%s %10ld.%9.9ld\n", 1510 0 stevel Xtarhdr.x_path, sp->st_mtim.tv_sec, 1511 0 stevel sp->st_mtim.tv_nsec); 1512 0 stevel else 1513 0 stevel (void) fprintf(tfile, "%.*s %10ld.%9.9ld\n", 1514 0 stevel NAMSIZ, dblock.dbuf.name, sp->st_mtim.tv_sec, 1515 0 stevel sp->st_mtim.tv_nsec); 1516 0 stevel } 1517 0 stevel 1518 0 stevel #if defined(O_XATTR) 1519 0 stevel Hiddendir = 0; 1520 0 stevel if (xattrp && dblock.dbuf.typeflag == _XATTR_HDRTYPE) { 1521 0 stevel if (xattrbadhead) { 1522 0 stevel free(xattrhead); 1523 0 stevel xattrp = NULL; 1524 0 stevel xattr_linkp = NULL; 1525 0 stevel xattrhead = NULL; 1526 0 stevel } else { 1527 5331 amw char *aname = basename(xattrapath); 1528 5331 amw size_t xindex = aname - xattrapath; 1529 5331 amw 1530 5331 amw if (xattrapath[xindex] == '.' && 1531 5331 amw xattrapath[xindex + 1] == '\0' && 1532 0 stevel xattrp->h_typeflag == '5') { 1533 0 stevel Hiddendir = 1; 1534 0 stevel sp->st_mode = 1535 1231 marks (S_IFDIR | (sp->st_mode & POSIXMODES)); 1536 0 stevel } 1537 0 stevel dblock.dbuf.typeflag = xattrp->h_typeflag; 1538 0 stevel } 1539 0 stevel } 1540 0 stevel #endif 1541 0 stevel } 1542 0 stevel 1543 0 stevel 1544 0 stevel /* 1545 0 stevel * passtape - skip over a file on the tape 1546 0 stevel * 1547 0 stevel * passtape skips over the next data file on the tape. 1548 0 stevel * The tape directory entry must be in dblock.dbuf. This 1549 0 stevel * routine just eats the number of blocks computed from the 1550 0 stevel * directory size entry; the tape must be (logically) positioned 1551 0 stevel * right after thee directory info. 1552 0 stevel */ 1553 0 stevel 1554 0 stevel static void 1555 0 stevel passtape(void) 1556 0 stevel { 1557 0 stevel blkcnt_t blocks; 1558 0 stevel char buf[TBLOCK]; 1559 0 stevel 1560 0 stevel /* 1561 0 stevel * Types link(1), sym-link(2), char special(3), blk special(4), 1562 0 stevel * directory(5), and FIFO(6) do not have data blocks associated 1563 0 stevel * with them so just skip reading the data block. 1564 0 stevel */ 1565 0 stevel if (dblock.dbuf.typeflag == '1' || dblock.dbuf.typeflag == '2' || 1566 1266 ceastha dblock.dbuf.typeflag == '3' || dblock.dbuf.typeflag == '4' || 1567 1266 ceastha dblock.dbuf.typeflag == '5' || dblock.dbuf.typeflag == '6') 1568 0 stevel return; 1569 0 stevel blocks = TBLOCKS(stbuf.st_size); 1570 0 stevel 1571 0 stevel /* if operating on disk, seek instead of reading */ 1572 0 stevel if (NotTape) 1573 0 stevel seekdisk(blocks); 1574 0 stevel else 1575 0 stevel while (blocks-- > 0) 1576 0 stevel readtape(buf); 1577 0 stevel } 1578 0 stevel 1579 5331 amw #if defined(O_XATTR) 1580 5331 amw static int 1581 5331 amw is_sysattr(char *name) 1582 5331 amw { 1583 5331 amw return ((strcmp(name, VIEW_READONLY) == 0) || 1584 5331 amw (strcmp(name, VIEW_READWRITE) == 0)); 1585 5331 amw } 1586 5331 amw #endif 1587 5331 amw 1588 5331 amw #if defined(O_XATTR) 1589 5331 amw /* 1590 5331 amw * Verify the attribute, attrname, is an attribute we want to restore. 1591 5331 amw * Never restore read-only system attribute files. Only restore read-write 1592 5331 amw * system attributes files when -/ was specified, and only traverse into 1593 5331 amw * the 2nd level attribute directory containing only system attributes if 1594 5331 amw * -@ was specified. This keeps us from archiving 1595 5331 amw * <attribute name>/<read-write system attribute file> 1596 5331 amw * when -/ was specified without -@. 1597 5331 amw * 1598 5331 amw * attrname - attribute file name 1599 5331 amw * attrparent - attribute's parent name within the base file's attribute 1600 5331 amw * directory hierarchy 1601 5331 amw */ 1602 5331 amw static attr_status_t 1603 5331 amw verify_attr(char *attrname, char *attrparent, int arc_rwsysattr, 1604 5331 amw int *rw_sysattr) 1605 5331 amw { 1606 5331 amw #if defined(_PC_SATTR_ENABLED) 1607 5331 amw int attr_supported; 1608 5331 amw 1609 5331 amw /* Never restore read-only system attribute files */ 1610 5331 amw if ((attr_supported = sysattr_type(attrname)) == _RO_SATTR) { 1611 5331 amw *rw_sysattr = 0; 1612 5331 amw return (ATTR_SKIP); 1613 5331 amw } else { 1614 5331 amw *rw_sysattr = (attr_supported == _RW_SATTR); 1615 5331 amw } 1616 5331 amw #else 1617 5331 amw /* 1618 5331 amw * Only need to check if this attribute is an extended system 1619 5331 amw * attribute. 1620 5331 amw */ 1621 5331 amw if (*rw_sysattr = is_sysattr(attrname)) { 1622 5331 amw return (ATTR_SKIP); 1623 5331 amw } else { 1624 5331 amw return (ATTR_OK); 1625 5331 amw } 1626 5331 amw #endif /* _PC_SATTR_ENABLED */ 1627 5331 amw 1628 5331 amw /* 1629 5331 amw * If the extended system attribute file is specified with the 1630 5331 amw * arc_rwsysattr flag, as being transient (default extended 1631 5331 amw * attributes), then don't archive it. 1632 5331 amw */ 1633 5331 amw if (*rw_sysattr && !arc_rwsysattr) { 1634 5331 amw return (ATTR_SKIP); 1635 5331 amw } 1636 5331 amw 1637 5331 amw /* 1638 5331 amw * Only restore read-write system attribute files 1639 5331 amw * when -/ was specified. Only restore extended 1640 5331 amw * attributes when -@ was specified. 1641 5331 amw */ 1642 5331 amw if (atflag) { 1643 5331 amw if (!saflag) { 1644 5331 amw /* 1645 5331 amw * Only archive/restore the hidden directory "." if 1646 5331 amw * we're processing the top level hidden attribute 1647 5331 amw * directory. We don't want to process the 1648 5331 amw * hidden attribute directory of the attribute 1649 5331 amw * directory that contains only extended system 1650 5331 amw * attributes. 1651 5331 amw */ 1652 5331 amw if (*rw_sysattr || (Hiddendir && 1653 5331 amw (attrparent != NULL))) { 1654 5331 amw return (ATTR_SKIP); 1655 5331 amw } 1656 5331 amw } 1657 5331 amw } else if (saflag) { 1658 5331 amw /* 1659 5331 amw * Only archive/restore read-write extended system attribute 1660 5331 amw * files of the base file. 1661 5331 amw */ 1662 5331 amw if (!*rw_sysattr || (attrparent != NULL)) { 1663 5331 amw return (ATTR_SKIP); 1664 5331 amw } 1665 5331 amw } else { 1666 5331 amw return (ATTR_SKIP); 1667 5331 amw } 1668 5331 amw 1669 5331 amw return (ATTR_OK); 1670 5331 amw } 1671 5331 amw #endif 1672 5331 amw 1673 6525 ceastha static void 1674 6525 ceastha free_children(file_list_t *children) 1675 6525 ceastha { 1676 6525 ceastha file_list_t *child = children; 1677 6525 ceastha file_list_t *cptr; 1678 6525 ceastha 1679 6525 ceastha while (child != NULL) { 1680 6525 ceastha cptr = child->next; 1681 6525 ceastha if (child->name != NULL) { 1682 6525 ceastha free(child->name); 1683 6525 ceastha } 1684 6525 ceastha child = cptr; 1685 6525 ceastha } 1686 6525 ceastha } 1687 6525 ceastha 1688 5331 amw static int 1689 5331 amw putfile(char *longname, char *shortname, char *parent, attr_data_t *attrinfo, 1690 0 stevel int filetype, int lev, int symlink_lev) 1691 0 stevel { 1692 0 stevel int infile = -1; /* deliberately invalid */ 1693 0 stevel blkcnt_t blocks; 1694 0 stevel char buf[PATH_MAX + 2]; /* Add trailing slash and null */ 1695 0 stevel char *bigbuf; 1696 0 stevel int maxread; 1697 0 stevel int hint; /* amount to write to get "in sync" */ 1698 0 stevel char filetmp[PATH_MAX + 1]; 1699 0 stevel char *cp; 1700 0 stevel char *name; 1701 5331 amw char *attrparent = NULL; 1702 5331 amw char *longattrname = NULL; 1703 6525 ceastha file_list_t *child = NULL; 1704 6525 ceastha file_list_t *child_end = NULL; 1705 6525 ceastha file_list_t *cptr; 1706 0 stevel struct dirent *dp; 1707 0 stevel DIR *dirp; 1708 0 stevel int i; 1709 0 stevel int split; 1710 0 stevel int dirfd = -1; 1711 0 stevel int rc = PUT_NOTAS_LINK; 1712 0 stevel int archtype = 0; 1713 5331 amw int rw_sysattr = 0; 1714 0 stevel char newparent[PATH_MAX + MAXNAMLEN + 1]; 1715 0 stevel char *prefix = ""; 1716 0 stevel char *tmpbuf; 1717 0 stevel char goodbuf[PRESIZ + 2]; 1718 0 stevel char junkbuf[MAXNAM+1]; 1719 0 stevel char *lastslash; 1720 0 stevel int j; 1721 0 stevel struct stat sbuf; 1722 0 stevel int readlink_max; 1723 0 stevel 1724 0 stevel (void) memset(goodbuf, '\0', sizeof (goodbuf)); 1725 0 stevel (void) memset(junkbuf, '\0', sizeof (junkbuf)); 1726 0 stevel 1727 0 stevel xhdr_flgs = 0; 1728 0 stevel 1729 0 stevel if (filetype == XATTR_FILE) { 1730 5331 amw attrparent = attrinfo->attr_parent; 1731 5331 amw longattrname = attrinfo->attr_path; 1732 5331 amw dirfd = attrinfo->attr_parentfd; 1733 5750 ceastha rw_sysattr = attrinfo->attr_rw_sysattr; 1734 0 stevel } else { 1735 0 stevel dirfd = open(".", O_RDONLY); 1736 0 stevel } 1737 0 stevel 1738 0 stevel if (dirfd == -1) { 1739 0 stevel (void) fprintf(stderr, gettext( 1740 5331 amw "tar: unable to open%sdirectory %s%s%s%s\n"), 1741 0 stevel (filetype == XATTR_FILE) ? gettext(" attribute ") : " ", 1742 5331 amw (attrparent == NULL) ? "" : gettext("of attribute "), 1743 5331 amw (attrparent == NULL) ? "" : attrparent, 1744 5331 amw (attrparent == NULL) ? "" : gettext(" of "), 1745 0 stevel (filetype == XATTR_FILE) ? longname : parent); 1746 0 stevel goto out; 1747 0 stevel } 1748 0 stevel 1749 0 stevel if (lev > MAXLEV) { 1750 0 stevel (void) fprintf(stderr, 1751 0 stevel gettext("tar: directory nesting too deep, %s not dumped\n"), 1752 0 stevel longname); 1753 0 stevel goto out; 1754 0 stevel } 1755 0 stevel 1756 5331 amw if (getstat(dirfd, longname, shortname, attrparent)) 1757 0 stevel goto out; 1758 0 stevel 1759 0 stevel if (hflag) { 1760 0 stevel /* 1761 0 stevel * Catch nesting where a file is a symlink to its directory. 1762 0 stevel */ 1763 0 stevel j = fstatat(dirfd, shortname, &sbuf, AT_SYMLINK_NOFOLLOW); 1764 0 stevel if (S_ISLNK(sbuf.st_mode)) { 1765 0 stevel if (symlink_lev++ >= MAXSYMLINKS) { 1766 0 stevel (void) fprintf(stderr, gettext( 1767 0 stevel "tar: %s: Number of symbolic links " 1768 0 stevel "encountered during path name traversal " 1769 0 stevel "exceeds MAXSYMLINKS\n"), longname); 1770 0 stevel Errflg = 1; 1771 0 stevel goto out; 1772 0 stevel } 1773 0 stevel } 1774 0 stevel } 1775 0 stevel 1776 0 stevel /* 1777 0 stevel * Check if the input file is the same as the tar file we 1778 0 stevel * are creating 1779 0 stevel */ 1780 0 stevel if ((mt_ino == stbuf.st_ino) && (mt_dev == stbuf.st_dev)) { 1781 0 stevel (void) fprintf(stderr, gettext( 1782 5331 amw "tar: %s%s%s%s%s same as archive file\n"), 1783 5331 amw rw_sysattr ? gettext("system ") : "", 1784 5331 amw (longattrname == NULL) ? "" : gettext("attribute "), 1785 5331 amw (longattrname == NULL) ? "" : longattrname, 1786 5331 amw (longattrname == NULL) ? "" : gettext(" of "), 1787 5331 amw longname); 1788 0 stevel Errflg = 1; 1789 0 stevel goto out; 1790 0 stevel } 1791 0 stevel /* 1792 0 stevel * Check size limit - we can't archive files that 1793 0 stevel * exceed TAR_OFFSET_MAX bytes because of header 1794 0 stevel * limitations. Exclude file types that set 1795 0 stevel * st_size to zero below because they take no 1796 0 stevel * archive space to represent contents. 1797 0 stevel */ 1798 0 stevel if ((stbuf.st_size > (off_t)TAR_OFFSET_MAX) && 1799 0 stevel !S_ISDIR(stbuf.st_mode) && 1800 0 stevel !S_ISCHR(stbuf.st_mode) && 1801 0 stevel !S_ISBLK(stbuf.st_mode) && 1802 0 stevel (Eflag == 0)) { 1803 0 stevel (void) fprintf(stderr, gettext( 1804 5331 amw "tar: %s%s%s%s%s too large to archive. " 1805 5331 amw "Use E function modifier.\n"), 1806 5331 amw rw_sysattr ? gettext("system ") : "", 1807 5331 amw (longattrname == NULL) ? "" : gettext("attribute "), 1808 5331 amw (longattrname == NULL) ? "" : longattrname, 1809 5331 amw (longattrname == NULL) ? "" : gettext(" of "), 1810 5331 amw longname); 1811 0 stevel if (errflag) 1812 0 stevel exitflag = 1; 1813 0 stevel Errflg = 1; 1814 0 stevel goto out; 1815 0 stevel } 1816 0 stevel 1817 0 stevel if (tfile != NULL && checkupdate(longname) == 0) { 1818 0 stevel goto out; 1819 0 stevel } 1820 0 stevel if (checkw('r', longname) == 0) { 1821 0 stevel goto out; 1822 0 stevel } 1823 0 stevel 1824 0 stevel if (Fflag && checkf(shortname, stbuf.st_mode, Fflag) == 0) 1825 0 stevel goto out; 1826 0 stevel 1827 0 stevel if (Xflag) { 1828 0 stevel if (is_in_table(exclude_tbl, longname)) { 1829 0 stevel if (vflag) { 1830 0 stevel (void) fprintf(vfile, gettext( 1831 0 stevel "a %s excluded\n"), longname); 1832 0 stevel } 1833 0 stevel goto out; 1834 0 stevel } 1835 0 stevel } 1836 0 stevel 1837 0 stevel /* 1838 0 stevel * If the length of the fullname is greater than MAXNAM, 1839 0 stevel * print out a message and return (unless extended headers are used, 1840 0 stevel * in which case fullname is limited to PATH_MAX). 1841 0 stevel */ 1842 0 stevel 1843 0 stevel if ((((split = (int)strlen(longname)) > MAXNAM) && (Eflag == 0)) || 1844 0 stevel (split > PATH_MAX)) { 1845 0 stevel (void) fprintf(stderr, gettext( 1846 0 stevel "tar: %s: file name too long\n"), longname); 1847 0 stevel if (errflag) 1848 0 stevel exitflag = 1; 1849 0 stevel Errflg = 1; 1850 0 stevel goto out; 1851 0 stevel } 1852 0 stevel 1853 0 stevel /* 1854 0 stevel * We split the fullname into prefix and name components if any one 1855 0 stevel * of three conditions holds: 1856 0 stevel * -- the length of the fullname exceeds NAMSIZ, 1857 0 stevel * -- the length of the fullname equals NAMSIZ, and the shortname 1858 0 stevel * is less than NAMSIZ, (splitting in this case preserves 1859 0 stevel * compatibility with 5.6 and 5.5.1 tar), or 1860 0 stevel * -- the length of the fullname equals NAMSIZ, the file is a 1861 0 stevel * directory and we are not in POSIX-conformant mode (where 1862 0 stevel * trailing slashes are removed from directories). 1863 0 stevel */ 1864 0 stevel if ((split > NAMSIZ) || 1865 0 stevel (split == NAMSIZ && strlen(shortname) < NAMSIZ) || 1866 871 casper (split == NAMSIZ && S_ISDIR(stbuf.st_mode) && !Pflag)) { 1867 0 stevel /* 1868 0 stevel * Since path is limited to PRESIZ characters, look for the 1869 0 stevel * last slash within PRESIZ + 1 characters only. 1870 0 stevel */ 1871 0 stevel (void) strncpy(&goodbuf[0], longname, min(split, PRESIZ + 1)); 1872 0 stevel tmpbuf = goodbuf; 1873 0 stevel lastslash = strrchr(tmpbuf, '/'); 1874 0 stevel if (lastslash == NULL) { 1875 0 stevel i = split; /* Length of name */ 1876 0 stevel j = 0; /* Length of prefix */ 1877 0 stevel goodbuf[0] = '\0'; 1878 0 stevel } else { 1879 0 stevel *lastslash = '\0'; /* Terminate the prefix */ 1880 0 stevel j = strlen(tmpbuf); 1881 0 stevel i = split - j - 1; 1882 0 stevel } 1883 0 stevel /* 1884 0 stevel * If the filename is greater than NAMSIZ we can't 1885 0 stevel * archive the file unless we are using extended headers. 1886 0 stevel */ 1887 871 casper if ((i > NAMSIZ) || (i == NAMSIZ && S_ISDIR(stbuf.st_mode) && 1888 0 stevel !Pflag)) { 1889 0 stevel /* Determine which (filename or path) is too long. */ 1890 0 stevel lastslash = strrchr(longname, '/'); 1891 0 stevel if (lastslash != NULL) 1892 0 stevel i = strlen(lastslash + 1); 1893 0 stevel if (Eflag > 0) { 1894 0 stevel xhdr_flgs |= _X_PATH; 1895 0 stevel Xtarhdr.x_path = longname; 1896 0 stevel if (i <= NAMSIZ) 1897 0 stevel (void) strcpy(junkbuf, lastslash + 1); 1898 0 stevel else 1899 0 stevel (void) sprintf(junkbuf, "%llu", 1900 0 stevel xhdr_count + 1); 1901 0 stevel if (split - i - 1 > PRESIZ) 1902 0 stevel (void) strcpy(goodbuf, xhdr_dirname); 1903 0 stevel } else { 1904 0 stevel if ((i > NAMSIZ) || (i == NAMSIZ && 1905 871 casper S_ISDIR(stbuf.st_mode) && !Pflag)) 1906 0 stevel (void) fprintf(stderr, gettext( 1907 0 stevel "tar: %s: filename is greater than " 1908 0 stevel "%d\n"), lastslash == NULL ? 1909 0 stevel longname : lastslash + 1, NAMSIZ); 1910 0 stevel else 1911 0 stevel (void) fprintf(stderr, gettext( 1912 0 stevel "tar: %s: prefix is greater than %d" 1913 0 stevel "\n"), longname, PRESIZ); 1914 0 stevel if (errflag) 1915 0 stevel exitflag = 1; 1916 0 stevel Errflg = 1; 1917 0 stevel goto out; 1918 0 stevel } 1919 0 stevel } else 1920 0 stevel (void) strncpy(&junkbuf[0], longname + j + 1, 1921 0 stevel strlen(longname + j + 1)); 1922 0 stevel name = junkbuf; 1923 0 stevel prefix = goodbuf; 1924 0 stevel } else { 1925 0 stevel name = longname; 1926 0 stevel } 1927 0 stevel if (Aflag) { 1928 0 stevel if ((prefix != NULL) && (*prefix != '\0')) 1929 0 stevel while (*prefix == '/') 1930 0 stevel ++prefix; 1931 0 stevel else 1932 0 stevel while (*name == '/') 1933 0 stevel ++name; 1934 0 stevel } 1935 0 stevel 1936 0 stevel switch (stbuf.st_mode & S_IFMT) { 1937 0 stevel case S_IFDIR: 1938 0 stevel stbuf.st_size = (off_t)0; 1939 0 stevel blocks = TBLOCKS(stbuf.st_size); 1940 0 stevel 1941 0 stevel if (filetype != XATTR_FILE && Hiddendir == 0) { 1942 0 stevel i = 0; 1943 0 stevel cp = buf; 1944 0 stevel while ((*cp++ = longname[i++])) 1945 0 stevel ; 1946 0 stevel *--cp = '/'; 1947 0 stevel *++cp = 0; 1948 0 stevel } 1949 0 stevel if (!oflag) { 1950 0 stevel tomodes(&stbuf); 1951 0 stevel if (build_dblock(name, tchar, '5', filetype, 1952 0 stevel &stbuf, stbuf.st_dev, prefix) != 0) { 1953 0 stevel goto out; 1954 0 stevel } 1955 0 stevel if (!Pflag) { 1956 0 stevel /* 1957 0 stevel * Old archives require a slash at the end 1958 0 stevel * of a directory name. 1959 0 stevel * 1960 0 stevel * XXX 1961 0 stevel * If directory name is too long, will 1962 0 stevel * slash overfill field? 1963 0 stevel */ 1964 0 stevel if (strlen(name) > (unsigned)NAMSIZ-1) { 1965 0 stevel (void) fprintf(stderr, gettext( 1966 0 stevel "tar: %s: filename is greater " 1967 0 stevel "than %d\n"), name, NAMSIZ); 1968 0 stevel if (errflag) 1969 0 stevel exitflag = 1; 1970 0 stevel Errflg = 1; 1971 0 stevel goto out; 1972 0 stevel } else { 1973 0 stevel if (strlen(name) == (NAMSIZ - 1)) { 1974 0 stevel (void) memcpy(dblock.dbuf.name, 1975 0 stevel name, NAMSIZ); 1976 0 stevel dblock.dbuf.name[NAMSIZ-1] 1977 0 stevel = '/'; 1978 0 stevel } else 1979 0 stevel (void) sprintf(dblock.dbuf.name, 1980 0 stevel "%s/", name); 1981 0 stevel 1982 0 stevel /* 1983 0 stevel * need to recalculate checksum 1984 0 stevel * because the name changed. 1985 0 stevel */ 1986 0 stevel (void) sprintf(dblock.dbuf.chksum, 1987 0 stevel "%07o", checksum(&dblock)); 1988 0 stevel } 1989 0 stevel } 1990 0 stevel 1991 5331 amw if (put_extra_attributes(longname, shortname, 1992 5331 amw longattrname, prefix, filetype, '5') != 0) 1993 0 stevel goto out; 1994 0 stevel 1995 0 stevel #if defined(O_XATTR) 1996 0 stevel /* 1997 0 stevel * Reset header typeflag when archiving directory, since 1998 0 stevel * build_dblock changed it on us. 1999 0 stevel */ 2000 0 stevel if (filetype == XATTR_FILE) { 2001 0 stevel dblock.dbuf.typeflag = _XATTR_HDRTYPE; 2002 0 stevel } else { 2003 0 stevel dblock.dbuf.typeflag = '5'; 2004 0 stevel } 2005 0 stevel #else 2006 0 stevel dblock.dbuf.typeflag = '5'; 2007 0 stevel #endif 2008 0 stevel 2009 0 stevel (void) sprintf(dblock.dbuf.chksum, "%07o", 2010 0 stevel checksum(&dblock)); 2011 0 stevel 2012 0 stevel (void) writetbuf((char *)&dblock, 1); 2013 0 stevel } 2014 0 stevel if (vflag) { 2015 0 stevel #ifdef DEBUG 2016 0 stevel if (NotTape) 2017 0 stevel DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2018 0 stevel 0); 2019 0 stevel #endif 2020 0 stevel if (filetype == XATTR_FILE && Hiddendir) { 2021 5331 amw (void) fprintf(vfile, "a %s attribute %s ", 2022 5331 amw longname, longattrname); 2023 0 stevel 2024 0 stevel } else { 2025 0 stevel (void) fprintf(vfile, "a %s/ ", longname); 2026 0 stevel } 2027 0 stevel if (NotTape) 2028 0 stevel (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n", 2029 0 stevel K(blocks)); 2030 0 stevel else 2031 0 stevel (void) fprintf(vfile, gettext("%" FMT_blkcnt_t 2032 0 stevel " tape blocks\n"), blocks); 2033 0 stevel } 2034 0 stevel 2035 0 stevel /* 2036 0 stevel * If hidden dir then break now since xattrs_put() will do 2037 0 stevel * the iterating of the directory. 2038 0 stevel * 2039 5331 amw * At the moment, there can only be system attributes on 2040 5331 amw * attributes. There can be no attributes on attributes or 2041 5331 amw * directories within the attributes hidden directory hierarchy. 2042 0 stevel */ 2043 0 stevel if (filetype == XATTR_FILE) 2044 0 stevel break; 2045 0 stevel 2046 0 stevel if (*shortname != '/') 2047 0 stevel (void) sprintf(newparent, "%s/%s", parent, shortname); 2048 0 stevel else 2049 0 stevel (void) sprintf(newparent, "%s", shortname); 2050 0 stevel 2051 0 stevel if (chdir(shortname) < 0) { 2052 0 stevel vperror(0, "%s", newparent); 2053 0 stevel goto out; 2054 0 stevel } 2055 0 stevel 2056 0 stevel if ((dirp = opendir(".")) == NULL) { 2057 0 stevel vperror(0, gettext( 2058 5331 amw "can't open directory %s"), longname); 2059 0 stevel if (chdir(parent) < 0) 2060 0 stevel vperror(0, gettext("cannot change back?: %s"), 2061 0 stevel parent); 2062 0 stevel goto out; 2063 0 stevel } 2064 0 stevel 2065 6525 ceastha /* 2066 6525 ceastha * Create a list of files (children) in this directory to avoid 2067 6525 ceastha * having to perform telldir()/seekdir(). 2068 6525 ceastha */ 2069 0 stevel while ((dp = readdir(dirp)) != NULL && !term) { 2070 0 stevel if ((strcmp(".", dp->d_name) == 0) || 2071 0 stevel (strcmp("..", dp->d_name) == 0)) 2072 0 stevel continue; 2073 6525 ceastha if (((cptr = (file_list_t *)calloc(sizeof (char), 2074 6525 ceastha sizeof (file_list_t))) == NULL) || 2075 6525 ceastha ((cptr->name = strdup(dp->d_name)) == NULL)) { 2076 6525 ceastha vperror(1, gettext( 2077 6525 ceastha "Insufficient memory for directory " 2078 6525 ceastha "list entry %s/%s\n"), 2079 6525 ceastha newparent, dp->d_name); 2080 6525 ceastha } 2081 6525 ceastha 2082 6525 ceastha /* Add the file to the list */ 2083 6525 ceastha if (child == NULL) { 2084 6525 ceastha child = cptr; 2085 6525 ceastha } else { 2086 6525 ceastha child_end->next = cptr; 2087 6525 ceastha } 2088 6525 ceastha child_end = cptr; 2089 6525 ceastha } 2090 6525 ceastha (void) closedir(dirp); 2091 6525 ceastha 2092 6525 ceastha /* 2093 6525 ceastha * Archive each of the files in the current directory. 2094 6525 ceastha * If a file is a directory, putfile() is called 2095 6525 ceastha * recursively to archive the file hierarchy of the 2096 6525 ceastha * directory before archiving the next file in the 2097 6525 ceastha * current directory. 2098 6525 ceastha */ 2099 6525 ceastha while ((child != NULL) && !term) { 2100 6525 ceastha (void) strcpy(cp, child->name); 2101 5331 amw archtype = putfile(buf, cp, newparent, NULL, 2102 0 stevel NORMAL_FILE, lev + 1, symlink_lev); 2103 0 stevel 2104 0 stevel if (!exitflag) { 2105 5331 amw if ((atflag || saflag) && 2106 5331 amw (archtype == PUT_NOTAS_LINK)) { 2107 5331 amw xattrs_put(buf, cp, newparent, NULL); 2108 0 stevel } 2109 0 stevel } 2110 0 stevel if (exitflag) 2111 0 stevel break; 2112 0 stevel 2113 6525 ceastha /* Free each child as we are done processing it. */ 2114 6525 ceastha cptr = child; 2115 6525 ceastha child = child->next; 2116 6525 ceastha free(cptr->name); 2117 6525 ceastha free(cptr); 2118 6525 ceastha } 2119 6525 ceastha if ((child != NULL) && !term) { 2120 6525 ceastha free_children(child); 2121 6525 ceastha } 2122 0 stevel 2123 0 stevel if (chdir(parent) < 0) { 2124 0 stevel vperror(0, gettext("cannot change back?: %s"), parent); 2125 0 stevel } 2126 0 stevel 2127 0 stevel break; 2128 0 stevel 2129 0 stevel case S_IFLNK: 2130 0 stevel readlink_max = NAMSIZ; 2131 0 stevel if (stbuf.st_size > NAMSIZ) { 2132 0 stevel if (Eflag > 0) { 2133 0 stevel xhdr_flgs |= _X_LINKPATH; 2134 0 stevel readlink_max = PATH_MAX; 2135 0 stevel } else { 2136 0 stevel (void) fprintf(stderr, gettext( 2137 0 stevel "tar: %s: symbolic link too long\n"), 2138 0 stevel longname); 2139 0 stevel if (errflag) 2140 0 stevel exitflag = 1; 2141 0 stevel Errflg = 1; 2142 0 stevel goto out; 2143 0 stevel } 2144 0 stevel } 2145 0 stevel /* 2146 0 stevel * Sym-links need header size of zero since you 2147 0 stevel * don't store any data for this type. 2148 0 stevel */ 2149 0 stevel stbuf.st_size = (off_t)0; 2150 0 stevel tomodes(&stbuf); 2151 0 stevel i = readlink(shortname, filetmp, readlink_max); 2152 0 stevel if (i < 0) { 2153 0 stevel vperror(0, gettext( 2154 0 stevel "can't read symbolic link %s"), longname); 2155 0 stevel goto out; 2156 0 stevel } else { 2157 0 stevel filetmp[i] = 0; 2158 0 stevel } 2159 0 stevel if (vflag) 2160 0 stevel (void) fprintf(vfile, gettext( 2161 0 stevel "a %s symbolic link to %s\n"), 2162 0 stevel longname, filetmp); 2163 0 stevel if (xhdr_flgs & _X_LINKPATH) { 2164 0 stevel Xtarhdr.x_linkpath = filetmp; 2165 0 stevel if (build_dblock(name, tchar, '2', filetype, &stbuf, 2166 0 stevel stbuf.st_dev, prefix) != 0) 2167 0 stevel goto out; 2168 0 stevel } else 2169 0 stevel if (build_dblock(name, filetmp, '2', filetype, &stbuf, 2170 0 stevel stbuf.st_dev, prefix) != 0) 2171 0 stevel goto out; 2172 0 stevel (void) writetbuf((char *)&dblock, 1); 2173 0 stevel /* 2174 0 stevel * No acls for symlinks: mode is always 777 2175 0 stevel * dont call write ancillary 2176 0 stevel */ 2177 0 stevel rc = PUT_AS_LINK; 2178 0 stevel break; 2179 0 stevel case S_IFREG: 2180 0 stevel if ((infile = openat(dirfd, shortname, 0)) < 0) { 2181 5331 amw vperror(0, "unable to open %s%s%s%s", longname, 2182 5331 amw rw_sysattr ? gettext(" system") : "", 2183 0 stevel (filetype == XATTR_FILE) ? 2184 0 stevel gettext(" attribute ") : "", 2185 5331 amw (filetype == XATTR_FILE) ? (longattrname == NULL) ? 2186 5331 amw shortname : longattrname : ""); 2187 0 stevel goto out; 2188 0 stevel } 2189 0 stevel 2190 0 stevel blocks = TBLOCKS(stbuf.st_size); 2191 0 stevel 2192 5331 amw if (put_link(name, longname, shortname, longattrname, 2193 0 stevel prefix, filetype, '1') == 0) { 2194 0 stevel (void) close(infile); 2195 0 stevel rc = PUT_AS_LINK; 2196 0 stevel goto out; 2197 0 stevel } 2198 0 stevel 2199 0 stevel tomodes(&stbuf); 2200 0 stevel 2201 0 stevel /* correctly handle end of volume */ 2202 0 stevel while (mulvol && tapepos + blocks + 1 > blocklim) { 2203 0 stevel /* file won't fit */ 2204 0 stevel if (eflag) { 2205 0 stevel if (blocks <= blocklim) { 2206 0 stevel newvol(); 2207 0 stevel break; 2208 0 stevel } 2209 0 stevel (void) fprintf(stderr, gettext( 2210 0 stevel "tar: Single file cannot fit on volume\n")); 2211 0 stevel done(3); 2212 0 stevel } 2213 0 stevel /* split if floppy has some room and file is large */ 2214 0 stevel if (((blocklim - tapepos) >= EXTMIN) && 2215 0 stevel ((blocks + 1) >= blocklim/10)) { 2216 0 stevel splitfile(longname, infile, 2217 0 stevel name, prefix, filetype); 2218 0 stevel (void) close(dirfd); 2219 0 stevel (void) close(infile); 2220 0 stevel goto out; 2221 0 stevel } 2222 0 stevel newvol(); /* not worth it--just get new volume */ 2223 0 stevel } 2224 0 stevel #ifdef DEBUG 2225 0 stevel DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, 2226 0 stevel blocks); 2227 0 stevel #endif 2228 0 stevel if (build_dblock(name, tchar, '0', filetype, 2229 0 stevel &stbuf, stbuf.st_dev, prefix) != 0) { 2230 0 stevel goto out; 2231 0 stevel } 2232 0 stevel if (vflag) { 2233 0 stevel #ifdef DEBUG 2234 0 stevel if (NotTape) 2235 0 stevel DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2236 0 stevel 0); 2237 0 stevel #endif 2238 5331 amw (void) fprintf(vfile, "a %s%s%s%s ", longname, 2239 5331 amw rw_sysattr ? gettext(" system") : "", 2240 5331 amw (filetype == XATTR_FILE) ? gettext( 2241 5331 amw " attribute ") : "", 2242 0 stevel (filetype == XATTR_FILE) ? 2243 5331 amw longattrname : ""); 2244 0 stevel if (NotTape) 2245 0 stevel (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n", 2246 0 stevel K(blocks)); 2247 0 stevel else 2248 0 stevel (void) fprintf(vfile, 2249 0 stevel gettext("%" FMT_blkcnt_t " tape blocks\n"), 2250 0 stevel blocks); 2251 0 stevel } 2252 0 stevel 2253 5331 amw if (put_extra_attributes(longname, shortname, longattrname, 2254 5331 amw prefix, filetype, '0') != 0) 2255 0 stevel goto out; 2256 0 stevel 2257 0 stevel /* 2258 0 stevel * No need to reset typeflag for extended attribute here, since 2259 0 stevel * put_extra_attributes already set it and we haven't called 2260 0 stevel * build_dblock(). 2261 0 stevel */ 2262 0 stevel (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2263 0 stevel hint = writetbuf((char *)&dblock, 1); 2264 1266 ceastha maxread = max(min(stbuf.st_blksize, stbuf.st_size), 2265 1266 ceastha (nblock * TBLOCK)); 2266 0 stevel if ((bigbuf = calloc((unsigned)maxread, sizeof (char))) == 0) { 2267 0 stevel maxread = TBLOCK; 2268 0 stevel bigbuf = buf; 2269 0 stevel } 2270 0 stevel 2271 0 stevel while (((i = (int) 2272 0 stevel read(infile, bigbuf, min((hint*TBLOCK), maxread))) > 0) && 2273 0 stevel blocks) { 2274 0 stevel blkcnt_t nblks; 2275 0 stevel 2276 0 stevel nblks = ((i-1)/TBLOCK)+1; 2277 0 stevel if (nblks > blocks) 2278 0 stevel nblks = blocks; 2279 0 stevel hint = writetbuf(bigbuf, nblks); 2280 0 stevel blocks -= nblks; 2281 0 stevel } 2282 0 stevel (void) close(infile); 2283 0 stevel if (bigbuf != buf) 2284 0 stevel free(bigbuf); 2285 0 stevel if (i < 0) 2286 0 stevel vperror(0, gettext("Read error on %s"), longname); 2287 0 stevel else if (blocks != 0 || i != 0) { 2288 0 stevel (void) fprintf(stderr, gettext( 2289 0 stevel "tar: %s: file changed size\n"), longname); 2290 0 stevel if (errflag) { 2291 0 stevel exitflag = 1; 2292 0 stevel Errflg = 1; 2293 0 stevel } else if (!Dflag) { 2294 0 stevel Errflg = 1; 2295 0 stevel } 2296 0 stevel } 2297 0 stevel putempty(blocks); 2298 0 stevel break; 2299 0 stevel case S_IFIFO: 2300 0 stevel blocks = TBLOCKS(stbuf.st_size); 2301 0 stevel stbuf.st_size = (off_t)0; 2302 0 stevel 2303 5331 amw if (put_link(name, longname, shortname, longattrname, 2304 0 stevel prefix, filetype, '6') == 0) { 2305 0 stevel rc = PUT_AS_LINK; 2306 0 stevel goto out; 2307 0 stevel } 2308 0 stevel tomodes(&stbuf); 2309 0 stevel 2310 0 stevel while (mulvol && tapepos + blocks + 1 > blocklim) { 2311 0 stevel if (eflag) { 2312 0 stevel if (blocks <= blocklim) { 2313 0 stevel newvol(); 2314 0 stevel break; 2315 0 stevel } 2316 0 stevel (void) fprintf(stderr, gettext( 2317 0 stevel "tar: Single file cannot fit on volume\n")); 2318 0 stevel done(3); 2319 0 stevel } 2320 0 stevel 2321 0 stevel if (((blocklim - tapepos) >= EXTMIN) && 2322 0 stevel ((blocks + 1) >= blocklim/10)) { 2323 0 stevel splitfile(longname, infile, name, 2324 0 stevel prefix, filetype); 2325 0 stevel (void) close(dirfd); 2326 0 stevel (void) close(infile); 2327 0 stevel goto out; 2328 0 stevel } 2329 0 stevel newvol(); 2330 0 stevel } 2331 0 stevel #ifdef DEBUG 2332 0 stevel DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, 2333 0 stevel blocks); 2334 0 stevel #endif 2335 0 stevel if (vflag) { 2336 0 stevel #ifdef DEBUG 2337 0 stevel if (NotTape) 2338 0 stevel DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2339 0 stevel 0); 2340 0 stevel #endif 2341 0 stevel if (NotTape) 2342 0 stevel (void) fprintf(vfile, gettext("a %s %" 2343 0 stevel FMT_blkcnt_t "K\n "), longname, K(blocks)); 2344 0 stevel else 2345 0 stevel (void) fprintf(vfile, gettext( 2346 0 stevel "a %s %" FMT_blkcnt_t " tape blocks\n"), 2347 0 stevel longname, blocks); 2348 0 stevel } 2349 0 stevel if (build_dblock(name, tchar, '6', filetype, 2350 0 stevel &stbuf, stbuf.st_dev, prefix) != 0) 2351 0 stevel goto out; 2352 0 stevel 2353 5331 amw if (put_extra_attributes(longname, shortname, longattrname, 2354 5331 amw prefix, filetype, '6') != 0) 2355 0 stevel goto out; 2356 0 stevel 2357 0 stevel (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2358 0 stevel dblock.dbuf.typeflag = '6'; 2359 0 stevel 2360 0 stevel (void) writetbuf((char *)&dblock, 1); 2361 0 stevel break; 2362 0 stevel case S_IFCHR: 2363 0 stevel stbuf.st_size = (off_t)0; 2364 0 stevel blocks = TBLOCKS(stbuf.st_size); 2365 5331 amw if (put_link(name, longname, shortname, longattrname, 2366 5331 amw prefix, filetype, '3') == 0) { 2367 0 stevel rc = PUT_AS_LINK; 2368 0 stevel goto out; 2369 0 stevel } 2370 0 stevel tomodes(&stbuf); 2371 0 stevel 2372 0 stevel while (mulvol && tapepos + blocks + 1 > blocklim) { 2373 0 stevel if (eflag) { 2374 0 stevel if (blocks <= blocklim) { 2375 0 stevel newvol(); 2376 0 stevel break; 2377 0 stevel } 2378 0 stevel (void) fprintf(stderr, gettext( 2379 0 stevel "tar: Single file cannot fit on volume\n")); 2380 0 stevel done(3); 2381 0 stevel } 2382 0 stevel 2383 0 stevel if (((blocklim - tapepos) >= EXTMIN) && 2384 0 stevel ((blocks + 1) >= blocklim/10)) { 2385 0 stevel splitfile(longname, infile, name, 2386 0 stevel prefix, filetype); 2387 0 stevel (void) close(dirfd); 2388 0 stevel goto out; 2389 0 stevel } 2390 0 stevel newvol(); 2391 0 stevel } 2392 0 stevel #ifdef DEBUG 2393 0 stevel DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, 2394 0 stevel blocks); 2395 0 stevel #endif 2396 0 stevel if (vflag) { 2397 0 stevel #ifdef DEBUG 2398 0 stevel if (NotTape) 2399 0 stevel DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2400 0 stevel 0); 2401 0 stevel #endif 2402 0 stevel if (NotTape) 2403 0 stevel (void) fprintf(vfile, gettext("a %s %" 2404 0 stevel FMT_blkcnt_t "K\n"), longname, K(blocks)); 2405 0 stevel else 2406 0 stevel (void) fprintf(vfile, gettext("a %s %" 2407 0 stevel FMT_blkcnt_t " tape blocks\n"), longname, 2408 0 stevel blocks); 2409 0 stevel } 2410 0 stevel if (build_dblock(name, tchar, '3', 2411 0 stevel filetype, &stbuf, stbuf.st_rdev, prefix) != 0) 2412 0 stevel goto out; 2413 0 stevel 2414 5331 amw if (put_extra_attributes(longname, shortname, longattrname, 2415 0 stevel prefix, filetype, '3') != 0) 2416 0 stevel goto out; 2417 0 stevel 2418 0 stevel (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2419 0 stevel dblock.dbuf.typeflag = '3'; 2420 0 stevel 2421 0 stevel (void) writetbuf((char *)&dblock, 1); 2422 0 stevel break; 2423 0 stevel case S_IFBLK: 2424 0 stevel stbuf.st_size = (off_t)0; 2425 0 stevel blocks = TBLOCKS(stbuf.st_size); 2426 5331 amw if (put_link(name, longname, shortname, longattrname, 2427 5331 amw prefix, filetype, '4') == 0) { 2428 0 stevel rc = PUT_AS_LINK; 2429 0 stevel goto out; 2430 0 stevel } 2431 0 stevel tomodes(&stbuf); 2432 0 stevel 2433 0 stevel while (mulvol && tapepos + blocks + 1 > blocklim) { 2434 0 stevel if (eflag) { 2435 0 stevel if (blocks <= blocklim) { 2436 0 stevel newvol(); 2437 0 stevel break; 2438 0 stevel } 2439 0 stevel (void) fprintf(stderr, gettext( 2440 0 stevel "tar: Single file cannot fit on volume\n")); 2441 0 stevel done(3); 2442 0 stevel } 2443 0 stevel 2444 0 stevel if (((blocklim - tapepos) >= EXTMIN) && 2445 0 stevel ((blocks + 1) >= blocklim/10)) { 2446 0 stevel splitfile(longname, infile, 2447 0 stevel name, prefix, filetype); 2448 0 stevel (void) close(dirfd); 2449 0 stevel goto out; 2450 0 stevel } 2451 0 stevel newvol(); 2452 0 stevel } 2453 0 stevel #ifdef DEBUG 2454 0 stevel DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, 2455 0 stevel blocks); 2456 0 stevel #endif 2457 0 stevel if (vflag) { 2458 0 stevel #ifdef DEBUG 2459 0 stevel if (NotTape) 2460 0 stevel DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2461 0 stevel 0); 2462 0 stevel #endif 2463 0 stevel (void) fprintf(vfile, "a %s ", longname); 2464 0 stevel if (NotTape) 2465 0 stevel (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n", 2466 0 stevel K(blocks)); 2467 0 stevel else 2468 0 stevel (void) fprintf(vfile, gettext("%" 2469 0 stevel FMT_blkcnt_t " tape blocks\n"), blocks); 2470 0 stevel } 2471 0 stevel if (build_dblock(name, tchar, '4', 2472 0 stevel filetype, &stbuf, stbuf.st_rdev, prefix) != 0) 2473 0 stevel goto out; 2474 0 stevel 2475 5331 amw if (put_extra_attributes(longname, shortname, longattrname, 2476 0 stevel prefix, filetype, '4') != 0) 2477 0 stevel goto out; 2478 0 stevel 2479 0 stevel (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2480 0 stevel dblock.dbuf.typeflag = '4'; 2481 0 stevel 2482 0 stevel (void) writetbuf((char *)&dblock, 1); 2483 0 stevel break; 2484 0 stevel default: 2485 0 stevel (void) fprintf(stderr, gettext( 2486 0 stevel "tar: %s is not a file. Not dumped\n"), longname); 2487 0 stevel if (errflag) 2488 0 stevel exitflag = 1; 2489 0 stevel Errflg = 1; 2490 0 stevel goto out; 2491 0 stevel } 2492 0 stevel 2493 0 stevel out: 2494 5331 amw if ((dirfd != -1) && (filetype != XATTR_FILE)) { 2495 0 stevel (void) close(dirfd); 2496 0 stevel } 2497 0 stevel return (rc); 2498 0 stevel } 2499 0 stevel 2500 0 stevel 2501 0 stevel /* 2502 0 stevel * splitfile dump a large file across volumes 2503 0 stevel * 2504 0 stevel * splitfile(longname, fd); 2505 0 stevel * char *longname; full name of file 2506 0 stevel * int ifd; input file descriptor 2507 0 stevel * 2508 0 stevel * NOTE: only called by putfile() to dump a large file. 2509 0 stevel */ 2510 0 stevel 2511 0 stevel static void 2512 0 stevel splitfile(char *longname, int ifd, char *name, char *prefix, int filetype) 2513 0 stevel { 2514 0 stevel blkcnt_t blocks; 2515 0 stevel off_t bytes, s; 2516 0 stevel char buf[TBLOCK]; 2517 0 stevel int i, extents; 2518 0 stevel 2519 0 stevel blocks = TBLOCKS(stbuf.st_size); /* blocks file needs */ 2520 0 stevel 2521 0 stevel /* 2522 0 stevel * # extents = 2523 0 stevel * size of file after using up rest of this floppy 2524 0 stevel * blocks - (blocklim - tapepos) + 1 (for header) 2525 0 stevel * plus roundup value before divide by blocklim-1 2526 0 stevel * + (blocklim - 1) - 1 2527 0 stevel * all divided by blocklim-1 (one block for each header). 2528 0 stevel * this gives 2529 0 stevel * (blocks - blocklim + tapepos + 1 + blocklim - 2)/(blocklim-1) 2530 0 stevel * which reduces to the expression used. 2531 0 stevel * one is added to account for this first extent. 2532 0 stevel * 2533 0 stevel * When one is dealing with extremely large archives, one may want 2534 0 stevel * to allow for a large number of extents. This code should be 2535 0 stevel * revisited to determine if extents should be changed to something 2536 0 stevel * larger than an int. 2537 0 stevel */ 2538 0 stevel extents = (int)((blocks + tapepos - 1ULL)/(blocklim - 1ULL) + 1); 2539 0 stevel 2540 0 stevel if (extents < 2 || extents > MAXEXT) { /* let's be reasonable */ 2541 0 stevel (void) fprintf(stderr, gettext( 2542 0 stevel "tar: %s needs unusual number of volumes to split\n" 2543 0 stevel "tar: %s not dumped\n"), longname, longname); 2544 0 stevel return; 2545 0 stevel } 2546 0 stevel if (build_dblock(name, tchar, '0', filetype, 2547 0 stevel &stbuf, stbuf.st_dev, prefix) != 0) 2548 0 stevel return; 2549 0 stevel 2550 0 stevel dblock.dbuf.extotal = extents; 2551 0 stevel bytes = stbuf.st_size; 2552 0 stevel 2553 0 stevel /* 2554 0 stevel * The value contained in dblock.dbuf.efsize was formerly used when the 2555 0 stevel * v flag was specified in conjunction with the t flag. Although it is 2556 0 stevel * no longer used, older versions of tar will expect the former 2557 0 stevel * behaviour, so we must continue to write it to the archive. 2558 0 stevel * 2559 0 stevel * Since dblock.dbuf.efsize is 10 chars in size, the maximum value it 2560 0 stevel * can store is TAR_EFSIZE_MAX. If bytes exceeds that value, simply 2561 0 stevel * store 0. 2562 0 stevel */ 2563 0 stevel if (bytes <= TAR_EFSIZE_MAX) 2564 0 stevel (void) sprintf(dblock.dbuf.efsize, "%9" FMT_off_t_o, bytes); 2565 0 stevel else 2566 0 stevel (void) sprintf(dblock.dbuf.efsize, "%9" FMT_off_t_o, (off_t)0); 2567 0 stevel 2568 0 stevel (void) fprintf(stderr, gettext( 2569 0 stevel "tar: large file %s needs %d extents.\n" 2570 0 stevel "tar: current device seek position = %" FMT_blkcnt_t "K\n"), 2571 0 stevel longname, extents, K(tapepos)); 2572 0 stevel 2573 0 stevel s = (off_t)(blocklim - tapepos - 1) * TBLOCK; 2574 0 stevel for (i = 1; i <= extents; i++) { 2575 0 stevel if (i > 1) { 2576 0 stevel newvol(); 2577 0 stevel if (i == extents) 2578 0 stevel s = bytes; /* last ext. gets true bytes */ 2579 0 stevel else 2580 0 stevel s = (off_t)(blocklim - 1)*TBLOCK; /* all */ 2581 0 stevel } 2582 0 stevel bytes -= s; 2583 0 stevel blocks = TBLOCKS(s); 2584 0 stevel 2585 0 stevel (void) sprintf(dblock.dbuf.size, "%011" FMT_off_t_o, s); 2586 0 stevel dblock.dbuf.extno = i; 2587 0 stevel (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2588 0 stevel (void) writetbuf((char *)&dblock, 1); 2589 0 stevel 2590 0 stevel if (vflag) 2591 0 stevel (void) fprintf(vfile, 2592 0 stevel "+++ a %s %" FMT_blkcnt_t "K [extent #%d of %d]\n", 2593 0 stevel longname, K(blocks), i, extents); 2594 0 stevel while (blocks && read(ifd, buf, TBLOCK) > 0) { 2595 0 stevel blocks--; 2596 0 stevel (void) writetbuf(buf, 1); 2597 0 stevel } 2598 0 stevel if (blocks != 0) { 2599 0 stevel (void) fprintf(stderr, gettext( 2600 0 stevel "tar: %s: file changed size\n"), longname); 2601 0 stevel (void) fprintf(stderr, gettext( 2602 0 stevel "tar: aborting split file %s\n"), longname); 2603 0 stevel (void) close(ifd); 2604 0 stevel return; 2605 0 stevel } 2606 0 stevel } 2607 0 stevel (void) close(ifd); 2608 0 stevel if (vflag) 2609 0 stevel (void) fprintf(vfile, gettext("a %s %" FMT_off_t "K (in %d " 2610 0 stevel "extents)\n"), longname, K(TBLOCKS(stbuf.st_size)), 2611 0 stevel extents); 2612 0 stevel } 2613 0 stevel 2614 0 stevel /* 2615 0 stevel * convtoreg - determines whether the file should be converted to a 2616 0 stevel * regular file when extracted 2617 0 stevel * 2618 0 stevel * Returns 1 when file size > 0 and typeflag is not recognized 2619 0 stevel * Otherwise returns 0 2620 0 stevel */ 2621 0 stevel static int 2622 0 stevel convtoreg(off_t size) 2623 0 stevel { 2624 0 stevel if ((size > 0) && (dblock.dbuf.typeflag != '0') && 2625 0 stevel (dblock.dbuf.typeflag != NULL) && (dblock.dbuf.typeflag != '1') && 2626 0 stevel (dblock.dbuf.typeflag != '2') && (dblock.dbuf.typeflag != '3') && 2627 0 stevel (dblock.dbuf.typeflag != '4') && (dblock.dbuf.typeflag != '5') && 2628 0 stevel (dblock.dbuf.typeflag != '6') && (dblock.dbuf.typeflag != 'A') && 2629 0 stevel (dblock.dbuf.typeflag != _XATTR_HDRTYPE) && 2630 0 stevel (dblock.dbuf.typeflag != 'X')) { 2631 0 stevel return (1); 2632 0 stevel } 2633 0 stevel return (0); 2634 0 stevel } 2635 0 stevel 2636 5331 amw #if defined(O_XATTR) 2637 5331 amw static int 2638 5331 amw save_cwd(void) 2639 5331 amw { 2640 5331 amw return (open(".", O_RDONLY)); 2641 5331 amw } 2642 5331 amw #endif 2643 5331 amw 2644 5331 amw #if defined(O_XATTR) 2645 5331 amw static void 2646 5331 amw rest_cwd(int *cwd) 2647 5331 amw { 2648 5331 amw if (*cwd != -1) { 2649 5331 amw if (fchdir(*cwd) < 0) { 2650 5331 amw vperror(0, gettext( 2651 5331 amw "Cannot fchdir to attribute directory")); 2652 5331 amw exit(1); 2653 5331 amw } 2654 5331 amw (void) close(*cwd); 2655 5331 amw *cwd = -1; 2656 5331 amw } 2657 5331 amw } 2658 5331 amw #endif 2659 5331 amw 2660 5331 amw /* 2661 5331 amw * Verify the underlying file system supports the attribute type. 2662 5331 amw * Only archive extended attribute files when '-@' was specified. 2663 5331 amw * Only archive system extended attribute files if '-/' was specified. 2664 5331 amw */ 2665 5331 amw #if defined(O_XATTR) 2666 5331 amw static attr_status_t 2667 5750 ceastha verify_attr_support(char *filename, int attrflg, arc_action_t actflag, 2668 5750 ceastha int *ext_attrflg) 2669 5750 ceastha { 2670 5750 ceastha /* 2671 5750 ceastha * Verify extended attributes are supported/exist. We only 2672 5750 ceastha * need to check if we are processing a base file, not an 2673 5750 ceastha * extended attribute. 2674 5750 ceastha */ 2675 5750 ceastha if (attrflg) { 2676 5750 ceastha *ext_attrflg = (pathconf(filename, (actflag == ARC_CREATE) ? 2677 5750 ceastha _PC_XATTR_EXISTS : _PC_XATTR_ENABLED) == 1); 2678 5750 ceastha } 2679 5750 ceastha 2680 5331 amw if (atflag) { 2681 5750 ceastha if (!*ext_attrflg) { 2682 5331 amw #if defined(_PC_SATTR_ENABLED) 2683 5331 amw if (saflag) { 2684 5331 amw /* Verify system attributes are supported */ 2685 5331 amw if (sysattr_support(filename, 2686 5331 amw (actflag == ARC_CREATE) ? _PC_SATTR_EXISTS : 2687 5331 amw _PC_SATTR_ENABLED) != 1) { 2688 5331 amw return (ATTR_SATTR_ERR); 2689 5331 amw } 2690 5331 amw } else 2691 5331 amw return (ATTR_XATTR_ERR); 2692 5331 amw #else 2693 5331 amw return (ATTR_XATTR_ERR); 2694 5331 amw #endif /* _PC_SATTR_ENABLED */ 2695 5331 amw } 2696 5331 amw 2697 5331 amw #if defined(_PC_SATTR_ENABLED) 2698 5331 amw } else if (saflag) { 2699 5331 amw /* Verify system attributes are supported */ 2700 5331 amw if (sysattr_support(filename, (actflag == ARC_CREATE) ? 2701 5331 amw _PC_SATTR_EXISTS : _PC_SATTR_ENABLED) != 1) { 2702 5331 amw return (ATTR_SATTR_ERR); 2703 5331 amw } 2704 5331 amw #endif /* _PC_SATTR_ENABLED */ 2705 5331 amw } else { 2706 5331 amw return (ATTR_SKIP); 2707 5331 amw } 2708 5331 amw 2709 5331 amw return (ATTR_OK); 2710 5331 amw } 2711 5331 amw #endif 2712 5331 amw 2713 5331 amw #if defined(O_XATTR) 2714 5331 amw /* 2715 5331 amw * Recursively open attribute directories until the attribute directory 2716 5331 amw * containing the specified attribute, attrname, is opened. 2717 5331 amw * 2718 5331 amw * Currently, only 2 directory levels of attributes are supported, (i.e., 2719 5331 amw * extended system attributes on extended attributes). The following are 2720 5331 amw * the possible input combinations: 2721 5331 amw * 1. Open the attribute directory of the base file (don't change 2722 5331 amw * into it). 2723 5331 amw * attrinfo->parent = NULL 2724 5331 amw * attrname = '.' 2725 5331 amw * 2. Open the attribute directory of the base file and change into it. 2726 5331 amw * attrinfo->parent = NULL 2727 5331 amw * attrname = <attr> | <sys_attr> 2728 5331 amw * 3. Open the attribute directory of the base file, change into it, 2729 5331 amw * then recursively call open_attr_dir() to open the attribute's 2730 5331 amw * parent directory (don't change into it). 2731 5331 amw * attrinfo->parent = <attr> 2732 5331 amw * attrname = '.' 2733 5331 amw * 4. Open the attribute directory of the base file, change into it, 2734 5331 amw * then recursively call open_attr_dir() to open the attribute's 2735 5331 amw * parent directory and change into it. 2736 5331 amw * attrinfo->parent = <attr> 2737 5331 amw * attrname = <attr> | <sys_attr> 2738 5331 amw * 2739 5331 amw * An attribute directory will be opened only if the underlying file system 2740 5331 amw * supports the attribute type, and if the command line specifications (atflag 2741 5331 amw * and saflag) enable the processing of the attribute type. 2742 5331 amw * 2743 5331 amw * On succesful return, attrinfo->parentfd will be the file descriptor of the 2744 5331 amw * opened attribute directory. In addition, if the attribute is a read-write 2745 5331 amw * extended system attribute, attrinfo->rw_sysattr will be set to 1, otherwise 2746 5331 amw * it will be set to 0. 2747 5331 amw * 2748 5331 amw * Possible return values: 2749 5331 amw * ATTR_OK Successfully opened and, if needed, changed into the 2750 5331 amw * attribute directory containing attrname. 2751 5331 amw * ATTR_SKIP The command line specifications don't enable the 2752 5331 amw * processing of the attribute type. 2753 5331 amw * ATTR_CHDIR_ERR An error occurred while trying to change into an 2754 5331 amw * attribute directory. 2755 5331 amw * ATTR_OPEN_ERR An error occurred while trying to open an 2756 5331 amw * attribute directory. 2757 5331 amw * ATTR_XATTR_ERR The underlying file system doesn't support extended 2758 5331 amw * attributes. 2759 5331 amw * ATTR_SATTR_ERR The underlying file system doesn't support extended 2760 5331 amw * system attributes. 2761 5331 amw */ 2762 5331 amw static int 2763 5331 amw open_attr_dir(char *attrname, char *dirp, int cwd, attr_data_t *attrinfo) 2764 5331 amw { 2765 5331 amw attr_status_t rc; 2766 5331 amw int firsttime = (attrinfo->attr_parentfd == -1); 2767 5331 amw int saveerrno; 2768 5750 ceastha int ext_attr; 2769 5331 amw 2770 5331 amw /* 2771 5331 amw * open_attr_dir() was recursively called (input combination number 4), 2772 5331 amw * close the previously opened file descriptor as we've already changed 2773 5331 amw * into it. 2774 5331 amw */ 2775 5331 amw if (!firsttime) { 2776 5331 amw (void) close(attrinfo->attr_parentfd); 2777 5331 amw attrinfo->attr_parentfd = -1; 2778 5331 amw } 2779 5331 amw 2780 5331 amw /* 2781 5331 amw * Verify that the underlying file system supports the restoration 2782 5331 amw * of the attribute. 2783 5331 amw */ 2784 5750 ceastha if ((rc = verify_attr_support(dirp, firsttime, ARC_RESTORE, 2785 5750 ceastha &ext_attr)) != ATTR_OK) { 2786 5331 amw return (rc); 2787 5331 amw } 2788 5331 amw 2789 5331 amw /* Open the base file's attribute directory */ 2790 5331 amw if ((attrinfo->attr_parentfd = attropen(dirp, ".", O_RDONLY)) == -1) { 2791 5331 amw /* 2792 5331 amw * Save the errno from the attropen so it can be reported 2793 5331 amw * if the retry of the attropen fails. 2794 5331 amw */ 2795 5331 amw saveerrno = errno; 2796 5331 amw if ((attrinfo->attr_parentfd = retry_open_attr(-1, cwd, dirp, 2797 5331 amw NULL, ".", O_RDONLY, 0)) == -1) { 2798 5331 amw /* 2799 5331 amw * Reset typeflag back to real value so passtape 2800 5331 amw * will skip ahead correctly. 2801 5331 amw */ 2802 5331 amw dblock.dbuf.typeflag = _XATTR_HDRTYPE; 2803 5331 amw (void) close(attrinfo->attr_parentfd); 2804 5331 amw attrinfo->attr_parentfd = -1; 2805 5331 amw errno = saveerrno; 2806 5331 amw return (ATTR_OPEN_ERR); 2807 5331 amw } 2808 5331 amw } 2809 5331 amw 2810 5331 amw /* 2811 5331 amw * Change into the parent attribute's directory unless we are 2812 5331 amw * processing the hidden attribute directory of the base file itself. 2813 5331 amw */ 2814 5331 amw if ((Hiddendir == 0) || (firsttime && attrinfo->attr_parent != NULL)) { 2815 5331 amw if (fchdir(attrinfo->attr_parentfd) != 0) { 2816 5331 amw saveerrno = errno; 2817 5331 amw (void) close(attrinfo->attr_parentfd); 2818 5331 amw attrinfo->attr_parentfd = -1; 2819 5331 amw errno = saveerrno; 2820 5331 amw return (ATTR_CHDIR_ERR); 2821 5331 amw } 2822 5331 amw } 2823 5331 amw 2824 5331 amw /* Determine if the attribute should be processed */ 2825 5331 amw if ((rc = verify_attr(attrname, attrinfo->attr_parent, 1, 2826 5331 amw &attrinfo->attr_rw_sysattr)) != ATTR_OK) { 2827 5331 amw saveerrno = errno; 2828 5331 amw (void) close(attrinfo->attr_parentfd); 2829 5331 amw attrinfo->attr_parentfd = -1; 2830 5331 amw errno = saveerrno; 2831 5331 amw return (rc); 2832 5331 amw } 2833 5331 amw 2834 5331 amw /* 2835 5331 amw * If the attribute is an extended attribute, or extended system 2836 5331 amw * attribute, of an attribute (i.e., <attr>/<sys_attr>), then 2837 5331 amw * recursively call open_attr_dir() to open the attribute directory 2838 5331 amw * of the parent attribute. 2839 5331 amw */ 2840 5331 amw if (firsttime && (attrinfo->attr_parent != NULL)) { 2841 5331 amw return (open_attr_dir(attrname, attrinfo->attr_parent, 2842 5331 amw attrinfo->attr_parentfd, attrinfo)); 2843 5331 amw } 2844 5331 amw 2845 5331 amw return (ATTR_OK); 2846 5331 amw } 2847 5331 amw #endif 2848 5331 amw 2849 0 stevel static void 2850 0 stevel #ifdef _iBCS2 2851 0 stevel doxtract(char *argv[], int tbl_cnt) 2852 0 stevel #else 2853 0 stevel doxtract(char *argv[]) 2854 0 stevel #endif 2855 0 stevel { 2856 0 stevel struct stat xtractbuf; /* stat on file after extracting */ 2857 0 stevel blkcnt_t blocks; 2858 0 stevel off_t bytes; 2859 0 stevel int ofile; 2860 0 stevel int newfile; /* Does the file already exist */ 2861 0 stevel int xcnt = 0; /* count # files extracted */ 2862 0 stevel int fcnt = 0; /* count # files in argv list */ 2863 0 stevel int dir; 2864 0 stevel int dirfd = -1; 2865 5331 amw int cwd = -1; 2866 5750 ceastha int rw_sysattr; 2867 5331 amw int saveerrno; 2868 0 stevel uid_t Uid; 2869 0 stevel char *namep, *dirp, *comp, *linkp; /* for removing absolute paths */ 2870 0 stevel char dirname[PATH_MAX+1]; 2871 0 stevel char templink[PATH_MAX+1]; /* temp link with terminating NULL */ 2872 0 stevel int once = 1; 2873 0 stevel int error; 2874 0 stevel int symflag; 2875 0 stevel int want; 2876 5331 amw attr_data_t *attrinfo = NULL; /* attribute info */ 2877 789 ahrens acl_t *aclp = NULL; /* acl info */ 2878 1676 jpk char dot[] = "."; /* dirp for using realpath */ 2879 0 stevel timestruc_t time_zero; /* used for call to doDirTimes */ 2880 0 stevel int dircreate; 2881 0 stevel int convflag; 2882 0 stevel time_zero.tv_sec = 0; 2883 0 stevel time_zero.tv_nsec = 0; 2884 1676 jpk 2885 1676 jpk /* reset Trusted Extensions variables */ 2886 1676 jpk rpath_flag = 0; 2887 1676 jpk lk_rpath_flag = 0; 2888 1676 jpk dir_flag = 0; 2889 1676 jpk mld_flag = 0; 2890 1676 jpk bslundef(&bs_label); 2891 1676 jpk bsllow(&admin_low); 2892 1676 jpk bslhigh(&admin_high); 2893 1676 jpk orig_namep = 0; 2894 0 stevel 2895 0 stevel dumping = 0; /* for newvol(), et al: we are not writing */ 2896 0 stevel 2897 0 stevel /* 2898 0 stevel * Count the number of files that are to be extracted 2899 0 stevel */ 2900 0 stevel Uid = getuid(); 2901 0 stevel 2902 0 stevel #ifdef _iBCS2 2903 0 stevel initarg(argv, Filefile); 2904 0 stevel while (nextarg() != NULL) 2905 0 stevel ++fcnt; 2906 0 stevel fcnt += tbl_cnt; 2907 0 stevel #endif /* _iBCS2 */ 2908 0 stevel 2909 0 stevel for (;;) { 2910 0 stevel convflag = 0; 2911 0 stevel symflag = 0; 2912 0 stevel dir = 0; 2913 5750 ceastha Hiddendir = 0; 2914 5750 ceastha rw_sysattr = 0; 2915 0 stevel ofile = -1; 2916 0 stevel 2917 5331 amw if (dirfd != -1) { 2918 5331 amw (void) close(dirfd); 2919 5331 amw dirfd = -1; 2920 5331 amw } 2921 5331 amw if (ofile != -1) { 2922 5331 amw if (close(ofile) != 0) 2923 5331 amw vperror(2, gettext("close error")); 2924 5331 amw } 2925 5331 amw 2926 5331 amw #if defined(O_XATTR) 2927 5331 amw if (cwd != -1) { 2928 5331 amw rest_cwd(&cwd); 2929 5331 amw } 2930 5331 amw #endif 2931 5331 amw 2932 0 stevel /* namep is set by wantit to point to the full name */ 2933 5331 amw if ((want = wantit(argv, &namep, &dirp, &comp, 2934 5331 amw &attrinfo)) == 0) { 2935 5331 amw #if defined(O_XATTR) 2936 5331 amw if (xattrp != NULL) { 2937 0 stevel free(xattrhead); 2938 0 stevel xattrp = NULL; 2939 0 stevel xattr_linkp = NULL; 2940 0 stevel xattrhead = NULL; 2941 0 stevel } 2942 0 stevel #endif 2943 0 stevel continue; 2944 0 stevel } 2945 0 stevel if (want == -1) 2946 0 stevel break; 2947 1676 jpk 2948 1676 jpk /* Trusted Extensions */ 2949 1676 jpk /* 2950 1676 jpk * During tar extract (x): 2951 1676 jpk * If the pathname of the restored file has been 2952 1676 jpk * reconstructed from the ancillary file, 2953 1676 jpk * use it to process the normal file. 2954 1676 jpk */ 2955 1676 jpk if (mld_flag) { /* Skip over .MLD. directory */ 2956 1676 jpk mld_flag = 0; 2957 1676 jpk passtape(); 2958 1676 jpk continue; 2959 1676 jpk } 2960 1676 jpk orig_namep = namep; /* save original */ 2961 1676 jpk if (rpath_flag) { 2962 1676 jpk namep = real_path; /* use zone path */ 2963 1676 jpk comp = real_path; /* use zone path */ 2964 1676 jpk dirp = dot; /* work from the top */ 2965 1676 jpk rpath_flag = 0; /* reset */ 2966 1676 jpk } 2967 0 stevel 2968 0 stevel if (dirfd != -1) 2969 0 stevel (void) close(dirfd); 2970 0 stevel 2971 0 stevel (void) strcpy(&dirname[0], namep); 2972 0 stevel dircreate = checkdir(&dirname[0]); 2973 0 stevel 2974 0 stevel #if defined(O_XATTR) 2975 5331 amw if (xattrp != NULL) { 2976 5331 amw int rc; 2977 5331 amw 2978 5331 amw if (((cwd = save_cwd()) == -1) || 2979 5331 amw ((rc = open_attr_dir(comp, dirp, cwd, 2980 5331 amw attrinfo)) != ATTR_OK)) { 2981 5331 amw if (cwd == -1) { 2982 5331 amw vperror(0, gettext( 2983 5331 amw "unable to save current working " 2984 5331 amw "directory while processing " 2985 5331 amw "attribute %s of %s"), 2986 5331 amw dirp, attrinfo->attr_path); 2987 5331 amw } else if (rc != ATTR_SKIP) { 2988 1231 marks (void) fprintf(vfile, 2989 1231 marks gettext("tar: cannot open " 2990 5331 amw "%sattribute %s of file %s: %s\n"), 2991 5331 amw attrinfo->attr_rw_sysattr ? gettext( 2992 5331 amw "system ") : "", 2993 5331 amw comp, dirp, strerror(errno)); 2994 5331 amw } 2995 5331 amw free(xattrhead); 2996 5331 amw xattrp = NULL; 2997 5331 amw xattr_linkp = NULL; 2998 5331 amw xattrhead = NULL; 2999 5331 amw 3000 0 stevel passtape(); 3001 0 stevel continue; 3002 5331 amw } else { 3003 5331 amw dirfd = attrinfo->attr_parentfd; 3004 5331 amw rw_sysattr = attrinfo->attr_rw_sysattr; 3005 5331 amw } 3006 5331 amw } else { 3007 5331 amw dirfd = open(dirp, O_RDONLY); 3008 5331 amw } 3009 5331 amw #else 3010 5331 amw dirfd = open(dirp, O_RDONLY); 3011 5331 amw #endif 3012 5331 amw if (dirfd == -1) { 3013 5331 amw (void) fprintf(vfile, gettext( 3014 5331 amw "tar: cannot open %s: %s\n"), 3015 5331 amw dirp, strerror(errno)); 3016 5331 amw passtape(); 3017 5331 amw continue; 3018 0 stevel } 3019 0 stevel 3020 0 stevel if (xhdr_flgs & _X_LINKPATH) 3021 0 stevel (void) strcpy(templink, Xtarhdr.x_linkpath); 3022 0 stevel else { 3023 0 stevel #if defined(O_XATTR) 3024 0 stevel if (xattrp && dblock.dbuf.typeflag == '1') { 3025 0 stevel (void) sprintf(templink, "%.*s", NAMSIZ, 3026 0 stevel xattrp->h_names); 3027 0 stevel } else { 3028 0 stevel (void) sprintf(templink, "%.*s", NAMSIZ, 3029 0 stevel dblock.dbuf.linkname); 3030 0 stevel } 3031 0 stevel #else 3032 0 stevel (void) sprintf(templink, "%.*s", NAMSIZ, 3033 0 stevel dblock.dbuf.linkname); 3034 0 stevel #endif 3035 0 stevel } 3036 0 stevel 3037 0 stevel if (Fflag) { 3038 0 stevel char *s; 3039 0 stevel 3040 0 stevel if ((s = strrchr(namep, '/')) == 0) 3041 0 stevel s = namep; 3042 0 stevel 3043 0 stevel else 3044 0 stevel s++; 3045 0 stevel if (checkf(s, stbuf.st_mode, Fflag) == 0) { 3046 0 stevel passtape(); 3047 0 stevel continue; 3048 0 stevel } 3049 0 stevel } 3050 0 stevel 3051 0 stevel if (checkw('x', namep) == 0) { 3052 0 stevel passtape(); 3053 0 stevel continue; 3054 0 stevel } 3055 0 stevel if (once) { 3056 0 stevel if (strcmp(dblock.dbuf.magic, magic_type) == 0) { 3057 0 stevel if (geteuid() == (uid_t)0) { 3058 0 stevel checkflag = 1; 3059 0 stevel pflag = 1; 3060 0 stevel } else { 3061 0 stevel /* get file creation mask */ 3062 0 stevel Oumask = umask(0); 3063 0 stevel (void) umask(Oumask); 3064 0 stevel } 3065 0 stevel once = 0; 3066 0 stevel } else { 3067 0 stevel if (geteuid() == (uid_t)0) { 3068 0 stevel pflag = 1; 3069 0 stevel checkflag = 2; 3070 0 stevel } 3071 0 stevel if (!pflag) { 3072 0 stevel /* get file creation mask */ 3073 0 stevel Oumask = umask(0); 3074 0 stevel (void) umask(Oumask); 3075 0 stevel } 3076 0 stevel once = 0; 3077 0 stevel } 3078 0 stevel } 3079 0 stevel 3080 0 stevel #if defined(O_XATTR) 3081 0 stevel /* 3082 0 stevel * Handle extraction of hidden attr dir. 3083 0 stevel * Dir is automatically created, we only 3084 0 stevel * need to update mode and perm's. 3085 0 stevel */ 3086 5331 amw if ((xattrp != NULL) && Hiddendir == 1) { 3087 5331 amw bytes = stbuf.st_size; 3088 5331 amw blocks = TBLOCKS(bytes); 3089 5331 amw if (vflag) { 3090 5331 amw (void) fprintf(vfile, 3091 5331 amw "x %s%s%s, %" FMT_off_t " bytes, ", namep, 3092 5331 amw gettext(" attribute "), 3093 5331 amw xattrapath, bytes); 3094 5331 amw if (NotTape) 3095 5331 amw (void) fprintf(vfile, 3096 5331 amw "%" FMT_blkcnt_t "K\n", K(blocks)); 3097 5331 amw else 3098 5331 amw (void) fprintf(vfile, gettext("%" 3099 5331 amw FMT_blkcnt_t " tape blocks\n"), 3100 5331 amw blocks); 3101 5331 amw } 3102 5331 amw 3103 5331 amw /* 3104 5331 amw * Set the permissions and mode of the attribute 3105 5331 amw * unless the attribute is a system attribute (can't 3106 5331 amw * successfully do this) or the hidden attribute 3107 5331 amw * directory (".") of an attribute (when the attribute 3108 5331 amw * is restored, the hidden attribute directory of an 3109 5331 amw * attribute is transient). Note: when the permissions 3110 5331 amw * and mode are set for the hidden attribute directory 3111 5331 amw * of a file on a system supporting extended system 3112 5331 amw * attributes, even though it returns successfully, it 3113 5331 amw * will not have any affect since the attribute 3114 5331 amw * directory is transient. 3115 5331 amw */ 3116 5331 amw if (attrinfo->attr_parent == NULL) { 3117 5331 amw if (fchownat(dirfd, ".", stbuf.st_uid, 3118 5331 amw stbuf.st_gid, 0) != 0) { 3119 5331 amw vperror(0, gettext( 3120 5331 amw "%s%s%s: failed to set ownership " 3121 5331 amw "of attribute directory"), namep, 3122 5331 amw gettext(" attribute "), xattrapath); 3123 5331 amw } 3124 5331 amw 3125 5331 amw if (fchmod(dirfd, stbuf.st_mode) != 0) { 3126 5331 amw vperror(0, gettext( 3127 5331 amw "%s%s%s: failed to set permissions " 3128 5331 amw "of attribute directory"), namep, 3129 5331 amw gettext(" attribute "), xattrapath); 3130 5331 amw } 3131 0 stevel } 3132 0 stevel goto filedone; 3133 0 stevel } 3134 0 stevel #endif 3135 0 stevel 3136 0 stevel if (dircreate && (!is_posix || dblock.dbuf.typeflag == '5')) { 3137 0 stevel dir = 1; 3138 0 stevel if (vflag) { 3139 0 stevel (void) fprintf(vfile, "x %s, 0 bytes, ", 3140 0 stevel &dirname[0]); 3141 0 stevel if (NotTape) 3142 0 stevel (void) fprintf(vfile, "0K\n"); 3143 0 stevel else 3144 0 stevel (void) fprintf(vfile, gettext("%" 3145 0 stevel FMT_blkcnt_t " tape blocks\n"), 3146 0 stevel (blkcnt_t)0); 3147 0 stevel } 3148 0 stevel goto filedone; 3149 0 stevel } 3150 0 stevel 3151 0 stevel if (dblock.dbuf.typeflag == '6') { /* FIFO */ 3152 0 stevel if (rmdir(namep) < 0) { 3153 0 stevel if (errno == ENOTDIR) 3154 0 stevel (void) unlink(namep); 3155 0 stevel } 3156 0 stevel linkp = templink; 3157 0 stevel if (*linkp != NULL) { 3158 0 stevel if (Aflag && *linkp == '/') 3159 0 stevel linkp++; 3160 0 stevel if (link(linkp, namep) < 0) { 3161 0 stevel (void) fprintf(stderr, gettext( 3162 0 stevel "tar: %s: cannot link\n"), namep); 3163 0 stevel continue; 3164 0 stevel } 3165 0 stevel if (vflag) 3166 0 stevel (void) fprintf(vfile, gettext( 3167 5331 amw "x %s linked to %s\n"), namep, 3168 5331 amw linkp); 3169 0 stevel xcnt++; /* increment # files extracted */ 3170 0 stevel continue; 3171 0 stevel } 3172 0 stevel if (mknod(namep, (int)(Gen.g_mode|S_IFIFO), 3173 0 stevel (int)Gen.g_devmajor) < 0) { 3174 0 stevel vperror(0, gettext("%s: mknod failed"), namep); 3175 0 stevel continue; 3176 0 stevel } 3177 0 stevel bytes = stbuf.st_size; 3178 0 stevel blocks = TBLOCKS(bytes); 3179 0 stevel if (vflag) { 3180 0 stevel (void) fprintf(vfile, "x %s, %" FMT_off_t 3181 0 stevel " bytes, ", namep, bytes); 3182 0 stevel if (NotTape) 3183 0 stevel (void) fprintf(vfile, "%" FMT_blkcnt_t 3184 0 stevel "K\n", K(blocks)); 3185 0 stevel else 3186 0 stevel (void) fprintf(vfile, gettext("%" 3187 0