Fix a bug where tar could change perms and ownership of dirs pointed
to by symlink within a tarball. -Erik
This commit is contained in:
		@@ -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 
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* 
 | 
			
		||||
 
 | 
			
		||||
@@ -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));
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										27
									
								
								tar.c
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								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;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* 
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								utility.c
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user