Date: Wed, 21 May 1997 11:41:58 +0200 (MET DST) From: Martin Birgmeier <mbirg@austria.ds.philips.com> To: FreeBSD-gnats-submit@FreeBSD.ORG Subject: bin/3648: find(1) extension for file flags Message-ID: <199705210941.LAA25804@ida.interface-business.de> Resent-Message-ID: <199705210950.CAA01094@hub.freebsd.org>
index | next in thread | raw e-mail
>Number: 3648
>Category: bin
>Synopsis: find(1) extension for file flags
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Wed May 21 02:50:01 PDT 1997
>Last-Modified:
>Originator: Martin Birgmeier
>Organization:
Philips Speech Processing, Austria
>Release: FreeBSD 2.2-STABLE i386
>Environment:
>Description:
I wanted find(1) to be able to check file flags... While working on this,
I found a bug in bin/ls/stat_flags.c, and largely rewrote the latter for
easier maintenance. Below you find both patches. Please forward them to
the NetBSD and OpenBSD groups as well.
Thanks for the system & best regards,
Martin
P.S. I'd also like to have HP-UX's -newer[acm][acm]{0,1} functions
to find(1), as well as my own invention (or someone else's?)
-date[acm]{0,1} [+-]{0,1}<free-form-date-time>. Once I find
some spare time again, I'll do that - unless you are faster :-). This
would be made easier by incorporating the various getdate.y(3) into the
C (or other?) library.
>How-To-Repeat:
>Fix:
==================== cut here ====================
*** /usr/src/bin/ls/stat_flags.c Sat Sep 24 04:55:57 1994
--- /users/martin/find/stat_flags.c Thu May 8 11:13:20 1997
***************
*** 43,54 ****
#include <stddef.h>
#include <string.h>
! #define SAPPEND(s) { \
! if (prefix != NULL) \
! (void)strcat(string, prefix); \
! (void)strcat(string, s); \
! prefix = ","; \
! }
/*
* flags_to_string --
--- 43,69 ----
#include <stddef.h>
#include <string.h>
! static struct {
! char *name;
! u_long flag;
! int invert;
! } mapping[] = {
! /* canonical names per flag first, all prefixed by "no" */
! { "nosappend", SF_APPEND, 0 },
! { "nosappnd", SF_APPEND, 0 },
! { "noarchived", SF_ARCHIVED, 0 },
! { "noarch", SF_ARCHIVED, 0 },
! { "nosimmutable", SF_IMMUTABLE, 0 },
! { "noschange", SF_IMMUTABLE, 0 },
! { "noschg", SF_IMMUTABLE, 0 },
! { "nouappend", UF_APPEND, 0 },
! { "nouappnd", UF_APPEND, 0 },
! { "nouimmutable", UF_IMMUTABLE, 0 },
! { "nouchange", UF_IMMUTABLE, 0 },
! { "nouchg", UF_IMMUTABLE, 0 },
! { "nodump", UF_NODUMP, 1 }
! };
! #define nmappings (sizeof(mapping) / sizeof(mapping[0]))
/*
* flags_to_string --
***************
*** 61,94 ****
char *def;
{
static char string[128];
! char *prefix;
!
! string[0] = '\0';
! prefix = NULL;
! if (flags & UF_APPEND)
! SAPPEND("uappnd");
! if (flags & UF_IMMUTABLE)
! SAPPEND("uchg");
! if (flags & UF_NODUMP)
! SAPPEND("nodump");
! if (flags & SF_APPEND)
! SAPPEND("sappnd");
! if (flags & SF_ARCHIVED)
! SAPPEND("arch");
! if (flags & SF_IMMUTABLE)
! SAPPEND("schg");
! return (prefix == NULL && def != NULL ? def : string);
! }
! #define TEST(a, b, f) { \
! if (!memcmp(a, b, sizeof(b))) { \
! if (clear) { \
! if (clrp) \
! *clrp |= (f); \
! } else if (setp) \
! *setp |= (f); \
! break; \
! } \
}
/*
--- 76,98 ----
char *def;
{
static char string[128];
! char *sp, *dp;
! u_long setflags;
! int i;
! setflags = flags;
! dp = string;
! for (i = 0; i < nmappings; i++) {
! if (setflags & mapping[i].flag) {
! if (dp > string)
! *dp++ = ',';
! for (sp = mapping[i].invert ? mapping[i].name :
! mapping[i].name + 2; *sp; *dp++ = *sp++) ;
! setflags &= ~mapping[i].flag;
! }
! }
! *dp++ = '\0';
! return (dp == string && def != NULL ? def : string);
}
/*
***************
*** 102,111 ****
char **stringp;
u_long *setp, *clrp;
{
- int clear;
char *string, *p;
- clear = 0;
if (setp)
*setp = 0;
if (clrp)
--- 106,114 ----
char **stringp;
u_long *setp, *clrp;
{
char *string, *p;
+ int i;
if (setp)
*setp = 0;
if (clrp)
***************
*** 115,150 ****
*stringp = p;
if (*p == '\0')
continue;
! if (p[0] == 'n' && p[1] == 'o') {
! clear = 1;
! p += 2;
! }
! switch (p[0]) {
! case 'a':
! TEST(p, "arch", SF_ARCHIVED);
! TEST(p, "archived", SF_ARCHIVED);
! return (1);
! case 'd':
! clear = !clear;
! TEST(p, "dump", UF_NODUMP);
! return (1);
! case 's':
! TEST(p, "sappnd", SF_APPEND);
! TEST(p, "sappend", SF_APPEND);
! TEST(p, "schg", SF_IMMUTABLE);
! TEST(p, "schange", SF_IMMUTABLE);
! TEST(p, "simmutable", SF_IMMUTABLE);
! return (1);
! case 'u':
! TEST(p, "uappnd", UF_APPEND);
! TEST(p, "uappend", UF_APPEND);
! TEST(p, "uchg", UF_IMMUTABLE);
! TEST(p, "uchange", UF_IMMUTABLE);
! TEST(p, "uimmutable", UF_IMMUTABLE);
! /* FALLTHROUGH */
! default:
! return (1);
}
}
! return (0);
}
--- 118,146 ----
*stringp = p;
if (*p == '\0')
continue;
! for (i = 0; i < nmappings; i++) {
! if (strcmp(p, mapping[i].name + 2) == 0) {
! if (mapping[i].invert) {
! if (clrp)
! *clrp |= mapping[i].flag;
! } else {
! if (setp)
! *setp |= mapping[i].flag;
! }
! break;
! } else if (strcmp(p, mapping[i].name) == 0) {
! if (mapping[i].invert) {
! if (setp)
! *setp |= mapping[i].flag;
! } else {
! if (clrp)
! *clrp |= mapping[i].flag;
! }
! break;
! }
}
+ if (i == nmappings)
+ return 1;
}
! return 0;
}
==================== cut here ====================
==================== cut here ====================
diff -c /usr/src/usr.bin/find/Makefile /users/martin/find/Makefile
*** /usr/src/usr.bin/find/Makefile Fri May 27 14:31:10 1994
--- /users/martin/find/Makefile Wed May 7 21:33:15 1997
***************
*** 1,6 ****
# @(#)Makefile 8.1 (Berkeley) 6/6/93
PROG= find
! SRCS= find.c function.c ls.c main.c misc.c operator.c option.c
.include <bsd.prog.mk>
--- 1,7 ----
# @(#)Makefile 8.1 (Berkeley) 6/6/93
PROG= find
! SRCS= find.c function.c ls.c main.c misc.c operator.c option.c stat_flags.c
! .PATH: /usr/src/bin/ls
.include <bsd.prog.mk>
diff -c /usr/src/usr.bin/find/extern.h /users/martin/find/extern.h
*** /usr/src/usr.bin/find/extern.h Fri Oct 4 14:54:04 1996
--- /users/martin/find/extern.h Wed May 7 21:37:51 1997
***************
*** 52,57 ****
--- 52,58 ----
PLAN *c_delete __P((void));
PLAN *c_depth __P((void));
PLAN *c_exec __P((char ***, int));
+ PLAN *c_flags __P((char *));
PLAN *c_follow __P((void));
PLAN *c_fstype __P((char *));
PLAN *c_group __P((char *));
diff -c /usr/src/usr.bin/find/find.1 /users/martin/find/find.1
*** /usr/src/usr.bin/find/find.1 Wed May 7 19:36:47 1997
--- /users/martin/find/find.1 Thu May 8 11:18:21 1997
***************
*** 270,275 ****
--- 270,288 ----
If the mode is not preceded by a dash, this primary evaluates to true if
the bits in the mode exactly match the file's mode bits.
Note, the first character of a symbolic mode may not be a dash (``\-'').
+ .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 (``\-''),
+ or if they match the specified flags (if these are preceded by a dash).
+ The
+ .Ar flags
+ are specified using symbolic names (see
+ .Xr chflags 1 ).
+ Note that this is different from
+ .Ic -perm ,
+ which only allows you to specify flags which are set.
.It Ic -print
This primary always evaluates to true.
It prints the pathname of the current file to standard output.
***************
*** 399,404 ****
--- 412,418 ----
that are newer than ``ttt''.
.El
.Sh SEE ALSO
+ .Xr chflags 1 ,
.Xr chmod 1 ,
.Xr locate 1 ,
.Xr stat 2 ,
diff -c /usr/src/usr.bin/find/find.h /users/martin/find/find.h
*** /usr/src/usr.bin/find/find.h Fri Oct 4 14:54:05 1996
--- /users/martin/find/find.h Wed May 7 21:36:00 1997
***************
*** 39,45 ****
/* node type */
enum ntype {
N_AND = 1, /* must start > 0 */
! N_ATIME, N_CLOSEPAREN, N_CTIME, N_DEPTH, N_EXEC, N_EXPR, N_FOLLOW,
N_FSTYPE, N_GROUP, N_INUM, N_LINKS, N_LS, N_MTIME, N_NAME, N_NEWER,
N_NOGROUP, N_NOT, N_NOUSER, N_OK, N_OPENPAREN, N_OR, N_PATH,
N_PERM, N_PRINT, N_PRUNE, N_SIZE, N_TYPE, N_USER, N_XDEV,
--- 39,46 ----
/* node type */
enum ntype {
N_AND = 1, /* must start > 0 */
! N_ATIME, N_CLOSEPAREN, N_CTIME, N_DEPTH, N_EXEC, N_EXPR, N_FLAGS,
! N_FOLLOW,
N_FSTYPE, N_GROUP, N_INUM, N_LINKS, N_LS, N_MTIME, N_NAME, N_NEWER,
N_NOGROUP, N_NOT, N_NOUSER, N_OK, N_OPENPAREN, N_OR, N_PATH,
N_PERM, N_PRINT, N_PRUNE, N_SIZE, N_TYPE, N_USER, N_XDEV,
***************
*** 64,69 ****
--- 65,74 ----
gid_t _g_data; /* gid */
ino_t _i_data; /* inode */
mode_t _m_data; /* mode mask */
+ struct {
+ u_long _f_flags;
+ u_long _f_mask;
+ } fl;
nlink_t _l_data; /* link count */
off_t _o_data; /* file size */
time_t _t_data; /* time value */
***************
*** 81,88 ****
} PLAN;
#define a_data p_un._a_data
#define c_data p_un._c_data
! #define i_data p_un._i_data
#define g_data p_un._g_data
#define l_data p_un._l_data
#define m_data p_un._m_data
#define mt_data p_un._mt_data
--- 86,95 ----
} PLAN;
#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 g_data p_un._g_data
+ #define i_data p_un._i_data
#define l_data p_un._l_data
#define m_data p_un._m_data
#define mt_data p_un._mt_data
diff -c /usr/src/usr.bin/find/function.c /users/martin/find/function.c
*** /usr/src/usr.bin/find/function.c Sun Feb 16 09:41:05 1997
--- /users/martin/find/function.c Thu May 8 11:26:34 1997
***************
*** 57,62 ****
--- 57,64 ----
#include "find.h"
+ int string_to_flags __P((char **, u_long *, u_long *));
+
#define COMPARE(a, b) { \
switch (plan->flags) { \
case F_EQUAL: \
***************
*** 763,772 ****
}
if ((set = setmode(perm)) == NULL)
! err(1, "-perm: %s: illegal mode string", perm);
new->m_data = getmode(set, 0);
return (new);
}
/*
--- 765,820 ----
}
if ((set = setmode(perm)) == NULL)
! errx(1, "-perm: %s: illegal mode string", perm);
new->m_data = getmode(set, 0);
return (new);
+ }
+
+ int
+ f_flags(plan, entry)
+ PLAN *plan;
+ FTSENT *entry;
+ {
+ u_long flags;
+
+ flags = entry->fts_statp->st_flags &
+ (UF_NODUMP | UF_IMMUTABLE | UF_APPEND | UF_OPAQUE |
+ SF_ARCHIVED | SF_IMMUTABLE | SF_APPEND);
+ 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;
+ else
+ return flags == plan->fl_flags;
+ /* NOTREACHED */
+ }
+
+ PLAN *
+ c_flags(flags_str)
+ char *flags_str;
+ {
+ PLAN *new;
+ u_long flags, notflags;
+
+ ftsoptions &= ~FTS_NOSTAT;
+
+ new = palloc(N_FLAGS, f_flags);
+
+ if (*flags_str == '-') {
+ new->flags = F_ATLEAST;
+ flags_str++;
+ }
+ if (string_to_flags(&flags_str, &flags, ¬flags) == 1)
+ errx(1, "-flags: %s: illegal flags string", flags_str);
+
+ new->fl_flags = flags;
+ new->fl_mask = flags | notflags;
+ #if 0
+ printf("flags = %08x, mask = %08x (%08x, %08x)\n",
+ new->fl_flags, new->fl_mask, flags, notflags);
+ #endif
+ return new;
}
/*
diff -c /usr/src/usr.bin/find/option.c /users/martin/find/option.c
*** /usr/src/usr.bin/find/option.c Fri Oct 4 14:54:07 1996
--- /users/martin/find/option.c Wed May 7 20:50:35 1997
***************
*** 63,68 ****
--- 63,69 ----
{ "-delete", N_DELETE, c_delete, O_ZERO },
{ "-depth", N_DEPTH, c_depth, O_ZERO },
{ "-exec", N_EXEC, c_exec, O_ARGVP },
+ { "-flags", N_FLAGS, c_flags, O_ARGV },
{ "-follow", N_FOLLOW, c_follow, O_ZERO },
{ "-fstype", N_FSTYPE, c_fstype, O_ARGV },
{ "-group", N_GROUP, c_group, O_ARGV },
>Audit-Trail:
>Unformatted:
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199705210941.LAA25804>
