From c9f2fe69375b9322a4807902a05490c15a796ca4 Mon Sep 17 00:00:00 2001 From: imp Date: Sat, 23 Feb 2008 16:29:04 +0000 Subject: Implement a number of primaries present in GNU find, but not present in our find. The following are nops because they aren't relevant to our find: -ignore_readdir_race -noignore_readdir_race -noleaf The following aliaes were created: -gid -> -group [2] -uid -> -user [2] -wholename -> -path -iwholename -> ipath -mount -> -xdev -d -> -depth [1] The following new primaries were created: -lname like -name, but matches symbolic links only) -ilname like -lname but case insensitive -quit exit(0) -samefile returns true for hard links to the specified file -true Always true I changed one primary to match GNU find since I think our use of it violates POLA -false Always false (was an alias for -not!) Also, document the '+' modifier for -execdir, as well as all of the above. This was previously implemented. Document the remaining 7 primaries that are in GNU find, but aren't yet implemented in find(1) [1] This was done in GNU find for compatibility with FreeBSD, yet they mixed up command line args and primary args. [2] -uid/-gid in GNU find ONLY takes a numeric arg, but that arg does the normal range thing that. GNU find -user and -uid also take a numberic arg, but don't do the range processing. find(1) does both for -user and -group, so making -uid and -gid aliases is compatible for all non-error cases used in GNU find. While not perfect emulation, this seems a reasonable thing for us. --- usr.bin/find/extern.h | 3 ++ usr.bin/find/find.1 | 76 ++++++++++++++++++++++++++++++++++++++++++++++++- usr.bin/find/find.h | 1 + usr.bin/find/function.c | 60 ++++++++++++++++++++++++++++++++++++-- usr.bin/find/option.c | 24 +++++++++++++++- 5 files changed, 159 insertions(+), 5 deletions(-) (limited to 'usr.bin/find') diff --git a/usr.bin/find/extern.h b/usr.bin/find/extern.h index a6f09f4..716c1f5 100644 --- a/usr.bin/find/extern.h +++ b/usr.bin/find/extern.h @@ -74,6 +74,7 @@ creat_f c_nouser; creat_f c_perm; creat_f c_print; creat_f c_regex; +creat_f c_samefile; creat_f c_simple; creat_f c_size; creat_f c_type; @@ -90,6 +91,7 @@ exec_f f_depth; exec_f f_empty; exec_f f_exec; exec_f f_expr; +exec_f f_false; exec_f f_flags; exec_f f_fstype; exec_f f_group; @@ -108,6 +110,7 @@ exec_f f_perm; exec_f f_print; exec_f f_print0; exec_f f_prune; +exec_f f_quit; exec_f f_regex; exec_f f_size; exec_f f_type; diff --git a/usr.bin/find/find.1 b/usr.bin/find/find.1 index d8376d8..9393f9d 100644 --- a/usr.bin/find/find.1 +++ b/usr.bin/find/find.1 @@ -293,6 +293,12 @@ units. Please refer to the .Ic -atime primary description for information on supported time units. +.It Ic -d +Same as +.Ic depth . +GNU find implements this as a primary in mistaken emulation of +.Fx +.Xr find 1 . .It Ic -delete Delete found files and/or directories. Always returns true. @@ -365,6 +371,15 @@ The filename substituted for the string .Dq Li {} is not qualified. +.It Ic -execdir Ar utility Oo Ar argument ... Oc Li {} + +Same as +.Ic -execdir , +except that +.Dq Li {} +is replaced with as many pathnames as possible for each invocation of +.Ar utility . +This behaviour is similar to that of +.Xr xargs 1 . .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 ) . @@ -428,6 +443,15 @@ the .Nm is being executed and the latter matches any file system which is mounted read-only. +.It Ic -gid Ar gname +The same thing as +.Ar -group Ar gname +for compatibility with GNU find. +GNU find imposes a restriction that +.Ar gname +is numeric, while +.Xr find 1 +does not. .It Ic -group Ar gname True if the file belongs to the group .Ar gname . @@ -436,6 +460,12 @@ If is numeric and there is no such group name, then .Ar gname is treated as a group ID. +.It Ic -ignore_readdir_race +This option is for GNU find compatibility and is ignored. +.It Ic -ilname Ar pattern +Like +.Ic -lname , +but the match is case insensitive. .It Ic -iname Ar pattern Like .Ic -name , @@ -451,10 +481,18 @@ but the match is case insensitive. Like .Ic -regex , but the match is case insensitive. +.It Ic -iwholename Ar pattern +The same thing as +.Ic -ipath , +for GNU find compatibility. .It Ic -links Ar n True if the file has .Ar n links. +.It Ic -lname Ar pattern +Like +.Ic -name , +but the matched file must also be a symbolic link. .It Ic -ls This primary always evaluates to true. The following information for the current file is written to standard output: @@ -497,6 +535,10 @@ minutes. .It Ic -mnewer Ar file Same as .Ic -newer . +.It Ic -mount +The same thing as +.Ic -xdev , +for GNU find compatibility. .It Ic -mtime Ar n Ns Op Cm smhdw If no units are specified, this primary evaluates to true if the difference between the file last modification time and the time @@ -563,6 +605,13 @@ is equivalent to .Ic -newer . .It Ic -nogroup True if the file belongs to an unknown group. +.It Ic -noignore_readdir_race +This option is for GNU find compatibility and is ignored. +.It Ic -noleaf +This option is for GNU find compatibility. +In GNU find it disables an optimization not relevant to +.Xr find 1 , +so it is ignored. .It Ic -nouser True if the file belongs to an unknown user. .It Ic -ok Ar utility Oo Ar argument ... Oc Li \&; @@ -690,6 +739,14 @@ but not .Dq Li xyzzy or .Dq Li /foo/ . +.It Ic -samefile Ar name +True if the file is a hard link to +.Ar name . +If the command option +.Ic -L +is specified, it is also true if the file is a symbolic link and +points to +.Ar name . .It Ic -size Ar n Ns Op Cm ckMGTP True if the file's size, rounded up, in 512-byte blocks is .Ar n . @@ -739,6 +796,15 @@ FIFO .It Cm s socket .El +.It Ic -uid Ar uname +The same thing as +.Ar -user Ar uname +for compatibility with GNU find. +GNU find imposes a restriction that +.Ar uname +is numeric, while +.Xr find 1 +does not. .It Ic -user Ar uname True if the file belongs to the user .Ar uname . @@ -747,6 +813,10 @@ If is numeric and there is no such user name, then .Ar uname is treated as a user ID. +.It Ic -wholename Ar pattern +The same thing as +.Ic -path , +for GNU find compatibility. .El .Pp All primaries which take a numeric argument allow the number to be @@ -770,13 +840,17 @@ This evaluates to true if the parenthesized expression evaluates to true. .Pp .It Cm \&! Ar expression -.It Cm -false Ar expression .It Cm -not Ar expression This is the unary .Tn NOT operator. It evaluates to true if the expression is false. .Pp +.It Cm -false +Always false. +.It Cm -true +Always true. +.Pp .It Ar expression Cm -and Ar expression .It Ar expression expression The diff --git a/usr.bin/find/find.h b/usr.bin/find/find.h index c7366fa..5a465f1 100644 --- a/usr.bin/find/find.h +++ b/usr.bin/find/find.h @@ -74,6 +74,7 @@ typedef struct _plandata *creat_f(struct _option *, char ***); #define F_EXECPLUS 0x00020000 /* -exec ... {} + */ #define F_TIME_B 0x00040000 /* one of -Btime, -Bnewer, -newerB* */ #define F_TIME2_B 0x00080000 /* one of -newer?B */ +#define F_LINK 0x00100000 /* lname or ilname */ /* node definition */ typedef struct _plandata { diff --git a/usr.bin/find/function.c b/usr.bin/find/function.c index 5de9db0..4f823a2 100644 --- a/usr.bin/find/function.c +++ b/usr.bin/find/function.c @@ -474,7 +474,7 @@ c_delete(OPTION *option, char ***argvp __unused) /* * always_true -- * - * Always true, used for -maxdepth, -mindepth, -xdev and -follow + * Always true, used for -maxdepth, -mindepth, -xdev, -follow, and -true */ int f_always_true(PLAN *plan __unused, FTSENT *entry __unused) @@ -970,7 +970,7 @@ c_group(OPTION *option, char ***argvp) g = getgrnam(gname); if (g == NULL) { char* cp = gname; - if( gname[0] == '-' || gname[0] == '+' ) + if (gname[0] == '-' || gname[0] == '+') gname++; gid = atoi(gname); if (gid == 0 && gname[0] != '0') @@ -1009,6 +1009,30 @@ c_inum(OPTION *option, char ***argvp) } /* + * -samefile FN + * + * True if the file has the same inode (eg hard link) FN + */ + +/* f_samefile is just f_inum */ +PLAN * +c_samefile(OPTION *option, char ***argvp) +{ + char *fn; + PLAN *new; + struct stat sb; + + fn = nextarg(option, argvp); + ftsoptions &= ~FTS_NOSTAT; + + new = palloc(option); + if (stat(fn, &sb)) + err(1, "%s", fn); + new->i_data = sb.st_ino; + return new; +} + +/* * -links n functions -- * * True if the file has n links. @@ -1063,6 +1087,8 @@ c_ls(OPTION *option, char ***argvp __unused) int f_name(PLAN *plan, FTSENT *entry) { + if ((plan->flags & F_LINK) && !S_ISLNK(entry->fts_statp->st_mode)) + return 0; return !fnmatch(plan->c_data, entry->fts_name, plan->flags & F_IGNCASE ? FNM_CASEFOLD : 0); } @@ -1076,6 +1102,8 @@ c_name(OPTION *option, char ***argvp) pattern = nextarg(option, argvp); new = palloc(option); new->c_data = pattern; + if (new->flags & F_LINK) + ftsoptions &= ~FTS_NOSTAT; return new; } @@ -1353,7 +1381,7 @@ c_regex(OPTION *option, char ***argvp) return new; } -/* c_simple covers c_prune, c_openparen, c_closeparen, c_not, c_or */ +/* c_simple covers c_prune, c_openparen, c_closeparen, c_not, c_or, c_true, c_false */ PLAN * c_simple(OPTION *option, char ***argvp __unused) @@ -1635,3 +1663,29 @@ f_or(PLAN *plan, FTSENT *entry) } /* c_or == c_simple */ + +/* + * -false + * + * Always false. + */ +int +f_false(PLAN *plan __unused, FTSENT *entry __unused) +{ + return 0; +} + +/* c_false == c_simple */ + +/* + * -quit + * + * Exits the program + */ +int +f_quit(PLAN *plan __unused, FTSENT *entry __unused) +{ + exit(0); +} + +/* c_quit == c_simple */ diff --git a/usr.bin/find/option.c b/usr.bin/find/option.c index c1c59ea..7d06c91 100644 --- a/usr.bin/find/option.c +++ b/usr.bin/find/option.c @@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$"); int typecompare(const void *, const void *); /* NB: the following table must be sorted lexically. */ +/* Options listed with C++ comments are in gnu find, but not our find */ static OPTION const options[] = { { "!", c_simple, f_not, 0 }, { "(", c_simple, f_openparen, 0 }, @@ -74,26 +75,38 @@ static OPTION const options[] = { { "-cmin", c_Xmin, f_Xmin, F_TIME_C }, { "-cnewer", c_newer, f_newer, F_TIME_C }, { "-ctime", c_Xtime, f_Xtime, F_TIME_C }, + { "-d", c_depth, f_depth, 0 }, +// -daystart { "-delete", c_delete, f_delete, 0 }, { "-depth", c_depth, f_depth, 0 }, { "-empty", c_empty, f_empty, 0 }, { "-exec", c_exec, f_exec, 0 }, { "-execdir", c_exec, f_exec, F_EXECDIR }, - { "-false", c_simple, f_not, 0 }, + { "-false", c_simple, f_false, 0 }, { "-flags", c_flags, f_flags, 0 }, +// -fls { "-follow", c_follow, f_always_true, 0 }, +// -fprint +// -fprint0 +// -fprintf { "-fstype", c_fstype, f_fstype, 0 }, + { "-gid", c_group, f_group, 0 }, { "-group", c_group, f_group, 0 }, + { "-ignore_readdir_race",c_simple, f_always_true,0 }, + { "-ilname", c_name, f_name, F_LINK | F_IGNCASE }, { "-iname", c_name, f_name, F_IGNCASE }, { "-inum", c_inum, f_inum, 0 }, { "-ipath", c_name, f_path, F_IGNCASE }, { "-iregex", c_regex, f_regex, F_IGNCASE }, + { "-iwholename",c_name, f_path, F_IGNCASE }, { "-links", c_links, f_links, 0 }, + { "-lname", c_name, f_name, F_LINK }, { "-ls", c_ls, f_ls, 0 }, { "-maxdepth", c_mXXdepth, f_always_true, F_MAXDEPTH }, { "-mindepth", c_mXXdepth, f_always_true, 0 }, { "-mmin", c_Xmin, f_Xmin, 0 }, { "-mnewer", c_newer, f_newer, 0 }, + { "-mount", c_xdev, f_always_true, 0 }, { "-mtime", c_Xtime, f_Xtime, 0 }, { "-name", c_name, f_name, 0 }, { "-newer", c_newer, f_newer, 0 }, @@ -118,6 +131,8 @@ static OPTION const options[] = { { "-newermm", c_newer, f_newer, 0 }, { "-newermt", c_newer, f_newer, F_TIME2_T }, { "-nogroup", c_nogroup, f_nogroup, 0 }, + { "-noignore_readdir_race",c_simple, f_always_true,0 }, + { "-noleaf", c_simple, f_always_true, 0 }, { "-not", c_simple, f_not, 0 }, { "-nouser", c_nouser, f_nouser, 0 }, { "-o", c_simple, f_or, 0 }, @@ -128,12 +143,19 @@ static OPTION const options[] = { { "-perm", c_perm, f_perm, 0 }, { "-print", c_print, f_print, 0 }, { "-print0", c_print, f_print0, 0 }, +// -printf { "-prune", c_simple, f_prune, 0 }, + { "-quit", c_simple, f_quit, 0 }, { "-regex", c_regex, f_regex, 0 }, + { "-samefile", c_samefile, f_inum, 0 }, { "-size", c_size, f_size, 0 }, + { "-true", c_simple, f_always_true, 0 }, { "-type", c_type, f_type, 0 }, + { "-uid", c_user, f_user, 0 }, { "-user", c_user, f_user, 0 }, + { "-wholename", c_name, f_path, 0 }, { "-xdev", c_xdev, f_always_true, 0 }, +// -xtype }; /* -- cgit v1.1