From nobody@FreeBSD.org  Tue Jul 31 17:29:09 2001
Return-Path: <nobody@FreeBSD.org>
Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21])
	by hub.freebsd.org (Postfix) with ESMTP id C809937B403
	for <freebsd-gnats-submit@FreeBSD.org>; Tue, 31 Jul 2001 17:29:09 -0700 (PDT)
	(envelope-from nobody@FreeBSD.org)
Received: (from nobody@localhost)
	by freefall.freebsd.org (8.11.4/8.11.4) id f710T9L20748;
	Tue, 31 Jul 2001 17:29:09 -0700 (PDT)
	(envelope-from nobody)
Message-Id: <200108010029.f710T9L20748@freefall.freebsd.org>
Date: Tue, 31 Jul 2001 17:29:09 -0700 (PDT)
From: Joshua Goodall <joshua@roughtrade.net>
To: freebsd-gnats-submit@FreeBSD.org
Subject: [patch] lchflags support
X-Send-Pr-Version: www-1.0

>Number:         29355
>Category:       kern
>Synopsis:       [kernel] [patch] add lchflags support
>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:   Tue Jul 31 17:30:00 PDT 2001
>Closed-Date:    Tue Nov 13 20:50:21 UTC 2012
>Last-Modified:  Tue Nov 13 20:50:21 UTC 2012
>Originator:     Joshua Goodall
>Release:        -current
>Organization:
>Environment:
-current (& -stable)
>Description:
Of the general syscall group [lf]?(utimes|chflags|chown|chmod|stat), the interfaces to VOP_GETATTR & VOP_SETATTR, only lchflags is missing. We can however set flags on symlinks with fsdb(8), or by a mount with NetBSD.

see thread "flags on symlinks" in -hackers/-fs for more (start here):
http://docs.freebsd.org/cgi/getmsg.cgi?fetch=0+0+archive/2001/freebsd-hackers/20010729.freebsd-hackers

bde effectively gave me the go-ahead, I think.

Some code is from NetBSD but this patch is a more complete treatment of all possible side-effects in the base system.

Reviewed-by: cmc
"Review-already-requested-from": bde, adrian

>How-To-Repeat:
n/a
>Fix:
http://www.roughtrade.net/bsd/README.lchflags
http://www.roughtrade.net/bsd/lchflags.diff

>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->adrian 
Responsible-Changed-By: adrian 
Responsible-Changed-When: Wed Aug 29 03:28:23 PDT 2001 
Responsible-Changed-Why:  
I already told Joshua that I'd take care of this. 
(when I get home. :-) 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=29355 

From: Joshua Goodall <joshua@roughtrade.net>
To: freebsd-gnats-submit@FreeBSD.org
Cc:  
Subject: Re: kern/29355 lchflags syscall and supporting userland
Date: Mon, 1 Apr 2002 15:19:33 +1000

 [resent to correct gnats address, oops]
 
 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
 
 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];
Responsible-Changed-From-To: adrian->alfred 
Responsible-Changed-By: benno 
Responsible-Changed-When: Tue Apr 16 23:32:04 PDT 2002 
Responsible-Changed-Why:  
Josh asked me to review this, but I don't feel comfortable as it's not an area 
I'm familiar with.  Alfred has offered to have a go at it. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=29355 

From: Joshua Goodall <joshua@roughtrade.net>
To: freebsd-gnats-submit@FreeBSD.org
Cc:  
Subject: Re: kern/29355 lchflags syscall and supporting userland
Date: Mon, 6 May 2002 11:40:20 +1000

 Update of this patch to prevent bitrot.
 
 n.b. mux has committed an incomplete variant today without credit.
 
 Joshua
 
 Index: sys/kern/syscalls.c
 ===================================================================
 RCS file: /cvs/src/sys/kern/syscalls.c,v
 retrieving revision 1.108
 diff -u -u -r1.108 syscalls.c
 --- sys/kern/syscalls.c	17 Apr 2002 13:06:36 -0000	1.108
 +++ sys/kern/syscalls.c	18 Apr 2002 01:40:46 -0000
 @@ -2,8 +2,8 @@
   * System call names.
   *
   * DO NOT EDIT-- this file is automatically generated.
 - * $FreeBSD: src/sys/kern/syscalls.c,v 1.108 2002/04/17 13:06:36 mux Exp $
 - * created from FreeBSD: src/sys/kern/syscalls.master,v 1.109 2002/04/14 05:31:47 alc Exp 
 + * $FreeBSD$
 + * created from FreeBSD: src/sys/kern/syscalls.master,v 1.110 2002/04/17 13:05:13 mux Exp 
   */
  
  char *syscallnames[] = {
 @@ -398,4 +398,5 @@
  	"#388",			/* 388 = __mac_set_fd */
  	"#389",			/* 389 = __mac_set_file */
  	"kenv",			/* 390 = kenv */
 +	"lchflags",			/* 391 = lchflags */
  };
 Index: sys/kern/vfs_syscalls.c
 ===================================================================
 RCS file: /cvs/src/sys/kern/vfs_syscalls.c,v
 retrieving revision 1.250
 diff -u -u -r1.250 vfs_syscalls.c
 --- sys/kern/vfs_syscalls.c	4 May 2002 19:50:09 -0000	1.250
 +++ sys/kern/vfs_syscalls.c	5 May 2002 15:12:50 -0000
 @@ -2826,7 +2826,7 @@
  }
  
  /*
 - * Common implementation code for chflags() and fchflags().
 + * Common implementation code for chflags(), lchflags and fchflags().
   */
  static int
  setfflags(td, vp, flags)
 @@ -2884,6 +2884,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/kern/syscalls.master
 ===================================================================
 RCS file: /cvs/src/sys/kern/syscalls.master,v
 retrieving revision 1.110
 diff -u -u -r1.110 syscalls.master
 --- sys/kern/syscalls.master	17 Apr 2002 13:05:13 -0000	1.110
 +++ sys/kern/syscalls.master	17 Apr 2002 22:09:29 -0000
 @@ -561,3 +561,4 @@
  389	UNIMPL	BSD	__mac_set_file
  390	STD	BSD	{ int kenv(int what, const char *name, char *value, \
  			    int len); }
 +391	STD	BSD	{ int lchflags(char *path, int flags); }
 Index: sys/kern/init_sysent.c
 ===================================================================
 RCS file: /cvs/src/sys/kern/init_sysent.c,v
 retrieving revision 1.121
 diff -u -u -r1.121 init_sysent.c
 --- sys/kern/init_sysent.c	17 Apr 2002 13:06:35 -0000	1.121
 +++ sys/kern/init_sysent.c	18 Apr 2002 01:40:46 -0000
 @@ -2,8 +2,8 @@
   * System call switch table.
   *
   * DO NOT EDIT-- this file is automatically generated.
 - * $FreeBSD: src/sys/kern/init_sysent.c,v 1.121 2002/04/17 13:06:35 mux Exp $
 - * created from FreeBSD: src/sys/kern/syscalls.master,v 1.109 2002/04/14 05:31:47 alc Exp 
 + * $FreeBSD$
 + * created from FreeBSD: src/sys/kern/syscalls.master,v 1.110 2002/04/17 13:05:13 mux Exp 
   */
  
  #include "opt_compat.h"
 @@ -413,4 +413,5 @@
  	{ 0, (sy_call_t *)nosys },			/* 388 = __mac_set_fd */
  	{ 0, (sy_call_t *)nosys },			/* 389 = __mac_set_file */
  	{ AS(kenv_args), (sy_call_t *)kenv },		/* 390 = kenv */
 +	{ AS(lchflags_args), (sy_call_t *)lchflags },	/* 391 = lchflags */
  };
 Index: sys/sys/stat.h
 ===================================================================
 RCS file: /cvs/src/sys/sys/stat.h,v
 retrieving revision 1.23
 diff -u -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.107
 diff -u -u -r1.107 syscall.h
 --- sys/sys/syscall.h	17 Apr 2002 13:06:36 -0000	1.107
 +++ sys/sys/syscall.h	18 Apr 2002 01:40:46 -0000
 @@ -2,8 +2,8 @@
   * System call numbers.
   *
   * DO NOT EDIT-- this file is automatically generated.
 - * $FreeBSD: src/sys/sys/syscall.h,v 1.107 2002/04/17 13:06:36 mux Exp $
 - * created from FreeBSD: src/sys/kern/syscalls.master,v 1.109 2002/04/14 05:31:47 alc Exp 
 + * $FreeBSD$
 + * created from FreeBSD: src/sys/kern/syscalls.master,v 1.110 2002/04/17 13:05:13 mux Exp 
   */
  
  #define	SYS_syscall	0
 @@ -304,4 +304,5 @@
  #define	SYS_thread_wakeup	382
  #define	SYS_kse_yield	383
  #define	SYS_kenv	390
 -#define	SYS_MAXSYSCALL	391
 +#define	SYS_lchflags	391
 +#define	SYS_MAXSYSCALL	392
 Index: sys/sys/sysproto.h
 ===================================================================
 RCS file: /cvs/src/sys/sys/sysproto.h,v
 retrieving revision 1.99
 diff -u -u -r1.99 sysproto.h
 --- sys/sys/sysproto.h	17 Apr 2002 13:06:36 -0000	1.99
 +++ sys/sys/sysproto.h	18 Apr 2002 01:40:46 -0000
 @@ -2,8 +2,8 @@
   * System call prototypes.
   *
   * DO NOT EDIT-- this file is automatically generated.
 - * $FreeBSD: src/sys/sys/sysproto.h,v 1.99 2002/04/17 13:06:36 mux Exp $
 - * created from FreeBSD: src/sys/kern/syscalls.master,v 1.109 2002/04/14 05:31:47 alc Exp 
 + * $FreeBSD$
 + * created from FreeBSD: src/sys/kern/syscalls.master,v 1.110 2002/04/17 13:05:13 mux Exp 
   */
  
  #ifndef _SYS_SYSPROTO_H_
 @@ -1111,6 +1111,10 @@
  	char value_l_[PADL_(char *)]; char * value; char value_r_[PADR_(char *)];
  	char len_l_[PADL_(int)]; int len; char len_r_[PADR_(int)];
  };
 +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 *);
 @@ -1361,6 +1365,7 @@
  int	thread_wakeup(struct thread *, struct thread_wakeup_args *);
  int	kse_yield(struct thread *, struct kse_yield_args *);
  int	kenv(struct thread *, struct kenv_args *);
 +int	lchflags(struct thread *, struct lchflags_args *);
  
  #ifdef COMPAT_43
  
 Index: sys/sys/syscall.mk
 ===================================================================
 RCS file: /cvs/src/sys/sys/syscall.mk,v
 retrieving revision 1.62
 diff -u -u -r1.62 syscall.mk
 --- sys/sys/syscall.mk	17 Apr 2002 13:06:36 -0000	1.62
 +++ sys/sys/syscall.mk	18 Apr 2002 01:40:46 -0000
 @@ -1,7 +1,7 @@
  # FreeBSD system call names.
  # DO NOT EDIT-- this file is automatically generated.
 -# $FreeBSD: src/sys/sys/syscall.mk,v 1.62 2002/04/17 13:06:36 mux Exp $
 -# created from FreeBSD: src/sys/kern/syscalls.master,v 1.109 2002/04/14 05:31:47 alc Exp 
 +# $FreeBSD$
 +# created from FreeBSD: src/sys/kern/syscalls.master,v 1.110 2002/04/17 13:05:13 mux Exp 
  MIASM =  \
  	syscall.o \
  	exit.o \
 @@ -253,4 +253,5 @@
  	kse_new.o \
  	thread_wakeup.o \
  	kse_yield.o \
 -	kenv.o
 +	kenv.o \
 +	lchflags.o
 Index: bin/cp/utils.c
 ===================================================================
 RCS file: /cvs/src/bin/cp/utils.c,v
 retrieving revision 1.34
 diff -u -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 -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 -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 -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 -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.32
 diff -u -u -r1.32 tape.c
 --- sbin/restore/tape.c	2 May 2002 17:39:19 -0000	1.32
 +++ sbin/restore/tape.c	6 May 2002 01:12:31 -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) {
 @@ -565,14 +569,6 @@
  		return (genliteraldir(name, curfile.ino));
  
  	case IFLNK:
 -	  {
 -		uid_t uid;
 -		gid_t gid;
 -		int ret;
 -
 -		uid = curfile.dip->di_uid;
 -		gid = curfile.dip->di_gid;
 -
  		lnkbuf[0] = '\0';
  		pathlen = 0;
  		getfile(xtrlnkfile, xtrlnkskip);
 @@ -581,17 +577,14 @@
  			    "%s: zero length symbolic link (ignored)\n", name);
  			return (GOOD);
  		}
 -		ret = linkit(lnkbuf, name, SYMLINK);
 -		if (ret == GOOD) {
 -			if (lchown(name, uid, gid))
 -				perror(name);
 -			if (lchmod(name, mode))
 -				perror(name);
 -			lutimes(name, timep);
 -		}
 -		/* symbolic link doesn't have any flags */
 -		return (ret);
 -	  }
 +		if (linkit(lnkbuf, name, SYMLINK) == GOOD) {
 +			(void) lchown(name, uid, gid);
 +			(void) lchmod(name, mode);
 +			(void) lutimes(name, timep);
 +			(void) lchflags(name, flags);
 +			return (GOOD);
 +		}
 +		return (FAIL);
  
  	case IFIFO:
  		vprintf(stdout, "extract fifo %s\n", name);
 @@ -607,9 +600,9 @@
  			skipfile();
  			return (FAIL);
  		}
 -		(void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid);
 +		(void) chown(name, uid, gid);
  		(void) chmod(name, mode);
 -		utimes(name, timep);
 +		(void) utimes(name, timep);
  		(void) chflags(name, flags);
  		skipfile();
  		return (GOOD);
 @@ -629,9 +622,9 @@
  			skipfile();
  			return (FAIL);
  		}
 -		(void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid);
 +		(void) chown(name, uid, gid);
  		(void) chmod(name, mode);
 -		utimes(name, timep);
 +		(void) utimes(name, timep);
  		(void) chflags(name, flags);
  		skipfile();
  		return (GOOD);
 @@ -651,7 +644,7 @@
  			skipfile();
  			return (FAIL);
  		}
 -		(void) fchown(ofile, curfile.dip->di_uid, curfile.dip->di_gid);
 +		(void) fchown(ofile, uid, gid);
  		(void) fchmod(ofile, mode);
  		getfile(xtrfile, xtrskip);
  		(void) close(ofile);
 Index: usr.bin/chflags/chflags.1
 ===================================================================
 RCS file: /cvs/src/usr.bin/chflags/chflags.1,v
 retrieving revision 1.14
 diff -u -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 -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.42
 diff -u -u -r1.42 function.c
 --- usr.bin/find/function.c	2 Apr 2002 10:45:34 -0000	1.42
 +++ usr.bin/find/function.c	8 Apr 2002 12:00:38 -0000
 @@ -400,7 +400,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 -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 -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 -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 -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.31
 diff -u -u -r1.31 extract.c
 --- usr.sbin/pkg_install/add/extract.c	1 Apr 2002 09:39:05 -0000	1.31
 +++ usr.sbin/pkg_install/add/extract.c	8 Apr 2002 12:01:19 -0000
 @@ -60,7 +60,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);
 @@ -136,7 +136,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];
  
Responsible-Changed-From-To: alfred->mux 
Responsible-Changed-By: rwatson 
Responsible-Changed-When: Sun May 5 20:09:20 PDT 2002 
Responsible-Changed-Why:  
Maxime committed a parallel (and largely identical) version of the kernel 
code, but didn't know about this PR.  He should go ahead and do the userland 
stuff documented here. 



http://www.freebsd.org/cgi/query-pr.cgi?pr=29355 

From: Joshua Goodall <joshua@roughtrade.net>
To: FreeBSD-gnats-submit@FreeBSD.org, mux@freebsd.org
Cc:  
Subject: Re: kern/29355: [patch] lchflags support
Date: Wed, 4 Dec 2002 12:17:42 +1100

 --2fHTh5uZTiUOsy+g
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 Latest rev of this patch attached.
 
 J
 
 --2fHTh5uZTiUOsy+g
 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.39
 diff -u -r1.39 utils.c
 --- bin/cp/utils.c	18 Oct 2002 14:45:00 -0000	1.39
 +++ bin/cp/utils.c	30 Nov 2002 13:02:57 -0000
 @@ -211,7 +211,7 @@
  		warn("symlink: %s", llink);
  		return (1);
  	}
 -	return (0);
 +	return (pflag ? setfile(p->fts_statp, 0) : 0);
  }
  
  int
 @@ -256,11 +256,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;
 @@ -275,7 +275,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;
 @@ -284,14 +284,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/rm/rm.c
 ===================================================================
 RCS file: /cvs/src/bin/rm/rm.c,v
 retrieving revision 1.42
 diff -u -r1.42 rm.c
 --- bin/rm/rm.c	21 Aug 2002 17:32:42 -0000	1.42
 +++ bin/rm/rm.c	10 Sep 2002 13:41:37 -0000
 @@ -239,7 +239,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) {
  			/*
 @@ -329,7 +329,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: lib/libc/sys/chflags.2
 ===================================================================
 RCS file: /cvs/src/lib/libc/sys/chflags.2,v
 retrieving revision 1.22
 diff -u -r1.22 chflags.2
 --- lib/libc/sys/chflags.2	15 Jul 2002 20:59:12 -0000	1.22
 +++ lib/libc/sys/chflags.2	10 Sep 2002 13:41:37 -0000
 @@ -48,9 +48,9 @@
  .Ft int
  .Fn chflags "const char *path"  "u_long flags"
  .Ft int
 -.Fn lchflags "const char *path" "int 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
 @@ -186,3 +186,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.37
 diff -u -r1.37 tape.c
 --- sbin/restore/tape.c	25 Sep 2002 04:06:37 -0000	1.37
 +++ sbin/restore/tape.c	30 Nov 2002 13:09:50 -0000
 @@ -574,6 +574,7 @@
  			(void) lchmod(name, mode);
  			(void) lutimes(name, ctimep);
  			(void) lutimes(name, mtimep);
 +			(void) lchflags(name, flags);
  			return (GOOD);
  		}
  		return (FAIL);
 Index: sys/kern/vfs_syscalls.c
 ===================================================================
 RCS file: /cvs/src/sys/kern/vfs_syscalls.c,v
 retrieving revision 1.297
 diff -u -r1.297 vfs_syscalls.c
 --- sys/kern/vfs_syscalls.c	27 Oct 2002 23:23:51 -0000	1.297
 +++ sys/kern/vfs_syscalls.c	30 Nov 2002 13:11:52 -0000
 @@ -1908,7 +1908,7 @@
  }
  
  /*
 - * Common implementation code for chflags() and fchflags().
 + * Common implementation code for chflags(), lchflags and fchflags().
   */
  static int
  setfflags(td, vp, flags)
 @@ -1982,8 +1982,15 @@
  }
  
  /*
 - * Same as chflags() but doesn't follow symlinks.
 + * 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;
 Index: sys/sys/stat.h
 ===================================================================
 RCS file: /cvs/src/sys/sys/stat.h,v
 retrieving revision 1.30
 diff -u -r1.30 stat.h
 --- sys/sys/stat.h	11 Oct 2002 15:52:14 -0000	1.30
 +++ sys/sys/stat.h	1 Dec 2002 08:31:40 -0000
 @@ -273,7 +273,7 @@
  
  #ifndef _POSIX_SOURCE
  int	chflags(const char *, unsigned long);
 -int	lchflags(const char *, int);
 +int	lchflags(const char *, unsigned long);
  int	fchflags(int, unsigned long);
  int	fchmod(int, mode_t);
  int	lchmod(const char *, mode_t);
 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	10 Sep 2002 13:41:38 -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.16
 diff -u -r1.16 chflags.c
 --- usr.bin/chflags/chflags.c	4 Sep 2002 23:28:58 -0000	1.16
 +++ usr.bin/chflags/chflags.c	10 Sep 2002 13:41:38 -0000
 @@ -64,13 +64,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;
 @@ -87,6 +88,9 @@
  		case 'R':
  			Rflag = 1;
  			break;
 +		case 'h':
 +			hflag = 1;
 +			break;
  		case '?':
  		default:
  			usage();
 @@ -106,7 +110,7 @@
  			fts_options |= FTS_LOGICAL;
  		}
  	} else
 -		fts_options = FTS_LOGICAL;
 +		fts_options = hflag ? FTS_PHYSICAL : FTS_LOGICAL;
  
  	flags = *argv;
  	if (*flags >= '0' && *flags <= '7') {
 @@ -131,6 +135,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. */
 @@ -146,28 +151,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");
 @@ -178,6 +199,6 @@
  usage(void)
  {
  	(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.47
 diff -u -r1.47 function.c
 --- usr.bin/find/function.c	10 Aug 2002 20:19:03 -0000	1.47
 +++ usr.bin/find/function.c	10 Sep 2002 13:41:38 -0000
 @@ -403,7 +403,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.23
 diff -u -r1.23 compare.c
 --- usr.sbin/mtree/compare.c	15 Jul 2002 12:17:31 -0000	1.23
 +++ usr.sbin/mtree/compare.c	10 Sep 2002 13:41:38 -0000
 @@ -61,7 +61,7 @@
  #include "mtree.h"
  #include "extern.h"
  
 -extern int uflag;
 +extern int Lflag, uflag;
  extern int lineno;
  
  static const char *ftype(u_int);
 @@ -127,7 +127,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
 @@ -141,7 +141,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
 @@ -233,7 +233,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
 @@ -301,7 +301,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.38
 diff -u -r1.38 mtree.8
 --- usr.sbin/mtree/mtree.8	14 Jul 2002 14:44:30 -0000	1.38
 +++ usr.sbin/mtree/mtree.8	10 Sep 2002 13:41:38 -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.20
 diff -u -r1.20 mtree.c
 --- usr.sbin/mtree/mtree.c	11 Jul 2002 18:42:53 -0000	1.20
 +++ usr.sbin/mtree/mtree.c	10 Sep 2002 13:41:38 -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];
  
 @@ -105,6 +105,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.17
 diff -u -r1.17 verify.c
 --- usr.sbin/mtree/verify.c	11 Jul 2002 18:42:53 -0000	1.17
 +++ usr.sbin/mtree/verify.c	10 Sep 2002 13:41:38 -0000
 @@ -206,6 +206,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.35
 diff -u -r1.35 extract.c
 --- usr.sbin/pkg_install/add/extract.c	2 Aug 2002 17:28:02 -0000	1.35
 +++ usr.sbin/pkg_install/add/extract.c	10 Sep 2002 13:41:38 -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];
  
 
 --2fHTh5uZTiUOsy+g--
State-Changed-From-To: open->feedback 
State-Changed-By: arundel 
State-Changed-When: Sat Aug 21 00:22:46 UTC 2010 
State-Changed-Why:  
It appears lchflags support has now been fully integrated into FreeBSD. 
However this needs to be confirmed. Also it is unclear, if lchflags support is 
present in all branches. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=29355 

From: Garrett Cooper <gcooper@FreeBSD.org>
To: bug-followup@FreeBSD.org, joshua@roughtrade.net
Cc:  
Subject: Re: kern/29355: [kernel] [patch] add lchflags support
Date: Mon, 17 Jan 2011 13:55:25 -0800

     lchflags was added to base over 8 yerars ago [1]. Please close this PR.
 Thanks,
 -Garrett
 
 1. http://svn.freebsd.org/viewvc/base?view=revision&revision=96085

From: Joshua Goodall <joshua@roughtrade.net>
To: Garrett Cooper <gcooper@FreeBSD.org>
Cc: <bug-followup@FreeBSD.org>
Subject: Re: kern/29355: [kernel] [patch] add lchflags support
Date: Tue, 18 Jan 2011 11:07:12 +1100

  On Mon, 17 Jan 2011 13:55:25 -0800, Garrett Cooper 
  <gcooper@FreeBSD.org> wrote:
 > lchflags was added to base over 8 yerars ago [1]. Please close this 
 > PR.
 > Thanks,
 > -Garrett
 >
 > 1. http://svn.freebsd.org/viewvc/base?view=revision&revision=96085
 
  Yet after all these years the PR has still not been fully committed. 
  The gap in mtree's -L implementation may still remain and pkg_install 
  was not updated.
 
  Had it been fully committed at the time then PRs bin/111226 and 
  bin/101660 may not have arisen.
 
  The syscall committed has a signature different to that in the PR, but 
  I doubt this will be fixed.
 
  Thanks
  Josh
 

From: Garrett Cooper <gcooper@FreeBSD.org>
To: Joshua Goodall <joshua@roughtrade.net>
Cc: bug-followup@freebsd.org
Subject: Re: kern/29355: [kernel] [patch] add lchflags support
Date: Mon, 17 Jan 2011 16:46:14 -0800

 On Mon, Jan 17, 2011 at 4:07 PM, Joshua Goodall <joshua@roughtrade.net> wrote:
 >
 > On Mon, 17 Jan 2011 13:55:25 -0800, Garrett Cooper <gcooper@FreeBSD.org>
 > wrote:
 >>
 >> lchflags was added to base over 8 years ago [1]. Please close this PR.
 >>
 >> 1. http://svn.freebsd.org/viewvc/base?view=revision&revision=96085
 >
 > Yet after all these years the PR has still not been fully committed. The gap
 > in mtree's -L implementation may still remain and pkg_install was not
 > updated.
 
     Some of this logic is in the right direction, but it warrants
 closer inspection as this may break utilities by accident. I'll see
 whether or not it's the case and open another PR and/or attach it to
 the one I have open for mtree -L not doing the right thing.
 
 > Had it been fully committed at the time then PRs bin/111226 and bin/101660
 > may not have arisen.
 
     You may be right, but unfortunately I can't change mistakes made
 in the past :(.
 
 > The syscall committed has a signature different to that in the PR, but I
 > doubt this will be fixed.
 
     Well, that awesome inconsistency is going to be fixed soon (I
 hope) via a patch I sent to fs@ as the calls should all be the same
 and there's a bi-arch issue when using unsigned long as the flags
 argument in chflags(2) / fchflags(2). It should be listed in the
 archives in ~12 hours:
 http://lists.freebsd.org/pipermail/freebsd-fs/2011-January/thread.html
 .
 Thanks,
 -Garrett
Responsible-Changed-From-To: mux->freebsd-bugs 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Thu Jun 23 18:03:56 UTC 2011 
Responsible-Changed-Why:  
mux has returned his commit bit for safekeeping. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=29355 
State-Changed-From-To: feedback->closed 
State-Changed-By: eadler 
State-Changed-When: Tue Nov 13 20:50:19 UTC 2012 
State-Changed-Why:  
at this point mtree will be  replaced with      the netbsd one and so 
many other changes have or will be made that this PR need not be open 

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