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:
parent
8f74c2663b
commit
46b993ff99
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user