diff options
author | Rob Landley <rob@landley.net> | 2013-01-18 06:03:00 -0600 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2013-01-18 06:03:00 -0600 |
commit | 5ddc31287f78f3ca69d30e46dd1ec1a000f7dec7 (patch) | |
tree | 7766cc2f80fefdc1b33c272da555f4b149cdc7be /toys/posix/cp.c | |
parent | 3a99aef5072b6bdc50be26c23d49d5260042e385 (diff) | |
download | toybox-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.c | 36 |
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++) { |