summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Andersen <andersen@codepoet.org>2000-04-08 20:58:35 +0000
committerErik Andersen <andersen@codepoet.org>2000-04-08 20:58:35 +0000
commit84e09e443796b52d41de9fd9b06b598591a6b66c (patch)
treed28a4a89eb5185f9c413e6c95a4f56afb45fca83
parentecd512453ce8f7a7c8a3b5d523855a2b52d626c5 (diff)
downloadbusybox-w32-84e09e443796b52d41de9fd9b06b598591a6b66c.tar.gz
busybox-w32-84e09e443796b52d41de9fd9b06b598591a6b66c.tar.bz2
busybox-w32-84e09e443796b52d41de9fd9b06b598591a6b66c.zip
Fix tar checksum calculation bug.
-Erik
-rw-r--r--archival/tar.c88
-rw-r--r--tar.c88
2 files changed, 110 insertions, 66 deletions
diff --git a/archival/tar.c b/archival/tar.c
index 49d4d2ecf..02fde0a64 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -154,10 +154,6 @@ struct TarInfo
154}; 154};
155typedef struct TarInfo TarInfo; 155typedef struct TarInfo TarInfo;
156 156
157/* Static data */
158static const unsigned long TarChecksumOffset = (const unsigned long)&(((TarHeader *)0)->chksum);
159
160
161/* Local procedures to restore files from a tar file. */ 157/* Local procedures to restore files from a tar file. */
162static int readTarFile(const char* tarName, int extractFlag, int listFlag, 158static int readTarFile(const char* tarName, int extractFlag, int listFlag,
163 int tostdoutFlag, int verboseFlag, char** excludeList); 159 int tostdoutFlag, int verboseFlag, char** excludeList);
@@ -472,10 +468,23 @@ static int
472readTarHeader(struct TarHeader *rawHeader, struct TarInfo *header) 468readTarHeader(struct TarHeader *rawHeader, struct TarInfo *header)
473{ 469{
474 int i; 470 int i;
475 long chksum, sum; 471 long chksum, sum=0;
476 unsigned char *s = (unsigned char *)rawHeader; 472 unsigned char *s = (unsigned char *)rawHeader;
477 473
478 header->name = rawHeader->name; 474 header->name = rawHeader->name;
475 /* Check for and relativify any absolute paths */
476 if ( *(header->name) == '/' ) {
477 static int alreadyWarned=FALSE;
478
479 while (*(header->name) == '/')
480 ++*(header->name);
481
482 if (alreadyWarned == FALSE) {
483 errorMsg("tar: Removing leading '/' from member names\n");
484 alreadyWarned = TRUE;
485 }
486 }
487
479 header->mode = getOctal(rawHeader->mode, sizeof(rawHeader->mode)); 488 header->mode = getOctal(rawHeader->mode, sizeof(rawHeader->mode));
480 header->uid = getOctal(rawHeader->uid, sizeof(rawHeader->uid)); 489 header->uid = getOctal(rawHeader->uid, sizeof(rawHeader->uid));
481 header->gid = getOctal(rawHeader->gid, sizeof(rawHeader->gid)); 490 header->gid = getOctal(rawHeader->gid, sizeof(rawHeader->gid));
@@ -484,16 +493,32 @@ readTarHeader(struct TarHeader *rawHeader, struct TarInfo *header)
484 chksum = getOctal(rawHeader->chksum, sizeof(rawHeader->chksum)); 493 chksum = getOctal(rawHeader->chksum, sizeof(rawHeader->chksum));
485 header->type = rawHeader->typeflag; 494 header->type = rawHeader->typeflag;
486 header->linkname = rawHeader->linkname; 495 header->linkname = rawHeader->linkname;
496 /* Check for and relativify any absolute paths */
497 if ( *(header->linkname) == '/' ) {
498 static int alreadyWarned=FALSE;
499
500 while (*(header->linkname) == '/')
501 ++*(header->linkname);
502
503 if (alreadyWarned == FALSE) {
504 errorMsg("tar: Removing leading '/' from link names\n");
505 alreadyWarned = TRUE;
506 }
507 }
487 header->devmajor = getOctal(rawHeader->devmajor, sizeof(rawHeader->devmajor)); 508 header->devmajor = getOctal(rawHeader->devmajor, sizeof(rawHeader->devmajor));
488 header->devminor = getOctal(rawHeader->devminor, sizeof(rawHeader->devminor)); 509 header->devminor = getOctal(rawHeader->devminor, sizeof(rawHeader->devminor));
489 510
490 /* Check the checksum */ 511 /* Check the checksum */
491 sum = ' ' * sizeof(rawHeader->chksum); 512 for (i = sizeof(*rawHeader); i-- != 0;) {
492 for ( i = TarChecksumOffset; i > 0; i-- )
493 sum += *s++;
494 s += sizeof(rawHeader->chksum);
495 for ( i = (512 - TarChecksumOffset - sizeof(rawHeader->chksum)); i > 0; i-- )
496 sum += *s++; 513 sum += *s++;
514 }
515 /* Remove the effects of the checksum field (replace
516 * with blanks for the purposes of the checksum) */
517 s = rawHeader->chksum;
518 for (i = sizeof(rawHeader->chksum) ; i-- != 0;) {
519 sum -= *s++;
520 }
521 sum += ' ' * sizeof(rawHeader->chksum);
497 if (sum == chksum ) 522 if (sum == chksum )
498 return ( TRUE); 523 return ( TRUE);
499 return( FALSE); 524 return( FALSE);
@@ -511,7 +536,6 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag,
511 int errorFlag=FALSE; 536 int errorFlag=FALSE;
512 TarHeader rawHeader; 537 TarHeader rawHeader;
513 TarInfo header; 538 TarInfo header;
514 int alreadyWarned=FALSE;
515 //int skipFileFlag=FALSE; 539 //int skipFileFlag=FALSE;
516 540
517 /* Open the tar file for reading. */ 541 /* Open the tar file for reading. */
@@ -545,18 +569,6 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag,
545 if ( *(header.name) == '\0' ) 569 if ( *(header.name) == '\0' )
546 goto endgame; 570 goto endgame;
547 571
548 /* Check for and relativify any absolute paths */
549 if ( *(header.name) == '/' ) {
550
551 while (*(header.name) == '/')
552 ++*(header.name);
553
554 if (alreadyWarned == FALSE) {
555 errorMsg("Absolute path detected, removing leading slashes\n");
556 alreadyWarned = TRUE;
557 }
558 }
559
560 /* Special treatment if the list (-t) flag is on */ 572 /* Special treatment if the list (-t) flag is on */
561 if (verboseFlag == TRUE && extractFlag == FALSE) { 573 if (verboseFlag == TRUE && extractFlag == FALSE) {
562 int len, len1; 574 int len, len1;
@@ -751,13 +763,14 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st
751 errorMsg("tar: Removing leading '/' from member names\n"); 763 errorMsg("tar: Removing leading '/' from member names\n");
752 alreadyWarned=TRUE; 764 alreadyWarned=TRUE;
753 } 765 }
754 strcpy(header.name, fileName+1); 766 strncpy(header.name, fileName+1, sizeof(header.name));
755 } 767 }
756 else { 768 else {
757 strcpy(header.name, fileName); 769 strncpy(header.name, fileName, sizeof(header.name));
758 } 770 }
759#if 0 771
760 /* Now that leading '/''s have been removed */ 772 /* Now that leading '/''s have been removed,
773 * check for excluded files.... */
761 for (tmpList=tbInfo->excludeList; tmpList && *tmpList; tmpList++) { 774 for (tmpList=tbInfo->excludeList; tmpList && *tmpList; tmpList++) {
762 printf( "comparing '%s' and '%s'", *tmpList, header.name); 775 printf( "comparing '%s' and '%s'", *tmpList, header.name);
763 if (strcmp( *tmpList, header.name)==0) 776 if (strcmp( *tmpList, header.name)==0)
@@ -765,7 +778,6 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st
765 else 778 else
766 printf( "\n"); 779 printf( "\n");
767 } 780 }
768#endif
769 781
770 putOctal(header.mode, sizeof(header.mode), statbuf->st_mode); 782 putOctal(header.mode, sizeof(header.mode), statbuf->st_mode);
771 putOctal(header.uid, sizeof(header.uid), statbuf->st_uid); 783 putOctal(header.uid, sizeof(header.uid), statbuf->st_uid);
@@ -775,15 +787,15 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st
775 strncpy(header.magic, TAR_MAGIC TAR_VERSION, 787 strncpy(header.magic, TAR_MAGIC TAR_VERSION,
776 TAR_MAGIC_LEN + TAR_VERSION_LEN ); 788 TAR_MAGIC_LEN + TAR_VERSION_LEN );
777 789
790 /* Enter the user and group names (default to root if it fails) */
778 my_getpwuid(header.uname, statbuf->st_uid); 791 my_getpwuid(header.uname, statbuf->st_uid);
779 /* Put some sort of sane fallback in place... */
780 if (! *header.uname) 792 if (! *header.uname)
781 strncpy(header.uname, "root", 5); 793 strcpy(header.uname, "root");
782 my_getgrgid(header.gname, statbuf->st_gid); 794 my_getgrgid(header.gname, statbuf->st_gid);
783 if (! *header.uname) 795 if (! *header.uname)
784 strncpy(header.uname, "root", 5); 796 strcpy(header.uname, "root");
785 797
786 // FIXME: (or most likely not) I break Hard Links 798 // FIXME (or most likely not): I break Hard Links
787 if (S_ISLNK(statbuf->st_mode)) { 799 if (S_ISLNK(statbuf->st_mode)) {
788 char buffer[BUFSIZ]; 800 char buffer[BUFSIZ];
789 header.typeflag = SYMTYPE; 801 header.typeflag = SYMTYPE;
@@ -791,7 +803,17 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st
791 errorMsg("Error reading symlink '%s': %s\n", header.name, strerror(errno)); 803 errorMsg("Error reading symlink '%s': %s\n", header.name, strerror(errno));
792 return ( FALSE); 804 return ( FALSE);
793 } 805 }
794 strncpy(header.linkname, buffer, sizeof(header.linkname)); 806 if (*buffer=='/') {
807 static int alreadyWarned=FALSE;
808 if (alreadyWarned==FALSE) {
809 errorMsg("tar: Removing leading '/' from link names\n");
810 alreadyWarned=TRUE;
811 }
812 strncpy(header.linkname, buffer+1, sizeof(header.linkname));
813 }
814 else {
815 strncpy(header.linkname, buffer, sizeof(header.linkname));
816 }
795 } else if (S_ISDIR(statbuf->st_mode)) { 817 } else if (S_ISDIR(statbuf->st_mode)) {
796 header.typeflag = DIRTYPE; 818 header.typeflag = DIRTYPE;
797 strncat(header.name, "/", sizeof(header.name)); 819 strncat(header.name, "/", sizeof(header.name));
diff --git a/tar.c b/tar.c
index 49d4d2ecf..02fde0a64 100644
--- a/tar.c
+++ b/tar.c
@@ -154,10 +154,6 @@ struct TarInfo
154}; 154};
155typedef struct TarInfo TarInfo; 155typedef struct TarInfo TarInfo;
156 156
157/* Static data */
158static const unsigned long TarChecksumOffset = (const unsigned long)&(((TarHeader *)0)->chksum);
159
160
161/* Local procedures to restore files from a tar file. */ 157/* Local procedures to restore files from a tar file. */
162static int readTarFile(const char* tarName, int extractFlag, int listFlag, 158static int readTarFile(const char* tarName, int extractFlag, int listFlag,
163 int tostdoutFlag, int verboseFlag, char** excludeList); 159 int tostdoutFlag, int verboseFlag, char** excludeList);
@@ -472,10 +468,23 @@ static int
472readTarHeader(struct TarHeader *rawHeader, struct TarInfo *header) 468readTarHeader(struct TarHeader *rawHeader, struct TarInfo *header)
473{ 469{
474 int i; 470 int i;
475 long chksum, sum; 471 long chksum, sum=0;
476 unsigned char *s = (unsigned char *)rawHeader; 472 unsigned char *s = (unsigned char *)rawHeader;
477 473
478 header->name = rawHeader->name; 474 header->name = rawHeader->name;
475 /* Check for and relativify any absolute paths */
476 if ( *(header->name) == '/' ) {
477 static int alreadyWarned=FALSE;
478
479 while (*(header->name) == '/')
480 ++*(header->name);
481
482 if (alreadyWarned == FALSE) {
483 errorMsg("tar: Removing leading '/' from member names\n");
484 alreadyWarned = TRUE;
485 }
486 }
487
479 header->mode = getOctal(rawHeader->mode, sizeof(rawHeader->mode)); 488 header->mode = getOctal(rawHeader->mode, sizeof(rawHeader->mode));
480 header->uid = getOctal(rawHeader->uid, sizeof(rawHeader->uid)); 489 header->uid = getOctal(rawHeader->uid, sizeof(rawHeader->uid));
481 header->gid = getOctal(rawHeader->gid, sizeof(rawHeader->gid)); 490 header->gid = getOctal(rawHeader->gid, sizeof(rawHeader->gid));
@@ -484,16 +493,32 @@ readTarHeader(struct TarHeader *rawHeader, struct TarInfo *header)
484 chksum = getOctal(rawHeader->chksum, sizeof(rawHeader->chksum)); 493 chksum = getOctal(rawHeader->chksum, sizeof(rawHeader->chksum));
485 header->type = rawHeader->typeflag; 494 header->type = rawHeader->typeflag;
486 header->linkname = rawHeader->linkname; 495 header->linkname = rawHeader->linkname;
496 /* Check for and relativify any absolute paths */
497 if ( *(header->linkname) == '/' ) {
498 static int alreadyWarned=FALSE;
499
500 while (*(header->linkname) == '/')
501 ++*(header->linkname);
502
503 if (alreadyWarned == FALSE) {
504 errorMsg("tar: Removing leading '/' from link names\n");
505 alreadyWarned = TRUE;
506 }
507 }
487 header->devmajor = getOctal(rawHeader->devmajor, sizeof(rawHeader->devmajor)); 508 header->devmajor = getOctal(rawHeader->devmajor, sizeof(rawHeader->devmajor));
488 header->devminor = getOctal(rawHeader->devminor, sizeof(rawHeader->devminor)); 509 header->devminor = getOctal(rawHeader->devminor, sizeof(rawHeader->devminor));
489 510
490 /* Check the checksum */ 511 /* Check the checksum */
491 sum = ' ' * sizeof(rawHeader->chksum); 512 for (i = sizeof(*rawHeader); i-- != 0;) {
492 for ( i = TarChecksumOffset; i > 0; i-- )
493 sum += *s++;
494 s += sizeof(rawHeader->chksum);
495 for ( i = (512 - TarChecksumOffset - sizeof(rawHeader->chksum)); i > 0; i-- )
496 sum += *s++; 513 sum += *s++;
514 }
515 /* Remove the effects of the checksum field (replace
516 * with blanks for the purposes of the checksum) */
517 s = rawHeader->chksum;
518 for (i = sizeof(rawHeader->chksum) ; i-- != 0;) {
519 sum -= *s++;
520 }
521 sum += ' ' * sizeof(rawHeader->chksum);
497 if (sum == chksum ) 522 if (sum == chksum )
498 return ( TRUE); 523 return ( TRUE);
499 return( FALSE); 524 return( FALSE);
@@ -511,7 +536,6 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag,
511 int errorFlag=FALSE; 536 int errorFlag=FALSE;
512 TarHeader rawHeader; 537 TarHeader rawHeader;
513 TarInfo header; 538 TarInfo header;
514 int alreadyWarned=FALSE;
515 //int skipFileFlag=FALSE; 539 //int skipFileFlag=FALSE;
516 540
517 /* Open the tar file for reading. */ 541 /* Open the tar file for reading. */
@@ -545,18 +569,6 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag,
545 if ( *(header.name) == '\0' ) 569 if ( *(header.name) == '\0' )
546 goto endgame; 570 goto endgame;
547 571
548 /* Check for and relativify any absolute paths */
549 if ( *(header.name) == '/' ) {
550
551 while (*(header.name) == '/')
552 ++*(header.name);
553
554 if (alreadyWarned == FALSE) {
555 errorMsg("Absolute path detected, removing leading slashes\n");
556 alreadyWarned = TRUE;
557 }
558 }
559
560 /* Special treatment if the list (-t) flag is on */ 572 /* Special treatment if the list (-t) flag is on */
561 if (verboseFlag == TRUE && extractFlag == FALSE) { 573 if (verboseFlag == TRUE && extractFlag == FALSE) {
562 int len, len1; 574 int len, len1;
@@ -751,13 +763,14 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st
751 errorMsg("tar: Removing leading '/' from member names\n"); 763 errorMsg("tar: Removing leading '/' from member names\n");
752 alreadyWarned=TRUE; 764 alreadyWarned=TRUE;
753 } 765 }
754 strcpy(header.name, fileName+1); 766 strncpy(header.name, fileName+1, sizeof(header.name));
755 } 767 }
756 else { 768 else {
757 strcpy(header.name, fileName); 769 strncpy(header.name, fileName, sizeof(header.name));
758 } 770 }
759#if 0 771
760 /* Now that leading '/''s have been removed */ 772 /* Now that leading '/''s have been removed,
773 * check for excluded files.... */
761 for (tmpList=tbInfo->excludeList; tmpList && *tmpList; tmpList++) { 774 for (tmpList=tbInfo->excludeList; tmpList && *tmpList; tmpList++) {
762 printf( "comparing '%s' and '%s'", *tmpList, header.name); 775 printf( "comparing '%s' and '%s'", *tmpList, header.name);
763 if (strcmp( *tmpList, header.name)==0) 776 if (strcmp( *tmpList, header.name)==0)
@@ -765,7 +778,6 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st
765 else 778 else
766 printf( "\n"); 779 printf( "\n");
767 } 780 }
768#endif
769 781
770 putOctal(header.mode, sizeof(header.mode), statbuf->st_mode); 782 putOctal(header.mode, sizeof(header.mode), statbuf->st_mode);
771 putOctal(header.uid, sizeof(header.uid), statbuf->st_uid); 783 putOctal(header.uid, sizeof(header.uid), statbuf->st_uid);
@@ -775,15 +787,15 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st
775 strncpy(header.magic, TAR_MAGIC TAR_VERSION, 787 strncpy(header.magic, TAR_MAGIC TAR_VERSION,
776 TAR_MAGIC_LEN + TAR_VERSION_LEN ); 788 TAR_MAGIC_LEN + TAR_VERSION_LEN );
777 789
790 /* Enter the user and group names (default to root if it fails) */
778 my_getpwuid(header.uname, statbuf->st_uid); 791 my_getpwuid(header.uname, statbuf->st_uid);
779 /* Put some sort of sane fallback in place... */
780 if (! *header.uname) 792 if (! *header.uname)
781 strncpy(header.uname, "root", 5); 793 strcpy(header.uname, "root");
782 my_getgrgid(header.gname, statbuf->st_gid); 794 my_getgrgid(header.gname, statbuf->st_gid);
783 if (! *header.uname) 795 if (! *header.uname)
784 strncpy(header.uname, "root", 5); 796 strcpy(header.uname, "root");
785 797
786 // FIXME: (or most likely not) I break Hard Links 798 // FIXME (or most likely not): I break Hard Links
787 if (S_ISLNK(statbuf->st_mode)) { 799 if (S_ISLNK(statbuf->st_mode)) {
788 char buffer[BUFSIZ]; 800 char buffer[BUFSIZ];
789 header.typeflag = SYMTYPE; 801 header.typeflag = SYMTYPE;
@@ -791,7 +803,17 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st
791 errorMsg("Error reading symlink '%s': %s\n", header.name, strerror(errno)); 803 errorMsg("Error reading symlink '%s': %s\n", header.name, strerror(errno));
792 return ( FALSE); 804 return ( FALSE);
793 } 805 }
794 strncpy(header.linkname, buffer, sizeof(header.linkname)); 806 if (*buffer=='/') {
807 static int alreadyWarned=FALSE;
808 if (alreadyWarned==FALSE) {
809 errorMsg("tar: Removing leading '/' from link names\n");
810 alreadyWarned=TRUE;
811 }
812 strncpy(header.linkname, buffer+1, sizeof(header.linkname));
813 }
814 else {
815 strncpy(header.linkname, buffer, sizeof(header.linkname));
816 }
795 } else if (S_ISDIR(statbuf->st_mode)) { 817 } else if (S_ISDIR(statbuf->st_mode)) {
796 header.typeflag = DIRTYPE; 818 header.typeflag = DIRTYPE;
797 strncat(header.name, "/", sizeof(header.name)); 819 strncat(header.name, "/", sizeof(header.name));