tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Proposed chown(8)/chgrp(1) enhancement



Seems to me that a recursive chown/chgrp, in a large directory with
_most_but_not_all files already set to the desired owner/group, can
be rather wastefull.  As near as I can tell, the kernel is called
for every file, even those for whom the update of attributes is
effectively a no-op.  Further, these no-op calls apparently trigger
other non-updates to the filesystem whjich can affect files' mtime
and/or atime.

(FWIW, I frequently end up with such a directory when a CVS update
picks up a new file and I forgot to su(8) to the owner's UID first!
The new files get my current owner uid while all the other files
are owned by someone else.)

I propose the attached enhancement to chown/chgrp to avoid setting
a new user/group value if the desired values are already set.  The
change is pretty simple.

Note that this change also modifies the changes that might be made
to a file's setuid/setgid mode bits.  Current code simply clears the
bits for every file, whether or not the user/group is really being
updated.  The attached patch only clears the bits if the user/group
is also being _changed_ from its current value.

Comments?  Useful?  Suggestions?  Should I commit?

+--------------------+--------------------------+----------------------+
| Paul Goyette       | PGP Key fingerprint:     | E-mail addresses:    |
| (Retired)          | FA29 0E3B 35AF E8AE 6651 | paul%whooppee.com@localhost    |
| Software Developer | 0786 F758 55DE 53BA 7731 | pgoyette%netbsd.org@localhost  |
| & Network Engineer |                          | pgoyette99%gmail.com@localhost |
+--------------------+--------------------------+----------------------+
Index: chgrp.1
===================================================================
RCS file: /cvsroot/src/sbin/chown/chgrp.1,v
retrieving revision 1.8
diff -u -p -r1.8 chgrp.1
--- chgrp.1	4 Jul 2017 06:52:20 -0000	1.8
+++ chgrp.1	28 Apr 2023 19:01:05 -0000
@@ -31,7 +31,7 @@
 .\"     from: @(#)chgrp.1	8.3 (Berkeley) 3/31/94
 .\"	$NetBSD: chgrp.1,v 1.8 2017/07/04 06:52:20 wiz Exp $
 .\"
-.Dd October 22, 2012
+.Dd May 1, 2023
 .Dt CHGRP 1
 .Os
 .Sh NAME
@@ -86,6 +86,9 @@ option is specified, no symbolic links a
 .It Fl R
 Change the group ID for the file hierarchies rooted
 in the files instead of just the files themselves.
+.It Fl d
+Do not attempt to update a file's group if it is already set to the
+desired value.
 .It Fl f
 The force option ignores errors, except for usage errors and doesn't
 query about strange modes (unless the user does not have proper permissions).
@@ -164,6 +167,8 @@ utility is expected to be POSIX 1003.2 c
 .Pp
 The
 .Fl v
-option and the use of ``#'' to force a numeric group ID
+and
+.Fl d
+options and the use of ``#'' to force a numeric group ID
 are extensions to
 .St -p1003.2 .
Index: chown.8
===================================================================
RCS file: /cvsroot/src/sbin/chown/chown.8,v
retrieving revision 1.12
diff -u -p -r1.12 chown.8
--- chown.8	4 Jul 2017 06:53:12 -0000	1.12
+++ chown.8	28 Apr 2023 19:01:05 -0000
@@ -28,7 +28,7 @@
 .\"     from: @(#)chown.8	8.3 (Berkeley) 3/31/94
 .\"	$NetBSD: chown.8,v 1.12 2017/07/04 06:53:12 wiz Exp $
 .\"
-.Dd September 11, 2016
+.Dd May 1, 2023
 .Dt CHOWN 8
 .Os
 .Sh NAME
@@ -84,6 +84,9 @@ option is specified, no symbolic links a
 .It Fl R
 Change the user ID and/or the group ID for the file hierarchies rooted
 in the files instead of just the files themselves.
+.It Fl d
+Do not attempt to update a file's owner or group if it is already
+set to the desired value.
 .It Fl f
 Do not report any failure to change file owner or group, nor modify
 the exit status to reflect such failures.
@@ -174,7 +177,9 @@ command is expected to be POSIX 1003.2 c
 .Pp
 The
 .Fl v
-option and the use of ``#'' to force a numeric lookup
+and
+.Fl d
+options and the use of ``#'' to force a numeric lookup
 are extensions to
 .St -p1003.2 .
 .Sh HISTORY
Index: chown.c
===================================================================
RCS file: /cvsroot/src/sbin/chown/chown.c,v
retrieving revision 1.9
diff -u -p -r1.9 chown.c
--- chown.c	28 Apr 2023 09:56:45 -0000	1.9
+++ chown.c	28 Apr 2023 19:01:05 -0000
@@ -82,7 +82,7 @@ main(int argc, char **argv)
 {
 	FTS *ftsp;
 	FTSENT *p;
-	int Hflag, Lflag, Rflag, ch, fflag, fts_options, hflag, rval, vflag;
+	int Hflag, Lflag, Rflag, ch, fflag, fts_options, hflag, rval, vflag, dflag;
 	char *cp, *reference;
 	int (*change_owner)(const char *, uid_t, gid_t);
 
@@ -94,13 +94,16 @@ main(int argc, char **argv)
 	ischown = (myname[2] == 'o');
 	reference = NULL;
 
-	Hflag = Lflag = Rflag = fflag = hflag = vflag = 0;
-	while ((ch = getopt_long(argc, argv, "HLPRfhv",
+	Hflag = Lflag = Rflag = fflag = hflag = vflag = dflag = 0;
+	while ((ch = getopt_long(argc, argv, "HLPRdfhv",
 	    chown_longopts, NULL)) != -1)
 		switch (ch) {
 		case 1:
 			reference = optarg;
 			break;
+		case 'd':
+			dflag = 1;
+			break;
 		case 'H':
 			Hflag = 1;
 			Lflag = 0;
@@ -232,6 +235,15 @@ main(int argc, char **argv)
 			break;
 		}
 
+		/*
+		 * If dflag was set, and the owner and group are already
+		 * set to the right value, skip any attempt to update.
+		 */
+		if (dflag &&
+		    ( uid == -1 || p->fts_statp->st_uid == uid ) &&
+		    ( gid == -1 || p->fts_statp->st_gid == gid ))
+			continue;
+
 		if ((*change_owner)(p->fts_accpath, uid, gid) && !fflag) {
 			warn("%s", p->fts_path);
 			rval = EXIT_FAILURE;
@@ -294,8 +306,8 @@ usage(void)
 {
 
 	(void)fprintf(stderr,
-	    "Usage: %s [-R [-H | -L | -P]] [-fhv] %s file ...\n"
-	    "\t%s [-R [-H | -L | -P]] [-fhv] --reference=rfile file ...\n",
+	    "Usage: %s [-R [-H | -L | -P]] [-dfhv] %s file ...\n"
+	    "\t%s [-R [-H | -L | -P]] [-dfhv] --reference=rfile file ...\n",
 	    myname, ischown ? "owner:group|owner|:group" : "group",
 	    myname);
 	exit(EXIT_FAILURE);


Home | Main Index | Thread Index | Old Index