aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog4
-rw-r--r--archival/tar.c27
-rw-r--r--internal.h2
-rw-r--r--tar.c27
-rw-r--r--utility.c13
5 files changed, 47 insertions, 26 deletions
diff --git a/Changelog b/Changelog
index 4b65b3b27..aa56355c1 100644
--- 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
diff --git a/archival/tar.c b/archival/tar.c
index adae6c94c..21ef24dcb 100644
--- a/archival/tar.c
+++ b/archival/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;
+ }
}
/*
diff --git a/internal.h b/internal.h
index e57096d4a..2b07d672d 100644
--- a/internal.h
+++ b/internal.h
@@ -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 adae6c94c..21ef24dcb 100644
--- 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;
+ }
}
/*
diff --git a/utility.c b/utility.c
index ade47bde0..4b67ce9b7 100644
--- 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