diff options
author | Erik Andersen <andersen@codepoet.org> | 2000-04-07 06:55:38 +0000 |
---|---|---|
committer | Erik Andersen <andersen@codepoet.org> | 2000-04-07 06:55:38 +0000 |
commit | 6a34b539dbee50780efb9a25d834d7ea1f287297 (patch) | |
tree | 4fcd53eb56525ac8f522765b209356b002053d22 | |
parent | 825aead68b26a5857330972bd1c6adb9f78047ab (diff) | |
download | busybox-w32-6a34b539dbee50780efb9a25d834d7ea1f287297.tar.gz busybox-w32-6a34b539dbee50780efb9a25d834d7ea1f287297.tar.bz2 busybox-w32-6a34b539dbee50780efb9a25d834d7ea1f287297.zip |
Slightly better fringe case handling and GNU tar like error messages.
-Erik
-rw-r--r-- | archival/tar.c | 134 | ||||
-rw-r--r-- | tar.c | 134 |
2 files changed, 172 insertions, 96 deletions
diff --git a/archival/tar.c b/archival/tar.c index 979821ec0..91baa2ddb 100644 --- a/archival/tar.c +++ b/archival/tar.c | |||
@@ -261,6 +261,19 @@ extern int tar_main(int argc, char **argv) | |||
261 | } | 261 | } |
262 | 262 | ||
263 | static void | 263 | static void |
264 | fixUpPermissions(TarInfo *header) | ||
265 | { | ||
266 | struct utimbuf t; | ||
267 | /* Now set permissions etc for the new file */ | ||
268 | chown(header->name, header->uid, header->gid); | ||
269 | chmod(header->name, header->mode); | ||
270 | /* Reset the time */ | ||
271 | t.actime = time(0); | ||
272 | t.modtime = header->mtime; | ||
273 | utime(header->name, &t); | ||
274 | } | ||
275 | |||
276 | static int | ||
264 | tarExtractRegularFile(TarInfo *header, int extractFlag, int tostdoutFlag) | 277 | tarExtractRegularFile(TarInfo *header, int extractFlag, int tostdoutFlag) |
265 | { | 278 | { |
266 | size_t writeSize; | 279 | size_t writeSize; |
@@ -295,7 +308,7 @@ tarExtractRegularFile(TarInfo *header, int extractFlag, int tostdoutFlag) | |||
295 | if ( (readSize = fullRead(header->tarFd, buffer, readSize)) <= 0 ) { | 308 | if ( (readSize = fullRead(header->tarFd, buffer, readSize)) <= 0 ) { |
296 | /* Tarball seems to have a problem */ | 309 | /* Tarball seems to have a problem */ |
297 | errorMsg("tar: Unexpected EOF in archive\n"); | 310 | errorMsg("tar: Unexpected EOF in archive\n"); |
298 | return; | 311 | return( FALSE); |
299 | } | 312 | } |
300 | if ( readSize < writeSize ) | 313 | if ( readSize < writeSize ) |
301 | writeSize = readSize; | 314 | writeSize = readSize; |
@@ -306,7 +319,7 @@ tarExtractRegularFile(TarInfo *header, int extractFlag, int tostdoutFlag) | |||
306 | if ((actualWriteSz=fullWrite(outFd, buffer, writeSize)) != writeSize ) { | 319 | if ((actualWriteSz=fullWrite(outFd, buffer, writeSize)) != writeSize ) { |
307 | /* Output file seems to have a problem */ | 320 | /* Output file seems to have a problem */ |
308 | errorMsg(io_error, header->name, strerror(errno)); | 321 | errorMsg(io_error, header->name, strerror(errno)); |
309 | return; | 322 | return( FALSE); |
310 | } | 323 | } |
311 | } | 324 | } |
312 | 325 | ||
@@ -316,41 +329,23 @@ tarExtractRegularFile(TarInfo *header, int extractFlag, int tostdoutFlag) | |||
316 | /* Now we are done writing the file out, so try | 329 | /* Now we are done writing the file out, so try |
317 | * and fix up the permissions and whatnot */ | 330 | * and fix up the permissions and whatnot */ |
318 | if (extractFlag==TRUE && tostdoutFlag==FALSE) { | 331 | if (extractFlag==TRUE && tostdoutFlag==FALSE) { |
319 | struct utimbuf t; | ||
320 | /* Now set permissions etc for the new file */ | ||
321 | fchown(outFd, header->uid, header->gid); | ||
322 | fchmod(outFd, header->mode & ~S_IFMT); | ||
323 | close(outFd); | 332 | close(outFd); |
324 | /* File must be closed before trying to change the date */ | 333 | fixUpPermissions(header); |
325 | t.actime = time(0); | ||
326 | t.modtime = header->mtime; | ||
327 | utime(header->name, &t); | ||
328 | } | 334 | } |
335 | return( TRUE); | ||
329 | } | 336 | } |
330 | 337 | ||
331 | static void | 338 | static int |
332 | fixUpPermissions(TarInfo *header) | ||
333 | { | ||
334 | struct utimbuf t; | ||
335 | /* Now set permissions etc for the new file */ | ||
336 | chown(header->name, header->uid, header->gid); | ||
337 | chmod(header->name, header->mode); | ||
338 | /* Reset the time */ | ||
339 | t.actime = time(0); | ||
340 | t.modtime = header->mtime; | ||
341 | utime(header->name, &t); | ||
342 | } | ||
343 | |||
344 | static void | ||
345 | tarExtractDirectory(TarInfo *header, int extractFlag, int tostdoutFlag) | 339 | tarExtractDirectory(TarInfo *header, int extractFlag, int tostdoutFlag) |
346 | { | 340 | { |
347 | 341 | ||
348 | if (extractFlag==FALSE || tostdoutFlag==TRUE) | 342 | if (extractFlag==FALSE || tostdoutFlag==TRUE) |
349 | return; | 343 | return( TRUE); |
350 | 344 | ||
351 | if (createPath(header->name, header->mode) != TRUE) { | 345 | if (createPath(header->name, header->mode) != TRUE) { |
352 | errorMsg("Error creating directory '%s': %s", header->name, strerror(errno)); | 346 | errorMsg("tar: %s: Cannot mkdir: %s\n", |
353 | return; | 347 | header->name, strerror(errno)); |
348 | return( FALSE); | ||
354 | } | 349 | } |
355 | /* make the final component, just in case it was | 350 | /* make the final component, just in case it was |
356 | * omitted by createPath() (which will skip the | 351 | * omitted by createPath() (which will skip the |
@@ -358,35 +353,37 @@ tarExtractDirectory(TarInfo *header, int extractFlag, int tostdoutFlag) | |||
358 | if (mkdir(header->name, header->mode) == 0) { | 353 | if (mkdir(header->name, header->mode) == 0) { |
359 | fixUpPermissions(header); | 354 | fixUpPermissions(header); |
360 | } | 355 | } |
356 | return( TRUE); | ||
361 | } | 357 | } |
362 | 358 | ||
363 | static void | 359 | static int |
364 | tarExtractHardLink(TarInfo *header, int extractFlag, int tostdoutFlag) | 360 | tarExtractHardLink(TarInfo *header, int extractFlag, int tostdoutFlag) |
365 | { | 361 | { |
366 | if (extractFlag==FALSE || tostdoutFlag==TRUE) | 362 | if (extractFlag==FALSE || tostdoutFlag==TRUE) |
367 | return; | 363 | return( TRUE); |
368 | 364 | ||
369 | if (link(header->linkname, header->name) < 0) { | 365 | if (link(header->linkname, header->name) < 0) { |
370 | errorMsg("Error creating hard link '%s' to '%s': %s\n", | 366 | errorMsg("tar: %s: Cannot create hard link to '%s': %s\n", |
371 | header->name, header->linkname, strerror(errno)); | 367 | header->name, header->linkname, strerror(errno)); |
372 | return; | 368 | return( FALSE); |
373 | } | 369 | } |
374 | 370 | ||
375 | /* Now set permissions etc for the new directory */ | 371 | /* Now set permissions etc for the new directory */ |
376 | fixUpPermissions(header); | 372 | fixUpPermissions(header); |
373 | return( TRUE); | ||
377 | } | 374 | } |
378 | 375 | ||
379 | static void | 376 | static int |
380 | tarExtractSymLink(TarInfo *header, int extractFlag, int tostdoutFlag) | 377 | tarExtractSymLink(TarInfo *header, int extractFlag, int tostdoutFlag) |
381 | { | 378 | { |
382 | if (extractFlag==FALSE || tostdoutFlag==TRUE) | 379 | if (extractFlag==FALSE || tostdoutFlag==TRUE) |
383 | return; | 380 | return( TRUE); |
384 | 381 | ||
385 | #ifdef S_ISLNK | 382 | #ifdef S_ISLNK |
386 | if (symlink(header->linkname, header->name) < 0) { | 383 | if (symlink(header->linkname, header->name) < 0) { |
387 | errorMsg("Error creating symlink '%s' to '%s': %s\n", | 384 | errorMsg("tar: %s: Cannot create symlink to '%s': %s\n", |
388 | header->name, header->linkname, strerror(errno)); | 385 | header->name, header->linkname, strerror(errno)); |
389 | return; | 386 | return( FALSE); |
390 | } | 387 | } |
391 | /* Try to change ownership of the symlink. | 388 | /* Try to change ownership of the symlink. |
392 | * If libs doesn't support that, don't bother. | 389 | * If libs doesn't support that, don't bother. |
@@ -399,24 +396,36 @@ tarExtractSymLink(TarInfo *header, int extractFlag, int tostdoutFlag) | |||
399 | /* Do not change permissions or date on symlink, | 396 | /* Do not change permissions or date on symlink, |
400 | * since it changes the pointed to file instead. duh. */ | 397 | * since it changes the pointed to file instead. duh. */ |
401 | #else | 398 | #else |
402 | fprintf(stderr, "Cannot create symbolic links\n"); | 399 | errorMsg("tar: %s: Cannot create symlink to '%s': %s\n", |
400 | header->name, header->linkname, | ||
401 | "symlinks not supported"); | ||
403 | #endif | 402 | #endif |
403 | return( TRUE); | ||
404 | } | 404 | } |
405 | 405 | ||
406 | static void | 406 | static int |
407 | tarExtractSpecial(TarInfo *header, int extractFlag, int tostdoutFlag) | 407 | tarExtractSpecial(TarInfo *header, int extractFlag, int tostdoutFlag) |
408 | { | 408 | { |
409 | if (extractFlag==FALSE || tostdoutFlag==TRUE) | 409 | if (extractFlag==FALSE || tostdoutFlag==TRUE) |
410 | return; | 410 | return( TRUE); |
411 | 411 | ||
412 | if (S_ISCHR(header->mode) || S_ISBLK(header->mode) || S_ISSOCK(header->mode)) { | 412 | if (S_ISCHR(header->mode) || S_ISBLK(header->mode) || S_ISSOCK(header->mode)) { |
413 | mknod(header->name, header->mode, makedev(header->devmajor, header->devminor)); | 413 | if (mknod(header->name, header->mode, makedev(header->devmajor, header->devminor)) < 0) { |
414 | errorMsg("tar: %s: Cannot mknod: %s\n", | ||
415 | header->name, strerror(errno)); | ||
416 | return( FALSE); | ||
417 | } | ||
414 | } else if (S_ISFIFO(header->mode)) { | 418 | } else if (S_ISFIFO(header->mode)) { |
415 | mkfifo(header->name, header->mode); | 419 | if (mkfifo(header->name, header->mode) < 0) { |
420 | errorMsg("tar: %s: Cannot mkfifo: %s\n", | ||
421 | header->name, strerror(errno)); | ||
422 | return( FALSE); | ||
423 | } | ||
416 | } | 424 | } |
417 | 425 | ||
418 | /* Now set permissions etc for the new directory */ | 426 | /* Now set permissions etc for the new directory */ |
419 | fixUpPermissions(header); | 427 | fixUpPermissions(header); |
428 | return( TRUE); | ||
420 | } | 429 | } |
421 | 430 | ||
422 | /* Read an octal value in a field of the specified width, with optional | 431 | /* Read an octal value in a field of the specified width, with optional |
@@ -535,7 +544,20 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag, | |||
535 | char buf[35]; | 544 | char buf[35]; |
536 | struct tm *tm = localtime (&(header.mtime)); | 545 | struct tm *tm = localtime (&(header.mtime)); |
537 | 546 | ||
538 | len=printf("%s %d/%-d ", modeString(header.mode), header.uid, header.gid); | 547 | len=printf("%s ", modeString(header.mode)); |
548 | memset(buf, 0, 8*sizeof(char)); | ||
549 | my_getpwuid(buf, header.uid); | ||
550 | if (! *buf) | ||
551 | len+=printf("%d", header.uid); | ||
552 | else | ||
553 | len+=printf("%s", buf); | ||
554 | memset(buf, 0, 8*sizeof(char)); | ||
555 | my_getgrgid(buf, header.gid); | ||
556 | if (! *buf) | ||
557 | len+=printf("/%-d ", header.gid); | ||
558 | else | ||
559 | len+=printf("/%-s ", buf); | ||
560 | |||
539 | if (header.type==CHRTYPE || header.type==BLKTYPE) { | 561 | if (header.type==CHRTYPE || header.type==BLKTYPE) { |
540 | len1=snprintf(buf, sizeof(buf), "%ld,%-ld ", | 562 | len1=snprintf(buf, sizeof(buf), "%ld,%-ld ", |
541 | header.devmajor, header.devminor); | 563 | header.devmajor, header.devminor); |
@@ -558,11 +580,15 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag, | |||
558 | if (verboseFlag == TRUE || listFlag == TRUE) { | 580 | if (verboseFlag == TRUE || listFlag == TRUE) { |
559 | /* Now the normal listing */ | 581 | /* Now the normal listing */ |
560 | printf("%s", header.name); | 582 | printf("%s", header.name); |
583 | } | ||
584 | if (verboseFlag == TRUE && listFlag == TRUE) { | ||
561 | /* If this is a link, say so */ | 585 | /* If this is a link, say so */ |
562 | if (header.type==LNKTYPE) | 586 | if (header.type==LNKTYPE) |
563 | printf(" link to %s", header.linkname); | 587 | printf(" link to %s", header.linkname); |
564 | else if (header.type==SYMTYPE) | 588 | else if (header.type==SYMTYPE) |
565 | printf(" -> %s", header.linkname); | 589 | printf(" -> %s", header.linkname); |
590 | } | ||
591 | if (verboseFlag == TRUE || listFlag == TRUE) { | ||
566 | printf("\n"); | 592 | printf("\n"); |
567 | } | 593 | } |
568 | 594 | ||
@@ -573,6 +599,8 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag, | |||
573 | skipFileFlag = TRUE; | 599 | skipFileFlag = TRUE; |
574 | } | 600 | } |
575 | #endif | 601 | #endif |
602 | /* Remove any clutter lying in our way */ | ||
603 | unlink( header.name); | ||
576 | 604 | ||
577 | /* If we got here, we can be certain we have a legitimate | 605 | /* If we got here, we can be certain we have a legitimate |
578 | * header to work with. So work with it. */ | 606 | * header to work with. So work with it. */ |
@@ -582,22 +610,27 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag, | |||
582 | /* If the name ends in a '/' then assume it is | 610 | /* If the name ends in a '/' then assume it is |
583 | * supposed to be a directory, and fall through */ | 611 | * supposed to be a directory, and fall through */ |
584 | if (header.name[strlen(header.name)-1] != '/') { | 612 | if (header.name[strlen(header.name)-1] != '/') { |
585 | tarExtractRegularFile(&header, extractFlag, tostdoutFlag); | 613 | if (tarExtractRegularFile(&header, extractFlag, tostdoutFlag)==FALSE) |
614 | errorFlag=TRUE; | ||
586 | break; | 615 | break; |
587 | } | 616 | } |
588 | case DIRTYPE: | 617 | case DIRTYPE: |
589 | tarExtractDirectory( &header, extractFlag, tostdoutFlag); | 618 | if (tarExtractDirectory( &header, extractFlag, tostdoutFlag)==FALSE) |
619 | errorFlag=TRUE; | ||
590 | break; | 620 | break; |
591 | case LNKTYPE: | 621 | case LNKTYPE: |
592 | tarExtractHardLink( &header, extractFlag, tostdoutFlag); | 622 | if (tarExtractHardLink( &header, extractFlag, tostdoutFlag)==FALSE) |
623 | errorFlag=TRUE; | ||
593 | break; | 624 | break; |
594 | case SYMTYPE: | 625 | case SYMTYPE: |
595 | tarExtractSymLink( &header, extractFlag, tostdoutFlag); | 626 | if (tarExtractSymLink( &header, extractFlag, tostdoutFlag)==FALSE) |
627 | errorFlag=TRUE; | ||
596 | break; | 628 | break; |
597 | case CHRTYPE: | 629 | case CHRTYPE: |
598 | case BLKTYPE: | 630 | case BLKTYPE: |
599 | case FIFOTYPE: | 631 | case FIFOTYPE: |
600 | tarExtractSpecial( &header, extractFlag, tostdoutFlag); | 632 | if (tarExtractSpecial( &header, extractFlag, tostdoutFlag)==FALSE) |
633 | errorFlag=TRUE; | ||
601 | break; | 634 | break; |
602 | default: | 635 | default: |
603 | close( tarFd); | 636 | close( tarFd); |
@@ -610,14 +643,19 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag, | |||
610 | errorMsg( "Error reading '%s': %s\n", tarName, strerror(errno)); | 643 | errorMsg( "Error reading '%s': %s\n", tarName, strerror(errno)); |
611 | return ( FALSE); | 644 | return ( FALSE); |
612 | } | 645 | } |
613 | else | 646 | else if (errorFlag==TRUE) { |
647 | errorMsg( "tar: Error exit delayed from previous errors\n"); | ||
648 | return( FALSE); | ||
649 | } else | ||
614 | return( status); | 650 | return( status); |
615 | 651 | ||
616 | /* Stuff to do when we are done */ | 652 | /* Stuff to do when we are done */ |
617 | endgame: | 653 | endgame: |
618 | close( tarFd); | 654 | close( tarFd); |
619 | if ( *(header.name) == '\0' ) { | 655 | if ( *(header.name) == '\0' ) { |
620 | if (errorFlag==FALSE) | 656 | if (errorFlag==TRUE) |
657 | errorMsg( "tar: Error exit delayed from previous errors\n"); | ||
658 | else | ||
621 | return( TRUE); | 659 | return( TRUE); |
622 | } | 660 | } |
623 | return( FALSE); | 661 | return( FALSE); |
@@ -261,6 +261,19 @@ extern int tar_main(int argc, char **argv) | |||
261 | } | 261 | } |
262 | 262 | ||
263 | static void | 263 | static void |
264 | fixUpPermissions(TarInfo *header) | ||
265 | { | ||
266 | struct utimbuf t; | ||
267 | /* Now set permissions etc for the new file */ | ||
268 | chown(header->name, header->uid, header->gid); | ||
269 | chmod(header->name, header->mode); | ||
270 | /* Reset the time */ | ||
271 | t.actime = time(0); | ||
272 | t.modtime = header->mtime; | ||
273 | utime(header->name, &t); | ||
274 | } | ||
275 | |||
276 | static int | ||
264 | tarExtractRegularFile(TarInfo *header, int extractFlag, int tostdoutFlag) | 277 | tarExtractRegularFile(TarInfo *header, int extractFlag, int tostdoutFlag) |
265 | { | 278 | { |
266 | size_t writeSize; | 279 | size_t writeSize; |
@@ -295,7 +308,7 @@ tarExtractRegularFile(TarInfo *header, int extractFlag, int tostdoutFlag) | |||
295 | if ( (readSize = fullRead(header->tarFd, buffer, readSize)) <= 0 ) { | 308 | if ( (readSize = fullRead(header->tarFd, buffer, readSize)) <= 0 ) { |
296 | /* Tarball seems to have a problem */ | 309 | /* Tarball seems to have a problem */ |
297 | errorMsg("tar: Unexpected EOF in archive\n"); | 310 | errorMsg("tar: Unexpected EOF in archive\n"); |
298 | return; | 311 | return( FALSE); |
299 | } | 312 | } |
300 | if ( readSize < writeSize ) | 313 | if ( readSize < writeSize ) |
301 | writeSize = readSize; | 314 | writeSize = readSize; |
@@ -306,7 +319,7 @@ tarExtractRegularFile(TarInfo *header, int extractFlag, int tostdoutFlag) | |||
306 | if ((actualWriteSz=fullWrite(outFd, buffer, writeSize)) != writeSize ) { | 319 | if ((actualWriteSz=fullWrite(outFd, buffer, writeSize)) != writeSize ) { |
307 | /* Output file seems to have a problem */ | 320 | /* Output file seems to have a problem */ |
308 | errorMsg(io_error, header->name, strerror(errno)); | 321 | errorMsg(io_error, header->name, strerror(errno)); |
309 | return; | 322 | return( FALSE); |
310 | } | 323 | } |
311 | } | 324 | } |
312 | 325 | ||
@@ -316,41 +329,23 @@ tarExtractRegularFile(TarInfo *header, int extractFlag, int tostdoutFlag) | |||
316 | /* Now we are done writing the file out, so try | 329 | /* Now we are done writing the file out, so try |
317 | * and fix up the permissions and whatnot */ | 330 | * and fix up the permissions and whatnot */ |
318 | if (extractFlag==TRUE && tostdoutFlag==FALSE) { | 331 | if (extractFlag==TRUE && tostdoutFlag==FALSE) { |
319 | struct utimbuf t; | ||
320 | /* Now set permissions etc for the new file */ | ||
321 | fchown(outFd, header->uid, header->gid); | ||
322 | fchmod(outFd, header->mode & ~S_IFMT); | ||
323 | close(outFd); | 332 | close(outFd); |
324 | /* File must be closed before trying to change the date */ | 333 | fixUpPermissions(header); |
325 | t.actime = time(0); | ||
326 | t.modtime = header->mtime; | ||
327 | utime(header->name, &t); | ||
328 | } | 334 | } |
335 | return( TRUE); | ||
329 | } | 336 | } |
330 | 337 | ||
331 | static void | 338 | static int |
332 | fixUpPermissions(TarInfo *header) | ||
333 | { | ||
334 | struct utimbuf t; | ||
335 | /* Now set permissions etc for the new file */ | ||
336 | chown(header->name, header->uid, header->gid); | ||
337 | chmod(header->name, header->mode); | ||
338 | /* Reset the time */ | ||
339 | t.actime = time(0); | ||
340 | t.modtime = header->mtime; | ||
341 | utime(header->name, &t); | ||
342 | } | ||
343 | |||
344 | static void | ||
345 | tarExtractDirectory(TarInfo *header, int extractFlag, int tostdoutFlag) | 339 | tarExtractDirectory(TarInfo *header, int extractFlag, int tostdoutFlag) |
346 | { | 340 | { |
347 | 341 | ||
348 | if (extractFlag==FALSE || tostdoutFlag==TRUE) | 342 | if (extractFlag==FALSE || tostdoutFlag==TRUE) |
349 | return; | 343 | return( TRUE); |
350 | 344 | ||
351 | if (createPath(header->name, header->mode) != TRUE) { | 345 | if (createPath(header->name, header->mode) != TRUE) { |
352 | errorMsg("Error creating directory '%s': %s", header->name, strerror(errno)); | 346 | errorMsg("tar: %s: Cannot mkdir: %s\n", |
353 | return; | 347 | header->name, strerror(errno)); |
348 | return( FALSE); | ||
354 | } | 349 | } |
355 | /* make the final component, just in case it was | 350 | /* make the final component, just in case it was |
356 | * omitted by createPath() (which will skip the | 351 | * omitted by createPath() (which will skip the |
@@ -358,35 +353,37 @@ tarExtractDirectory(TarInfo *header, int extractFlag, int tostdoutFlag) | |||
358 | if (mkdir(header->name, header->mode) == 0) { | 353 | if (mkdir(header->name, header->mode) == 0) { |
359 | fixUpPermissions(header); | 354 | fixUpPermissions(header); |
360 | } | 355 | } |
356 | return( TRUE); | ||
361 | } | 357 | } |
362 | 358 | ||
363 | static void | 359 | static int |
364 | tarExtractHardLink(TarInfo *header, int extractFlag, int tostdoutFlag) | 360 | tarExtractHardLink(TarInfo *header, int extractFlag, int tostdoutFlag) |
365 | { | 361 | { |
366 | if (extractFlag==FALSE || tostdoutFlag==TRUE) | 362 | if (extractFlag==FALSE || tostdoutFlag==TRUE) |
367 | return; | 363 | return( TRUE); |
368 | 364 | ||
369 | if (link(header->linkname, header->name) < 0) { | 365 | if (link(header->linkname, header->name) < 0) { |
370 | errorMsg("Error creating hard link '%s' to '%s': %s\n", | 366 | errorMsg("tar: %s: Cannot create hard link to '%s': %s\n", |
371 | header->name, header->linkname, strerror(errno)); | 367 | header->name, header->linkname, strerror(errno)); |
372 | return; | 368 | return( FALSE); |
373 | } | 369 | } |
374 | 370 | ||
375 | /* Now set permissions etc for the new directory */ | 371 | /* Now set permissions etc for the new directory */ |
376 | fixUpPermissions(header); | 372 | fixUpPermissions(header); |
373 | return( TRUE); | ||
377 | } | 374 | } |
378 | 375 | ||
379 | static void | 376 | static int |
380 | tarExtractSymLink(TarInfo *header, int extractFlag, int tostdoutFlag) | 377 | tarExtractSymLink(TarInfo *header, int extractFlag, int tostdoutFlag) |
381 | { | 378 | { |
382 | if (extractFlag==FALSE || tostdoutFlag==TRUE) | 379 | if (extractFlag==FALSE || tostdoutFlag==TRUE) |
383 | return; | 380 | return( TRUE); |
384 | 381 | ||
385 | #ifdef S_ISLNK | 382 | #ifdef S_ISLNK |
386 | if (symlink(header->linkname, header->name) < 0) { | 383 | if (symlink(header->linkname, header->name) < 0) { |
387 | errorMsg("Error creating symlink '%s' to '%s': %s\n", | 384 | errorMsg("tar: %s: Cannot create symlink to '%s': %s\n", |
388 | header->name, header->linkname, strerror(errno)); | 385 | header->name, header->linkname, strerror(errno)); |
389 | return; | 386 | return( FALSE); |
390 | } | 387 | } |
391 | /* Try to change ownership of the symlink. | 388 | /* Try to change ownership of the symlink. |
392 | * If libs doesn't support that, don't bother. | 389 | * If libs doesn't support that, don't bother. |
@@ -399,24 +396,36 @@ tarExtractSymLink(TarInfo *header, int extractFlag, int tostdoutFlag) | |||
399 | /* Do not change permissions or date on symlink, | 396 | /* Do not change permissions or date on symlink, |
400 | * since it changes the pointed to file instead. duh. */ | 397 | * since it changes the pointed to file instead. duh. */ |
401 | #else | 398 | #else |
402 | fprintf(stderr, "Cannot create symbolic links\n"); | 399 | errorMsg("tar: %s: Cannot create symlink to '%s': %s\n", |
400 | header->name, header->linkname, | ||
401 | "symlinks not supported"); | ||
403 | #endif | 402 | #endif |
403 | return( TRUE); | ||
404 | } | 404 | } |
405 | 405 | ||
406 | static void | 406 | static int |
407 | tarExtractSpecial(TarInfo *header, int extractFlag, int tostdoutFlag) | 407 | tarExtractSpecial(TarInfo *header, int extractFlag, int tostdoutFlag) |
408 | { | 408 | { |
409 | if (extractFlag==FALSE || tostdoutFlag==TRUE) | 409 | if (extractFlag==FALSE || tostdoutFlag==TRUE) |
410 | return; | 410 | return( TRUE); |
411 | 411 | ||
412 | if (S_ISCHR(header->mode) || S_ISBLK(header->mode) || S_ISSOCK(header->mode)) { | 412 | if (S_ISCHR(header->mode) || S_ISBLK(header->mode) || S_ISSOCK(header->mode)) { |
413 | mknod(header->name, header->mode, makedev(header->devmajor, header->devminor)); | 413 | if (mknod(header->name, header->mode, makedev(header->devmajor, header->devminor)) < 0) { |
414 | errorMsg("tar: %s: Cannot mknod: %s\n", | ||
415 | header->name, strerror(errno)); | ||
416 | return( FALSE); | ||
417 | } | ||
414 | } else if (S_ISFIFO(header->mode)) { | 418 | } else if (S_ISFIFO(header->mode)) { |
415 | mkfifo(header->name, header->mode); | 419 | if (mkfifo(header->name, header->mode) < 0) { |
420 | errorMsg("tar: %s: Cannot mkfifo: %s\n", | ||
421 | header->name, strerror(errno)); | ||
422 | return( FALSE); | ||
423 | } | ||
416 | } | 424 | } |
417 | 425 | ||
418 | /* Now set permissions etc for the new directory */ | 426 | /* Now set permissions etc for the new directory */ |
419 | fixUpPermissions(header); | 427 | fixUpPermissions(header); |
428 | return( TRUE); | ||
420 | } | 429 | } |
421 | 430 | ||
422 | /* Read an octal value in a field of the specified width, with optional | 431 | /* Read an octal value in a field of the specified width, with optional |
@@ -535,7 +544,20 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag, | |||
535 | char buf[35]; | 544 | char buf[35]; |
536 | struct tm *tm = localtime (&(header.mtime)); | 545 | struct tm *tm = localtime (&(header.mtime)); |
537 | 546 | ||
538 | len=printf("%s %d/%-d ", modeString(header.mode), header.uid, header.gid); | 547 | len=printf("%s ", modeString(header.mode)); |
548 | memset(buf, 0, 8*sizeof(char)); | ||
549 | my_getpwuid(buf, header.uid); | ||
550 | if (! *buf) | ||
551 | len+=printf("%d", header.uid); | ||
552 | else | ||
553 | len+=printf("%s", buf); | ||
554 | memset(buf, 0, 8*sizeof(char)); | ||
555 | my_getgrgid(buf, header.gid); | ||
556 | if (! *buf) | ||
557 | len+=printf("/%-d ", header.gid); | ||
558 | else | ||
559 | len+=printf("/%-s ", buf); | ||
560 | |||
539 | if (header.type==CHRTYPE || header.type==BLKTYPE) { | 561 | if (header.type==CHRTYPE || header.type==BLKTYPE) { |
540 | len1=snprintf(buf, sizeof(buf), "%ld,%-ld ", | 562 | len1=snprintf(buf, sizeof(buf), "%ld,%-ld ", |
541 | header.devmajor, header.devminor); | 563 | header.devmajor, header.devminor); |
@@ -558,11 +580,15 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag, | |||
558 | if (verboseFlag == TRUE || listFlag == TRUE) { | 580 | if (verboseFlag == TRUE || listFlag == TRUE) { |
559 | /* Now the normal listing */ | 581 | /* Now the normal listing */ |
560 | printf("%s", header.name); | 582 | printf("%s", header.name); |
583 | } | ||
584 | if (verboseFlag == TRUE && listFlag == TRUE) { | ||
561 | /* If this is a link, say so */ | 585 | /* If this is a link, say so */ |
562 | if (header.type==LNKTYPE) | 586 | if (header.type==LNKTYPE) |
563 | printf(" link to %s", header.linkname); | 587 | printf(" link to %s", header.linkname); |
564 | else if (header.type==SYMTYPE) | 588 | else if (header.type==SYMTYPE) |
565 | printf(" -> %s", header.linkname); | 589 | printf(" -> %s", header.linkname); |
590 | } | ||
591 | if (verboseFlag == TRUE || listFlag == TRUE) { | ||
566 | printf("\n"); | 592 | printf("\n"); |
567 | } | 593 | } |
568 | 594 | ||
@@ -573,6 +599,8 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag, | |||
573 | skipFileFlag = TRUE; | 599 | skipFileFlag = TRUE; |
574 | } | 600 | } |
575 | #endif | 601 | #endif |
602 | /* Remove any clutter lying in our way */ | ||
603 | unlink( header.name); | ||
576 | 604 | ||
577 | /* If we got here, we can be certain we have a legitimate | 605 | /* If we got here, we can be certain we have a legitimate |
578 | * header to work with. So work with it. */ | 606 | * header to work with. So work with it. */ |
@@ -582,22 +610,27 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag, | |||
582 | /* If the name ends in a '/' then assume it is | 610 | /* If the name ends in a '/' then assume it is |
583 | * supposed to be a directory, and fall through */ | 611 | * supposed to be a directory, and fall through */ |
584 | if (header.name[strlen(header.name)-1] != '/') { | 612 | if (header.name[strlen(header.name)-1] != '/') { |
585 | tarExtractRegularFile(&header, extractFlag, tostdoutFlag); | 613 | if (tarExtractRegularFile(&header, extractFlag, tostdoutFlag)==FALSE) |
614 | errorFlag=TRUE; | ||
586 | break; | 615 | break; |
587 | } | 616 | } |
588 | case DIRTYPE: | 617 | case DIRTYPE: |
589 | tarExtractDirectory( &header, extractFlag, tostdoutFlag); | 618 | if (tarExtractDirectory( &header, extractFlag, tostdoutFlag)==FALSE) |
619 | errorFlag=TRUE; | ||
590 | break; | 620 | break; |
591 | case LNKTYPE: | 621 | case LNKTYPE: |
592 | tarExtractHardLink( &header, extractFlag, tostdoutFlag); | 622 | if (tarExtractHardLink( &header, extractFlag, tostdoutFlag)==FALSE) |
623 | errorFlag=TRUE; | ||
593 | break; | 624 | break; |
594 | case SYMTYPE: | 625 | case SYMTYPE: |
595 | tarExtractSymLink( &header, extractFlag, tostdoutFlag); | 626 | if (tarExtractSymLink( &header, extractFlag, tostdoutFlag)==FALSE) |
627 | errorFlag=TRUE; | ||
596 | break; | 628 | break; |
597 | case CHRTYPE: | 629 | case CHRTYPE: |
598 | case BLKTYPE: | 630 | case BLKTYPE: |
599 | case FIFOTYPE: | 631 | case FIFOTYPE: |
600 | tarExtractSpecial( &header, extractFlag, tostdoutFlag); | 632 | if (tarExtractSpecial( &header, extractFlag, tostdoutFlag)==FALSE) |
633 | errorFlag=TRUE; | ||
601 | break; | 634 | break; |
602 | default: | 635 | default: |
603 | close( tarFd); | 636 | close( tarFd); |
@@ -610,14 +643,19 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag, | |||
610 | errorMsg( "Error reading '%s': %s\n", tarName, strerror(errno)); | 643 | errorMsg( "Error reading '%s': %s\n", tarName, strerror(errno)); |
611 | return ( FALSE); | 644 | return ( FALSE); |
612 | } | 645 | } |
613 | else | 646 | else if (errorFlag==TRUE) { |
647 | errorMsg( "tar: Error exit delayed from previous errors\n"); | ||
648 | return( FALSE); | ||
649 | } else | ||
614 | return( status); | 650 | return( status); |
615 | 651 | ||
616 | /* Stuff to do when we are done */ | 652 | /* Stuff to do when we are done */ |
617 | endgame: | 653 | endgame: |
618 | close( tarFd); | 654 | close( tarFd); |
619 | if ( *(header.name) == '\0' ) { | 655 | if ( *(header.name) == '\0' ) { |
620 | if (errorFlag==FALSE) | 656 | if (errorFlag==TRUE) |
657 | errorMsg( "tar: Error exit delayed from previous errors\n"); | ||
658 | else | ||
621 | return( TRUE); | 659 | return( TRUE); |
622 | } | 660 | } |
623 | return( FALSE); | 661 | return( FALSE); |