diff options
author | Pádraig Brady <P@draigBrady.com> | 2022-04-10 16:59:40 +0100 |
---|---|---|
committer | Pádraig Brady <P@draigBrady.com> | 2022-04-13 00:37:12 +0100 |
commit | 52139fd69034446695af60c8064a38e5e795227c (patch) | |
tree | 4cae09f5104ba1341d4517c85851a5be3e3ea675 | |
parent | 6e9bf0765fb8931eddfd17736cb0554192c26fad (diff) | |
download | coreutils-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-- | NEWS | 5 | ||||
-rw-r--r-- | src/system.h | 18 |
2 files changed, 11 insertions, 12 deletions
@@ -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) |