From dan@dan.emsphone.com  Mon Nov 29 04:44:43 2004
Return-Path: <dan@dan.emsphone.com>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 3007616A4CE
	for <FreeBSD-gnats-submit@freebsd.org>; Mon, 29 Nov 2004 04:44:43 +0000 (GMT)
Received: from dan.emsphone.com (dan.emsphone.com [199.67.51.101])
	by mx1.FreeBSD.org (Postfix) with ESMTP id C617543D31
	for <FreeBSD-gnats-submit@freebsd.org>; Mon, 29 Nov 2004 04:44:42 +0000 (GMT)
	(envelope-from dan@dan.emsphone.com)
Received: (from dan@localhost)
	by dan.emsphone.com (8.13.1/8.13.1) id iAT4ig0Q045278;
	Sun, 28 Nov 2004 22:44:42 -0600 (CST)
	(envelope-from dan)
Message-Id: <200411290444.iAT4ig0Q045278@dan.emsphone.com>
Date: Sun, 28 Nov 2004 22:44:42 -0600 (CST)
From: Dan Nelson <dnelson@allantgroup.com>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [PATCH] allow chflags to set flags on symlinks
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         74500
>Category:       bin
>Synopsis:       [PATCH] allow chflags to set flags on symlinks
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Mon Nov 29 04:50:21 GMT 2004
>Closed-Date:    Sun Apr 16 16:56:19 GMT 2006
>Last-Modified:  Sun Apr 16 16:56:19 GMT 2006
>Originator:     Dan Nelson
>Release:        FreeBSD 5.3-STABLE i386
>Organization:
The Allant Group
>Environment:
System: FreeBSD dan.emsphone.com 5.3-STABLE FreeBSD 5.3-STABLE #373: Fri Nov 26 21:49:32 CST 2004 zsh@dan.emsphone.com:/usr/src/sys/i386/compile/DANSMP i386


	
>Description:
	

/bin/chflags always calls chflags(2), which means that it drills
through symlinks and changes attricutes on the underlying files.  This
may not be what is intended if the user wants to prevent the symlink
itself from being changed (to point to a different location, for
example).

The prototypes for chflags and fchflags are also incorrect; they take
an int argument, not an unsigned long.

>How-To-Repeat:
	
>Fix:

Apply the following patch which adds the -h switch, copied from the
chown code.  A newer version may be at
http://dan.allantgroup.com/FreeBSD/ .

Index: /usr/src/sys/sys/stat.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/stat.h,v
retrieving revision 1.40
diff -u -r1.40 stat.h
--- /usr/src/sys/sys/stat.h	17 Jun 2004 17:16:52 -0000	1.40
+++ /usr/src/sys/sys/stat.h	11 Nov 2004 20:06:24 -0000
@@ -299,11 +299,11 @@
 #ifndef _KERNEL
 __BEGIN_DECLS
 #if __BSD_VISIBLE
-int	chflags(const char *, unsigned long);
+int	chflags(const char *, int);
 #endif
 int	chmod(const char *, mode_t);
 #if __BSD_VISIBLE
-int	fchflags(int, unsigned long);
+int	fchflags(int, int);
 int	fchmod(int, mode_t);
 #endif
 int	fstat(int, struct stat *);
Index: /usr/src/bin/chflags/chflags.1
===================================================================
RCS file: /home/ncvs/src/bin/chflags/chflags.1,v
retrieving revision 1.18
diff -u -r1.18 chflags.1
--- /usr/src/bin/chflags/chflags.1	6 Apr 2004 20:06:44 -0000	1.18
+++ /usr/src/bin/chflags/chflags.1	11 Nov 2004 20:01:49 -0000
@@ -39,6 +39,7 @@
 .Nd change file flags
 .Sh SYNOPSIS
 .Nm
+.Op Fl h
 .Oo
 .Fl R
 .Op Fl H | Fl L | Fl P
@@ -72,6 +73,9 @@
 .It Fl R
 Change the file flags for the file hierarchies rooted
 in the files instead of just the files themselves.
+.It Fl h
+If the file is a symbolic link, change the user ID and/or the
+group ID of the link itself.
 .El
 .Pp
 The flags are specified as an octal number or a comma separated list
Index: /usr/src/bin/chflags/chflags.c
===================================================================
RCS file: /home/ncvs/src/bin/chflags/chflags.c,v
retrieving revision 1.20
diff -u -r1.20 chflags.c
--- /usr/src/bin/chflags/chflags.c	6 Apr 2004 20:06:44 -0000	1.20
+++ /usr/src/bin/chflags/chflags.c	11 Nov 2004 20:04:01 -0000
@@ -62,11 +62,11 @@
 	FTSENT *p;
 	u_long clear, set;
 	long val;
-	int Hflag, Lflag, Pflag, Rflag, ch, fts_options, oct, rval;
+	int Hflag, Lflag, Pflag, Rflag, hflag, ch, fts_options, oct, rval;
 	char *flags, *ep;
 
-	Hflag = Lflag = Pflag = Rflag = 0;
-	while ((ch = getopt(argc, argv, "HLPR")) != -1)
+	Hflag = Lflag = Pflag = Rflag = hflag = 0;
+	while ((ch = getopt(argc, argv, "HLPRh")) != -1)
 		switch (ch) {
 		case 'H':
 			Hflag = 1;
@@ -83,6 +83,9 @@
 		case 'R':
 			Rflag = 1;
 			break;
+		case 'h':
+			hflag = 1;
+			break;
 		case '?':
 		default:
 			usage();
@@ -95,6 +98,9 @@
 
 	if (Rflag) {
 		fts_options = FTS_PHYSICAL;
+		if (hflag && (Hflag || Lflag))
+			errx(1, "the -R%c and -h options may not be "
+				"specified together", Hflag ? 'H' : 'L');
 		if (Hflag)
 			fts_options |= FTS_COMFOLLOW;
 		if (Lflag) {
@@ -102,7 +108,7 @@
 			fts_options |= FTS_LOGICAL;
 		}
 	} else
-		fts_options = FTS_LOGICAL;
+		fts_options = hflag ? FTS_PHYSICAL : FTS_LOGICAL;
 
 	flags = *argv;
 	if (*flags >= '0' && *flags <= '7') {
@@ -148,17 +154,20 @@
 			 * don't point to anything and ones that we found
 			 * doing a physical walk.
 			 */
-			continue;
+			if (hflag)
+				break;
+			else
+				continue;
 		default:
 			break;
 		}
 		if (oct) {
-			if (!chflags(p->fts_accpath, set))
+			if (!(hflag ? lchflags : chflags)(p->fts_accpath, set))
 				continue;
 		} else {
 			p->fts_statp->st_flags |= set;
 			p->fts_statp->st_flags &= clear;
-			if (!chflags(p->fts_accpath, (u_long)p->fts_statp->st_flags))
+			if (!(hflag ? lchflags : chflags)(p->fts_accpath, (u_long)p->fts_statp->st_flags))
 				continue;
 		}
 		warn("%s", p->fts_path);
@@ -173,6 +182,6 @@
 usage(void)
 {
 	(void)fprintf(stderr,
-	    "usage: chflags [-R [-H | -L | -P]] flags file ...\n");
+	    "usage: chflags [-h] [-R [-H | -L | -P]] flags file ...\n");
 	exit(1);
 }


>Release-Note:
>Audit-Trail:

From: Ceri Davies <ceri@submonkey.net>
To: Dan Nelson <dnelson@allantgroup.com>
Cc: FreeBSD-gnats-submit@FreeBSD.org
Subject: Re: bin/74500: [PATCH] allow chflags to set flags on symlinks
Date: Mon, 29 Nov 2004 11:24:06 +0000

 On Sun, Nov 28, 2004 at 10:44:42PM -0600, Dan Nelson wrote:
 > 
 > /bin/chflags always calls chflags(2), which means that it drills
 > through symlinks and changes attricutes on the underlying files.  This
 > may not be what is intended if the user wants to prevent the symlink
 > itself from being changed (to point to a different location, for
 > example).
 > 
 > The prototypes for chflags and fchflags are also incorrect; they take
 > an int argument, not an unsigned long.
 > 
 > >How-To-Repeat:
 > 	
 > >Fix:
 > 
 > Apply the following patch which adds the -h switch, copied from the
 > chown code.  A newer version may be at
 > http://dan.allantgroup.com/FreeBSD/ .
 > 
 > @@ -72,6 +73,9 @@
 >  .It Fl R
 >  Change the file flags for the file hierarchies rooted
 >  in the files instead of just the files themselves.
 > +.It Fl h
 > +If the file is a symbolic link, change the user ID and/or the
 > +group ID of the link itself.
 
 A little bit *too* copied from chown? ;-)
 
 Ceri
 -- 
 Only two things are infinite, the universe and human stupidity, and I'm
 not sure about the former.			  -- Einstein (attrib.)

From: Chris Dillon <cdillon@wolves.k12.mo.us>
To: bug-followup@FreeBSD.org, dnelson@allantgroup.com
Cc:  
Subject: Re: bin/74500 : [PATCH] allow chflags to set flags on symlinks
Date: Wed, 27 Jul 2005 15:27:35 -0500 (CDT)

 I wanted to point out that I have been using this patch for quite a 
 while now, but thought I would mention that the following part of the 
 patch is not strictly necessary:
 
   	if (Rflag) {
   		fts_options = FTS_PHYSICAL;
 +		if (hflag && (Hflag || Lflag))
 +			errx(1, "the -R%c and -h options may not be "
 +				"specified together", Hflag ? 'H' : 'L');
 
 
 It is OK to use '-R' and '-h', and '-H || -L' together, but may not 
 have the expected behaviour.  This behaviour is already (indirectly) 
 documented in the manual page, so there is no reason to prevent it.
 
 If the filespec to chflags contains a symlink, as expected, you must 
 use '-L' or '-H' to have that symlink in the filespec followed.  When 
 combining one of these options with '-h' and '-R', for example when 
 using '-h -H -R' with the filespec containing a symlink pointing to a 
 directory, the symlink and everything under the directory it is 
 pointing to will have its flag changed, but the actual directory the 
 symlink is pointing to (the link target) will NOT have its flag 
 changed.  This is the expected behaviour of the lchflags() system call 
 and is correct with that in mind.  Even the chflags(1) manual page 
 says '-h' will "change the flag of the link rather than the file to 
 which it points", so this is documented.
 
 With that in mind, I think we should also have an option to "change 
 the flag of the link AND the file to which it points".  This should 
 apply to chmod(1) and chown(1) as well.
 
 -- 
   Chris Dillon - cdillon(at)wolves.k12.mo.us
   FreeBSD: The fastest, most open, and most stable OS on the planet
   - Available for IA32, IA64, AMD64, PC98, Alpha, and UltraSPARC architectures
   - PowerPC, ARM, MIPS, and S/390 under development
   - http://www.freebsd.org
 
 Q: Because it reverses the logical flow of conversation.
 A: Why is putting a reply at the top of the message frowned upon?
 
State-Changed-From-To: open->closed 
State-Changed-By: maxim 
State-Changed-When: Sun Apr 16 16:55:09 UTC 2006 
State-Changed-Why:  
dd@ has committed this feature.  Thanks! 

http://www.freebsd.org/cgi/query-pr.cgi?pr=74500 
>Unformatted:
