diff --git a/usr.bin/find/find.1 b/usr.bin/find/find.1 index 99d496720985..5945d58e7bee 100644 --- a/usr.bin/find/find.1 +++ b/usr.bin/find/find.1 @@ -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 diff --git a/usr.bin/find/find.h b/usr.bin/find/find.h index ce09344ec506..b2c73c305875 100644 --- a/usr.bin/find/find.h +++ b/usr.bin/find/find.h @@ -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 diff --git a/usr.bin/find/function.c b/usr.bin/find/function.c index 522d27e50075..a729ca7ef59f 100644 --- a/usr.bin/find/function.c +++ b/usr.bin/find/function.c @@ -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, ¬flags) == 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; }