The implementation of -flags was broken and did not match the (poorly)

documented behavior.  Only a certain set of file flags were recognized,
and "no" flags did not match files that have corresponding flags bits
turned off.

Fix and extend the -flags functionality as follows:

: -flags [-|+]<flags>,<notflags>
:    The flags are specified using symbolic names (see chflags(1)).
:    Those with the "no" prefix (except "nodump") are said to be
:    <notflags>.  Flags in <flags> are checked to be set, and flags in
:    <notflags> are checked to be not set.  Note that this is different
:    from -perm, which only allows the user to specify mode bits that
:    are set.
:
:    If flags are preceded by a dash (``-''), this primary evaluates
:    to true if at least all of the bits in <flags> and none of the bits
:    in <notflags> are set in the file's flags bits.  If flags are pre-
:    ceded by a plus (``+''), this primary evaluates to true if any of
:    the bits in <flags> is set in the file's flags bits, or any of the
:    bits in <notflags> is not set in the file's flags bits.  Otherwise,
:    this primary evaluates to true if the bits in <flags> exactly match
:    the file's flags bits, and none of the <flags> bits match those of
:    <notflags>.

MFC after:	2 weeks
This commit is contained in:
Ruslan Ermilov 2001-09-04 16:09:01 +00:00
parent db2077f8e1
commit 7fd5ee41e3
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=82972
3 changed files with 79 additions and 31 deletions

View File

@ -243,20 +243,50 @@ The filename substituted for
the string
.Dq Li {}
is not qualified.
.It Ic -flags Op Fl Ns Ar flags
This primary evaluates to true if exactly those flags of the file are
set which are also set using the specified
.Ar flags
(if these are not preceded by a dash
.Pq Dq Li - ,
or if they match the specified flags (if these are preceded by a dash).
The
.Ar flags
are specified using symbolic names (see
.It Ic -flags Oo Cm - Ns | Ns Cm + Oc Ns Ar flags , Ns Ar notflags
The flags are specified using symbolic names (see
.Xr chflags 1 ) .
Those with the
.Qq Li no
prefix (except
.Qq Li nodump )
are said to be
.Ar notflags .
Flags in
.Ar flags
are checked to be set, and flags in
.Ar notflags
are checked to be not set.
Note that this is different from
.Ic -perm ,
which only allows you to specify flags which are set.
which only allows the user to specify mode bits that are set.
.Pp
If flags are preceded by a dash
.Pq Dq Li - ,
this primary evaluates to true
if at least all of the bits in
.Ar flags
and none of the bits in
.Ar notflags
are set in the file's flags bits.
If flags are preceded by a plus
.Pq Dq Li + ,
this primary evaluates to true
if any of the bits in
.Ar flags
is set in the file's flags bits,
or any of the bits in
.Ar notflags
is not set in the file's flags bits.
Otherwise,
this primary evaluates to true
if the bits in
.Ar flags
exactly match the file's flags bits,
and none of the
.Ar flags
bits match those of
.Ar notflags .
.It Ic -fstype Ar type
True if the file is contained in a file system of type
.Ar type .
@ -428,29 +458,44 @@ Slashes
.Pq Dq Li /
are treated as normal characters and do not have to be
matched explicitly.
.It Ic -perm Oo Fl Oc Ns Ar mode
.It Ic -perm Oo Cm - Ns | Ns Cm + Oc Ns Ar mode
The
.Ar mode
may be either symbolic (see
.Xr chmod 1 )
or an octal number.
If the mode is symbolic, a starting value of zero is assumed and the
mode sets or clears permissions without regard to the process' file mode
If the
.Ar mode
is symbolic, a starting value of zero is assumed and the
.Ar mode
sets or clears permissions without regard to the process' file mode
creation mask.
If the mode is octal, only bits 07777
If the
.Ar mode
is octal, only bits 07777
.Pq Dv S_ISUID | S_ISGID | S_ISTXT | S_IRWXU | S_IRWXG | S_IRWXO
of the file's mode bits participate
in the comparison.
If the mode is preceded by a dash
If the
.Ar mode
is preceded by a dash
.Pq Dq Li - ,
this primary evaluates to true
if at least all of the bits in the mode are set in the file's mode bits.
If the mode is preceded by a plus
if at least all of the bits in the
.Ar mode
are set in the file's mode bits.
If the
.Ar mode
is preceded by a plus
.Pq Dq Li + ,
this primary evaluates to true
if any of the bits in the mode are set in the file's mode bits.
if any of the bits in the
.Ar mode
are set in the file's mode bits.
Otherwise, this primary evaluates to true if
the bits in the mode exactly match the file's mode bits.
the bits in the
.Ar mode
exactly match the file's mode bits.
Note, the first character of a symbolic mode may not be a dash
.Pq Dq Li - .
.It Ic -print

View File

@ -81,7 +81,7 @@ typedef struct _plandata {
mode_t _m_data; /* mode mask */
struct {
u_long _f_flags;
u_long _f_mask;
u_long _f_notflags;
} fl;
nlink_t _l_data; /* link count */
off_t _o_data; /* file size */
@ -102,7 +102,7 @@ typedef struct _plandata {
#define a_data p_un._a_data
#define c_data p_un._c_data
#define fl_flags p_un.fl._f_flags
#define fl_mask p_un.fl._f_mask
#define fl_notflags p_un.fl._f_notflags
#define g_data p_un._g_data
#define i_data p_un._i_data
#define l_data p_un._l_data

View File

@ -550,16 +550,16 @@ f_flags(plan, entry)
{
u_long flags;
flags = entry->fts_statp->st_flags &
(UF_NODUMP | UF_IMMUTABLE | UF_APPEND | UF_OPAQUE |
SF_ARCHIVED | SF_IMMUTABLE | SF_APPEND);
flags = entry->fts_statp->st_flags;
if (plan->flags & F_ATLEAST)
/* note that plan->fl_flags always is a subset of
plan->fl_mask */
return (flags & plan->fl_mask) == plan->fl_flags;
return (flags | plan->fl_flags) == flags &&
!(flags & plan->fl_notflags);
else if (plan->flags & F_ANY)
return (flags & plan->fl_flags) ||
(flags | plan->fl_notflags) != flags;
else
return flags == plan->fl_flags;
/* NOTREACHED */
return flags == plan->fl_flags &&
!(plan->fl_flags & plan->fl_notflags);
}
PLAN *
@ -579,12 +579,15 @@ c_flags(option, argvp)
if (*flags_str == '-') {
new->flags |= F_ATLEAST;
flags_str++;
} else if (*flags_str == '+') {
new->flags |= F_ANY;
flags_str++;
}
if (strtofflags(&flags_str, &flags, &notflags) == 1)
errx(1, "%s: %s: illegal flags string", option->name, flags_str);
new->fl_flags = flags;
new->fl_mask = flags | notflags;
new->fl_notflags = notflags;
return new;
}