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.
This commit is contained in:
Warner Losh 2008-02-23 16:29:04 +00:00
parent 8f74c2663b
commit 46b993ff99
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=176478
5 changed files with 159 additions and 5 deletions

View File

@ -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;

View File

@ -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

View File

@ -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 {

View File

@ -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')
@ -1008,6 +1008,30 @@ c_inum(OPTION *option, char ***argvp)
return new;
}
/*
* -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 --
*
@ -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 */

View File

@ -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
};
/*