From: Fabian Groffen Date: Sat, 13 Oct 2007 11:55:50 +0000 (-0000) Subject: Retain access and modification times for files and directories. X-Git-Url: http://git.tremily.us/gitweb.cgi?a=commitdiff_plain;h=99de99e0e81813cec06ff0c02f7b6401eea7eef6;p=portage.git Retain access and modification times for files and directories. svn path=/main/branches/prefix/; revision=8104 --- diff --git a/configure.in b/configure.in index 2b5bb6c58..196cd5eb7 100644 --- a/configure.in +++ b/configure.in @@ -48,8 +48,8 @@ GENTOO_PATH_GNUPROG(GREP, [grep]) dnl Checks for header files. AC_HEADER_STDC -AC_CHECK_HEADERS([string.h errno.h unistd.h stdio.h stdlib.h]) -AC_CHECK_HEADERS([sys/stat.h sys/types.h dirent.h]) +AC_CHECK_HEADERS([string.h strings.h errno.h unistd.h stdio.h stdlib.h]) +AC_CHECK_HEADERS([sys/stat.h sys/types.h dirent.h sys/time.h]) AC_CHECK_LIBS([readdir], [c]) AC_CHECK_LIBS([strcpy], [c]) diff --git a/src/chpathtool.c b/src/chpathtool.c index 99c568339..2388fa93b 100644 --- a/src/chpathtool.c +++ b/src/chpathtool.c @@ -21,6 +21,7 @@ #include #include #include +#include /* Don't allocate too much, or you'll be paying for waiting on IO, * size -1 to align in memory. */ @@ -160,25 +161,22 @@ int dirwalk(char *src, char *srcp, char *trg, char *trgp) { DIR *d; struct dirent *de; struct stat s; + struct timeval times[2]; char *st; char *tt; - if (stat(trg, &s) != 0) { - /* try to create the target directory, retaining attributes */ - if (stat(src, &s) != 0) { - fprintf(stderr, "cannot stat %s: %s\n", src, strerror(errno)); - return(-1); - } - if (mkdir(trg, s.st_mode) != 0) { + if (lstat(trg, &s) != 0) { + /* initially create directory read/writably by owner, set + * permissions like src when we're done processing this + * directory. */ + if (mkdir(trg, S_IRWXU) != 0) { fprintf(stderr, "failed to create directory %s: %s\n", trg, strerror(errno)); return(-1); } - if (lchown(trg, s.st_uid, s.st_gid) != 0) { - fprintf(stderr, "failed to set ownership of %s: %s\n", - trg, strerror(errno)); - return(-1); - } + } else { + fprintf(stderr, "directory already exists: %s\n", trg); + return(-1); } if ((d = opendir(src)) == NULL) { @@ -199,7 +197,7 @@ int dirwalk(char *src, char *srcp, char *trg, char *trgp) { st += 1 + strlen(de->d_name); tt += 1 + strlen(de->d_name); - if (stat(src, &s) != 0) { + if (lstat(src, &s) != 0) { fprintf(stderr, "cannot stat %s: %s\n", src, strerror(errno)); closedir(d); return(-1); @@ -229,7 +227,9 @@ int dirwalk(char *src, char *srcp, char *trg, char *trgp) { S_ISREG(s.st_mode) ) { - /* FIXME: handle hard links! */ + /* FIXME: handle hard links! (keep track of files with >1 + * refs, match those with a list of known files */ + /* copy */ if (chpath(src, trg) != 0) { closedir(d); @@ -251,6 +251,15 @@ int dirwalk(char *src, char *srcp, char *trg, char *trgp) { trg, strerror(errno)); return(-1); } + times[0].tv_sec = s.st_atimespec.tv_sec; + times[0].tv_usec = s.st_atimespec.tv_nsec; + times[1].tv_sec = s.st_mtimespec.tv_sec; + times[1].tv_usec = s.st_mtimespec.tv_nsec; + if (utimes(trg, times) != 0) { + fprintf(stderr, "failed to set utimes of %s: %s\n", + trg, strerror(errno)); + return(-1); + } } else if ( S_ISLNK(s.st_mode) ) @@ -260,10 +269,11 @@ int dirwalk(char *src, char *srcp, char *trg, char *trgp) { char *pb = buf; char *pr = rep; char *p = NULL; - int len = readlink(trg, buf, MAX_PATH - 1); + int len = readlink(src, buf, MAX_PATH - 1); buf[len] = '\0'; - /* replace occurences of magic by value in the string */ - while ((p = strstr(pb, magic)) != NULL) { + /* replace occurences of magic by value in the string if + * absolute */ + if (buf[0] == '/') while ((p = strstr(pb, magic)) != NULL) { memcpy(pr, pb, p - pb); pr += p - pb; memcpy(pr, value, valuelen); @@ -272,7 +282,23 @@ int dirwalk(char *src, char *srcp, char *trg, char *trgp) { } memcpy(pr, pb, (&buf[0] + len) - pb); - symlink(trg, rep); + if (symlink(rep, trg) != 0) { + fprintf(stderr, "failed to create symlink %s -> %s: %s\n", + trg, rep, strerror(errno)); + return(-1); + } + + /* fix permissions */ + if (stat(src, &s) != 0) { + fprintf(stderr, "cannot stat %s: %s\n", + src, strerror(errno)); + return(-1); + } + if (lchown(trg, s.st_uid, s.st_gid) != 0) { + fprintf(stderr, "failed to set ownership of %s: %s\n", + trg, strerror(errno)); + return(-1); + } } /* restore modified path */ @@ -282,6 +308,31 @@ int dirwalk(char *src, char *srcp, char *trg, char *trgp) { } closedir(d); + /* fix permissions/ownership etc. */ + if (stat(src, &s) != 0) { + fprintf(stderr, "cannot stat %s: %s\n", src, strerror(errno)); + return(-1); + } + if (chmod(trg, s.st_mode) != 0) { + fprintf(stderr, "failed to set permissions of %s: %s\n", + trg, strerror(errno)); + return(-1); + } + if (lchown(trg, s.st_uid, s.st_gid) != 0) { + fprintf(stderr, "failed to set ownership of %s: %s\n", + trg, strerror(errno)); + return(-1); + } + times[0].tv_sec = s.st_atimespec.tv_sec; + times[0].tv_usec = s.st_atimespec.tv_nsec; + times[1].tv_sec = s.st_mtimespec.tv_sec; + times[1].tv_usec = s.st_mtimespec.tv_nsec; + if (utimes(trg, times) != 0) { + fprintf(stderr, "failed to set utimes of %s: %s\n", + trg, strerror(errno)); + return(-1); + } + return(0); }