summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Andersen2000-04-08 20:58:35 +0000
committerErik Andersen2000-04-08 20:58:35 +0000
commit84e09e443796b52d41de9fd9b06b598591a6b66c (patch)
treed28a4a89eb5185f9c413e6c95a4f56afb45fca83
parentecd512453ce8f7a7c8a3b5d523855a2b52d626c5 (diff)
downloadbusybox-84e09e443796b52d41de9fd9b06b598591a6b66c.zip
busybox-84e09e443796b52d41de9fd9b06b598591a6b66c.tar.gz
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 49d4d2e..02fde0a 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -154,10 +154,6 @@ struct TarInfo
};
typedef struct TarInfo TarInfo;
-/* Static data */
-static const unsigned long TarChecksumOffset = (const unsigned long)&(((TarHeader *)0)->chksum);
-
-
/* Local procedures to restore files from a tar file. */
static int readTarFile(const char* tarName, int extractFlag, int listFlag,
int tostdoutFlag, int verboseFlag, char** excludeList);
@@ -472,10 +468,23 @@ static int
readTarHeader(struct TarHeader *rawHeader, struct TarInfo *header)
{
int i;
- long chksum, sum;
+ long chksum, sum=0;
unsigned char *s = (unsigned char *)rawHeader;
header->name = rawHeader->name;
+ /* Check for and relativify any absolute paths */
+ if ( *(header->name) == '/' ) {
+ static int alreadyWarned=FALSE;
+
+ while (*(header->name) == '/')
+ ++*(header->name);
+
+ if (alreadyWarned == FALSE) {
+ errorMsg("tar: Removing leading '/' from member names\n");
+ alreadyWarned = TRUE;
+ }
+ }
+
header->mode = getOctal(rawHeader->mode, sizeof(rawHeader->mode));
header->uid = getOctal(rawHeader->uid, sizeof(rawHeader->uid));
header->gid = getOctal(rawHeader->gid, sizeof(rawHeader->gid));
@@ -484,16 +493,32 @@ readTarHeader(struct TarHeader *rawHeader, struct TarInfo *header)
chksum = getOctal(rawHeader->chksum, sizeof(rawHeader->chksum));
header->type = rawHeader->typeflag;
header->linkname = rawHeader->linkname;
+ /* Check for and relativify any absolute paths */
+ if ( *(header->linkname) == '/' ) {
+ static int alreadyWarned=FALSE;
+
+ while (*(header->linkname) == '/')
+ ++*(header->linkname);
+
+ if (alreadyWarned == FALSE) {
+ errorMsg("tar: Removing leading '/' from link names\n");
+ alreadyWarned = TRUE;
+ }
+ }
header->devmajor = getOctal(rawHeader->devmajor, sizeof(rawHeader->devmajor));
header->devminor = getOctal(rawHeader->devminor, sizeof(rawHeader->devminor));
/* Check the checksum */
- sum = ' ' * sizeof(rawHeader->chksum);
- for ( i = TarChecksumOffset; i > 0; i-- )
- sum += *s++;
- s += sizeof(rawHeader->chksum);
- for ( i = (512 - TarChecksumOffset - sizeof(rawHeader->chksum)); i > 0; i-- )
+ for (i = sizeof(*rawHeader); i-- != 0;) {
sum += *s++;
+ }
+ /* Remove the effects of the checksum field (replace
+ * with blanks for the purposes of the checksum) */
+ s = rawHeader->chksum;
+ for (i = sizeof(rawHeader->chksum) ; i-- != 0;) {
+ sum -= *s++;
+ }
+ sum += ' ' * sizeof(rawHeader->chksum);
if (sum == chksum )
return ( TRUE);
return( FALSE);
@@ -511,7 +536,6 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag,
int errorFlag=FALSE;
TarHeader rawHeader;
TarInfo header;
- int alreadyWarned=FALSE;
//int skipFileFlag=FALSE;
/* Open the tar file for reading. */
@@ -545,18 +569,6 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag,
if ( *(header.name) == '\0' )
goto endgame;
- /* Check for and relativify any absolute paths */
- if ( *(header.name) == '/' ) {
-
- while (*(header.name) == '/')
- ++*(header.name);
-
- if (alreadyWarned == FALSE) {
- errorMsg("Absolute path detected, removing leading slashes\n");
- alreadyWarned = TRUE;
- }
- }
-
/* Special treatment if the list (-t) flag is on */
if (verboseFlag == TRUE && extractFlag == FALSE) {
int len, len1;
@@ -751,13 +763,14 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st
errorMsg("tar: Removing leading '/' from member names\n");
alreadyWarned=TRUE;
}
- strcpy(header.name, fileName+1);
+ strncpy(header.name, fileName+1, sizeof(header.name));
}
else {
- strcpy(header.name, fileName);
+ strncpy(header.name, fileName, sizeof(header.name));
}
-#if 0
- /* Now that leading '/''s have been removed */
+
+ /* Now that leading '/''s have been removed,
+ * check for excluded files.... */
for (tmpList=tbInfo->excludeList; tmpList && *tmpList; tmpList++) {
printf( "comparing '%s' and '%s'", *tmpList, header.name);
if (strcmp( *tmpList, header.name)==0)
@@ -765,7 +778,6 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st
else
printf( "\n");
}
-#endif
putOctal(header.mode, sizeof(header.mode), statbuf->st_mode);
putOctal(header.uid, sizeof(header.uid), statbuf->st_uid);
@@ -775,15 +787,15 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st
strncpy(header.magic, TAR_MAGIC TAR_VERSION,
TAR_MAGIC_LEN + TAR_VERSION_LEN );
+ /* Enter the user and group names (default to root if it fails) */
my_getpwuid(header.uname, statbuf->st_uid);
- /* Put some sort of sane fallback in place... */
if (! *header.uname)
- strncpy(header.uname, "root", 5);
+ strcpy(header.uname, "root");
my_getgrgid(header.gname, statbuf->st_gid);
if (! *header.uname)
- strncpy(header.uname, "root", 5);
+ strcpy(header.uname, "root");
- // FIXME: (or most likely not) I break Hard Links
+ // FIXME (or most likely not): I break Hard Links
if (S_ISLNK(statbuf->st_mode)) {
char buffer[BUFSIZ];
header.typeflag = SYMTYPE;
@@ -791,7 +803,17 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st
errorMsg("Error reading symlink '%s': %s\n", header.name, strerror(errno));
return ( FALSE);
}
- strncpy(header.linkname, buffer, sizeof(header.linkname));
+ if (*buffer=='/') {
+ static int alreadyWarned=FALSE;
+ if (alreadyWarned==FALSE) {
+ errorMsg("tar: Removing leading '/' from link names\n");
+ alreadyWarned=TRUE;
+ }
+ strncpy(header.linkname, buffer+1, sizeof(header.linkname));
+ }
+ else {
+ strncpy(header.linkname, buffer, sizeof(header.linkname));
+ }
} else if (S_ISDIR(statbuf->st_mode)) {
header.typeflag = DIRTYPE;
strncat(header.name, "/", sizeof(header.name));
diff --git a/tar.c b/tar.c
index 49d4d2e..02fde0a 100644
--- a/tar.c
+++ b/tar.c
@@ -154,10 +154,6 @@ struct TarInfo
};
typedef struct TarInfo TarInfo;
-/* Static data */
-static const unsigned long TarChecksumOffset = (const unsigned long)&(((TarHeader *)0)->chksum);
-
-
/* Local procedures to restore files from a tar file. */
static int readTarFile(const char* tarName, int extractFlag, int listFlag,
int tostdoutFlag, int verboseFlag, char** excludeList);
@@ -472,10 +468,23 @@ static int
readTarHeader(struct TarHeader *rawHeader, struct TarInfo *header)
{
int i;
- long chksum, sum;
+ long chksum, sum=0;
unsigned char *s = (unsigned char *)rawHeader;
header->name = rawHeader->name;
+ /* Check for and relativify any absolute paths */
+ if ( *(header->name) == '/' ) {
+ static int alreadyWarned=FALSE;
+
+ while (*(header->name) == '/')
+ ++*(header->name);
+
+ if (alreadyWarned == FALSE) {
+ errorMsg("tar: Removing leading '/' from member names\n");
+ alreadyWarned = TRUE;
+ }
+ }
+
header->mode = getOctal(rawHeader->mode, sizeof(rawHeader->mode));
header->uid = getOctal(rawHeader->uid, sizeof(rawHeader->uid));
header->gid = getOctal(rawHeader->gid, sizeof(rawHeader->gid));
@@ -484,16 +493,32 @@ readTarHeader(struct TarHeader *rawHeader, struct TarInfo *header)
chksum = getOctal(rawHeader->chksum, sizeof(rawHeader->chksum));
header->type = rawHeader->typeflag;
header->linkname = rawHeader->linkname;
+ /* Check for and relativify any absolute paths */
+ if ( *(header->linkname) == '/' ) {
+ static int alreadyWarned=FALSE;
+
+ while (*(header->linkname) == '/')
+ ++*(header->linkname);
+
+ if (alreadyWarned == FALSE) {
+ errorMsg("tar: Removing leading '/' from link names\n");
+ alreadyWarned = TRUE;
+ }
+ }
header->devmajor = getOctal(rawHeader->devmajor, sizeof(rawHeader->devmajor));
header->devminor = getOctal(rawHeader->devminor, sizeof(rawHeader->devminor));
/* Check the checksum */
- sum = ' ' * sizeof(rawHeader->chksum);
- for ( i = TarChecksumOffset; i > 0; i-- )
- sum += *s++;
- s += sizeof(rawHeader->chksum);
- for ( i = (512 - TarChecksumOffset - sizeof(rawHeader->chksum)); i > 0; i-- )
+ for (i = sizeof(*rawHeader); i-- != 0;) {
sum += *s++;
+ }
+ /* Remove the effects of the checksum field (replace
+ * with blanks for the purposes of the checksum) */
+ s = rawHeader->chksum;
+ for (i = sizeof(rawHeader->chksum) ; i-- != 0;) {
+ sum -= *s++;
+ }
+ sum += ' ' * sizeof(rawHeader->chksum);
if (sum == chksum )
return ( TRUE);
return( FALSE);
@@ -511,7 +536,6 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag,
int errorFlag=FALSE;
TarHeader rawHeader;
TarInfo header;
- int alreadyWarned=FALSE;
//int skipFileFlag=FALSE;
/* Open the tar file for reading. */
@@ -545,18 +569,6 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag,
if ( *(header.name) == '\0' )
goto endgame;
- /* Check for and relativify any absolute paths */
- if ( *(header.name) == '/' ) {
-
- while (*(header.name) == '/')
- ++*(header.name);
-
- if (alreadyWarned == FALSE) {
- errorMsg("Absolute path detected, removing leading slashes\n");
- alreadyWarned = TRUE;
- }
- }
-
/* Special treatment if the list (-t) flag is on */
if (verboseFlag == TRUE && extractFlag == FALSE) {
int len, len1;
@@ -751,13 +763,14 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st
errorMsg("tar: Removing leading '/' from member names\n");
alreadyWarned=TRUE;
}
- strcpy(header.name, fileName+1);
+ strncpy(header.name, fileName+1, sizeof(header.name));
}
else {
- strcpy(header.name, fileName);
+ strncpy(header.name, fileName, sizeof(header.name));
}
-#if 0
- /* Now that leading '/''s have been removed */
+
+ /* Now that leading '/''s have been removed,
+ * check for excluded files.... */
for (tmpList=tbInfo->excludeList; tmpList && *tmpList; tmpList++) {
printf( "comparing '%s' and '%s'", *tmpList, header.name);
if (strcmp( *tmpList, header.name)==0)
@@ -765,7 +778,6 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st
else
printf( "\n");
}
-#endif
putOctal(header.mode, sizeof(header.mode), statbuf->st_mode);
putOctal(header.uid, sizeof(header.uid), statbuf->st_uid);
@@ -775,15 +787,15 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st
strncpy(header.magic, TAR_MAGIC TAR_VERSION,
TAR_MAGIC_LEN + TAR_VERSION_LEN );
+ /* Enter the user and group names (default to root if it fails) */
my_getpwuid(header.uname, statbuf->st_uid);
- /* Put some sort of sane fallback in place... */
if (! *header.uname)
- strncpy(header.uname, "root", 5);
+ strcpy(header.uname, "root");
my_getgrgid(header.gname, statbuf->st_gid);
if (! *header.uname)
- strncpy(header.uname, "root", 5);
+ strcpy(header.uname, "root");
- // FIXME: (or most likely not) I break Hard Links
+ // FIXME (or most likely not): I break Hard Links
if (S_ISLNK(statbuf->st_mode)) {
char buffer[BUFSIZ];
header.typeflag = SYMTYPE;
@@ -791,7 +803,17 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st
errorMsg("Error reading symlink '%s': %s\n", header.name, strerror(errno));
return ( FALSE);
}
- strncpy(header.linkname, buffer, sizeof(header.linkname));
+ if (*buffer=='/') {
+ static int alreadyWarned=FALSE;
+ if (alreadyWarned==FALSE) {
+ errorMsg("tar: Removing leading '/' from link names\n");
+ alreadyWarned=TRUE;
+ }
+ strncpy(header.linkname, buffer+1, sizeof(header.linkname));
+ }
+ else {
+ strncpy(header.linkname, buffer, sizeof(header.linkname));
+ }
} else if (S_ISDIR(statbuf->st_mode)) {
header.typeflag = DIRTYPE;
strncat(header.name, "/", sizeof(header.name));