Fix a bug where tar could change perms and ownership of dirs pointed
authorErik Andersen <andersen@codepoet.org>
Sun, 23 Jan 2000 02:14:20 +0000 (02:14 -0000)
committerErik Andersen <andersen@codepoet.org>
Sun, 23 Jan 2000 02:14:20 +0000 (02:14 -0000)
to by symlink within a tarball.
 -Erik

Changelog
archival/tar.c
internal.h
tar.c
utility.c

index 4b65b3b27924612efc31c3c41822fc3671f71fa1..aa56355c188c7a860b40fede2d4bd66ae55e0b59 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -1,6 +1,8 @@
 0.42
        * Made tar creation support in busybox tar optional.
-       You no longer _have_ to put a "-" in front of tar options.
+       * You no longer _have_ to put a "-" in front of tar options.
+       * Tar could inadvertently change permissions and ownership on
+           certain directories pointed to by symlinks.
        * Made grep and grep -h do the right thing wrt printing
            the file name (it failed to print files names in many cases).
        * Fix a namespace aliasing problem wereby if du was built in, the 
index adae6c94c842bb64e5d20c29869e41c4d6bdb0da..21ef24dcbc7f9530ad7c854ff2067c3e821dd19b 100644 (file)
@@ -542,8 +542,10 @@ readHeader (const TarHeader * hp, int fileCount, char **fileTable)
        printf ("x %s\n", outName);
 
     if (hardLink) {
-       if (link (hp->linkName, outName) < 0)
+       if (link (hp->linkName, outName) < 0) {
            perror (outName);
+           return;
+       }
        /* Set the file time */
        utb.actime = mtime;
        utb.modtime = mtime;
@@ -556,8 +558,10 @@ readHeader (const TarHeader * hp, int fileCount, char **fileTable)
 
     if (softLink) {
 #ifdef S_ISLNK
-       if (symlink (hp->linkName, outName) < 0)
+       if (symlink (hp->linkName, outName) < 0) {
            perror (outName);
+           return;
+       }
        /* Try to change ownership of the symlink.
         * If libs doesn't support that, don't bother.
         * Changing the pointed-to file is the Wrong Thing(tm).
@@ -582,15 +586,16 @@ readHeader (const TarHeader * hp, int fileCount, char **fileTable)
      * If the file is a directory, then just create the path.
      */
     if (S_ISDIR (mode)) {
-       createPath (outName, mode);
-       /* Set the file time */
-       utb.actime = mtime;
-       utb.modtime = mtime;
-       utime (outName, &utb);
-       /* Set the file permissions */
-       chown(outName, uid, gid);
-       chmod(outName, mode);
-       return;
+       if (createPath (outName, mode)==TRUE) { 
+           /* Set the file time */
+           utb.actime = mtime;
+           utb.modtime = mtime;
+           utime (outName, &utb);
+           /* Set the file permissions */
+           chown(outName, uid, gid);
+           chmod(outName, mode);
+           return;
+       }
     }
 
     /* 
index e57096d4aa37be3fc1764d8ca4019ea91b8f619b..2b07d672d20745c7d1c4f5e456da83cbecf7790e 100644 (file)
@@ -156,7 +156,7 @@ int recursiveAction(const char *fileName, int recurse, int followLinks, int dept
          int (*dirAction) (const char *fileName, struct stat* statbuf));
 const char* timeString(time_t timeVal);
 
-extern void createPath (const char *name, int mode);
+extern int createPath (const char *name, int mode);
 extern int parse_mode( const char* s, mode_t* theMode);
 extern void usage(const char *usage) __attribute__ ((noreturn));
 
diff --git a/tar.c b/tar.c
index adae6c94c842bb64e5d20c29869e41c4d6bdb0da..21ef24dcbc7f9530ad7c854ff2067c3e821dd19b 100644 (file)
--- a/tar.c
+++ b/tar.c
@@ -542,8 +542,10 @@ readHeader (const TarHeader * hp, int fileCount, char **fileTable)
        printf ("x %s\n", outName);
 
     if (hardLink) {
-       if (link (hp->linkName, outName) < 0)
+       if (link (hp->linkName, outName) < 0) {
            perror (outName);
+           return;
+       }
        /* Set the file time */
        utb.actime = mtime;
        utb.modtime = mtime;
@@ -556,8 +558,10 @@ readHeader (const TarHeader * hp, int fileCount, char **fileTable)
 
     if (softLink) {
 #ifdef S_ISLNK
-       if (symlink (hp->linkName, outName) < 0)
+       if (symlink (hp->linkName, outName) < 0) {
            perror (outName);
+           return;
+       }
        /* Try to change ownership of the symlink.
         * If libs doesn't support that, don't bother.
         * Changing the pointed-to file is the Wrong Thing(tm).
@@ -582,15 +586,16 @@ readHeader (const TarHeader * hp, int fileCount, char **fileTable)
      * If the file is a directory, then just create the path.
      */
     if (S_ISDIR (mode)) {
-       createPath (outName, mode);
-       /* Set the file time */
-       utb.actime = mtime;
-       utb.modtime = mtime;
-       utime (outName, &utb);
-       /* Set the file permissions */
-       chown(outName, uid, gid);
-       chmod(outName, mode);
-       return;
+       if (createPath (outName, mode)==TRUE) { 
+           /* Set the file time */
+           utb.actime = mtime;
+           utb.modtime = mtime;
+           utime (outName, &utb);
+           /* Set the file permissions */
+           chown(outName, uid, gid);
+           chmod(outName, mode);
+           return;
+       }
     }
 
     /* 
index ade47bde0906d30edff5880cb9ef8e52d207b1c1..4b67ce9b753dcd9f077d64a4b82d1f5ce6adbeb1 100644 (file)
--- a/utility.c
+++ b/utility.c
@@ -495,11 +495,12 @@ recursiveAction(const char *fileName, int recurse, int followLinks, int depthFir
  * while all previous ones get default protections.  Errors are not reported
  * here, as failures to restore files can be reported later.
  */
-extern void createPath (const char *name, int mode)
+extern int createPath (const char *name, int mode)
 {
     char *cp;
     char *cpOld;
     char buf[NAME_MAX];
+    int retVal=0;
 
     strcpy( buf, name);
     cp = strchr (buf, '/');
@@ -507,9 +508,17 @@ extern void createPath (const char *name, int mode)
        cpOld = cp;
        cp = strchr (cp + 1, '/');
        *cpOld = '\0';
-       mkdir (buf, cp ? 0777 : mode);
+       retVal = mkdir (buf, cp ? 0777 : mode);
        *cpOld = '/';
     }
+    /* Return the result from the final directory, as that
+     * is the one that counts */
+    if( retVal!=0) {
+       if ( errno!=EEXIST) {
+           return( FALSE);
+       }
+    }
+    return( TRUE);
 }
 #endif