mirror of
git://git.sv.gnu.org/coreutils.git
synced 2026-07-26 02:30:35 +02:00
chmod: fix erroneous warnings with -R --changes
For files with "special" bits set, we would stat the relative file name in the wrong directory, giving an erroneous ENOENT diagnostic. This issue was introduced with commit v5.92-653-gc1994c1 which changed fts to not change directory on traversal. * src/chmod.c (mode_changed): Use fts->fts_cwd_fd with fstatat rather than stat. All callers changed. * tests/chmod/c-option.sh: Add a test case. * NEWS: Mention the fix. Fixes http://bugs.gnu.org/17035
This commit is contained in:
committed by
Pádraig Brady
parent
5b790fda0e
commit
09eda9ed9d
@@ -4,6 +4,9 @@ GNU coreutils NEWS -*- outline -*-
|
||||
|
||||
** Bug fixes
|
||||
|
||||
chmod -Rc no longer issues erroneous warnings for files with special bits set.
|
||||
[bug introduced in coreutils-6.0]
|
||||
|
||||
cp -a, mv, and install --preserve-context, once again set the correct SELinux
|
||||
context for existing directories in the destination. Previously they set
|
||||
the context of an existing directory to that of its last copied descendent.
|
||||
|
||||
+7
-4
@@ -111,7 +111,8 @@ static struct option const long_options[] =
|
||||
The old mode was OLD_MODE, but it was changed to NEW_MODE. */
|
||||
|
||||
static bool
|
||||
mode_changed (char const *file, mode_t old_mode, mode_t new_mode)
|
||||
mode_changed (int dir_fd, char const *file, char const *file_full_name,
|
||||
mode_t old_mode, mode_t new_mode)
|
||||
{
|
||||
if (new_mode & (S_ISUID | S_ISGID | S_ISVTX))
|
||||
{
|
||||
@@ -120,10 +121,11 @@ mode_changed (char const *file, mode_t old_mode, mode_t new_mode)
|
||||
|
||||
struct stat new_stats;
|
||||
|
||||
if (stat (file, &new_stats) != 0)
|
||||
if (fstatat (dir_fd, file, &new_stats, 0) != 0)
|
||||
{
|
||||
if (! force_silent)
|
||||
error (0, errno, _("getting new attributes of %s"), quote (file));
|
||||
error (0, errno, _("getting new attributes of %s"),
|
||||
quote (file_full_name));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -283,7 +285,8 @@ process_file (FTS *fts, FTSENT *ent)
|
||||
if (verbosity != V_off)
|
||||
{
|
||||
bool changed = (chmod_succeeded
|
||||
&& mode_changed (file, old_mode, new_mode));
|
||||
&& mode_changed (fts->fts_cwd_fd, file, file_full_name,
|
||||
old_mode, new_mode));
|
||||
|
||||
if (changed || verbosity == V_high)
|
||||
{
|
||||
|
||||
@@ -37,4 +37,15 @@ case "$(cat out)" in
|
||||
*) cat out; fail=1 ;;
|
||||
esac
|
||||
|
||||
# From V5.1.0 to 8.22 this would stat the wrong file and
|
||||
# give an erroneous ENOENT diagnostic
|
||||
mkdir -p a/b || framework_failure_
|
||||
# chmod g+s might fail as detailed in setgid.sh
|
||||
# but we don't care about those edge cases here
|
||||
chmod g+s a/b
|
||||
# This should never warn, but it did when special
|
||||
# bits are set on b (the common case under test)
|
||||
chmod -c -R g+w a 2>err
|
||||
compare /dev/null err || fail=1
|
||||
|
||||
Exit $fail
|
||||
|
||||
Reference in New Issue
Block a user