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:
dd 2005-05-14 23:23:10 +00:00
parent c138dacf0c
commit a15208c6fb
2 changed files with 35 additions and 12 deletions

View File

@ -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

View File

@ -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);
}