From owner-freebsd-bugs Wed May 21 02:50:05 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.5/8.8.5) id CAA01104 for bugs-outgoing; Wed, 21 May 1997 02:50:05 -0700 (PDT) Received: (from gnats@localhost) by hub.freebsd.org (8.8.5/8.8.5) id CAA01094; Wed, 21 May 1997 02:50:02 -0700 (PDT) Resent-Date: Wed, 21 May 1997 02:50:02 -0700 (PDT) Resent-Message-Id: <199705210950.CAA01094@hub.freebsd.org> Resent-From: gnats (GNATS Management) Resent-To: freebsd-bugs Resent-Reply-To: FreeBSD-gnats@FreeBSD.ORG, Martin Birgmeier Received: from innocence.interface-business.de (innocence.interface-business.de [193.101.57.202]) by hub.freebsd.org (8.8.5/8.8.5) with ESMTP id CAA00832 for ; Wed, 21 May 1997 02:41:12 -0700 (PDT) Received: from ida.interface-business.de (ida.interface-business.de [193.101.57.203]) by innocence.interface-business.de (8.6.11/8.6.9) with SMTP id LAA18888 for ; Wed, 21 May 1997 11:40:27 +0200 Received: (from j@localhost) by ida.interface-business.de (8.8.5/8.7.3) id LAA25804; Wed, 21 May 1997 11:41:58 +0200 (MET DST) Message-Id: <199705210941.LAA25804@ida.interface-business.de> Date: Wed, 21 May 1997 11:41:58 +0200 (MET DST) From: Martin Birgmeier Reply-To: Martin Birgmeier To: FreeBSD-gnats-submit@FreeBSD.ORG X-Send-Pr-Version: 3.2 Subject: bin/3648: find(1) extension for file flags Sender: owner-bugs@FreeBSD.ORG X-Loop: FreeBSD.org Precedence: bulk >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}. 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 #include ! #define SAPPEND(s) { \ ! if (prefix != NULL) \ ! (void)strcat(string, prefix); \ ! (void)strcat(string, s); \ ! prefix = ","; \ ! } /* * flags_to_string -- --- 43,69 ---- #include #include ! 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 --- 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 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: