aboutsummaryrefslogtreecommitdiff
path: root/toys/posix/cp.c
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2013-01-18 06:03:00 -0600
committerRob Landley <rob@landley.net>2013-01-18 06:03:00 -0600
commit5ddc31287f78f3ca69d30e46dd1ec1a000f7dec7 (patch)
tree7766cc2f80fefdc1b33c272da555f4b149cdc7be /toys/posix/cp.c
parent3a99aef5072b6bdc50be26c23d49d5260042e385 (diff)
downloadtoybox-5ddc31287f78f3ca69d30e46dd1ec1a000f7dec7.tar.gz
Adjust umask(0) for cp -p so mknod doesn't have to try to fchmodat() without the unsupported symlink nofollow flag.0.4.3
Diffstat (limited to 'toys/posix/cp.c')
-rw-r--r--toys/posix/cp.c36
1 files changed, 19 insertions, 17 deletions
diff --git a/toys/posix/cp.c b/toys/posix/cp.c
index 55f4fe71..94b134aa 100644
--- a/toys/posix/cp.c
+++ b/toys/posix/cp.c
@@ -131,15 +131,16 @@ int cp_node(struct dirtree *try)
} else if (!S_ISREG(try->st.st_mode)
&& (try->parent || (flags & (FLAG_a|FLAG_r))))
{
- // symlink
- if (S_ISLNK(try->st.st_mode)) {
- int i = readlinkat(tfd, try->name, toybuf, sizeof(toybuf));
- if (i < 1 || i >= sizeof(toybuf)) break;
- else if (!symlinkat(toybuf, cfd, catch)) err = 0;
- // block, char, fifo, socket
- } else if (!mknodat(cfd, catch, try->st.st_mode, try->st.st_rdev)) {
- err = 0;
- if (flags & (FLAG_a|FLAG_p)) fdout = AT_FDCWD;
+ int i;
+
+ // make symlink, or make block/char/fifo/socket
+ if (S_ISLNK(try->st.st_mode)
+ ? (0 < (i = readlinkat(tfd, try->name, toybuf, sizeof(toybuf))) &&
+ sizeof(toybuf) > i && !symlinkat(toybuf, cfd, catch))
+ : !mknodat(cfd, catch, try->st.st_mode, try->st.st_rdev))
+ {
+ err = 0;
+ fdout = AT_FDCWD;
}
// Copy contents of file.
@@ -173,15 +174,14 @@ int cp_node(struct dirtree *try)
// If we can't get a filehandle to the actual object, use racy functions
if (fdout == AT_FDCWD) {
- if (fchownat(cfd, catch, try->st.st_uid, try->st.st_gid,
- AT_SYMLINK_NOFOLLOW)
- || utimensat(cfd, catch, times, AT_SYMLINK_NOFOLLOW)
- || fchmodat(cfd, catch, try->st.st_mode&07777, 0))
- err = "%s";
+ fchownat(cfd, catch, try->st.st_uid, try->st.st_gid,
+ AT_SYMLINK_NOFOLLOW);
+ utimensat(cfd, catch, times, AT_SYMLINK_NOFOLLOW);
+ // permission bits already correct for mknod, don't apply to symlink
} else {
- if (fchown(fdout, try->st.st_uid, try->st.st_gid)
- || futimens(fdout, times) || fchmod(fdout, try->st.st_mode&07777))
- err = "%s";
+ fchown(fdout, try->st.st_uid, try->st.st_gid);
+ futimens(fdout, times);
+ fchmod(fdout, try->st.st_mode);
}
}
@@ -199,6 +199,8 @@ void cp_main(void)
if (toys.optc>1 && !destdir) error_exit("'%s' not directory", destname);
+ if (toys.optflags & (FLAG_a|FLAG_p)) umask(0);
+
// Loop through sources
for (i=0; i<toys.optc; i++) {