summaryrefslogtreecommitdiffstats
path: root/bin
diff options
context:
space:
mode:
authormckay <mckay@FreeBSD.org>2001-12-11 13:18:10 +0000
committermckay <mckay@FreeBSD.org>2001-12-11 13:18:10 +0000
commita6a1f2b728695247ffe0ffb64f387726737e3894 (patch)
treeb1d1f24b5d1e5e3e6a15c55735b04e9dc4b26478 /bin
parent46e660813b1062946c620efd70dfa17841e3fc6a (diff)
downloadFreeBSD-src-a6a1f2b728695247ffe0ffb64f387726737e3894.zip
FreeBSD-src-a6a1f2b728695247ffe0ffb64f387726737e3894.tar.gz
Preserve directory timestamps with -p. Allow non-empty read-only
directories to be copied. Apply umask to newly created directories when -p is not specified. PR: 27970 PR: 31633 MFC after: 4 days
Diffstat (limited to 'bin')
-rw-r--r--bin/cp/cp.c50
1 files changed, 39 insertions, 11 deletions
diff --git a/bin/cp/cp.c b/bin/cp/cp.c
index 3fe4af4..e48830d 100644
--- a/bin/cp/cp.c
+++ b/bin/cp/cp.c
@@ -248,6 +248,14 @@ copy(argv, type, fts_options)
FTSENT *curr;
int base = 0, dne, badcp, nlen, rval;
char *p, *target_mid;
+ mode_t mask;
+
+ /*
+ * Keep an inverted copy of the umask, for use in correcting
+ * permissions on created directories when not using -p.
+ */
+ mask = ~umask(0777);
+ umask(~mask);
if ((ftsp = fts_open(argv, fts_options, mastercmp)) == NULL)
err(1, NULL);
@@ -264,8 +272,6 @@ copy(argv, type, fts_options)
warnx("%s: directory causes a cycle", curr->fts_path);
badcp = rval = 1;
continue;
- case FTS_DP: /* Ignore, continue. */
- continue;
}
/*
@@ -323,6 +329,25 @@ copy(argv, type, fts_options)
STRIP_TRAILING_SLASH(to);
}
+ if (curr->fts_info == FTS_DP) {
+ /*
+ * We are finished copying to this directory. If
+ * -p is in effect, set permissions and timestamps.
+ * Otherwise, if we created this directory, set the
+ * correct permissions, limited by the umask.
+ */
+ if (pflag)
+ rval = setfile(curr->fts_statp, 0);
+ else if (curr->fts_number) {
+ mode_t perm = curr->fts_statp->st_mode & mask;
+ if (chmod(to.p_path, perm)) {
+ warn("chmod: %s", to.p_path);
+ rval = 1;
+ }
+ }
+ continue;
+ }
+
/* Not an error but need to remember it happened */
if (stat(to.p_path, &to_stat) == -1)
dne = 1;
@@ -376,16 +401,19 @@ copy(argv, type, fts_options)
err(1, "%s", to.p_path);
}
/*
- * If not -p and directory didn't exist, set it to be
- * the same as the from directory, umodified by the
- * umask; arguably wrong, but it's been that way
- * forever.
+ * Arrange to correct directory permissions later
+ * (in the post-order phase) if this is a new
+ * directory and the permissions aren't the final
+ * ones we want yet. Note that mkdir() does not
+ * honour setuid, setgid nor sticky bits, but we
+ * normally want to preserve them on directories.
*/
- if (pflag && setfile(curr->fts_statp, 0))
- badcp = rval = 1;
- else if (dne)
- (void)chmod(to.p_path,
- curr->fts_statp->st_mode);
+ {
+ mode_t mode = curr->fts_statp->st_mode;
+ curr->fts_number = dne &&
+ ((mode & (S_ISUID|S_ISGID|S_ISTXT)) ||
+ ((mode | S_IRWXU) & mask) != (mode & mask));
+ }
break;
case S_IFBLK:
case S_IFCHR:
OpenPOWER on IntegriCloud