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
This commit is contained in:
Dima Dorfman 2005-05-14 23:23:10 +00:00
parent fd57e549e0
commit 7e81a15205
2 changed files with 35 additions and 12 deletions

View File

@ -32,7 +32,7 @@
.\" @(#)chflags.1 8.4 (Berkeley) 5/2/95 .\" @(#)chflags.1 8.4 (Berkeley) 5/2/95
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd February 24, 2005 .Dd May 14, 2005
.Dt CHFLAGS 1 .Dt CHFLAGS 1
.Os .Os
.Sh NAME .Sh NAME
@ -40,6 +40,7 @@
.Nd change file flags .Nd change file flags
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm .Nm
.Op Fl h
.Oo .Oo
.Fl R .Fl R
.Op Fl H | Fl L | Fl P .Op Fl H | Fl L | Fl P
@ -61,6 +62,11 @@ If the
.Fl R .Fl R
option is specified, symbolic links on the command line are followed. option is specified, symbolic links on the command line are followed.
(Symbolic links encountered in the tree traversal are not 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 .It Fl L
If the If the
.Fl R .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) clear the nodump flag (owner or super-user only)
.El .El
.Pp .Pp
Symbolic links do not have flags, so unless the Unless the
.Fl H .Fl H ,
.Fl L ,
or or
.Fl L .Fl h
option is set, options are given,
.Nm .Nm
on a symbolic link always succeeds and has no effect. on a symbolic link always succeeds and has no effect.
The The

View File

@ -62,11 +62,12 @@ main(int argc, char *argv[])
FTSENT *p; FTSENT *p;
u_long clear, set; u_long clear, set;
long val; long val;
int Hflag, Lflag, Rflag, ch, fts_options, oct, rval; int Hflag, Lflag, Rflag, hflag, ch, fts_options, oct, rval;
char *flags, *ep; char *flags, *ep;
int (*change_flags)(const char *, unsigned long);
Hflag = Lflag = Rflag = 0; Hflag = Lflag = Rflag = hflag = 0;
while ((ch = getopt(argc, argv, "HLPR")) != -1) while ((ch = getopt(argc, argv, "HLPRh")) != -1)
switch (ch) { switch (ch) {
case 'H': case 'H':
Hflag = 1; Hflag = 1;
@ -82,6 +83,9 @@ main(int argc, char *argv[])
case 'R': case 'R':
Rflag = 1; Rflag = 1;
break; break;
case 'h':
hflag = 1;
break;
case '?': case '?':
default: default:
usage(); usage();
@ -94,6 +98,9 @@ main(int argc, char *argv[])
if (Rflag) { if (Rflag) {
fts_options = FTS_PHYSICAL; fts_options = FTS_PHYSICAL;
if (hflag)
errx(1, "the -R and -h options "
"may not be specified together");
if (Hflag) if (Hflag)
fts_options |= FTS_COMFOLLOW; fts_options |= FTS_COMFOLLOW;
if (Lflag) { if (Lflag) {
@ -103,6 +110,12 @@ main(int argc, char *argv[])
} else } else
fts_options = FTS_LOGICAL; 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; flags = *argv;
if (*flags >= '0' && *flags <= '7') { if (*flags >= '0' && *flags <= '7') {
errno = 0; errno = 0;
@ -147,17 +160,20 @@ main(int argc, char *argv[])
* don't point to anything and ones that we found * don't point to anything and ones that we found
* doing a physical walk. * doing a physical walk.
*/ */
continue; if (!hflag)
continue;
/* FALLTHROUGH */
default: default:
break; break;
} }
if (oct) { if (oct) {
if (!chflags(p->fts_accpath, set)) if (!(*change_flags)(p->fts_accpath, set))
continue; continue;
} else { } else {
p->fts_statp->st_flags |= set; p->fts_statp->st_flags |= set;
p->fts_statp->st_flags &= clear; 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; continue;
} }
warn("%s", p->fts_path); warn("%s", p->fts_path);
@ -172,6 +188,6 @@ void
usage(void) usage(void)
{ {
(void)fprintf(stderr, (void)fprintf(stderr,
"usage: chflags [-R [-H | -L | -P]] flags file ...\n"); "usage: chflags [-h] [-R [-H | -L | -P]] flags file ...\n");
exit(1); exit(1);
} }