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:
parent
fd57e549e0
commit
7e81a15205
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=146224
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user