From a1f977598138ebf8f5f1672daa936255cf3affc1 Mon Sep 17 00:00:00 2001 From: Matt Kraai Date: Tue, 19 Dec 2000 06:24:08 +0000 Subject: [PATCH] Fix tar handling of absolute paths and excluded directories. --- archival/tar.c | 66 +++++++++++++++++++++++------------------------ busybox.h | 1 + include/busybox.h | 1 + tar.c | 66 +++++++++++++++++++++++------------------------ utility.c | 13 +++++----- 5 files changed, 73 insertions(+), 74 deletions(-) diff --git a/archival/tar.c b/archival/tar.c index c6a2a6627..463cc50c7 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -252,8 +252,8 @@ extern int tar_main(int argc, char **argv) if (excludeList[excludeListSize] == NULL) error_msg_and_die( "Option requires an argument: No file specified\n"); /* Remove leading "/"s */ - if (*excludeList[excludeListSize] =='/') - excludeList[excludeListSize] = (excludeList[excludeListSize])+1; + while (*excludeList[excludeListSize] =='/') + excludeList[excludeListSize]++; /* Tack a NULL onto the end of the list */ excludeList[++excludeListSize] = NULL; stopIt=TRUE; @@ -940,43 +940,12 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st { long chksum=0; struct TarHeader header; -#if defined BB_FEATURE_TAR_EXCLUDE - char** tmpList; -#endif const unsigned char *cp = (const unsigned char *) &header; ssize_t size = sizeof(struct TarHeader); memset( &header, 0, size); - if (*fileName=='/') { - static int alreadyWarned=FALSE; - if (alreadyWarned==FALSE) { - error_msg("Removing leading '/' from member names\n"); - alreadyWarned=TRUE; - } - strncpy(header.name, fileName+1, sizeof(header.name)); - } - else { - strncpy(header.name, fileName, sizeof(header.name)); - } - -#if defined BB_FEATURE_TAR_EXCLUDE - /* Check for excluded files.... */ - for (tmpList=tbInfo->excludeList; tmpList && *tmpList; tmpList++) { - /* Do some extra hoop jumping for when directory names - * end in '/' but the entry in tmpList doesn't */ - if (strncmp( *tmpList, header.name, strlen(*tmpList))==0 || ( - header.name[strlen(header.name)-1]=='/' - && strncmp( *tmpList, header.name, - MIN(strlen(header.name)-1, strlen(*tmpList)))==0)) { - /* Set the mode to something that is not a regular file, thereby - * faking out writeTarFile into thinking that nothing further need - * be done for this file. Yes, I know this is ugly, but it works. */ - statbuf->st_mode = 0; - return( TRUE); - } - } -#endif + strncpy(header.name, fileName, sizeof(header.name)); putOctal(header.mode, sizeof(header.mode), statbuf->st_mode); putOctal(header.uid, sizeof(header.uid), statbuf->st_uid); @@ -1065,6 +1034,9 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* userData) { struct TarBallInfo *tbInfo = (struct TarBallInfo *)userData; +#if defined BB_FEATURE_TAR_EXCLUDE + char** tmpList; +#endif /* ** Check to see if we are dealing with a hard link. @@ -1097,11 +1069,37 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* return( TRUE); } + while (fileName[0] == '/') { + static int alreadyWarned=FALSE; + if (alreadyWarned==FALSE) { + error_msg("Removing leading '/' from member names\n"); + alreadyWarned=TRUE; + } + fileName++; + } + if (strlen(fileName) >= NAME_SIZE) { error_msg(name_longer_than_foo, NAME_SIZE); return ( TRUE); } + if (fileName[0] == '\0') + return TRUE; + +#if defined BB_FEATURE_TAR_EXCLUDE + /* Check for excluded files.... */ + for (tmpList=tbInfo->excludeList; tmpList && *tmpList; tmpList++) { + /* Do some extra hoop jumping for when directory names + * end in '/' but the entry in tmpList doesn't */ + if (strncmp( *tmpList, fileName, strlen(*tmpList))==0 || ( + fileName[strlen(fileName)-1]=='/' + && strncmp( *tmpList, fileName, + MIN(strlen(fileName)-1, strlen(*tmpList)))==0)) { + return SKIP; + } + } +#endif + if (writeTarHeader(tbInfo, fileName, statbuf)==FALSE) { return( FALSE); } diff --git a/busybox.h b/busybox.h index 442352537..ae256fe7b 100644 --- a/busybox.h +++ b/busybox.h @@ -47,6 +47,7 @@ /* Some useful definitions */ #define FALSE ((int) 0) #define TRUE ((int) 1) +#define SKIP ((int) 2) /* for mtab.c */ #define MTAB_GETMOUNTPT '1' diff --git a/include/busybox.h b/include/busybox.h index 442352537..ae256fe7b 100644 --- a/include/busybox.h +++ b/include/busybox.h @@ -47,6 +47,7 @@ /* Some useful definitions */ #define FALSE ((int) 0) #define TRUE ((int) 1) +#define SKIP ((int) 2) /* for mtab.c */ #define MTAB_GETMOUNTPT '1' diff --git a/tar.c b/tar.c index c6a2a6627..463cc50c7 100644 --- a/tar.c +++ b/tar.c @@ -252,8 +252,8 @@ extern int tar_main(int argc, char **argv) if (excludeList[excludeListSize] == NULL) error_msg_and_die( "Option requires an argument: No file specified\n"); /* Remove leading "/"s */ - if (*excludeList[excludeListSize] =='/') - excludeList[excludeListSize] = (excludeList[excludeListSize])+1; + while (*excludeList[excludeListSize] =='/') + excludeList[excludeListSize]++; /* Tack a NULL onto the end of the list */ excludeList[++excludeListSize] = NULL; stopIt=TRUE; @@ -940,43 +940,12 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st { long chksum=0; struct TarHeader header; -#if defined BB_FEATURE_TAR_EXCLUDE - char** tmpList; -#endif const unsigned char *cp = (const unsigned char *) &header; ssize_t size = sizeof(struct TarHeader); memset( &header, 0, size); - if (*fileName=='/') { - static int alreadyWarned=FALSE; - if (alreadyWarned==FALSE) { - error_msg("Removing leading '/' from member names\n"); - alreadyWarned=TRUE; - } - strncpy(header.name, fileName+1, sizeof(header.name)); - } - else { - strncpy(header.name, fileName, sizeof(header.name)); - } - -#if defined BB_FEATURE_TAR_EXCLUDE - /* Check for excluded files.... */ - for (tmpList=tbInfo->excludeList; tmpList && *tmpList; tmpList++) { - /* Do some extra hoop jumping for when directory names - * end in '/' but the entry in tmpList doesn't */ - if (strncmp( *tmpList, header.name, strlen(*tmpList))==0 || ( - header.name[strlen(header.name)-1]=='/' - && strncmp( *tmpList, header.name, - MIN(strlen(header.name)-1, strlen(*tmpList)))==0)) { - /* Set the mode to something that is not a regular file, thereby - * faking out writeTarFile into thinking that nothing further need - * be done for this file. Yes, I know this is ugly, but it works. */ - statbuf->st_mode = 0; - return( TRUE); - } - } -#endif + strncpy(header.name, fileName, sizeof(header.name)); putOctal(header.mode, sizeof(header.mode), statbuf->st_mode); putOctal(header.uid, sizeof(header.uid), statbuf->st_uid); @@ -1065,6 +1034,9 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* userData) { struct TarBallInfo *tbInfo = (struct TarBallInfo *)userData; +#if defined BB_FEATURE_TAR_EXCLUDE + char** tmpList; +#endif /* ** Check to see if we are dealing with a hard link. @@ -1097,11 +1069,37 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* return( TRUE); } + while (fileName[0] == '/') { + static int alreadyWarned=FALSE; + if (alreadyWarned==FALSE) { + error_msg("Removing leading '/' from member names\n"); + alreadyWarned=TRUE; + } + fileName++; + } + if (strlen(fileName) >= NAME_SIZE) { error_msg(name_longer_than_foo, NAME_SIZE); return ( TRUE); } + if (fileName[0] == '\0') + return TRUE; + +#if defined BB_FEATURE_TAR_EXCLUDE + /* Check for excluded files.... */ + for (tmpList=tbInfo->excludeList; tmpList && *tmpList; tmpList++) { + /* Do some extra hoop jumping for when directory names + * end in '/' but the entry in tmpList doesn't */ + if (strncmp( *tmpList, fileName, strlen(*tmpList))==0 || ( + fileName[strlen(fileName)-1]=='/' + && strncmp( *tmpList, fileName, + MIN(strlen(fileName)-1, strlen(*tmpList)))==0)) { + return SKIP; + } + } +#endif + if (writeTarHeader(tbInfo, fileName, statbuf)==FALSE) { return( FALSE); } diff --git a/utility.c b/utility.c index 34341c8d3..b06abf464 100644 --- a/utility.c +++ b/utility.c @@ -663,17 +663,18 @@ int recursive_action(const char *fileName, if (S_ISDIR(statbuf.st_mode)) { DIR *dir; - dir = opendir(fileName); - if (!dir) { - perror_msg("%s", fileName); - return FALSE; - } if (dirAction != NULL && depthFirst == FALSE) { status = dirAction(fileName, &statbuf, userData); if (status == FALSE) { perror_msg("%s", fileName); return FALSE; - } + } else if (status == SKIP) + return TRUE; + } + dir = opendir(fileName); + if (!dir) { + perror_msg("%s", fileName); + return FALSE; } while ((next = readdir(dir)) != NULL) { char nextFile[BUFSIZ + 1];