From a15208c6fbb88b817909d4ed60bc476644076486 Mon Sep 17 00:00:00 2001 From: dd Date: Sat, 14 May 2005 23:23:10 +0000 Subject: Add an interface to the lchflags(2) syscall. The new -h option is analogous to chmod(1)'s -h. It allows setting flags on symbolic links, which *do* exist in 5.x+ despite a claim to the contrary in the chflags(1) man page. Suggested by: Chris Dillon --- bin/chflags/chflags.1 | 17 ++++++++++++----- bin/chflags/chflags.c | 30 +++++++++++++++++++++++------- 2 files changed, 35 insertions(+), 12 deletions(-) (limited to 'bin/chflags') diff --git a/bin/chflags/chflags.1 b/bin/chflags/chflags.1 index 426c98e..e1200db 100644 --- a/bin/chflags/chflags.1 +++ b/bin/chflags/chflags.1 @@ -32,7 +32,7 @@ .\" @(#)chflags.1 8.4 (Berkeley) 5/2/95 .\" $FreeBSD$ .\" -.Dd February 24, 2005 +.Dd May 14, 2005 .Dt CHFLAGS 1 .Os .Sh NAME @@ -40,6 +40,7 @@ .Nd change file flags .Sh SYNOPSIS .Nm +.Op Fl h .Oo .Fl R .Op Fl H | Fl L | Fl P @@ -61,6 +62,11 @@ If the .Fl R option is specified, symbolic links on the command line are followed. (Symbolic links encountered in the tree traversal are not followed.) +.It Fl h +If the +.Ar file +is a symbolic link, +change the mode of the link itself rather than the file to which it points. .It Fl L If the .Fl R @@ -114,11 +120,12 @@ clear the user immutable flag (owner or super-user only) clear the nodump flag (owner or super-user only) .El .Pp -Symbolic links do not have flags, so unless the -.Fl H +Unless the +.Fl H , +.Fl L , or -.Fl L -option is set, +.Fl h +options are given, .Nm on a symbolic link always succeeds and has no effect. The diff --git a/bin/chflags/chflags.c b/bin/chflags/chflags.c index 18c3cf6..273ba4c 100644 --- a/bin/chflags/chflags.c +++ b/bin/chflags/chflags.c @@ -62,11 +62,12 @@ main(int argc, char *argv[]) FTSENT *p; u_long clear, set; long val; - int Hflag, Lflag, Rflag, ch, fts_options, oct, rval; + int Hflag, Lflag, Rflag, hflag, ch, fts_options, oct, rval; char *flags, *ep; + int (*change_flags)(const char *, unsigned long); - Hflag = Lflag = Rflag = 0; - while ((ch = getopt(argc, argv, "HLPR")) != -1) + Hflag = Lflag = Rflag = hflag = 0; + while ((ch = getopt(argc, argv, "HLPRh")) != -1) switch (ch) { case 'H': Hflag = 1; @@ -82,6 +83,9 @@ main(int argc, char *argv[]) case 'R': Rflag = 1; break; + case 'h': + hflag = 1; + break; case '?': default: usage(); @@ -94,6 +98,9 @@ main(int argc, char *argv[]) if (Rflag) { fts_options = FTS_PHYSICAL; + if (hflag) + errx(1, "the -R and -h options " + "may not be specified together"); if (Hflag) fts_options |= FTS_COMFOLLOW; if (Lflag) { @@ -103,6 +110,12 @@ main(int argc, char *argv[]) } else fts_options = FTS_LOGICAL; + /* XXX: Why don't chflags and lchflags have compatible prototypes? */ + if (hflag) + change_flags = (int (*)(const char *, unsigned long))lchflags; + else + change_flags = chflags; + flags = *argv; if (*flags >= '0' && *flags <= '7') { errno = 0; @@ -147,17 +160,20 @@ main(int argc, char *argv[]) * don't point to anything and ones that we found * doing a physical walk. */ - continue; + if (!hflag) + continue; + /* FALLTHROUGH */ default: break; } if (oct) { - if (!chflags(p->fts_accpath, set)) + if (!(*change_flags)(p->fts_accpath, set)) continue; } else { p->fts_statp->st_flags |= set; p->fts_statp->st_flags &= clear; - if (!chflags(p->fts_accpath, (u_long)p->fts_statp->st_flags)) + if (!(*change_flags)(p->fts_accpath, + (u_long)p->fts_statp->st_flags)) continue; } warn("%s", p->fts_path); @@ -172,6 +188,6 @@ void usage(void) { (void)fprintf(stderr, - "usage: chflags [-R [-H | -L | -P]] flags file ...\n"); + "usage: chflags [-h] [-R [-H | -L | -P]] flags file ...\n"); exit(1); } -- cgit v1.1