diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2006-03-08 18:57:39 +0000 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2006-03-08 18:57:39 +0000 |
commit | cf40950274fc2e1cd3d827710ccfd352c614b12d (patch) | |
tree | e2c85816c95b84c85bfefb7f1d93fbe6d31e8681 | |
parent | e190228997c9f33137977ed945d55bd37c1058d6 (diff) | |
download | coreutils-cf40950274fc2e1cd3d827710ccfd352c614b12d.tar.xz |
(set_fd_flags): Handle file-creation flags on file
descriptors, rather than ignoring them.
-rw-r--r-- | src/dd.c | 36 |
1 files changed, 34 insertions, 2 deletions
@@ -1325,12 +1325,44 @@ copy_with_unblock (char const *buf, size_t nread) static void set_fd_flags (int fd, int add_flags, char const *name) { + /* Ignore file creation flags that are no-ops on file descriptors. */ + add_flags &= ~ (O_NOCTTY | O_NOFOLLOW); + if (add_flags) { int old_flags = fcntl (fd, F_GETFL); int new_flags = old_flags | add_flags; - if (old_flags < 0 - || (new_flags != old_flags && fcntl (fd, F_SETFL, new_flags) == -1)) + bool ok = true; + if (old_flags < 0) + ok = false; + else if (old_flags != new_flags) + { + if (new_flags & (O_DIRECTORY | O_NOLINKS)) + { + /* NEW_FLAGS contains at least one file creation flag that + requires some checking of the open file descriptor. */ + struct stat st; + if (fstat (fd, &st) != 0) + ok = false; + else if ((new_flags & O_DIRECTORY) && ! S_ISDIR (st.st_mode)) + { + errno = ENOTDIR; + ok = false; + } + else if ((new_flags & O_NOLINKS) && 1 < st.st_nlink) + { + errno = EMLINK; + ok = false; + } + new_flags &= ~ (O_DIRECTORY | O_NOLINKS); + } + + if (ok && old_flags != new_flags + && fcntl (fd, F_SETFL, new_flags) == -1) + ok = false; + } + + if (!ok) error (EXIT_FAILURE, errno, _("setting flags for %s"), quote (name)); } } |