From ce5b466bcce4edbd8a57ed3fa91911936bd11927 Mon Sep 17 00:00:00 2001
From: Erik Andersen <andersen@codepoet.org>
Date: Thu, 27 Jan 2000 19:50:47 +0000
Subject: copyFile could call chmod on a symlink, changing the perms of the
 pointed to file.  Minor fix to tar for directory handling.  -Erik

---
 Changelog      |  8 ++++++--
 archival/tar.c |  1 +
 tar.c          |  1 +
 utility.c      | 26 +++++++++++++-------------
 4 files changed, 21 insertions(+), 15 deletions(-)

diff --git a/Changelog b/Changelog
index 8dc40ca83..6581b5c90 100644
--- a/Changelog
+++ b/Changelog
@@ -25,7 +25,8 @@
 	    contributed Friedrich Vedder <fwv@myrtle.lahn.de>
 	* Cosmetic fix to busybox.c (Don't print a comma at the
 	    end of line if there are no more application names).
-	* Fixed a stupid bug in "head" option handling ("head -n" would segfault).
+	* Fixed a stupid bug in "head" option handling ("head -n" 
+	    would segfault).
 	* Moved commonly used functions "xmalloc()" and "exit()"
 	    to utility.c (with proper #ifdef's).
 	* Created a tiny tail implementation, removing -c, -q, -v, and making
@@ -37,7 +38,10 @@
 	* Fixed mount and umount.  Previously they could leak loop device 
 	    allocations, causing the system to quickly run out.  Fix for umount
 	    by Ben Collins <bcollins@debian.org>, and mount was fixed by me.
-	* ls formatting on 8 char user names fixed by Randolph Chung <tausq@debian.org>.
+	* ls formatting on eight charactor user names fixed by 
+	    Randolph Chung <tausq@debian.org>.
+	* cp could, when copying symlinks, change permissions of the
+	    files pointed to by the symlinks.
 
 
 	-Erik Andersen
diff --git a/archival/tar.c b/archival/tar.c
index aedb36a23..0fa09ffd8 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -596,6 +596,7 @@ readHeader (const TarHeader * hp, int fileCount, char **fileTable)
 	    chmod(outName, mode);
 	    return;
 	}
+	return;
     }
 
     /* 
diff --git a/tar.c b/tar.c
index aedb36a23..0fa09ffd8 100644
--- a/tar.c
+++ b/tar.c
@@ -596,6 +596,7 @@ readHeader (const TarHeader * hp, int fileCount, char **fileTable)
 	    chmod(outName, mode);
 	    return;
 	}
+	return;
     }
 
     /* 
diff --git a/utility.c b/utility.c
index 5ff03d7a0..69637c475 100644
--- a/utility.c
+++ b/utility.c
@@ -131,6 +131,7 @@ copyFile( const char *srcName, const char *destName,
     struct stat dstStatBuf;
     struct utimbuf times;
 
+    /* Grab the source file's stats */
     if (followLinks == FALSE)
 	result = stat(srcName, &srcStatBuf);
     else 
@@ -140,6 +141,7 @@ copyFile( const char *srcName, const char *destName,
 	return FALSE;
     }
 
+    /* Grab the dest file's stats */
     if (followLinks == FALSE)
 	result = stat(destName, &dstStatBuf);
     else 
@@ -223,18 +225,18 @@ copyFile( const char *srcName, const char *destName,
     }
 
     if (setModes == TRUE) {
-	//fprintf(stderr, "Setting permissions for %s\n", destName);
-	chmod(destName, srcStatBuf.st_mode);
+	if (! S_ISLNK(srcStatBuf.st_mode)) {
+	    chown(destName, srcStatBuf.st_uid, srcStatBuf.st_gid);
+	    /* Never chmod a symlink; it follows the link */
+	    chmod(destName, srcStatBuf.st_mode);
+	}
 #if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
-	if (followLinks == FALSE)
+	else { 
 	    lchown(destName, srcStatBuf.st_uid, srcStatBuf.st_gid);
-	else
+	}
 #endif
-	    chown(destName, srcStatBuf.st_uid, srcStatBuf.st_gid);
-
 	times.actime = srcStatBuf.st_atime;
 	times.modtime = srcStatBuf.st_mtime;
-
 	utime(destName, &times);
     }
 
@@ -414,6 +416,7 @@ recursiveAction(const char *fileName, int recurse, int followLinks, int depthFir
 	status = lstat(fileName, &statbuf);
 
     if (status < 0) {
+	fprintf(stderr, "status=%d followLinks=%d TRUE=%d\n", status, followLinks, TRUE);
 	perror(fileName);
 	return (FALSE);
     }
@@ -515,14 +518,11 @@ extern int createPath (const char *name, int mode)
 	cp = strchr (cp + 1, '/');
 	*cpOld = '\0';
 	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) {
+	if (retVal != 0 && errno != EEXIST) {
+	    perror( buf);
 	    return( FALSE);
 	}
+	*cpOld = '/';
     }
     return( TRUE);
 }
-- 
cgit v1.2.3