Hello,

I have found an error in chgrp and chown regarding symlinks.
If a system supports lchown(2) calls, this call is used
to change the symlink itself while chown(2) is used for
changing the referenced file. In either case, lstat(2) is
used for getting owner/group information of the file. This
results in an apparently nondeterministic behaviour when
changing the owner/group of the referenced file.

Moreover, in both tools the global variable `change_symlinks'
is set to 1 by default. This results in changing the link
rather than the referenced file by default. While chown
has the option `--dereference', chgrp is missing this option
leading in not beeing able to change the group of the
referenced file.

Both problems are resolvedby the attached patch, relative to
the current fileutils-4.0 version.

Corinna Vinschen
--- ChangeLog.old       Sun Apr  2 10:49:30 2000
+++ ChangeLog   Sun Apr  2 10:55:40 2000
@@ -1,3 +1,13 @@
+2000-04-02  Corinna Vinschen  <[EMAIL PROTECTED]>
+
+        * src/chgrp.c: Add long option `--dereference'.
+        (change_file_group): Use lstat(2) if change_symlinks is set,
+        stat(2) otherwise.
+        (usage): Reflect new option `--dereference'.
+        (main): Add case label for new option `--dereference'.
+        * src/chown.c (change_file_owner): Use lstat(2) if change_symlinks
+        is set, stat(2) otherwise.
+
 1998-11-14  Jim Meyering  <[EMAIL PROTECTED]>
 
        * Version 4.0.
--- chgrp.c.old Sat Apr  1 14:41:57 2000
+++ chgrp.c     Sat Apr  1 14:57:38 2000
@@ -104,6 +104,7 @@ static struct option const long_options[
 {
   {"recursive", no_argument, 0, 'R'},
   {"changes", no_argument, 0, 'c'},
+  {"dereference", no_argument, 0, CHAR_MAX + 2},
   {"no-dereference", no_argument, 0, 'h'},
   {"silent", no_argument, 0, 'f'},
   {"quiet", no_argument, 0, 'f'},
@@ -182,7 +183,8 @@ change_file_group (const char *file, int
   struct stat file_stats;
   int errors = 0;
 
-  if (lstat (file, &file_stats))
+  if ((change_symlinks && lstat (file, &file_stats))
+      || (!change_symlinks && stat (file, &file_stats)))
     {
       if (force_silent == 0)
        error (0, errno, "%s", file);
@@ -305,6 +307,8 @@ Usage: %s [OPTION]... GROUP FILE...\n\
 Change the group membership of each FILE to GROUP.\n\
 \n\
   -c, --changes          like verbose but report only when a change is made\n\
+      --dereference      affect the referent of each symbolic link, rather\n\
+                         than the symbolic link itself\n\
   -h, --no-dereference   affect symbolic links instead of any referenced file\n\
                          (available only on systems with lchown system call)\n\
   -f, --silent, --quiet  suppress most error messages\n\
@@ -342,6 +346,9 @@ main (int argc, char **argv)
          break;
        case CHAR_MAX + 1:
          reference_file = optarg;
+         break;
+       case CHAR_MAX + 2:
+         change_symlinks = 0;
          break;
        case 'R':
          recurse = 1;
--- chown.c.old Sat Apr  1 14:41:47 2000
+++ chown.c     Sat Apr  1 14:43:16 2000
@@ -172,7 +172,8 @@ change_file_owner (int cmdline_arg, cons
   gid_t newgroup;
   int errors = 0;
 
-  if (lstat (file, &file_stats))
+  if ((change_symlinks && lstat (file, &file_stats))
+      || (!change_symlinks && stat (file, &file_stats)))
     {
       if (force_silent == 0)
        error (0, errno, "%s", file);

Reply via email to