diff options
author | dd <dd@FreeBSD.org> | 2005-05-14 23:23:10 +0000 |
---|---|---|
committer | dd <dd@FreeBSD.org> | 2005-05-14 23:23:10 +0000 |
commit | a15208c6fbb88b817909d4ed60bc476644076486 (patch) | |
tree | fb692eca432b08ed003fc04bef1bb4e8b0f9d483 /bin/chflags | |
parent | c138dacf0cfab71856dbdc3a17fafb8d56f55dca (diff) | |
download | FreeBSD-src-a15208c6fbb88b817909d4ed60bc476644076486.zip FreeBSD-src-a15208c6fbb88b817909d4ed60bc476644076486.tar.gz |
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
Diffstat (limited to 'bin/chflags')
-rw-r--r-- | bin/chflags/chflags.1 | 17 | ||||
-rw-r--r-- | bin/chflags/chflags.c | 30 |
2 files changed, 35 insertions, 12 deletions
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); } |