summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPádraig Brady <P@draigBrady.com>2022-04-10 16:59:40 +0100
committerPádraig Brady <P@draigBrady.com>2022-04-13 00:37:12 +0100
commit52139fd69034446695af60c8064a38e5e795227c (patch)
tree4cae09f5104ba1341d4517c85851a5be3e3ea675
parent6e9bf0765fb8931eddfd17736cb0554192c26fad (diff)
downloadcoreutils-52139fd69034446695af60c8064a38e5e795227c.tar.gz
cp,mv,install: avoid EACCES with non directory destination
* src/system.h (target_directory_operand): Also check with stat() on systems with O_SEARCH, to avoid open("file", O_SEARCH|O_DIRECTORY) returning EACCES rather than ENOTDIR, which was seen on Solaris 11.4 when operating on non dirs without execute bit set. * NEWS: Remove related bug entry, as that issue was only introduced after coreutils v9.0 was released. Reported by Bruno Haible.
-rw-r--r--NEWS5
-rw-r--r--src/system.h18
2 files changed, 11 insertions, 12 deletions
diff --git a/NEWS b/NEWS
index 69feffcbc..85fd5be12 100644
--- a/NEWS
+++ b/NEWS
@@ -21,11 +21,6 @@ GNU coreutils NEWS -*- outline -*-
and B is in some other file system.
[bug introduced in coreutils-9.0]
- cp, mv, and install, on older systems like Solaris 10 without O_DIRECTORY
- support, avoid opening non directory destination operands. Opening such
- files can have side effects, like hanging with a fifo for example.
- [bug introduced in coreutils-9.0]
-
On macOS, fmt no longer corrupts multi-byte characters
by misdetecting their component bytes as spaces.
[This bug was present in "the beginning".]
diff --git a/src/system.h b/src/system.h
index c24cb4dc3..768c3a1f2 100644
--- a/src/system.h
+++ b/src/system.h
@@ -137,19 +137,23 @@ target_directory_operand (char const *file)
return AT_FDCWD;
int fd = -1;
- bool is_a_dir = false;
+ int maybe_dir = -1;
struct stat st;
- /* On old systems like Solaris 10, check with stat first
- lest we try to open a fifo for example and hang. */
- if (!O_DIRECTORY && stat (file, &st) == 0)
+ /* On old systems without O_DIRECTORY, like Solaris 10,
+ check with stat first lest we try to open a fifo for example and hang.
+ Also check on systems with O_PATHSEARCH == O_SEARCH, like Solaris 11,
+ where open() was seen to return EACCES for non executable non dirs.
+ */
+ if ((!O_DIRECTORY || (O_PATHSEARCH == O_SEARCH))
+ && stat (file, &st) == 0)
{
- is_a_dir = !!S_ISDIR (st.st_mode);
- if (! is_a_dir)
+ maybe_dir = S_ISDIR (st.st_mode);
+ if (! maybe_dir)
errno = ENOTDIR;
}
- if (O_DIRECTORY || is_a_dir)
+ if (maybe_dir)
fd = open (file, O_PATHSEARCH | O_DIRECTORY);
if (!O_DIRECTORY && 0 <= fd)