Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 1 Apr 2002 15:10:46 +1000
From:      Joshua Goodall <joshua@roughtrade.net>
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: kern/29355 lchflags syscall and supporting userland
Message-ID:  <20020401051046.GC30787@roughtrade.net>

next in thread | raw e-mail | index | archive | help

--6TrnltStXW4iwmi0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

I have attached an updated version of this change, and it's
also available at http://www.roughtrade.net/bsd/lchflags.diff
with a readme at  http://www.roughtrade.net/bsd/README.lchflags

original justification at:
http://docs.freebsd.org/cgi/getmsg.cgi?fetch=1862+0+archive/2001/freebsd-hackers/20010729.freebsd-hackers

This PR appears to have undergone committer timeout, perhaps
it could be reassigned?

Joshua

--6TrnltStXW4iwmi0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="lchflags.diff"

Index: bin/cp/utils.c
===================================================================
RCS file: /cvs/src/bin/cp/utils.c,v
retrieving revision 1.34
diff -u -r1.34 utils.c
--- bin/cp/utils.c	22 Feb 2002 21:24:14 -0000	1.34
+++ bin/cp/utils.c	29 Mar 2002 09:50:16 -0000
@@ -205,7 +205,7 @@
 		warn("symlink: %s", llink);
 		return (1);
 	}
-	return (0);
+	return (pflag ? setfile(p->fts_statp, 0) : 0);
 }
 
 int
@@ -250,11 +250,11 @@
 
 	TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atimespec);
 	TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtimespec);
-	if (utimes(to.p_path, tv)) {
+	if (lutimes(to.p_path, tv)) {
 		warn("utimes: %s", to.p_path);
 		rval = 1;
 	}
-	if (fd ? fstat(fd, &ts) : stat(to.p_path, &ts))
+	if (fd ? fstat(fd, &ts) : lstat(to.p_path, &ts))
 		gotstat = 0;
 	else {
 		gotstat = 1;
@@ -269,7 +269,7 @@
 	 */
 	if (!gotstat || fs->st_uid != ts.st_uid || fs->st_gid != ts.st_gid)
 		if (fd ? fchown(fd, fs->st_uid, fs->st_gid) :
-		    chown(to.p_path, fs->st_uid, fs->st_gid)) {
+		    lchown(to.p_path, fs->st_uid, fs->st_gid)) {
 			if (errno != EPERM) {
 				warn("chown: %s", to.p_path);
 				rval = 1;
@@ -278,14 +278,14 @@
 		}
 
 	if (!gotstat || fs->st_mode != ts.st_mode)
-		if (fd ? fchmod(fd, fs->st_mode) : chmod(to.p_path, fs->st_mode)) {
+		if (fd ? fchmod(fd, fs->st_mode) : lchmod(to.p_path, fs->st_mode)) {
 			warn("chmod: %s", to.p_path);
 			rval = 1;
 		}
 
 	if (!gotstat || fs->st_flags != ts.st_flags)
 		if (fd ?
-		    fchflags(fd, fs->st_flags) : chflags(to.p_path, fs->st_flags)) {
+		    fchflags(fd, fs->st_flags) : lchflags(to.p_path, fs->st_flags)) {
 			warn("chflags: %s", to.p_path);
 			rval = 1;
 		}
Index: bin/ln/symlink.7
===================================================================
RCS file: /cvs/src/bin/ln/symlink.7,v
retrieving revision 1.20
diff -u -r1.20 symlink.7
--- bin/ln/symlink.7	14 Aug 2001 10:01:43 -0000	1.20
+++ bin/ln/symlink.7	29 Mar 2002 09:44:19 -0000
@@ -106,11 +106,14 @@
 would return a file descriptor to the file
 .Dq afile .
 .Pp
-There are six system calls that do not follow links, and which operate
+There are nine system calls that do not follow links, and which operate
 on the symbolic link itself.
 They are:
+.Xr lchflags 2 ,
+.Xr lchmod 2 ,
 .Xr lchown 2 ,
 .Xr lstat 2 ,
+.Xr lutimes 2 ,
 .Xr readlink 2 ,
 .Xr rename 2 ,
 .Xr rmdir 2 ,
@@ -126,12 +129,16 @@
 is applied to a symbolic link, it fails with the error
 .Er ENOTDIR .
 .Pp
-The owner and group of an existing symbolic link can be changed by
-means of the
-.Xr lchown 2
-system call.
-The other file attributes, such as the modification time and access
-permissions, are not used by the system and cannot be changed.
+The flags, access permissions, owner/group and modification time of
+an existing symbolic link can be changed by means of the
+.Xr lchflags 2
+.Xr lchmod 2 ,
+.Xr lchown 2 ,
+and 
+.Xr lutimes 2 ,
+system calls, respectively. Of these only the flags are used by
+the system, so a symbolic link can be made immutable. The access
+permissions and ownership are ignored.
 .Pp
 The
 .Bx 4.4
@@ -441,8 +448,11 @@
 .Xr pax 1 ,
 .Xr rm 1 ,
 .Xr tar 1 ,
+.Xr lchflags 2 ,
+.Xr lchmod 2 ,
 .Xr lchown 2 ,
 .Xr lstat 2 ,
+.Xr lutimes 2 ,
 .Xr readlink 2 ,
 .Xr rename 2 ,
 .Xr symlink 2 ,
Index: bin/rm/rm.c
===================================================================
RCS file: /cvs/src/bin/rm/rm.c,v
retrieving revision 1.36
diff -u -r1.36 rm.c
--- bin/rm/rm.c	14 Feb 2002 01:59:47 -0000	1.36
+++ bin/rm/rm.c	29 Mar 2002 09:44:19 -0000
@@ -237,7 +237,7 @@
 		if (!uid &&
 		    (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
 		    !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)))
-			rval = chflags(p->fts_accpath,
+			rval = lchflags(p->fts_accpath,
 				       p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE));
 		if (rval == 0) {
 			/*
@@ -327,7 +327,7 @@
 		if (!uid &&
 		    (sb.st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
 		    !(sb.st_flags & (SF_APPEND|SF_IMMUTABLE)))
-			rval = chflags(f, sb.st_flags & ~(UF_APPEND|UF_IMMUTABLE));
+			rval = lchflags(f, sb.st_flags & ~(UF_APPEND|UF_IMMUTABLE));
 		if (rval == 0) {
 			if (S_ISWHT(sb.st_mode))
 				rval = undelete(f);
Index: contrib/gdb/gdb/proc-events.c
===================================================================
RCS file: /cvs/src/contrib/gdb/gdb/proc-events.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 proc-events.c
--- contrib/gdb/gdb/proc-events.c	4 Aug 2000 09:34:08 -0000	1.1.1.1
+++ contrib/gdb/gdb/proc-events.c	29 Mar 2002 09:44:19 -0000
@@ -525,6 +525,12 @@
 #if defined (SYS_ksigqueue)
   syscall_table[SYS_ksigqueue] = "ksigqueue";
 #endif
+#if defined (SYS_lchflags)
+  syscall_table[SYS_lchflags] = "lchflags";
+#endif
+#if defined (SYS_lchmod)
+  syscall_table[SYS_lchmod] = "lchmod";
+#endif
 #if defined (SYS_lchown)
   syscall_table[SYS_lchown] = "lchown";
 #endif
@@ -548,6 +554,9 @@
 #endif
 #if defined (SYS_lstat64)
   syscall_table[SYS_lstat64] = "lstat64";
+#endif
+#if defined (SYS_lutimes)
+  syscall_table[SYS_lutimes] = "lutimes";
 #endif
 #if defined (SYS_lvldom)
   syscall_table[SYS_lvldom] = "lvldom";
Index: lib/libc/sys/chflags.2
===================================================================
RCS file: /cvs/src/lib/libc/sys/chflags.2,v
retrieving revision 1.19
diff -u -r1.19 chflags.2
--- lib/libc/sys/chflags.2	1 Oct 2001 16:09:01 -0000	1.19
+++ lib/libc/sys/chflags.2	29 Mar 2002 09:44:19 -0000
@@ -37,7 +37,8 @@
 .Os
 .Sh NAME
 .Nm chflags ,
-.Nm fchflags
+.Nm fchflags ,
+.Nm lchflags
 .Nd set file flags
 .Sh LIBRARY
 .Lb libc
@@ -48,6 +49,8 @@
 .Fn chflags "const char *path"  "u_long flags"
 .Ft int
 .Fn fchflags "int fd" "u_long flags"
+.Ft int
+.Fn lchflags "const char *path"  "u_long flags"
 .Sh DESCRIPTION
 The file whose name
 is given by
@@ -57,6 +60,11 @@
 has its flags changed to
 .Fa flags .
 .Pp
+.Fn Lchflags
+is similar to
+.Fn chflags
+but does not follow symbolic links.
+.Pp
 The flags specified are formed by
 .Em or Ns 'ing
 the following values
@@ -171,3 +179,7 @@
 .Nm fchflags
 functions first appeared in
 .Bx 4.4 .
+The
+.Fn lchflags
+function first appeared in
+.Nx 1.5 .
Index: sbin/restore/tape.c
===================================================================
RCS file: /cvs/src/sbin/restore/tape.c,v
retrieving revision 1.31
diff -u -r1.31 tape.c
--- sbin/restore/tape.c	20 Mar 2002 22:49:40 -0000	1.31
+++ sbin/restore/tape.c	29 Mar 2002 09:51:44 -0000
@@ -529,6 +529,8 @@
 extractfile(char *name)
 {
 	int flags;
+	uid_t uid;
+	gid_t gid;
 	mode_t mode;
 	struct timeval timep[2];
 	struct entry *ep;
@@ -539,6 +541,8 @@
 	timep[0].tv_usec = curfile.dip->di_atimensec / 1000;
 	timep[1].tv_sec = curfile.dip->di_mtime;
 	timep[1].tv_usec = curfile.dip->di_mtimensec / 1000;
+	uid = curfile.dip->di_uid;
+	gid = curfile.dip->di_gid;
 	mode = curfile.dip->di_mode;
 	flags = curfile.dip->di_flags;
 	switch (mode & IFMT) {
@@ -573,7 +577,17 @@
 			    "%s: zero length symbolic link (ignored)\n", name);
 			return (GOOD);
 		}
-		return (linkit(lnkbuf, name, SYMLINK));
+		if (uflag)
+			(void) unlink(name);
+		if (linkit(lnkbuf, name, SYMLINK) == GOOD) {
+			(void) lutimes(name, timep);
+			(void) lchown(name, uid, gid);
+			(void) lchmod(name, mode);
+			(void) lchflags(name, flags);
+			return (GOOD);
+		} else {
+			return (FAIL);
+		}
 
 	case IFIFO:
 		vprintf(stdout, "extract fifo %s\n", name);
@@ -589,9 +603,9 @@
 			skipfile();
 			return (FAIL);
 		}
-		(void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid);
+		(void) utimes(name, timep);
+		(void) chown(name, uid, gid);
 		(void) chmod(name, mode);
-		utimes(name, timep);
 		(void) chflags(name, flags);
 		skipfile();
 		return (GOOD);
@@ -611,9 +625,9 @@
 			skipfile();
 			return (FAIL);
 		}
-		(void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid);
+		(void) utimes(name, timep);
+		(void) chown(name, uid, gid);
 		(void) chmod(name, mode);
-		utimes(name, timep);
 		(void) chflags(name, flags);
 		skipfile();
 		return (GOOD);
@@ -633,12 +647,12 @@
 			skipfile();
 			return (FAIL);
 		}
-		(void) fchown(ofile, curfile.dip->di_uid, curfile.dip->di_gid);
-		(void) fchmod(ofile, mode);
 		getfile(xtrfile, xtrskip);
+		(void) futimes(ofile, timep);
+		(void) fchown(ofile, uid, gid);
+		(void) fchmod(ofile, mode);
+		(void) fchflags(ofile, flags);
 		(void) close(ofile);
-		utimes(name, timep);
-		(void) chflags(name, flags);
 		return (GOOD);
 	}
 	/* NOTREACHED */
Index: sys/kern/init_sysent.c
===================================================================
RCS file: /cvs/src/sys/kern/init_sysent.c,v
retrieving revision 1.118
diff -u -r1.118 init_sysent.c
--- sys/kern/init_sysent.c	5 Mar 2002 16:13:00 -0000	1.118
+++ sys/kern/init_sysent.c	29 Mar 2002 10:12:20 -0000
@@ -2,7 +2,7 @@
  * System call switch table.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/kern/init_sysent.c,v 1.118 2002/03/05 16:13:00 rwatson Exp $
+ * $FreeBSD$
  * created from FreeBSD: src/sys/kern/syscalls.master,v 1.107 2002/03/05 16:11:11 rwatson Exp 
  */
 
@@ -412,4 +412,5 @@
 	{ 0, (sy_call_t *)nosys },			/* 387 = __mac_get_file */
 	{ 0, (sy_call_t *)nosys },			/* 388 = __mac_set_fd */
 	{ 0, (sy_call_t *)nosys },			/* 389 = __mac_set_file */
+	{ AS(lchflags_args), (sy_call_t *)lchflags },	/* 390 = lchflags */
 };
Index: sys/kern/syscalls.c
===================================================================
RCS file: /cvs/src/sys/kern/syscalls.c,v
retrieving revision 1.105
diff -u -r1.105 syscalls.c
--- sys/kern/syscalls.c	5 Mar 2002 16:13:00 -0000	1.105
+++ sys/kern/syscalls.c	29 Mar 2002 10:12:20 -0000
@@ -2,7 +2,7 @@
  * System call names.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/kern/syscalls.c,v 1.105 2002/03/05 16:13:00 rwatson Exp $
+ * $FreeBSD$
  * created from FreeBSD: src/sys/kern/syscalls.master,v 1.107 2002/03/05 16:11:11 rwatson Exp 
  */
 
@@ -397,4 +397,5 @@
 	"#387",			/* 387 = __mac_get_file */
 	"#388",			/* 388 = __mac_set_fd */
 	"#389",			/* 389 = __mac_set_file */
+	"lchflags",			/* 390 = lchflags */
 };
Index: sys/kern/syscalls.master
===================================================================
RCS file: /cvs/src/sys/kern/syscalls.master,v
retrieving revision 1.107
diff -u -r1.107 syscalls.master
--- sys/kern/syscalls.master	5 Mar 2002 16:11:11 -0000	1.107
+++ sys/kern/syscalls.master	29 Mar 2002 10:10:38 -0000
@@ -559,3 +559,4 @@
 387	UNIMPL	BSD	__mac_get_file
 388	UNIMPL	BSD	__mac_set_fd
 389	UNIMPL	BSD	__mac_set_file
+390	STD	BSD	{ int lchflags(char *path, int flags); }
Index: sys/kern/vfs_syscalls.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.241
diff -u -r1.241 vfs_syscalls.c
--- sys/kern/vfs_syscalls.c	28 Mar 2002 13:47:32 -0000	1.241
+++ sys/kern/vfs_syscalls.c	29 Mar 2002 10:01:14 -0000
@@ -2812,7 +2812,7 @@
 }
 
 /*
- * Common implementation code for chflags() and fchflags().
+ * Common implementation code for chflags(), lchflags and fchflags().
  */
 static int
 setfflags(td, vp, flags)
@@ -2870,6 +2870,36 @@
 	struct nameidata nd;
 
 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
+	if ((error = namei(&nd)) != 0)
+		return (error);
+	NDFREE(&nd, NDF_ONLY_PNBUF);
+	error = setfflags(td, nd.ni_vp, SCARG(uap, flags));
+	vrele(nd.ni_vp);
+	return error;
+}
+ 
+/*
+ * Change flags of a file given a path name (don't follow links).
+ */
+#ifndef _SYS_SYSPROTO_H_
+struct lchflags_args {
+	char	*path;
+	int	flags;
+};
+#endif
+/* ARGSUSED */
+int
+lchflags(td, uap)
+	struct thread *td;
+	register struct lchflags_args /* {
+		syscallarg(char *) path;
+		syscallarg(int) flags;
+	} */ *uap;
+{
+	int error;
+	struct nameidata nd;
+ 
+	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
 	if ((error = namei(&nd)) != 0)
 		return (error);
 	NDFREE(&nd, NDF_ONLY_PNBUF);
Index: sys/sys/param.h
===================================================================
RCS file: /cvs/src/sys/sys/param.h,v
retrieving revision 1.119
diff -u -r1.119 param.h
--- sys/sys/param.h	19 Mar 2002 20:18:40 -0000	1.119
+++ sys/sys/param.h	29 Mar 2002 10:02:11 -0000
@@ -52,7 +52,7 @@
  * there.
  */
 #undef __FreeBSD_version
-#define __FreeBSD_version 500032	/* Master, propagated to newvers */
+#define __FreeBSD_version 500033	/* Master, propagated to newvers */
 
 #ifndef NULL
 #define	NULL	0
Index: sys/sys/stat.h
===================================================================
RCS file: /cvs/src/sys/sys/stat.h,v
retrieving revision 1.23
diff -u -r1.23 stat.h
--- sys/sys/stat.h	19 Mar 2002 20:18:41 -0000	1.23
+++ sys/sys/stat.h	29 Mar 2002 10:05:49 -0000
@@ -256,6 +256,7 @@
 #ifndef _POSIX_SOURCE
 int	chflags(const char *, u_long);
 int	fchflags(int, u_long);
+int	lchflags(const char *, u_long);
 int	fchmod(int, mode_t);
 int	lchmod(const char *, mode_t);
 int	lstat(const char *, struct stat *);
Index: sys/sys/syscall.h
===================================================================
RCS file: /cvs/src/sys/sys/syscall.h,v
retrieving revision 1.104
diff -u -r1.104 syscall.h
--- sys/sys/syscall.h	5 Mar 2002 16:13:01 -0000	1.104
+++ sys/sys/syscall.h	29 Mar 2002 10:12:20 -0000
@@ -2,7 +2,7 @@
  * System call numbers.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/sys/syscall.h,v 1.104 2002/03/05 16:13:01 rwatson Exp $
+ * $FreeBSD$
  * created from FreeBSD: src/sys/kern/syscalls.master,v 1.107 2002/03/05 16:11:11 rwatson Exp 
  */
 
@@ -303,4 +303,5 @@
 #define	SYS_kse_new	381
 #define	SYS_thread_wakeup	382
 #define	SYS_kse_yield	383
-#define	SYS_MAXSYSCALL	390
+#define	SYS_lchflags	390
+#define	SYS_MAXSYSCALL	391
Index: sys/sys/syscall.mk
===================================================================
RCS file: /cvs/src/sys/sys/syscall.mk,v
retrieving revision 1.59
diff -u -r1.59 syscall.mk
--- sys/sys/syscall.mk	5 Mar 2002 16:13:01 -0000	1.59
+++ sys/sys/syscall.mk	29 Mar 2002 10:12:20 -0000
@@ -1,6 +1,6 @@
 # FreeBSD system call names.
 # DO NOT EDIT-- this file is automatically generated.
-# $FreeBSD: src/sys/sys/syscall.mk,v 1.59 2002/03/05 16:13:01 rwatson Exp $
+# $FreeBSD$
 # created from FreeBSD: src/sys/kern/syscalls.master,v 1.107 2002/03/05 16:11:11 rwatson Exp 
 MIASM =  \
 	syscall.o \
@@ -252,4 +252,5 @@
 	kse_wakeup.o \
 	kse_new.o \
 	thread_wakeup.o \
-	kse_yield.o
+	kse_yield.o \
+	lchflags.o
Index: sys/sys/sysproto.h
===================================================================
RCS file: /cvs/src/sys/sys/sysproto.h,v
retrieving revision 1.96
diff -u -r1.96 sysproto.h
--- sys/sys/sysproto.h	19 Mar 2002 20:18:41 -0000	1.96
+++ sys/sys/sysproto.h	29 Mar 2002 10:12:20 -0000
@@ -2,7 +2,7 @@
  * System call prototypes.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/sys/sysproto.h,v 1.96 2002/03/19 20:18:41 alfred Exp $
+ * $FreeBSD$
  * created from FreeBSD: src/sys/kern/syscalls.master,v 1.107 2002/03/05 16:11:11 rwatson Exp 
  */
 
@@ -1105,6 +1105,10 @@
 struct kse_yield_args {
 	register_t dummy;
 };
+struct lchflags_args {
+	char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+	char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+};
 int	nosys(struct thread *, struct nosys_args *);
 void	sys_exit(struct thread *, struct sys_exit_args *);
 int	fork(struct thread *, struct fork_args *);
@@ -1354,6 +1358,7 @@
 int	kse_new(struct thread *, struct kse_new_args *);
 int	thread_wakeup(struct thread *, struct thread_wakeup_args *);
 int	kse_yield(struct thread *, struct kse_yield_args *);
+int	lchflags(struct thread *, struct lchflags_args *);
 
 #ifdef COMPAT_43
 
Index: usr.bin/chflags/chflags.1
===================================================================
RCS file: /cvs/src/usr.bin/chflags/chflags.1,v
retrieving revision 1.14
diff -u -r1.14 chflags.1
--- usr.bin/chflags/chflags.1	15 Aug 2001 09:09:39 -0000	1.14
+++ usr.bin/chflags/chflags.1	29 Mar 2002 09:44:22 -0000
@@ -47,6 +47,7 @@
 .Fl R
 .Op Fl H | Fl L | Fl P
 .Oc
+.Op Fl h 
 .Ar flags
 .Ar
 .Sh DESCRIPTION
@@ -76,6 +77,11 @@
 .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 
+.Ar file 
+or a file encountered during directory traversal is a symbolic link, 
+the file flags of the link itself are changed. 
 .El
 .Pp
 The flags are specified as an octal number or a comma separated list
@@ -117,13 +123,6 @@
 the immutable bit should be cleared
 .El
 .Pp
-Symbolic links do not have flags, so unless the
-.Fl H
-or
-.Fl L
-option is set,
-.Nm
-on a symbolic link always succeeds and has no effect.
 The
 .Fl H ,
 .Fl L
@@ -141,6 +140,7 @@
 .Sh SEE ALSO
 .Xr ls 1 ,
 .Xr chflags 2 ,
+.Xr lchflags 2 ,
 .Xr stat 2 ,
 .Xr fts 3 ,
 .Xr symlink 7
Index: usr.bin/chflags/chflags.c
===================================================================
RCS file: /cvs/src/usr.bin/chflags/chflags.c,v
retrieving revision 1.14
diff -u -r1.14 chflags.c
--- usr.bin/chflags/chflags.c	22 Mar 2002 01:19:26 -0000	1.14
+++ usr.bin/chflags/chflags.c	29 Mar 2002 11:02:11 -0000
@@ -67,13 +67,14 @@
 {
 	FTS *ftsp;
 	FTSENT *p;
-	u_long clear, set;
+	u_long clear, set, newflags;
 	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;
+	int (*change_flags) __P((const char *, u_long));
 
-	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;
@@ -90,6 +91,9 @@
 		case 'R':
 			Rflag = 1;
 			break;
+		case 'h':
+			hflag = 1;
+			break;
 		case '?':
 		default:
 			usage();
@@ -109,7 +113,7 @@
 			fts_options |= FTS_LOGICAL;
 		}
 	} else
-		fts_options = FTS_LOGICAL;
+		fts_options = hflag ? FTS_PHYSICAL : FTS_LOGICAL;
 
 	flags = *argv;
 	if (*flags >= '0' && *flags <= '7') {
@@ -134,6 +138,7 @@
 		err(1, NULL);
 
 	for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
+		change_flags = chflags;
 		switch (p->fts_info) {
 		case FTS_D:
 			if (Rflag)		/* Change it at FTS_DP. */
@@ -149,28 +154,44 @@
 			warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
 			rval = 1;
 			continue;
-		case FTS_SL:			/* Ignore. */
+		case FTS_SL:			/* Ignore unless -h. */ 
+			/* 
+			 * All symlinks we found while doing a physical 
+			 * walk end up here. 
+			 */ 
+			if (!hflag) 
+				continue; 
+			/* 
+			 * Note that if we follow a symlink, fts_info is 
+			 * not FTS_SL but FTS_F or whatever.  And we should 
+			 * use lchflags only for FTS_SL and should use chflags 
+			 * for others. 
+			 */ 
+			change_flags = lchflags; 
+			break; 
+
 		case FTS_SLNONE:
 			/*
 			 * The only symlinks that end up here are ones that
-			 * don't point to anything and ones that we found
-			 * doing a physical walk.
+			 * don't point to anything. Note that if we are 
+			 * doing a physical walk, we never reach here unless 
+			 * we asked to follow explicitly (with -H or -L).
 			 */
 			continue;
 		default:
 			break;
 		}
-		if (oct) {
-			if (!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))
-				continue;
+		if (oct)
+			newflags = set;
+		else {
+			newflags = p->fts_statp->st_flags;
+			newflags |= set;
+			newflags &= clear;
+		}
+		if ((*change_flags)(p->fts_accpath, newflags)) {
+			warn("%s", p->fts_path);
+			rval = 1;
 		}
-		warn("%s", p->fts_path);
-		rval = 1;
 	}
 	if (errno)
 		err(1, "fts_read");
@@ -181,6 +202,6 @@
 usage()
 {
 	(void)fprintf(stderr,
-	    "usage: chflags [-R [-H | -L | -P]] flags file ...\n");
+	    "usage: chflags [-R [-H | -L | -P]] [-h] flags file ...\n");
 	exit(1);
 }
Index: usr.bin/find/function.c
===================================================================
RCS file: /cvs/src/usr.bin/find/function.c,v
retrieving revision 1.39
diff -u -r1.39 function.c
--- usr.bin/find/function.c	26 Mar 2002 12:05:34 -0000	1.39
+++ usr.bin/find/function.c	29 Mar 2002 09:44:22 -0000
@@ -401,7 +401,7 @@
 	if ((entry->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
 	    !(entry->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
 	    geteuid() == 0)
-		chflags(entry->fts_accpath,
+		lchflags(entry->fts_accpath,
 		       entry->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE));
 
 	/* rmdir directories, unlink everything else */
Index: usr.sbin/mtree/compare.c
===================================================================
RCS file: /cvs/src/usr.sbin/mtree/compare.c,v
retrieving revision 1.20
diff -u -r1.20 compare.c
--- usr.sbin/mtree/compare.c	6 Oct 2000 12:48:55 -0000	1.20
+++ usr.sbin/mtree/compare.c	29 Mar 2002 09:44:22 -0000
@@ -60,7 +60,7 @@
 #include "mtree.h"
 #include "extern.h"
 
-extern int uflag;
+extern int Lflag, uflag;
 extern int lineno;
 
 static char *ftype __P((u_int));
@@ -125,7 +125,7 @@
 		(void)printf("%suser expected %lu found %lu",
 		    tab, (u_long)s->st_uid, (u_long)p->fts_statp->st_uid);
 		if (uflag)
-			if (chown(p->fts_accpath, s->st_uid, -1))
+			if ((Lflag ? chown : lchown)(p->fts_accpath, s->st_uid, -1))
 				(void)printf(" not modified: %s\n",
 				    strerror(errno));
 			else
@@ -139,7 +139,7 @@
 		(void)printf("%sgid expected %lu found %lu",
 		    tab, (u_long)s->st_gid, (u_long)p->fts_statp->st_gid);
 		if (uflag)
-			if (chown(p->fts_accpath, -1, s->st_gid))
+			if ((Lflag ? chown : lchown)(p->fts_accpath, -1, s->st_gid))
 				(void)printf(" not modified: %s\n",
 				    strerror(errno));
 			else
@@ -231,7 +231,7 @@
 		free(fflags);
 
 		if (uflag)
-			if (chflags(p->fts_accpath, s->st_flags))
+			if ((Lflag ? chflags : lchflags)(p->fts_accpath, s->st_flags))
 				(void)printf(" not modified: %s\n",
 				    strerror(errno));
 			else
@@ -299,7 +299,7 @@
 	    strcmp(cp = rlink(p->fts_accpath), s->slink)) {
 		LABEL;
 		(void)printf("%slink_ref expected %s found %s\n",
-		      tab, cp, s->slink);
+		      tab, s->slink, cp);
 	}
 	return (label);
 }
Index: usr.sbin/mtree/mtree.8
===================================================================
RCS file: /cvs/src/usr.sbin/mtree/mtree.8,v
retrieving revision 1.35
diff -u -r1.35 mtree.8
--- usr.sbin/mtree/mtree.8	15 Aug 2001 09:09:46 -0000	1.35
+++ usr.sbin/mtree/mtree.8	29 Mar 2002 09:44:22 -0000
@@ -76,7 +76,7 @@
 Don't follow symbolic links in the file hierarchy, instead consider
 the symbolic link itself in any comparisons. This is the default.
 .It Fl U
-Modify the owner, group and permissions of existing files to match
+Modify the owner, group, flags and permissions of existing files to match
 the specification and create any missing directories or symbolic links.
 User, group and permissions must all be specified for missing directories
 to be created.
Index: usr.sbin/mtree/mtree.c
===================================================================
RCS file: /cvs/src/usr.sbin/mtree/mtree.c,v
retrieving revision 1.18
diff -u -r1.18 mtree.c
--- usr.sbin/mtree/mtree.c	25 Sep 2000 16:24:22 -0000	1.18
+++ usr.sbin/mtree/mtree.c	29 Mar 2002 09:44:22 -0000
@@ -58,7 +58,7 @@
 extern long int crc_total;
 
 int ftsoptions = FTS_PHYSICAL;
-int cflag, dflag, eflag, iflag, nflag, qflag, rflag, sflag, uflag, Uflag;
+int cflag, dflag, eflag, iflag, Lflag, nflag, qflag, rflag, sflag, uflag, Uflag;
 u_int keys;
 char fullpath[MAXPATHLEN];
 
@@ -107,6 +107,7 @@
 					keys |= parsekey(p, NULL);
 			break;
 		case 'L':
+			Lflag = 1;
 			ftsoptions &= ~FTS_PHYSICAL;
 			ftsoptions |= FTS_LOGICAL;
 			break;
Index: usr.sbin/mtree/verify.c
===================================================================
RCS file: /cvs/src/usr.sbin/mtree/verify.c,v
retrieving revision 1.15
diff -u -r1.15 verify.c
--- usr.sbin/mtree/verify.c	3 Oct 2000 13:13:47 -0000	1.15
+++ usr.sbin/mtree/verify.c	29 Mar 2002 09:44:22 -0000
@@ -205,6 +205,10 @@
 				if (lchown(path, p->st_uid, p->st_gid))
 					(void)printf("%s: user/group not modified: %s\n",
 					    path, strerror(errno));
+				if ((p->flags & F_FLAGS) && p->st_flags &&
+					lchflags(path, p->st_flags))
+					(void)printf("%s: symlink flags not set: %s\n",
+					    path, strerror(errno));
 				continue;
 			} else if (!(p->flags & F_MODE))
 			    (void)printf(" (directory not created: mode not specified)");
Index: usr.sbin/pkg_install/add/extract.c
===================================================================
RCS file: /cvs/src/usr.sbin/pkg_install/add/extract.c,v
retrieving revision 1.30
diff -u -r1.30 extract.c
--- usr.sbin/pkg_install/add/extract.c	10 Oct 2001 06:58:41 -0000	1.30
+++ usr.sbin/pkg_install/add/extract.c	29 Mar 2002 09:44:22 -0000
@@ -62,7 +62,7 @@
 	if (q->type == PLIST_FILE) {
 	    snprintf(try, FILENAME_MAX, "%s/%s", dir, q->name);
 	    if (make_preserve_name(bup, FILENAME_MAX, name, try) && fexists(bup)) {
-		(void)chflags(try, 0);
+		(void)lchflags(try, 0);
 		(void)unlink(try);
 		if (rename(bup, try))
 		    warnx("rollback: unable to rename %s back to %s", bup, try);
@@ -138,7 +138,7 @@
 		/* first try to rename it into place */
 		snprintf(try, FILENAME_MAX, "%s/%s", Directory, p->name);
 		if (fexists(try)) {
-		    (void)chflags(try, 0);	/* XXX hack - if truly immutable, rename fails */
+		    (void)lchflags(try, 0);	/* XXX hack - if truly immutable, rename fails */
 		    if (preserve && PkgName) {
 			char pf[FILENAME_MAX];
 

--6TrnltStXW4iwmi0--

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020401051046.GC30787>