summaryrefslogtreecommitdiff
path: root/src/chown-core.c
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2004-05-16 21:39:35 +0000
committerJim Meyering <jim@meyering.net>2004-05-16 21:39:35 +0000
commit37adce26809835f0ea8d96035e1f9cd93ab22645 (patch)
tree347a46cbad796b4186e4527f6707984e21683feb /src/chown-core.c
parent23e13a64a8d318bf8632c763399b1546709f8cc9 (diff)
downloadcoreutils-37adce26809835f0ea8d96035e1f9cd93ab22645.tar.xz
chown --dereference did nothing when the owner/group of a
symlink matched the desired owner/group. Reported by David Malone. Also reported in 1999 as http://bugs.debian.org/39642. (change_file_owner): When --dereference has been specified, and when processing a symlink, stat it to get the owner and group of the referent.
Diffstat (limited to 'src/chown-core.c')
-rw-r--r--src/chown-core.c30
1 files changed, 24 insertions, 6 deletions
diff --git a/src/chown-core.c b/src/chown-core.c
index 82fb4de0f..b52837bbd 100644
--- a/src/chown-core.c
+++ b/src/chown-core.c
@@ -175,7 +175,9 @@ change_file_owner (FTS *fts, FTSENT *ent,
struct Chown_option const *chopt)
{
const char *file_full_name = ent->fts_path;
- struct stat *file_stats = ent->fts_statp;
+ struct stat const *file_stats = ent->fts_statp;
+ struct stat const *target_stats;
+ struct stat stat_buf;
int errors = 0;
/* This is the second time we've seen this directory. */
@@ -207,12 +209,28 @@ change_file_owner (FTS *fts, FTSENT *ent,
return 1;
}
- if ((old_uid == (uid_t) -1 || file_stats->st_uid == old_uid)
- && (old_gid == (gid_t) -1 || file_stats->st_gid == old_gid))
+ /* If this is a symlink and we're dereferencing them,
+ stat it to get the permissions of the referent. */
+ if (S_ISLNK (file_stats->st_mode) && chopt->affect_symlink_referent)
{
- uid_t new_uid = (uid == (uid_t) -1 ? file_stats->st_uid : uid);
- gid_t new_gid = (gid == (gid_t) -1 ? file_stats->st_gid : gid);
- if (new_uid != file_stats->st_uid || new_gid != file_stats->st_gid)
+ if (stat (ent->fts_accpath, &stat_buf) != 0)
+ {
+ error (0, errno, _("cannot dereference %s"), quote (file_full_name));
+ return 1;
+ }
+ target_stats = &stat_buf;
+ }
+ else
+ {
+ target_stats = file_stats;
+ }
+
+ if ((old_uid == (uid_t) -1 || target_stats->st_uid == old_uid)
+ && (old_gid == (gid_t) -1 || target_stats->st_gid == old_gid))
+ {
+ uid_t new_uid = (uid == (uid_t) -1 ? target_stats->st_uid : uid);
+ gid_t new_gid = (gid == (gid_t) -1 ? target_stats->st_gid : gid);
+ if (new_uid != target_stats->st_uid || new_gid != target_stats->st_gid)
{
const char *file = ent->fts_accpath;
int fail;