From owner-freebsd-bugs Sun Mar 31 21:11:44 2002 Delivered-To: freebsd-bugs@freebsd.org Received: from yello.shallow.net (yello.shallow.net [203.18.243.120]) by hub.freebsd.org (Postfix) with ESMTP id 9BFAA37B41E for ; Sun, 31 Mar 2002 21:10:56 -0800 (PST) Received: by yello.shallow.net (Postfix, from userid 1001) id 018BD2A69; Mon, 1 Apr 2002 15:10:47 +1000 (EST) Date: Mon, 1 Apr 2002 15:10:46 +1000 From: Joshua Goodall To: freebsd-bugs@FreeBSD.org Subject: Re: kern/29355 lchflags syscall and supporting userland Message-ID: <20020401051046.GC30787@roughtrade.net> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="6TrnltStXW4iwmi0" Content-Disposition: inline User-Agent: Mutt/1.3.28i Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org --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