Change 111894 by ryanb@ryanb_yuki on 2006/12/18 14:27:32 Patch to find(1) that examines extended attributes. See extattr(2) for more information. Usage: -extattr Returns true if file contains attribute attrname in namespace. -extattrs Returns true if file contains -any- attributes in namespace. Affected files ... .. //depot/user/ryanb/src/usr.bin/find/extern.h#2 edit .. //depot/user/ryanb/src/usr.bin/find/find.1#4 edit .. //depot/user/ryanb/src/usr.bin/find/find.h#2 edit .. //depot/user/ryanb/src/usr.bin/find/function.c#2 edit .. //depot/user/ryanb/src/usr.bin/find/option.c#2 edit Differences ... --- usr.bin/find/extern.h.orig +++ usr.bin/find/extern.h @@ -59,6 +59,8 @@ creat_f c_depth; creat_f c_empty; creat_f c_exec; +creat_f c_extattr; +creat_f c_extattrs; creat_f c_flags; creat_f c_follow; creat_f c_fstype; @@ -90,6 +92,8 @@ exec_f f_empty; exec_f f_exec; exec_f f_expr; +exec_f f_extattr; +exec_f f_extattrs; exec_f f_flags; exec_f f_fstype; exec_f f_group; --- usr.bin/find/find.1.orig +++ usr.bin/find/find.1 @@ -363,6 +363,24 @@ the string .Dq Li {} is not qualified. +.It Ic -extattr Ar namespace Ar attrname +True if file contains extended attribute +.Ar attrname +in +.Ar namespace . +The +.Ar namespace +may be either +.Dq system +or +.Dq user . +See +.Xr extattr 2 +for more information on extended attributes. +.It Ic -extattrs Ar namespace +True if file contains any extended attributes in +.Ar namespace . +Please refer to the -extattrs description for more information. .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 ) . --- usr.bin/find/find.h.orig +++ usr.bin/find/find.h @@ -110,6 +110,10 @@ char *_a_data[2]; /* array of char pointers */ char *_c_data; /* char pointer */ regex_t *_re_data; /* regex */ + struct { + int _ea_ns; /* extattr namespace */ + char *_ea_attr; /* extattr key */ + } ea; } p_un; } PLAN; #define a_data p_un._a_data @@ -137,6 +141,8 @@ #define e_pbsize p_un.ex._e_pbsize #define e_psizemax p_un.ex._e_psizemax #define e_next p_un.ex._e_next +#define ea_ns p_un.ea._ea_ns +#define ea_attr p_un.ea._ea_attr typedef struct _option { const char *name; /* option name */ --- usr.bin/find/function.c.orig +++ usr.bin/find/function.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -66,6 +67,7 @@ #include #include #include +#include #include "find.h" @@ -771,6 +773,109 @@ } } +/** + * @brief Setup for extended -extattr + * + * Searches for a specific extended attribute (key only, not value). + * Usage: + * -extattr + * where namespace = system or user. + */ +PLAN * +c_extattr(OPTION *option, char ***argvp) +{ + PLAN *plan; + char *arg; + + /* Behavior varies if target is symlink, so demand stat() */ + ftsoptions &= ~FTS_NOSTAT; + + plan = palloc(option); + + /* Record desired namespace */ + arg = nextarg(option, argvp); + + /* Record attribute key */ + plan->ea_attr = nextarg(option, argvp); + + /* Validate namespace */ + if (extattr_string_to_namespace(arg, &plan->ea_ns) == -1) + errx(1, "%s: invalid namespace", arg); + + return(plan); +} + +/** + * @brief Search for a specific extended attribute + * + * @return 0 for no match, non-zero otherwise + */ +int +f_extattr(PLAN *plan, FTSENT *entry) +{ + int match = 0; + + if (S_ISLNK(entry->fts_statp->st_mode)) + match = extattr_get_link(entry->fts_accpath, plan->ea_ns, plan->ea_attr, NULL, 0); + else + match = extattr_get_file(entry->fts_accpath, plan->ea_ns, plan->ea_attr, NULL, 0); + + if (match == -1) { + if (errno != ENOATTR) + warn("%s", entry->fts_accpath); + match = 0; + } + + return match; +} + +/** + * @brief Setup for -extattrs (match if file has extattrs) + * + * Usage: -extattrs + * where namespace = system or user + */ +PLAN * +c_extattrs(OPTION *option, char ***argvp) +{ + PLAN *plan; + char *arg; + + /* Behavior varies if target is symlink, so demand stat() */ + ftsoptions &= ~FTS_NOSTAT; + + plan = palloc(option); + + /* Record & validate namespace */ + arg = nextarg(option, argvp); + + if (extattr_string_to_namespace(arg, &plan->ea_ns) == -1) + errx(1, "%s: invalid namespace", arg); + + return(plan); +} + +/** + * @brief Search for presence of -any- extattrs (system & user namespaces) + */ +int +f_extattrs(PLAN *plan, FTSENT *entry) +{ + int match = 0; + + if (S_ISLNK(entry->fts_statp->st_mode)) + match = extattr_list_link(entry->fts_accpath, plan->ea_ns, NULL, 0); + else + match = extattr_list_file(entry->fts_accpath, plan->ea_ns, NULL, 0); + + if (match == -1) { + warn("%s", entry->fts_accpath); + match = 0; + } + + return match; +} + int f_flags(PLAN *plan, FTSENT *entry) { --- usr.bin/find/option.c.orig +++ usr.bin/find/option.c @@ -79,6 +79,8 @@ { "-empty", c_empty, f_empty, 0 }, { "-exec", c_exec, f_exec, 0 }, { "-execdir", c_exec, f_exec, F_EXECDIR }, + { "-extattr", c_extattr, f_extattr, 0 }, + { "-extattrs", c_extattrs, f_extattrs, 0 }, { "-false", c_simple, f_not, 0 }, { "-flags", c_flags, f_flags, 0 }, { "-follow", c_follow, f_always_true, 0 },