Fix tar handling of absolute paths and excluded directories.
authorMatt Kraai <kraai@debian.org>
Tue, 19 Dec 2000 06:24:08 +0000 (06:24 -0000)
committerMatt Kraai <kraai@debian.org>
Tue, 19 Dec 2000 06:24:08 +0000 (06:24 -0000)
archival/tar.c
busybox.h
include/busybox.h
tar.c
utility.c

index c6a2a6627fe29555403503d20b8bc92cda93603f..463cc50c7450b4111ebf86413748b3d595115ef1 100644 (file)
@@ -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);
        } 
index 442352537956a9b3cf98d97aee086d4a63055373..ae256fe7be4dacdab1bacd6370ddf3b1147d495a 100644 (file)
--- 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'
index 442352537956a9b3cf98d97aee086d4a63055373..ae256fe7be4dacdab1bacd6370ddf3b1147d495a 100644 (file)
@@ -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 c6a2a6627fe29555403503d20b8bc92cda93603f..463cc50c7450b4111ebf86413748b3d595115ef1 100644 (file)
--- 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);
        } 
index 34341c8d32c5d19bafed8ac6584ba392dae5b928..b06abf4648da8df16d50e6250ac7ae2585b397af 100644 (file)
--- 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];