summaryrefslogtreecommitdiff
path: root/src/chown-core.c
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2006-10-13 21:11:53 +0000
committerJim Meyering <jim@meyering.net>2006-10-13 21:11:53 +0000
commit965232b5b9899e1939029c448d3870d92f35d1db (patch)
tree5eb77136a45586ce600f9d93c0b51e1e17260f8c /src/chown-core.c
parent5dea5d07cdad67d8ca1ce90eef9dc7847c057c02 (diff)
downloadcoreutils-965232b5b9899e1939029c448d3870d92f35d1db.tar.xz
More chown/chgrp dereferencing-related fixes.
* src/chown-core.c (change_file_owner): Don't use fts_statp if we're dereferencing symlinks. Reverse conjuncts, so that we use dereference file_stats (aka ent->fts_statp) only *after* we've confirmed that chopt->affect_symlink_referent is true. Otherwise, we might use ent->fts_statp uninitialized. Don't turn on FTS_NOSTAT when dereferencing symlinks. * tests/chown/deref: Update the expected diagnostic, now that this test case (trying to use "chown --dereference ..." on a dangling symlink) takes a different code path.
Diffstat (limited to 'src/chown-core.c')
-rw-r--r--src/chown-core.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/src/chown-core.c b/src/chown-core.c
index d1efe52b6..8a0d51dfa 100644
--- a/src/chown-core.c
+++ b/src/chown-core.c
@@ -305,7 +305,9 @@ change_file_owner (FTS *fts, FTSENT *ent,
file_stats = NULL;
}
else if (required_uid == (uid_t) -1 && required_gid == (gid_t) -1
- && chopt->verbosity == V_off && ! chopt->root_dev_ino)
+ && chopt->verbosity == V_off
+ && ! chopt->root_dev_ino
+ && ! chopt->affect_symlink_referent)
{
do_chown = true;
file_stats = ent->fts_statp;
@@ -316,7 +318,7 @@ change_file_owner (FTS *fts, FTSENT *ent,
/* If this is a symlink and we're dereferencing them,
stat it to get info on the referent. */
- if (S_ISLNK (file_stats->st_mode) && chopt->affect_symlink_referent)
+ if (chopt->affect_symlink_referent && S_ISLNK (file_stats->st_mode))
{
if (fstatat (fts->fts_cwd_fd, file, &stat_buf, 0) != 0)
{
@@ -454,6 +456,7 @@ chown_files (char **files, int bit_flags,
/* Use lstat and stat only if they're needed. */
int stat_flags = ((required_uid != (uid_t) -1 || required_gid != (gid_t) -1
+ || chopt->affect_symlink_referent
|| chopt->verbosity != V_off || chopt->root_dev_ino)
? 0
: FTS_NOSTAT);