Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/archival/tar.c
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/archival/tar.c
r821 r1770 24 24 */ 25 25 26 #include <f cntl.h>26 #include <fnmatch.h> 27 27 #include <getopt.h> 28 #include <search.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <unistd.h> 32 #include <fnmatch.h> 33 #include <string.h> 34 #include <errno.h> 35 #include <signal.h> 36 #include <sys/wait.h> 37 #include <sys/socket.h> 38 #include <sys/sysmacros.h> /* major() and minor() */ 28 #include "libbb.h" 39 29 #include "unarchive.h" 40 #include "busybox.h" 41 42 #ifdef CONFIG_FEATURE_TAR_CREATE 30 31 #define block_buf bb_common_bufsiz1 32 33 #if ENABLE_FEATURE_TAR_CREATE 43 34 44 35 /* Tar file constants */ … … 47 38 48 39 /* POSIX tar Header Block, from POSIX 1003.1-1990 */ 49 #define NAME_SIZE 100 50 struct TarHeader { /* byte offset */ 51 char name[NAME_SIZE]; /* 0-99 */ 52 char mode[8]; /* 100-107 */ 53 char uid[8]; /* 108-115 */ 54 char gid[8]; /* 116-123 */ 55 char size[12]; /* 124-135 */ 56 char mtime[12]; /* 136-147 */ 57 char chksum[8]; /* 148-155 */ 58 char typeflag; /* 156-156 */ 59 char linkname[NAME_SIZE]; /* 157-256 */ 60 char magic[6]; /* 257-262 */ 61 char version[2]; /* 263-264 */ 62 char uname[32]; /* 265-296 */ 63 char gname[32]; /* 297-328 */ 64 char devmajor[8]; /* 329-336 */ 65 char devminor[8]; /* 337-344 */ 66 char prefix[155]; /* 345-499 */ 67 char padding[12]; /* 500-512 (pad to exactly the TAR_BLOCK_SIZE) */ 40 #define NAME_SIZE 100 41 #define NAME_SIZE_STR "100" 42 typedef struct TarHeader TarHeader; 43 struct TarHeader { /* byte offset */ 44 char name[NAME_SIZE]; /* 0-99 */ 45 char mode[8]; /* 100-107 */ 46 char uid[8]; /* 108-115 */ 47 char gid[8]; /* 116-123 */ 48 char size[12]; /* 124-135 */ 49 char mtime[12]; /* 136-147 */ 50 char chksum[8]; /* 148-155 */ 51 char typeflag; /* 156-156 */ 52 char linkname[NAME_SIZE]; /* 157-256 */ 53 char magic[6]; /* 257-262 */ 54 char version[2]; /* 263-264 */ 55 char uname[32]; /* 265-296 */ 56 char gname[32]; /* 297-328 */ 57 char devmajor[8]; /* 329-336 */ 58 char devminor[8]; /* 337-344 */ 59 char prefix[155]; /* 345-499 */ 60 char padding[12]; /* 500-512 (pad to exactly the TAR_BLOCK_SIZE) */ 68 61 }; 69 typedef struct TarHeader TarHeader;70 62 71 63 /* 72 ** writeTarFile(), 64 ** writeTarFile(), writeFileToTarball(), and writeTarHeader() are 73 65 ** the only functions that deal with the HardLinkInfo structure. 74 66 ** Even these functions use the xxxHardLinkInfo() functions. … … 84 76 85 77 /* Some info to be carried along when creating a new tarball */ 78 typedef struct TarBallInfo TarBallInfo; 86 79 struct TarBallInfo { 87 char *fileName; /* File name of the tarball */88 80 int tarFd; /* Open-for-write file descriptor 89 81 for the tarball */ … … 97 89 HardLinkInfo *hlInfo; /* Hard Link Info for the current file */ 98 90 }; 99 typedef struct TarBallInfo TarBallInfo;100 91 101 92 /* A nice enum with all the possible tar file content types */ … … 116 107 117 108 /* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */ 118 static inlinevoid addHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr,109 static void addHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr, 119 110 struct stat *statbuf, 120 const char * name)111 const char *fileName) 121 112 { 122 113 /* Note: hlInfoHeadPtr can never be NULL! */ 123 114 HardLinkInfo *hlInfo; 124 115 125 hlInfo = (HardLinkInfo *) xmalloc(sizeof(HardLinkInfo) + strlen(name));116 hlInfo = xmalloc(sizeof(HardLinkInfo) + strlen(fileName)); 126 117 hlInfo->next = *hlInfoHeadPtr; 127 118 *hlInfoHeadPtr = hlInfo; … … 129 120 hlInfo->ino = statbuf->st_ino; 130 121 hlInfo->linkCount = statbuf->st_nlink; 131 strcpy(hlInfo->name, name);122 strcpy(hlInfo->name, fileName); 132 123 } 133 124 134 125 static void freeHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr) 135 126 { 136 HardLinkInfo *hlInfo = NULL;137 HardLinkInfo *hlInfoNext = NULL;127 HardLinkInfo *hlInfo; 128 HardLinkInfo *hlInfoNext; 138 129 139 130 if (hlInfoHeadPtr) { … … 146 137 *hlInfoHeadPtr = NULL; 147 138 } 148 return;149 139 } 150 140 151 141 /* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */ 152 static inlineHardLinkInfo *findHardLinkInfo(HardLinkInfo * hlInfo, struct stat *statbuf)142 static HardLinkInfo *findHardLinkInfo(HardLinkInfo * hlInfo, struct stat *statbuf) 153 143 { 154 144 while (hlInfo) { … … 157 147 hlInfo = hlInfo->next; 158 148 } 159 return (hlInfo);149 return hlInfo; 160 150 } 161 151 162 152 /* Put an octal string into the specified buffer. 163 * The number is zero and space padded and possibly null padded. 164 * Returns TRUE if successful. */ 165 static int putOctal(char *cp, int len, long value) 166 { 167 int tempLength; 168 char tempBuffer[32]; 153 * The number is zero padded and possibly null terminated. 154 * Stores low-order bits only if whole value does not fit. */ 155 static void putOctal(char *cp, int len, off_t value) 156 { 157 char tempBuffer[sizeof(off_t)*3+1]; 169 158 char *tempString = tempBuffer; 170 171 /* Create a string of the specified length with an initial space, 172 * leading zeroes and the octal number, and a trailing null. */173 sprintf(tempString, "%0*lo", len - 1, value);174 175 /* If the string is too large, suppress the leading space.*/176 tempLength = strlen(tempString) + 1;177 if (tempLength > len) {178 tempLength--;159 int width; 160 161 width = sprintf(tempBuffer, "%0*"OFF_FMT"o", len, value); 162 tempString += (width - len); 163 164 /* If string has leading zeroes, we can drop one */ 165 /* and field will have trailing '\0' */ 166 /* (increases chances of compat with other tars) */ 167 if (tempString[0] == '0') 179 168 tempString++; 180 } 181 182 /* If the string is still too large, suppress the trailing null. */ 183 if (tempLength > len) 184 tempLength--; 185 186 /* If the string is still too large, fail. */ 187 if (tempLength > len) 188 return FALSE; 189 190 /* Copy the string to the field. */ 169 170 /* Copy the string to the field */ 191 171 memcpy(cp, tempString, len); 192 193 return TRUE; 194 } 172 } 173 #define PUT_OCTAL(a, b) putOctal((a), sizeof(a), (b)) 174 175 static void chksum_and_xwrite(int fd, struct TarHeader* hp) 176 { 177 /* POSIX says that checksum is done on unsigned bytes 178 * (Sun and HP-UX gets it wrong... more details in 179 * GNU tar source) */ 180 const unsigned char *cp; 181 int chksum, size; 182 183 strcpy(hp->magic, "ustar "); 184 185 /* Calculate and store the checksum (i.e., the sum of all of the bytes of 186 * the header). The checksum field must be filled with blanks for the 187 * calculation. The checksum field is formatted differently from the 188 * other fields: it has 6 digits, a null, then a space -- rather than 189 * digits, followed by a null like the other fields... */ 190 memset(hp->chksum, ' ', sizeof(hp->chksum)); 191 cp = (const unsigned char *) hp; 192 chksum = 0; 193 size = sizeof(*hp); 194 do { chksum += *cp++; } while (--size); 195 putOctal(hp->chksum, sizeof(hp->chksum)-1, chksum); 196 197 /* Now write the header out to disk */ 198 xwrite(fd, hp, sizeof(*hp)); 199 } 200 201 #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS 202 static void writeLongname(int fd, int type, const char *name, int dir) 203 { 204 static const struct { 205 char mode[8]; /* 100-107 */ 206 char uid[8]; /* 108-115 */ 207 char gid[8]; /* 116-123 */ 208 char size[12]; /* 124-135 */ 209 char mtime[12]; /* 136-147 */ 210 } prefilled = { 211 "0000000", 212 "0000000", 213 "0000000", 214 "00000000000", 215 "00000000000", 216 }; 217 struct TarHeader header; 218 int size; 219 220 dir = !!dir; /* normalize: 0/1 */ 221 size = strlen(name) + 1 + dir; /* GNU tar uses strlen+1 */ 222 /* + dir: account for possible '/' */ 223 224 memset(&header, 0, sizeof(header)); 225 strcpy(header.name, "././@LongLink"); 226 memcpy(header.mode, prefilled.mode, sizeof(prefilled)); 227 PUT_OCTAL(header.size, size); 228 header.typeflag = type; 229 chksum_and_xwrite(fd, &header); 230 231 /* Write filename[/] and pad the block. */ 232 /* dir=0: writes 'name<NUL>', pads */ 233 /* dir=1: writes 'name', writes '/<NUL>', pads */ 234 dir *= 2; 235 xwrite(fd, name, size - dir); 236 xwrite(fd, "/", dir); 237 size = (-size) & (TAR_BLOCK_SIZE-1); 238 memset(&header, 0, size); 239 xwrite(fd, &header, size); 240 } 241 #endif 195 242 196 243 /* Write out a tar header for the specified file/directory/whatever */ 197 static inline int writeTarHeader(struct TarBallInfo *tbInfo, 198 const char *header_name, const char *real_name, struct stat *statbuf) 199 { 200 long chksum = 0; 244 void BUG_tar_header_size(void); 245 static int writeTarHeader(struct TarBallInfo *tbInfo, 246 const char *header_name, const char *fileName, struct stat *statbuf) 247 { 201 248 struct TarHeader header; 202 const unsigned char *cp = (const unsigned char *) &header; 203 ssize_t size = sizeof(struct TarHeader); 204 205 memset(&header, 0, size); 206 207 safe_strncpy(header.name, header_name, sizeof(header.name)); 208 209 putOctal(header.mode, sizeof(header.mode), statbuf->st_mode); 210 putOctal(header.uid, sizeof(header.uid), statbuf->st_uid); 211 putOctal(header.gid, sizeof(header.gid), statbuf->st_gid); 212 putOctal(header.size, sizeof(header.size), 0); /* Regular file size is handled later */ 213 putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime); 214 strcpy(header.magic, "ustar "); 215 216 /* Enter the user and group names (default to root if it fails) */ 217 if (bb_getpwuid(header.uname, statbuf->st_uid, sizeof(header.uname)) == NULL) 218 strcpy(header.uname, "root"); 219 if (bb_getgrgid(header.gname, statbuf->st_gid, sizeof(header.gname)) == NULL) 220 strcpy(header.gname, "root"); 249 250 if (sizeof(header) != 512) 251 BUG_tar_header_size(); 252 253 memset(&header, 0, sizeof(struct TarHeader)); 254 255 strncpy(header.name, header_name, sizeof(header.name)); 256 257 /* POSIX says to mask mode with 07777. */ 258 PUT_OCTAL(header.mode, statbuf->st_mode & 07777); 259 PUT_OCTAL(header.uid, statbuf->st_uid); 260 PUT_OCTAL(header.gid, statbuf->st_gid); 261 memset(header.size, '0', sizeof(header.size)-1); /* Regular file size is handled later */ 262 PUT_OCTAL(header.mtime, statbuf->st_mtime); 263 264 /* Enter the user and group names */ 265 safe_strncpy(header.uname, get_cached_username(statbuf->st_uid), sizeof(header.uname)); 266 safe_strncpy(header.gname, get_cached_groupname(statbuf->st_gid), sizeof(header.gname)); 221 267 222 268 if (tbInfo->hlInfo) { … … 225 271 strncpy(header.linkname, tbInfo->hlInfo->name, 226 272 sizeof(header.linkname)); 273 #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS 274 /* Write out long linkname if needed */ 275 if (header.linkname[sizeof(header.linkname)-1]) 276 writeLongname(tbInfo->tarFd, GNULONGLINK, 277 tbInfo->hlInfo->name, 0); 278 #endif 227 279 } else if (S_ISLNK(statbuf->st_mode)) { 228 char *lpath = xreadlink(real_name); 229 230 if (!lpath) /* Already printed err msg inside xreadlink() */ 231 return (FALSE); 280 char *lpath = xmalloc_readlink_or_warn(fileName); 281 if (!lpath) 282 return FALSE; 232 283 header.typeflag = SYMTYPE; 233 284 strncpy(header.linkname, lpath, sizeof(header.linkname)); 285 #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS 286 /* Write out long linkname if needed */ 287 if (header.linkname[sizeof(header.linkname)-1]) 288 writeLongname(tbInfo->tarFd, GNULONGLINK, lpath, 0); 289 #else 290 /* If it is larger than 100 bytes, bail out */ 291 if (header.linkname[sizeof(header.linkname)-1]) { 292 free(lpath); 293 bb_error_msg("names longer than "NAME_SIZE_STR" chars not supported"); 294 return FALSE; 295 } 296 #endif 234 297 free(lpath); 235 298 } else if (S_ISDIR(statbuf->st_mode)) { 236 299 header.typeflag = DIRTYPE; 237 strncat(header.name, "/", sizeof(header.name)); 300 /* Append '/' only if there is a space for it */ 301 if (!header.name[sizeof(header.name)-1]) 302 header.name[strlen(header.name)] = '/'; 238 303 } else if (S_ISCHR(statbuf->st_mode)) { 239 304 header.typeflag = CHRTYPE; 240 putOctal(header.devmajor, sizeof(header.devmajor), 241 major(statbuf->st_rdev)); 242 putOctal(header.devminor, sizeof(header.devminor), 243 minor(statbuf->st_rdev)); 305 PUT_OCTAL(header.devmajor, major(statbuf->st_rdev)); 306 PUT_OCTAL(header.devminor, minor(statbuf->st_rdev)); 244 307 } else if (S_ISBLK(statbuf->st_mode)) { 245 308 header.typeflag = BLKTYPE; 246 putOctal(header.devmajor, sizeof(header.devmajor), 247 major(statbuf->st_rdev)); 248 putOctal(header.devminor, sizeof(header.devminor), 249 minor(statbuf->st_rdev)); 309 PUT_OCTAL(header.devmajor, major(statbuf->st_rdev)); 310 PUT_OCTAL(header.devminor, minor(statbuf->st_rdev)); 250 311 } else if (S_ISFIFO(statbuf->st_mode)) { 251 312 header.typeflag = FIFOTYPE; 252 313 } else if (S_ISREG(statbuf->st_mode)) { 314 if (sizeof(statbuf->st_size) > 4 315 && statbuf->st_size > (off_t)0777777777777LL 316 ) { 317 bb_error_msg_and_die("cannot store file '%s' " 318 "of size %"OFF_FMT"d, aborting", 319 fileName, statbuf->st_size); 320 } 253 321 header.typeflag = REGTYPE; 254 putOctal(header.size, sizeof(header.size), statbuf->st_size);322 PUT_OCTAL(header.size, statbuf->st_size); 255 323 } else { 256 bb_error_msg("%s: Unknown file type", real_name); 257 return (FALSE); 258 } 259 260 /* Calculate and store the checksum (i.e., the sum of all of the bytes of 261 * the header). The checksum field must be filled with blanks for the 262 * calculation. The checksum field is formatted differently from the 263 * other fields: it has [6] digits, a null, then a space -- rather than 264 * digits, followed by a null like the other fields... */ 265 memset(header.chksum, ' ', sizeof(header.chksum)); 266 cp = (const unsigned char *) &header; 267 while (size-- > 0) 268 chksum += *cp++; 269 putOctal(header.chksum, 7, chksum); 324 bb_error_msg("%s: unknown file type", fileName); 325 return FALSE; 326 } 327 328 #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS 329 /* Write out long name if needed */ 330 /* (we, like GNU tar, output long linkname *before* long name) */ 331 if (header.name[sizeof(header.name)-1]) 332 writeLongname(tbInfo->tarFd, GNULONGNAME, 333 header_name, S_ISDIR(statbuf->st_mode)); 334 #endif 270 335 271 336 /* Now write the header out to disk */ 272 if ((size = 273 bb_full_write(tbInfo->tarFd, (char *) &header, 274 sizeof(struct TarHeader))) < 0) { 275 bb_error_msg(bb_msg_io_error, real_name); 276 return (FALSE); 277 } 278 /* Pad the header up to the tar block size */ 279 for (; size < TAR_BLOCK_SIZE; size++) { 280 write(tbInfo->tarFd, "\0", 1); 281 } 337 chksum_and_xwrite(tbInfo->tarFd, &header); 338 282 339 /* Now do the verbose thing (or not) */ 283 284 340 if (tbInfo->verboseFlag) { 285 341 FILE *vbFd = stdout; … … 287 343 if (tbInfo->tarFd == STDOUT_FILENO) /* If the archive goes to stdout, verbose to stderr */ 288 344 vbFd = stderr; 289 290 fprintf(vbFd, "%s\n", header.name); 291 } 292 293 return (TRUE); 294 } 295 296 # ifdef CONFIG_FEATURE_TAR_FROM 297 static inline int exclude_file(const llist_t *excluded_files, const char *file) 345 /* GNU "tar cvvf" prints "extended" listing a-la "ls -l" */ 346 /* We don't have such excesses here: for us "v" == "vv" */ 347 /* '/' is probably a GNUism */ 348 fprintf(vbFd, "%s%s\n", header_name, 349 S_ISDIR(statbuf->st_mode) ? "/" : ""); 350 } 351 352 return TRUE; 353 } 354 355 #if ENABLE_FEATURE_TAR_FROM 356 static int exclude_file(const llist_t *excluded_files, const char *file) 298 357 { 299 358 while (excluded_files) { … … 317 376 return 0; 318 377 } 319 # 378 #else 320 379 #define exclude_file(excluded_files, file) 0 321 # 380 #endif 322 381 323 382 static int writeFileToTarball(const char *fileName, struct stat *statbuf, 324 void *userData)383 void *userData, int depth ATTRIBUTE_UNUSED) 325 384 { 326 385 struct TarBallInfo *tbInfo = (struct TarBallInfo *) userData; … … 329 388 330 389 /* 331 ** Check to see if we are dealing with a hard link.332 ** If so -333 ** Treat the first occurance of a given dev/inode as a file while334 ** treating any additional occurances as hard links. This is done335 ** by adding the file information to the HardLinkInfo linked list.390 * Check to see if we are dealing with a hard link. 391 * If so - 392 * Treat the first occurance of a given dev/inode as a file while 393 * treating any additional occurances as hard links. This is done 394 * by adding the file information to the HardLinkInfo linked list. 336 395 */ 337 396 tbInfo->hlInfo = NULL; … … 345 404 if (S_ISSOCK(statbuf->st_mode)) { 346 405 bb_error_msg("%s: socket ignored", fileName); 347 return (TRUE);406 return TRUE; 348 407 } 349 408 … … 354 413 tbInfo->statBuf.st_ino == statbuf->st_ino) { 355 414 bb_error_msg("%s: file is the archive; skipping", fileName); 356 return (TRUE);415 return TRUE; 357 416 } 358 417 359 418 header_name = fileName; 360 419 while (header_name[0] == '/') { 361 static int alreadyWarned = FALSE;362 363 if ( alreadyWarned == FALSE) {364 bb_error_msg(" Removing leading '/' from member names");365 alreadyWarned = TRUE;420 static smallint warned; 421 422 if (!warned) { 423 bb_error_msg("removing leading '/' from member names"); 424 warned = 1; 366 425 } 367 426 header_name++; 368 427 } 369 428 429 #if !ENABLE_FEATURE_TAR_GNU_EXTENSIONS 370 430 if (strlen(fileName) >= NAME_SIZE) { 371 bb_error_msg(bb_msg_name_longer_than_foo, NAME_SIZE); 372 return (TRUE); 373 } 431 bb_error_msg("names longer than "NAME_SIZE_STR" chars not supported"); 432 return TRUE; 433 } 434 #endif 374 435 375 436 if (header_name[0] == '\0') 376 437 return TRUE; 377 438 378 if (ENABLE_FEATURE_TAR_FROM && 379 exclude_file(tbInfo->excludeList, header_name)) { 439 if (exclude_file(tbInfo->excludeList, header_name)) 380 440 return SKIP; 381 }382 441 383 442 /* Is this a regular file? */ 384 if ((tbInfo->hlInfo == NULL) && (S_ISREG(statbuf->st_mode))) { 385 443 if (tbInfo->hlInfo == NULL && S_ISREG(statbuf->st_mode)) { 386 444 /* open the file we want to archive, and make sure all is well */ 387 i f ((inputFileFd = open(fileName, O_RDONLY)) < 0) {388 bb_perror_msg("%s: Cannot open", fileName);389 return (FALSE);445 inputFileFd = open_or_warn(fileName, O_RDONLY); 446 if (inputFileFd < 0) { 447 return FALSE; 390 448 } 391 449 } … … 393 451 /* Add an entry to the tarball */ 394 452 if (writeTarHeader(tbInfo, header_name, fileName, statbuf) == FALSE) { 395 return (FALSE);453 return FALSE; 396 454 } 397 455 398 456 /* If it was a regular file, write out the body */ 399 if (inputFileFd >= 0 ) { 400 ssize_t readSize = 0; 401 402 /* write the file to the archive */ 403 readSize = bb_copyfd_eof(inputFileFd, tbInfo->tarFd); 457 if (inputFileFd >= 0) { 458 size_t readSize; 459 /* Write the file to the archive. */ 460 /* We record size into header first, */ 461 /* and then write out file. If file shrinks in between, */ 462 /* tar will be corrupted. So we don't allow for that. */ 463 /* NB: GNU tar 1.16 warns and pads with zeroes */ 464 /* or even seeks back and updates header */ 465 bb_copyfd_exact_size(inputFileFd, tbInfo->tarFd, statbuf->st_size); 466 ////off_t readSize; 467 ////readSize = bb_copyfd_size(inputFileFd, tbInfo->tarFd, statbuf->st_size); 468 ////if (readSize != statbuf->st_size && readSize >= 0) { 469 //// bb_error_msg_and_die("short read from %s, aborting", fileName); 470 ////} 471 472 /* Check that file did not grow in between? */ 473 /* if (safe_read(inputFileFd, 1) == 1) warn but continue? */ 474 404 475 close(inputFileFd); 405 476 406 477 /* Pad the file up to the tar block size */ 407 for (; (readSize % TAR_BLOCK_SIZE) != 0; readSize++) 408 write(tbInfo->tarFd, "\0", 1); 409 } 410 411 return (TRUE); 412 } 413 414 static inline int writeTarFile(const int tar_fd, const int verboseFlag, 478 /* (a few tricks here in the name of code size) */ 479 readSize = (-(int)statbuf->st_size) & (TAR_BLOCK_SIZE-1); 480 memset(block_buf, 0, readSize); 481 xwrite(tbInfo->tarFd, block_buf, readSize); 482 } 483 484 return TRUE; 485 } 486 487 static int writeTarFile(const int tar_fd, const int verboseFlag, 415 488 const unsigned long dereferenceFlag, const llist_t *include, 416 489 const llist_t *exclude, const int gzip) 417 490 { 418 491 pid_t gzipPid = 0; 419 420 492 int errorFlag = FALSE; 421 ssize_t size;422 493 struct TarBallInfo tbInfo; 423 494 … … 431 502 * can avoid including the tarball into itself.... */ 432 503 if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0) 433 bb_perror_msg_and_die(" Couldnt stat tar file");504 bb_perror_msg_and_die("cannot stat tar file"); 434 505 435 506 if ((ENABLE_FEATURE_TAR_GZIP || ENABLE_FEATURE_TAR_BZIP2) && gzip) { … … 437 508 int gzipStatusPipe[2] = { -1, -1 }; 438 509 volatile int vfork_exec_errno = 0; 439 char *zip_exec = (gzip == 1) ? "gzip" : "bzip2"; 440 441 442 if (pipe(gzipDataPipe) < 0 || pipe(gzipStatusPipe) < 0) 443 bb_perror_msg_and_die("create pipe"); 444 445 signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */ 446 447 # if __GNUC__ 448 /* Avoid vfork clobbering */ 449 (void) &include; 450 (void) &errorFlag; 451 (void) &zip_exec; 452 # endif 510 const char *zip_exec = (gzip == 1) ? "gzip" : "bzip2"; 511 512 xpipe(gzipDataPipe); 513 xpipe(gzipStatusPipe); 514 515 signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */ 516 517 #if defined(__GNUC__) && __GNUC__ 518 /* Avoid vfork clobbering */ 519 (void) &include; 520 (void) &errorFlag; 521 (void) &zip_exec; 522 #endif 453 523 454 524 gzipPid = vfork(); … … 458 528 close(gzipDataPipe[1]); 459 529 460 if (tbInfo.tarFd != 1) 461 dup2(tbInfo.tarFd, 1); 530 dup2(tbInfo.tarFd, 1); 462 531 463 532 close(gzipStatusPipe[0]); 464 533 fcntl(gzipStatusPipe[1], F_SETFD, FD_CLOEXEC); /* close on exec shows success */ 465 534 466 execlp(zip_exec, zip_exec, "-f", NULL);535 BB_EXECLP(zip_exec, zip_exec, "-f", NULL); 467 536 vfork_exec_errno = errno; 468 537 … … 476 545 char buf; 477 546 478 int n = bb_full_read(gzipStatusPipe[0], &buf, 1);547 int n = full_read(gzipStatusPipe[0], &buf, 1); 479 548 480 549 if (n == 0 && vfork_exec_errno != 0) { 481 550 errno = vfork_exec_errno; 482 bb_perror_msg_and_die(" Couldnot exec %s", zip_exec);551 bb_perror_msg_and_die("cannot exec %s", zip_exec); 483 552 } else if ((n < 0) && (errno == EAGAIN || errno == EINTR)) 484 553 continue; /* try it again */ … … 495 564 /* Read the directory/files and iterate over them one at a time */ 496 565 while (include) { 497 if (!recursive_action(include->data, TRUE, dereferenceFlag, 498 FALSE, writeFileToTarball, writeFileToTarball, &tbInfo)) 566 if (!recursive_action(include->data, ACTION_RECURSE | 567 (dereferenceFlag ? ACTION_FOLLOWLINKS : 0), 568 writeFileToTarball, writeFileToTarball, &tbInfo, 0)) 499 569 { 500 570 errorFlag = TRUE; … … 503 573 } 504 574 /* Write two empty blocks to the end of the archive */ 505 for (size = 0; size < (2 * TAR_BLOCK_SIZE); size++)506 write(tbInfo.tarFd, "\0", 1);575 memset(block_buf, 0, 2*TAR_BLOCK_SIZE); 576 xwrite(tbInfo.tarFd, block_buf, 2*TAR_BLOCK_SIZE); 507 577 508 578 /* To be pedantically correct, we would check if the tarball … … 519 589 520 590 if (errorFlag) 521 bb_error_msg("Error exit delayed from previous errors"); 522 523 if (gzipPid && waitpid(gzipPid, NULL, 0)==-1) 524 bb_error_msg("Couldnt wait"); 525 526 return !errorFlag; 591 bb_error_msg("error exit delayed from previous errors"); 592 593 if (gzipPid) { 594 int status; 595 if (waitpid(gzipPid, &status, 0) == -1) 596 bb_perror_msg("waitpid"); 597 else if (!WIFEXITED(status) || WEXITSTATUS(status)) 598 /* gzip was killed or has exited with nonzero! */ 599 errorFlag = TRUE; 600 } 601 return errorFlag; 527 602 } 528 603 #else … … 530 605 const unsigned long dereferenceFlag, const llist_t *include, 531 606 const llist_t *exclude, const int gzip); 532 #endif /* tar_create*/533 534 #if def CONFIG_FEATURE_TAR_FROM607 #endif /* FEATURE_TAR_CREATE */ 608 609 #if ENABLE_FEATURE_TAR_FROM 535 610 static llist_t *append_file_list_to_list(llist_t *list) 536 611 { … … 542 617 543 618 while (cur) { 544 src_stream = bb_xfopen(cur->data, "r");619 src_stream = xfopen(cur->data, "r"); 545 620 tmp = cur; 546 621 cur = cur->link; 547 622 free(tmp); 548 while ((line = bb_get_chomped_line_from_file(src_stream)) != NULL) 549 llist_add_to(&newlist, line); 623 while ((line = xmalloc_getline(src_stream)) != NULL) { 624 /* kill trailing '/' unless the string is just "/" */ 625 char *cp = last_char_is(line, '/'); 626 if (cp > line) 627 *cp = '\0'; 628 llist_add_to(&newlist, line); 629 } 550 630 fclose(src_stream); 551 631 } … … 553 633 } 554 634 #else 555 #define append_file_list_to_list(x) 556 #endif 557 558 #if def CONFIG_FEATURE_TAR_COMPRESS635 #define append_file_list_to_list(x) 0 636 #endif 637 638 #if ENABLE_FEATURE_TAR_COMPRESS 559 639 static char get_header_tar_Z(archive_handle_t *archive_handle) 560 640 { 561 /* Can t lseek over pipe's */562 archive_handle->seek = seek_by_ char;641 /* Can't lseek over pipes */ 642 archive_handle->seek = seek_by_read; 563 643 564 644 /* do the decompression, and cleanup */ 565 if ( bb_xread_char(archive_handle->src_fd) != 0x1f ||566 bb_xread_char(archive_handle->src_fd) != 0x9d)567 {568 bb_error_msg_and_die(" Invalid magic");569 } 570 571 archive_handle->src_fd = open_transformer(archive_handle->src_fd, uncompress );645 if (xread_char(archive_handle->src_fd) != 0x1f 646 || xread_char(archive_handle->src_fd) != 0x9d 647 ) { 648 bb_error_msg_and_die("invalid magic"); 649 } 650 651 archive_handle->src_fd = open_transformer(archive_handle->src_fd, uncompress, "uncompress", "uncompress", "-cf", "-", NULL); 572 652 archive_handle->offset = 0; 573 while (get_header_tar(archive_handle) == EXIT_SUCCESS); 653 while (get_header_tar(archive_handle) == EXIT_SUCCESS) 654 /* nothing */; 574 655 575 656 /* Can only do one file at a time */ 576 return (EXIT_FAILURE);657 return EXIT_FAILURE; 577 658 } 578 659 #else 579 #define get_header_tar_Z 0 580 #endif 581 582 #define CTX_TEST (1 << 0) 583 #define CTX_EXTRACT (1 << 1) 584 #define TAR_OPT_BASEDIR (1 << 2) 585 #define TAR_OPT_TARNAME (1 << 3) 586 #define TAR_OPT_2STDOUT (1 << 4) 587 #define TAR_OPT_P (1 << 5) 588 #define TAR_OPT_VERBOSE (1 << 6) 589 #define TAR_OPT_KEEP_OLD (1 << 7) 590 591 #define TAR_OPT_AFTER_START 8 592 593 #define CTX_CREATE (1 << (TAR_OPT_AFTER_START)) 594 #define TAR_OPT_DEREFERENCE (1 << (TAR_OPT_AFTER_START + 1)) 595 #ifdef CONFIG_FEATURE_TAR_CREATE 596 # define TAR_OPT_STR_CREATE "ch" 597 # define TAR_OPT_AFTER_CREATE TAR_OPT_AFTER_START + 2 598 #else 599 # define TAR_OPT_STR_CREATE "" 600 # define TAR_OPT_AFTER_CREATE TAR_OPT_AFTER_START 601 #endif 602 603 #define TAR_OPT_BZIP2 (1 << (TAR_OPT_AFTER_CREATE)) 604 #ifdef CONFIG_FEATURE_TAR_BZIP2 605 # define TAR_OPT_STR_BZIP2 "j" 606 # define TAR_OPT_AFTER_BZIP2 TAR_OPT_AFTER_CREATE + 1 607 #else 608 # define TAR_OPT_STR_BZIP2 "" 609 # define TAR_OPT_AFTER_BZIP2 TAR_OPT_AFTER_CREATE 610 #endif 611 612 #define TAR_OPT_LZMA (1 << (TAR_OPT_AFTER_BZIP2)) 613 #ifdef CONFIG_FEATURE_TAR_LZMA 614 # define TAR_OPT_STR_LZMA "a" 615 # define TAR_OPT_AFTER_LZMA TAR_OPT_AFTER_BZIP2 + 1 616 #else 617 # define TAR_OPT_STR_LZMA "" 618 # define TAR_OPT_AFTER_LZMA TAR_OPT_AFTER_BZIP2 619 #endif 620 621 #define TAR_OPT_INCLUDE_FROM (1 << (TAR_OPT_AFTER_LZMA)) 622 #define TAR_OPT_EXCLUDE_FROM (1 << (TAR_OPT_AFTER_LZMA + 1)) 623 #ifdef CONFIG_FEATURE_TAR_FROM 624 # define TAR_OPT_STR_FROM "T:X:" 625 # define TAR_OPT_AFTER_FROM TAR_OPT_AFTER_LZMA + 2 626 #else 627 # define TAR_OPT_STR_FROM "" 628 # define TAR_OPT_AFTER_FROM TAR_OPT_AFTER_LZMA 629 #endif 630 631 #define TAR_OPT_GZIP (1 << (TAR_OPT_AFTER_FROM)) 632 #ifdef CONFIG_FEATURE_TAR_GZIP 633 # define TAR_OPT_STR_GZIP "z" 634 # define TAR_OPT_AFTER_GZIP TAR_OPT_AFTER_FROM + 1 635 #else 636 # define TAR_OPT_STR_GZIP "" 637 # define TAR_OPT_AFTER_GZIP TAR_OPT_AFTER_FROM 638 #endif 639 640 #define TAR_OPT_UNCOMPRESS (1 << (TAR_OPT_AFTER_GZIP)) 641 #ifdef CONFIG_FEATURE_TAR_COMPRESS 642 # define TAR_OPT_STR_COMPRESS "Z" 643 # define TAR_OPT_AFTER_COMPRESS TAR_OPT_AFTER_GZIP + 1 644 #else 645 # define TAR_OPT_STR_COMPRESS "" 646 # define TAR_OPT_AFTER_COMPRESS TAR_OPT_AFTER_GZIP 647 #endif 648 649 #define TAR_OPT_NOPRESERVE_OWN (1 << (TAR_OPT_AFTER_COMPRESS)) 650 #define TAR_OPT_NOPRESERVE_PERM (1 << (TAR_OPT_AFTER_COMPRESS + 1)) 651 #define TAR_OPT_STR_NOPRESERVE "\203\213" 652 #define TAR_OPT_AFTER_NOPRESERVE TAR_OPT_AFTER_COMPRESS + 2 653 654 static const char tar_options[]="txC:f:Opvk" \ 655 TAR_OPT_STR_CREATE \ 656 TAR_OPT_STR_BZIP2 \ 657 TAR_OPT_STR_LZMA \ 658 TAR_OPT_STR_FROM \ 659 TAR_OPT_STR_GZIP \ 660 TAR_OPT_STR_COMPRESS \ 661 TAR_OPT_STR_NOPRESERVE; 662 663 #ifdef CONFIG_FEATURE_TAR_LONG_OPTIONS 664 static const struct option tar_long_options[] = { 665 { "list", 0, NULL, 't' }, 666 { "extract", 0, NULL, 'x' }, 667 { "directory", 1, NULL, 'C' }, 668 { "file", 1, NULL, 'f' }, 669 { "to-stdout", 0, NULL, 'O' }, 670 { "same-permissions", 0, NULL, 'p' }, 671 { "verbose", 0, NULL, 'v' }, 672 { "keep-old", 0, NULL, 'k' }, 673 { "no-same-owner", 0, NULL, '\203' }, 674 { "no-same-permissions",0, NULL, '\213' }, 675 # ifdef CONFIG_FEATURE_TAR_CREATE 676 { "create", 0, NULL, 'c' }, 677 { "dereference", 0, NULL, 'h' }, 660 #define get_header_tar_Z NULL 661 #endif 662 663 #ifdef CHECK_FOR_CHILD_EXITCODE 664 /* Looks like it isn't needed - tar detects malformed (truncated) 665 * archive if e.g. bunzip2 fails */ 666 static int child_error; 667 668 static void handle_SIGCHLD(int status) 669 { 670 /* Actually, 'status' is a signo. We reuse it for other needs */ 671 672 /* Wait for any child without blocking */ 673 if (waitpid(-1, &status, WNOHANG) < 0) 674 /* wait failed?! I'm confused... */ 675 return; 676 677 if (WIFEXITED(status) && WEXITSTATUS(status)==0) 678 /* child exited with 0 */ 679 return; 680 /* Cannot happen? 681 if (!WIFSIGNALED(status) && !WIFEXITED(status)) return; */ 682 child_error = 1; 683 } 684 #endif 685 686 enum { 687 OPTBIT_KEEP_OLD = 7, 688 USE_FEATURE_TAR_CREATE( OPTBIT_CREATE ,) 689 USE_FEATURE_TAR_CREATE( OPTBIT_DEREFERENCE ,) 690 USE_FEATURE_TAR_BZIP2( OPTBIT_BZIP2 ,) 691 USE_FEATURE_TAR_LZMA( OPTBIT_LZMA ,) 692 USE_FEATURE_TAR_FROM( OPTBIT_INCLUDE_FROM,) 693 USE_FEATURE_TAR_FROM( OPTBIT_EXCLUDE_FROM,) 694 USE_FEATURE_TAR_GZIP( OPTBIT_GZIP ,) 695 USE_FEATURE_TAR_COMPRESS(OPTBIT_COMPRESS ,) 696 OPTBIT_NOPRESERVE_OWN, 697 OPTBIT_NOPRESERVE_PERM, 698 OPT_TEST = 1 << 0, // t 699 OPT_EXTRACT = 1 << 1, // x 700 OPT_BASEDIR = 1 << 2, // C 701 OPT_TARNAME = 1 << 3, // f 702 OPT_2STDOUT = 1 << 4, // O 703 OPT_P = 1 << 5, // p 704 OPT_VERBOSE = 1 << 6, // v 705 OPT_KEEP_OLD = 1 << 7, // k 706 OPT_CREATE = USE_FEATURE_TAR_CREATE( (1<<OPTBIT_CREATE )) + 0, // c 707 OPT_DEREFERENCE = USE_FEATURE_TAR_CREATE( (1<<OPTBIT_DEREFERENCE )) + 0, // h 708 OPT_BZIP2 = USE_FEATURE_TAR_BZIP2( (1<<OPTBIT_BZIP2 )) + 0, // j 709 OPT_LZMA = USE_FEATURE_TAR_LZMA( (1<<OPTBIT_LZMA )) + 0, // a 710 OPT_INCLUDE_FROM = USE_FEATURE_TAR_FROM( (1<<OPTBIT_INCLUDE_FROM)) + 0, // T 711 OPT_EXCLUDE_FROM = USE_FEATURE_TAR_FROM( (1<<OPTBIT_EXCLUDE_FROM)) + 0, // X 712 OPT_GZIP = USE_FEATURE_TAR_GZIP( (1<<OPTBIT_GZIP )) + 0, // z 713 OPT_COMPRESS = USE_FEATURE_TAR_COMPRESS((1<<OPTBIT_COMPRESS )) + 0, // Z 714 OPT_NOPRESERVE_OWN = 1 << OPTBIT_NOPRESERVE_OWN , // no-same-owner 715 OPT_NOPRESERVE_PERM = 1 << OPTBIT_NOPRESERVE_PERM, // no-same-permissions 716 }; 717 #if ENABLE_FEATURE_TAR_LONG_OPTIONS 718 static const char tar_longopts[] ALIGN1 = 719 "list\0" No_argument "t" 720 "extract\0" No_argument "x" 721 "directory\0" Required_argument "C" 722 "file\0" Required_argument "f" 723 "to-stdout\0" No_argument "O" 724 "same-permissions\0" No_argument "p" 725 "verbose\0" No_argument "v" 726 "keep-old\0" No_argument "k" 727 # if ENABLE_FEATURE_TAR_CREATE 728 "create\0" No_argument "c" 729 "dereference\0" No_argument "h" 678 730 # endif 679 # if def CONFIG_FEATURE_TAR_BZIP2680 { "bzip2", 0, NULL, 'j' },731 # if ENABLE_FEATURE_TAR_BZIP2 732 "bzip2\0" No_argument "j" 681 733 # endif 682 # if def CONFIG_FEATURE_TAR_LZMA683 { "lzma", 0, NULL, 'a' },734 # if ENABLE_FEATURE_TAR_LZMA 735 "lzma\0" No_argument "a" 684 736 # endif 685 # ifdef CONFIG_FEATURE_TAR_FROM 686 { "files-from", 1, NULL, 'T' }, 687 { "exclude-from", 1, NULL, 'X' }, 688 { "exclude", 1, NULL, '\n' }, 737 # if ENABLE_FEATURE_TAR_FROM 738 "files-from\0" Required_argument "T" 739 "exclude-from\0" Required_argument "X" 689 740 # endif 690 # if def CONFIG_FEATURE_TAR_GZIP691 { "gzip", 0, NULL, 'z' },741 # if ENABLE_FEATURE_TAR_GZIP 742 "gzip\0" No_argument "z" 692 743 # endif 693 # if def CONFIG_FEATURE_TAR_COMPRESS694 { "compress", 0, NULL, 'Z' },744 # if ENABLE_FEATURE_TAR_COMPRESS 745 "compress\0" No_argument "Z" 695 746 # endif 696 { 0, 0, 0, 0 } 697 }; 698 #else 699 #define tar_long_options 0 700 #endif 701 747 "no-same-owner\0" No_argument "\xfd" 748 "no-same-permissions\0" No_argument "\xfe" 749 /* --exclude takes next bit position in option mask, */ 750 /* therefore we have to either put it _after_ --no-same-perm */ 751 /* or add OPT[BIT]_EXCLUDE before OPT[BIT]_NOPRESERVE_OWN */ 752 # if ENABLE_FEATURE_TAR_FROM 753 "exclude\0" Required_argument "\xff" 754 # endif 755 ; 756 #endif 757 758 int tar_main(int argc, char **argv); 702 759 int tar_main(int argc, char **argv) 703 760 { … … 706 763 char *base_dir = NULL; 707 764 const char *tar_filename = "-"; 708 unsigned long opt; 765 unsigned opt; 766 int verboseFlag = 0; 767 #if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM 709 768 llist_t *excludes = NULL; 769 #endif 710 770 711 771 /* Initialise default values */ 712 772 tar_handle = init_handle(); 713 tar_handle->flags = ARCHIVE_CREATE_LEADING_DIRS | ARCHIVE_PRESERVE_DATE | ARCHIVE_EXTRACT_UNCONDITIONAL; 773 tar_handle->flags = ARCHIVE_CREATE_LEADING_DIRS 774 | ARCHIVE_PRESERVE_DATE 775 | ARCHIVE_EXTRACT_UNCONDITIONAL; 714 776 715 777 /* Prepend '-' to the first argument if required */ 716 bb_opt_complementally = ENABLE_FEATURE_TAR_CREATE ? 717 "--:X::T::\n::c:t:x:?:c--tx:t--cx:x--ct" : 718 "--:X::T::\n::t:x:?:t--x:x--t"; 719 if (ENABLE_FEATURE_TAR_LONG_OPTIONS) 720 bb_applet_long_options = tar_long_options; 721 opt = bb_getopt_ulflags(argc, argv, tar_options, 722 &base_dir, /* Change to dir <optarg> */ 723 &tar_filename /* archive filename */ 724 #ifdef CONFIG_FEATURE_TAR_FROM 725 , &(tar_handle->accept), 726 &(tar_handle->reject), 727 &excludes 728 #endif 729 ); 730 731 if (opt & CTX_TEST) { 732 if ((tar_handle->action_header == header_list) || 733 (tar_handle->action_header == header_verbose_list)) 734 { 735 tar_handle->action_header = header_verbose_list; 736 } else tar_handle->action_header = header_list; 737 } 738 if((opt & CTX_EXTRACT) && tar_handle->action_data != data_extract_to_stdout) 778 opt_complementary = "--:" // first arg is options 779 "tt:vv:" // count -t,-v 780 "?:" // bail out with usage instead of error return 781 "X::T::" // cumulative lists 782 #if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM 783 "\xff::" // cumulative lists for --exclude 784 #endif 785 USE_FEATURE_TAR_CREATE("c:") "t:x:" // at least one of these is reqd 786 USE_FEATURE_TAR_CREATE("c--tx:t--cx:x--ct") // mutually exclusive 787 SKIP_FEATURE_TAR_CREATE("t--x:x--t"); // mutually exclusive 788 #if ENABLE_FEATURE_TAR_LONG_OPTIONS 789 applet_long_options = tar_longopts; 790 #endif 791 opt = getopt32(argv, 792 "txC:f:Opvk" 793 USE_FEATURE_TAR_CREATE( "ch" ) 794 USE_FEATURE_TAR_BZIP2( "j" ) 795 USE_FEATURE_TAR_LZMA( "a" ) 796 USE_FEATURE_TAR_FROM( "T:X:") 797 USE_FEATURE_TAR_GZIP( "z" ) 798 USE_FEATURE_TAR_COMPRESS("Z" ) 799 , &base_dir // -C dir 800 , &tar_filename // -f filename 801 USE_FEATURE_TAR_FROM(, &(tar_handle->accept)) // T 802 USE_FEATURE_TAR_FROM(, &(tar_handle->reject)) // X 803 #if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM 804 , &excludes // --exclude 805 #endif 806 , &verboseFlag // combined count for -t and -v 807 , &verboseFlag // combined count for -t and -v 808 ); 809 810 if (verboseFlag) tar_handle->action_header = header_verbose_list; 811 if (verboseFlag == 1) tar_handle->action_header = header_list; 812 813 if (opt & OPT_EXTRACT) 739 814 tar_handle->action_data = data_extract_all; 740 815 741 if (opt & TAR_OPT_2STDOUT)816 if (opt & OPT_2STDOUT) 742 817 tar_handle->action_data = data_extract_to_stdout; 743 818 744 if (opt & TAR_OPT_VERBOSE) { 745 if ((tar_handle->action_header == header_list) || 746 (tar_handle->action_header == header_verbose_list)) 747 { 748 tar_handle->action_header = header_verbose_list; 749 } else 750 tar_handle->action_header = header_list; 751 } 752 if (opt & TAR_OPT_KEEP_OLD) 819 if (opt & OPT_KEEP_OLD) 753 820 tar_handle->flags &= ~ARCHIVE_EXTRACT_UNCONDITIONAL; 754 821 755 if (opt & TAR_OPT_NOPRESERVE_OWN)822 if (opt & OPT_NOPRESERVE_OWN) 756 823 tar_handle->flags |= ARCHIVE_NOPRESERVE_OWN; 757 824 758 if (opt & TAR_OPT_NOPRESERVE_PERM)825 if (opt & OPT_NOPRESERVE_PERM) 759 826 tar_handle->flags |= ARCHIVE_NOPRESERVE_PERM; 760 827 761 if ( ENABLE_FEATURE_TAR_GZIP && (opt & TAR_OPT_GZIP))828 if (opt & OPT_GZIP) 762 829 get_header_ptr = get_header_tar_gz; 763 830 764 if ( ENABLE_FEATURE_TAR_BZIP2 && (opt & TAR_OPT_BZIP2))831 if (opt & OPT_BZIP2) 765 832 get_header_ptr = get_header_tar_bz2; 766 833 767 if ( ENABLE_FEATURE_TAR_LZMA && (opt & TAR_OPT_LZMA))834 if (opt & OPT_LZMA) 768 835 get_header_ptr = get_header_tar_lzma; 769 836 770 if ( ENABLE_FEATURE_TAR_COMPRESS && (opt & TAR_OPT_UNCOMPRESS))837 if (opt & OPT_COMPRESS) 771 838 get_header_ptr = get_header_tar_Z; 772 839 773 if (ENABLE_FEATURE_TAR_FROM) { 774 tar_handle->reject = append_file_list_to_list(tar_handle->reject); 775 /* Append excludes to reject */ 776 while (excludes) { 777 llist_t *temp = excludes->link; 778 excludes->link = tar_handle->reject; 779 tar_handle->reject = excludes; 780 excludes = temp; 781 } 782 tar_handle->accept = append_file_list_to_list(tar_handle->accept); 783 } 840 #if ENABLE_FEATURE_TAR_FROM 841 tar_handle->reject = append_file_list_to_list(tar_handle->reject); 842 #if ENABLE_FEATURE_TAR_LONG_OPTIONS 843 /* Append excludes to reject */ 844 while (excludes) { 845 llist_t *next = excludes->link; 846 excludes->link = tar_handle->reject; 847 tar_handle->reject = excludes; 848 excludes = next; 849 } 850 #endif 851 tar_handle->accept = append_file_list_to_list(tar_handle->accept); 852 #endif 784 853 785 854 /* Check if we are reading from stdin */ … … 792 861 /* TODO: This is the same as in ar, separate function ? */ 793 862 while (optind < argc) { 794 char *filename_ptr = last_char_is(argv[optind], '/');795 if (filename_ptr > argv[optind])796 *filename_ptr = '\0';797 798 llist_add_to (&(tar_handle->accept), argv[optind]);863 /* kill trailing '/' unless the string is just "/" */ 864 char *cp = last_char_is(argv[optind], '/'); 865 if (cp > argv[optind]) 866 *cp = '\0'; 867 llist_add_to_end(&tar_handle->accept, argv[optind]); 799 868 optind++; 800 869 } 801 870 802 if ( (tar_handle->accept) || (tar_handle->reject))871 if (tar_handle->accept || tar_handle->reject) 803 872 tar_handle->filter = filter_accept_reject_list; 804 873 … … 808 877 int flags; 809 878 810 if ( ENABLE_FEATURE_TAR_CREATE && (opt & CTX_CREATE)) {879 if (opt & OPT_CREATE) { 811 880 /* Make sure there is at least one file to tar up. */ 812 881 if (tar_handle->accept == NULL) … … 814 883 815 884 tar_stream = stdout; 816 flags = O_WRONLY | O_CREAT | O_EXCL; 817 unlink(tar_filename); 885 /* Mimicking GNU tar 1.15.1: */ 886 flags = O_WRONLY|O_CREAT|O_TRUNC; 887 /* was doing unlink; open(O_WRONLY|O_CREAT|O_EXCL); why? */ 818 888 } else { 819 889 tar_stream = stdin; … … 821 891 } 822 892 823 if ( (tar_filename[0] == '-') && (tar_filename[1] == '\0')) {893 if (LONE_DASH(tar_filename)) { 824 894 tar_handle->src_fd = fileno(tar_stream); 825 tar_handle->seek = seek_by_ char;895 tar_handle->seek = seek_by_read; 826 896 } else { 827 tar_handle->src_fd = bb_xopen(tar_filename, flags);897 tar_handle->src_fd = xopen(tar_filename, flags); 828 898 } 829 899 } 830 900 831 901 if (base_dir) 832 bb_xchdir(base_dir); 902 xchdir(base_dir); 903 904 #ifdef CHECK_FOR_CHILD_EXITCODE 905 /* We need to know whether child (gzip/bzip/etc) exits abnormally */ 906 signal(SIGCHLD, handle_SIGCHLD); 907 #endif 833 908 834 909 /* create an archive */ 835 if (ENABLE_FEATURE_TAR_CREATE && (opt & CTX_CREATE)) { 836 int verboseFlag = FALSE; 910 if (opt & OPT_CREATE) { 837 911 int zipMode = 0; 838 839 912 if (ENABLE_FEATURE_TAR_GZIP && get_header_ptr == get_header_tar_gz) 840 913 zipMode = 1; 841 914 if (ENABLE_FEATURE_TAR_BZIP2 && get_header_ptr == get_header_tar_bz2) 842 915 zipMode = 2; 843 844 if ((tar_handle->action_header == header_list) || 845 (tar_handle->action_header == header_verbose_list)) 846 { 847 verboseFlag = TRUE; 848 } 849 writeTarFile(tar_handle->src_fd, verboseFlag, opt & TAR_OPT_DEREFERENCE, 916 /* NB: writeTarFile() closes tar_handle->src_fd */ 917 return writeTarFile(tar_handle->src_fd, verboseFlag, opt & OPT_DEREFERENCE, 850 918 tar_handle->accept, 851 tar_handle->reject, zipMode); 852 } else { 853 while (get_header_ptr(tar_handle) == EXIT_SUCCESS); 854 855 /* Check that every file that should have been extracted was */ 856 while (tar_handle->accept) { 857 if (!find_list_entry(tar_handle->reject, tar_handle->accept->data) 858 && !find_list_entry(tar_handle->passed, tar_handle->accept->data)) 859 { 860 bb_error_msg_and_die("%s: Not found in archive", tar_handle->accept->data); 861 } 862 tar_handle->accept = tar_handle->accept->link; 863 } 864 } 865 866 if (ENABLE_FEATURE_CLEAN_UP && tar_handle->src_fd != STDIN_FILENO) 919 tar_handle->reject, zipMode); 920 } 921 922 while (get_header_ptr(tar_handle) == EXIT_SUCCESS) 923 /* nothing */; 924 925 /* Check that every file that should have been extracted was */ 926 while (tar_handle->accept) { 927 if (!find_list_entry(tar_handle->reject, tar_handle->accept->data) 928 && !find_list_entry(tar_handle->passed, tar_handle->accept->data) 929 ) { 930 bb_error_msg_and_die("%s: not found in archive", 931 tar_handle->accept->data); 932 } 933 tar_handle->accept = tar_handle->accept->link; 934 } 935 if (ENABLE_FEATURE_CLEAN_UP /* && tar_handle->src_fd != STDIN_FILENO */) 867 936 close(tar_handle->src_fd); 868 937 869 return (EXIT_SUCCESS);870 } 938 return EXIT_SUCCESS; 939 }
Note:
See TracChangeset
for help on using the changeset viewer.