[Bcc'ed to -current]

Hi!

The current implementation of find(1) -flags primitive is a bit
icky and does not match the (poorly) documented behavior.  For
example, the fact that only a certain set of file flags is recognized
is not documented, and there is no reason for this behavior.  Also,
"no" flags don't take the desired effect to match files that have
corresponding flag bits unset.

The attached patch extends -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 you 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>.

Please review.


Cheers,
-- 
Ruslan Ermilov          Oracle Developer/DBA,
[EMAIL PROTECTED]           Sunbay Software AG,
[EMAIL PROTECTED]          FreeBSD committer,
+380.652.512.251        Simferopol, Ukraine

http://www.FreeBSD.org  The Power To Serve
http://www.oracle.com   Enabling The Information Age
Index: find.1
===================================================================
RCS file: /home/ncvs/src/usr.bin/find/find.1,v
retrieving revision 1.36
diff -u -p -r1.36 find.1
--- find.1      2001/06/29 12:59:20     1.36
+++ find.1      2001/08/30 16:27:29
@@ -428,45 +428,90 @@ matched explicitly.
 Like
 .Ic -path ,
 but the match is case insensitive.
-.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 -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 you 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 -print
 This primary always evaluates to true.
 It prints the pathname of the current file to standard output.
Index: find.h
===================================================================
RCS file: /home/ncvs/src/usr.bin/find/find.h,v
retrieving revision 1.11
diff -u -p -r1.11 find.h
--- find.h      2001/05/03 18:05:34     1.11
+++ find.h      2001/08/30 16:27:29
@@ -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
Index: function.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/find/function.c,v
retrieving revision 1.32
diff -u -p -r1.32 function.c
--- function.c  2001/08/30 13:17:58     1.32
+++ function.c  2001/08/30 16:28:02
@@ -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;
 }
 

Reply via email to