From cf40950274fc2e1cd3d827710ccfd352c614b12d Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 8 Mar 2006 18:57:39 +0000 Subject: (set_fd_flags): Handle file-creation flags on file descriptors, rather than ignoring them. --- src/dd.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/dd.c b/src/dd.c index b2bdf118c..b8512fbb5 100644 --- a/src/dd.c +++ b/src/dd.c @@ -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)); } } -- cgit v1.2.3-54-g00ecf