commands/find: original netbsd find
This commit is contained in:
parent
13d50be356
commit
fcd2a802a8
11 changed files with 4142 additions and 0 deletions
13
commands/find/Makefile
Normal file
13
commands/find/Makefile
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# $NetBSD: Makefile,v 1.12 2006/12/14 20:55:56 he Exp $
|
||||||
|
# from: @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||||
|
|
||||||
|
.include <bsd.own.mk>
|
||||||
|
|
||||||
|
PROG= find
|
||||||
|
SRCS= find.c function.c ls.c main.c misc.c operator.c option.c
|
||||||
|
WARNS= 4
|
||||||
|
|
||||||
|
LDADD+=-lutil
|
||||||
|
DPADD+=${LIBUTIL}
|
||||||
|
|
||||||
|
.include <bsd.prog.mk>
|
99
commands/find/extern.h
Normal file
99
commands/find/extern.h
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
/* $NetBSD: extern.h,v 1.28 2007/07/19 07:49:30 daniel Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993, 1994
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* from: @(#)extern.h 8.3 (Berkeley) 4/16/94
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
void brace_subst(char *, char **, char *, int *);
|
||||||
|
PLAN *find_create(char ***);
|
||||||
|
int find_execute(PLAN *, char **);
|
||||||
|
PLAN *find_formplan(char **);
|
||||||
|
int find_traverse(PLAN *, int (*)(PLAN *, void *), void *);
|
||||||
|
int f_expr(PLAN *, FTSENT *);
|
||||||
|
PLAN *not_squish(PLAN *);
|
||||||
|
PLAN *or_squish(PLAN *);
|
||||||
|
PLAN *paren_squish(PLAN *);
|
||||||
|
int plan_cleanup(PLAN *, void *);
|
||||||
|
void printlong(char *, char *, struct stat *);
|
||||||
|
int queryuser(char **);
|
||||||
|
void show_path(int);
|
||||||
|
|
||||||
|
PLAN *c_amin(char ***, int);
|
||||||
|
PLAN *c_anewer(char ***, int);
|
||||||
|
PLAN *c_atime(char ***, int);
|
||||||
|
PLAN *c_cmin(char ***, int);
|
||||||
|
PLAN *c_cnewer(char ***, int);
|
||||||
|
PLAN *c_ctime(char ***, int);
|
||||||
|
PLAN *c_delete(char ***, int);
|
||||||
|
PLAN *c_depth(char ***, int);
|
||||||
|
PLAN *c_empty(char ***, int);
|
||||||
|
PLAN *c_exec(char ***, int);
|
||||||
|
PLAN *c_execdir(char ***, int);
|
||||||
|
PLAN *c_exit(char ***, int);
|
||||||
|
PLAN *c_false(char ***, int);
|
||||||
|
PLAN *c_flags(char ***, int);
|
||||||
|
PLAN *c_follow(char ***, int);
|
||||||
|
PLAN *c_fprint(char ***, int);
|
||||||
|
PLAN *c_fstype(char ***, int);
|
||||||
|
PLAN *c_group(char ***, int);
|
||||||
|
PLAN *c_iname(char ***, int);
|
||||||
|
PLAN *c_inum(char ***, int);
|
||||||
|
PLAN *c_iregex(char ***, int);
|
||||||
|
PLAN *c_links(char ***, int);
|
||||||
|
PLAN *c_ls(char ***, int);
|
||||||
|
PLAN *c_maxdepth(char ***, int);
|
||||||
|
PLAN *c_mindepth(char ***, int);
|
||||||
|
PLAN *c_mmin(char ***, int);
|
||||||
|
PLAN *c_mtime(char ***, int);
|
||||||
|
PLAN *c_name(char ***, int);
|
||||||
|
PLAN *c_newer(char ***, int);
|
||||||
|
PLAN *c_nogroup(char ***, int);
|
||||||
|
PLAN *c_nouser(char ***, int);
|
||||||
|
PLAN *c_path(char ***, int);
|
||||||
|
PLAN *c_perm(char ***, int);
|
||||||
|
PLAN *c_print(char ***, int);
|
||||||
|
PLAN *c_print0(char ***, int);
|
||||||
|
PLAN *c_printx(char ***, int);
|
||||||
|
PLAN *c_prune(char ***, int);
|
||||||
|
PLAN *c_regex(char ***, int);
|
||||||
|
PLAN *c_size(char ***, int);
|
||||||
|
PLAN *c_type(char ***, int);
|
||||||
|
PLAN *c_user(char ***, int);
|
||||||
|
PLAN *c_xdev(char ***, int);
|
||||||
|
PLAN *c_openparen(char ***, int);
|
||||||
|
PLAN *c_closeparen(char ***, int);
|
||||||
|
PLAN *c_not(char ***, int);
|
||||||
|
PLAN *c_or(char ***, int);
|
||||||
|
PLAN *c_null(char ***, int);
|
||||||
|
|
||||||
|
extern int ftsoptions, isdeprecated, isdepth, isoutput, issort, isxargs,
|
||||||
|
regcomp_flags;
|
839
commands/find/find.1
Normal file
839
commands/find/find.1
Normal file
|
@ -0,0 +1,839 @@
|
||||||
|
.\" $NetBSD: find.1,v 1.66 2007/07/19 07:49:30 daniel Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 1990, 1993
|
||||||
|
.\" The Regents of the University of California. All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" This code is derived from software contributed to Berkeley by
|
||||||
|
.\" the Institute of Electrical and Electronics Engineers, Inc.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\" 3. Neither the name of the University nor the names of its contributors
|
||||||
|
.\" may be used to endorse or promote products derived from this software
|
||||||
|
.\" without specific prior written permission.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
.\" SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" from: @(#)find.1 8.7 (Berkeley) 5/9/95
|
||||||
|
.\"
|
||||||
|
.Dd July 19, 2007
|
||||||
|
.Dt FIND 1
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm find
|
||||||
|
.Nd walk a file hierarchy
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm
|
||||||
|
.Op Fl H | Fl L | Fl P
|
||||||
|
.Op Fl dEhsXx
|
||||||
|
.Ar file
|
||||||
|
.Op Ar file ...
|
||||||
|
.Op Ar expression
|
||||||
|
.Nm
|
||||||
|
.Op Fl H | Fl L | Fl P
|
||||||
|
.Op Fl dEhsXx
|
||||||
|
.Fl f Ar file
|
||||||
|
.Op Ar file ...
|
||||||
|
.Op Ar expression
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Nm
|
||||||
|
recursively descends the directory tree for each
|
||||||
|
.Ar file
|
||||||
|
listed, evaluating an
|
||||||
|
.Ar expression
|
||||||
|
(composed of the
|
||||||
|
.Dq primaries
|
||||||
|
and
|
||||||
|
.Dq operands
|
||||||
|
listed below) in terms
|
||||||
|
of each file in the tree.
|
||||||
|
.Pp
|
||||||
|
The options are as follows:
|
||||||
|
.Pp
|
||||||
|
.Bl -tag -width Ds
|
||||||
|
.It Fl H
|
||||||
|
The
|
||||||
|
.Fl H
|
||||||
|
option causes the file information and file type (see
|
||||||
|
.Xr stat 2 ) ,
|
||||||
|
returned for each symbolic link encountered on the command line to be
|
||||||
|
those of the file referenced by the link, not the link itself.
|
||||||
|
If the referenced file does not exist, the file information and type will
|
||||||
|
be for the link itself.
|
||||||
|
File information of all symbolic links not on the command line is that
|
||||||
|
of the link itself.
|
||||||
|
.It Fl L
|
||||||
|
The
|
||||||
|
.Fl L
|
||||||
|
option causes the file information and file type (see
|
||||||
|
.Xr stat 2 )
|
||||||
|
returned for each symbolic link to be those of the file referenced by the
|
||||||
|
link, not the link itself.
|
||||||
|
If the referenced file does not exist, the file information and type will
|
||||||
|
be for the link itself.
|
||||||
|
.It Fl P
|
||||||
|
The
|
||||||
|
.Fl P
|
||||||
|
option causes the file information and file type (see
|
||||||
|
.Xr stat 2 )
|
||||||
|
returned for each symbolic link to be those of the link itself.
|
||||||
|
.It Fl d
|
||||||
|
The
|
||||||
|
.Fl d
|
||||||
|
option causes
|
||||||
|
.Nm
|
||||||
|
to perform a depth-first traversal, i.e., directories
|
||||||
|
are visited in post-order and all entries in a directory will be acted
|
||||||
|
on before the directory itself.
|
||||||
|
By default,
|
||||||
|
.Nm
|
||||||
|
visits directories in pre-order, i.e., before their contents.
|
||||||
|
Note, the default is
|
||||||
|
.Ar not
|
||||||
|
a breadth-first traversal.
|
||||||
|
.It Fl E
|
||||||
|
The
|
||||||
|
.Fl E
|
||||||
|
option causes
|
||||||
|
.Ar regexp
|
||||||
|
arguments to primaries to be interpreted as extended regular
|
||||||
|
expressions (see
|
||||||
|
.Xr re_format 7 ) .
|
||||||
|
.It Fl f
|
||||||
|
The
|
||||||
|
.Fl f
|
||||||
|
option specifies a file hierarchy for
|
||||||
|
.Nm
|
||||||
|
to traverse.
|
||||||
|
File hierarchies may also be specified as the operands immediately
|
||||||
|
following the options.
|
||||||
|
.It Fl h
|
||||||
|
The
|
||||||
|
.Fl h
|
||||||
|
option causes the file information and file type (see
|
||||||
|
.Xr stat 2 ) ,
|
||||||
|
returned for each symbolic link to be those of the file referenced by the
|
||||||
|
link, not the link itself.
|
||||||
|
If the referenced file does not exist, the file information and type will
|
||||||
|
be for the link itself.
|
||||||
|
.It Fl s
|
||||||
|
The
|
||||||
|
.Fl s
|
||||||
|
option causes the entries of each directory to be sorted in
|
||||||
|
lexicographical order.
|
||||||
|
Note that the sorting is done only inside of each directory;
|
||||||
|
files in different directories are not sorted.
|
||||||
|
Therefore,
|
||||||
|
.Sq Li a/b
|
||||||
|
appears before
|
||||||
|
.Sq Li a.b ,
|
||||||
|
which is different from
|
||||||
|
.Dq Li "find ... \&| sort"
|
||||||
|
order.
|
||||||
|
.It Fl X
|
||||||
|
The
|
||||||
|
.Fl X
|
||||||
|
option is a modification to permit
|
||||||
|
.Nm
|
||||||
|
to be safely used in conjunction with
|
||||||
|
.Xr xargs 1 .
|
||||||
|
If a file name contains any of the delimiting characters used by
|
||||||
|
.Nm xargs ,
|
||||||
|
a diagnostic message is displayed on standard error, and the file
|
||||||
|
is skipped.
|
||||||
|
The delimiting characters include single
|
||||||
|
.Pq Dq \&'
|
||||||
|
and double
|
||||||
|
.Pq Dq \&"
|
||||||
|
quotes, backslash
|
||||||
|
.Pq Dq \e ,
|
||||||
|
space, tab and newline characters.
|
||||||
|
Alternatively, the
|
||||||
|
.Ic -print0
|
||||||
|
or
|
||||||
|
.Ic -printx
|
||||||
|
primaries can be used to format the output in a way that
|
||||||
|
.Nm xargs
|
||||||
|
can accept.
|
||||||
|
.It Fl x
|
||||||
|
The
|
||||||
|
.Fl x
|
||||||
|
option restricts the search to the file system containing the
|
||||||
|
directory specified.
|
||||||
|
Does not list mount points to other file systems.
|
||||||
|
.El
|
||||||
|
.Sh PRIMARIES
|
||||||
|
.Bl -tag -width Ds
|
||||||
|
.It Ic -amin Ar n
|
||||||
|
True if the difference between the file last access time and the time
|
||||||
|
.Nm
|
||||||
|
was started, rounded up to the next full minute, is
|
||||||
|
.Ar n
|
||||||
|
minutes.
|
||||||
|
.It Ic -anewer Ar file
|
||||||
|
True if the current file has a more recent last access time than
|
||||||
|
.Ar file .
|
||||||
|
.It Ic -atime Ar n
|
||||||
|
True if the difference between the file last access time and the time
|
||||||
|
.Nm
|
||||||
|
was started, rounded up to the next full 24-hour period, is
|
||||||
|
.Ar n
|
||||||
|
24-hour periods.
|
||||||
|
.It Ic -cmin Ar n
|
||||||
|
True if the difference between the time of last change of file status
|
||||||
|
information and the time
|
||||||
|
.Nm
|
||||||
|
was started, rounded up to the next full minute, is
|
||||||
|
.Ar n
|
||||||
|
minutes.
|
||||||
|
.It Ic -cnewer Ar file
|
||||||
|
True if the current file has a more recent last change time than
|
||||||
|
.Ar file .
|
||||||
|
.It Ic -ctime Ar n
|
||||||
|
True if the difference between the time of last change of file status
|
||||||
|
information and the time
|
||||||
|
.Nm
|
||||||
|
was started, rounded up to the next full 24-hour period, is
|
||||||
|
.Ar n
|
||||||
|
24-hour periods.
|
||||||
|
.It Ic -delete
|
||||||
|
Delete found files and/or directories.
|
||||||
|
Always returns True.
|
||||||
|
This executes from the current working directory as
|
||||||
|
.Nm
|
||||||
|
recurses down the tree.
|
||||||
|
It will not attempt to delete a filename with a
|
||||||
|
.Dq \/
|
||||||
|
character in its pathname relative to
|
||||||
|
.Dq \.
|
||||||
|
for security reasons.
|
||||||
|
Depth-first traversal processing is implied by this option.
|
||||||
|
This can also be invoked as
|
||||||
|
.Ic -rm .
|
||||||
|
.It Ic -empty
|
||||||
|
True if the current file or directory is empty.
|
||||||
|
.\" The ".sp" below is probably not the right way to get the desired effect.
|
||||||
|
.It Ic -exec Ar utility Oo argument ... Oc No ;
|
||||||
|
.sp -1l
|
||||||
|
.It Ic -exec Ar utility Oo argument ... Oc No {} +
|
||||||
|
Execute the specified
|
||||||
|
.Ar utility
|
||||||
|
with the specified arguments.
|
||||||
|
The list of arguments is terminated by
|
||||||
|
.Dq Li \&;
|
||||||
|
or
|
||||||
|
.Dq Li \&+ .
|
||||||
|
.Ar utility
|
||||||
|
will be executed from the directory from which
|
||||||
|
.Nm
|
||||||
|
was executed.
|
||||||
|
.Pp
|
||||||
|
If terminated by a semicolon
|
||||||
|
.Pq Dq \&; ,
|
||||||
|
the
|
||||||
|
.Ar utility
|
||||||
|
is invoked once per path.
|
||||||
|
If the string
|
||||||
|
.Dq {}
|
||||||
|
appears anywhere in the utility name or the arguments,
|
||||||
|
it is replaced by the pathname of the current file.
|
||||||
|
.Pp
|
||||||
|
If terminated by a plus sign
|
||||||
|
.Pq Dq \&+ ,
|
||||||
|
the pathnames for which the
|
||||||
|
primary is evaluated are aggregated into sets, and
|
||||||
|
.Ar utility
|
||||||
|
will be invoked once per set, similar to
|
||||||
|
.Xr xargs 1 .
|
||||||
|
If any invocation exits with non-zero exit status, then
|
||||||
|
.Nm
|
||||||
|
will eventually do so as well, but this does not cause
|
||||||
|
.Nm
|
||||||
|
to exit early.
|
||||||
|
The string
|
||||||
|
.Dq {}
|
||||||
|
must appear, and must appear last.
|
||||||
|
Each set is limitted to no more than 5,000 pathnames,
|
||||||
|
and is also limitted such that the invokation of
|
||||||
|
.Ar utility
|
||||||
|
does not exceed
|
||||||
|
.Dv ARG_MAX .
|
||||||
|
.It Ic -execdir Ar utility Oo argument ... Oc No ;
|
||||||
|
The
|
||||||
|
.Ic -execdir
|
||||||
|
primary is similar to the semicolon-terminated
|
||||||
|
.Pq Dq \&;
|
||||||
|
variant of the
|
||||||
|
.Ic -exec
|
||||||
|
primary, with the exception that
|
||||||
|
.Ar utility
|
||||||
|
will be executed from the directory that holds
|
||||||
|
the current file.
|
||||||
|
The filename substituted for the string
|
||||||
|
.Dq {}
|
||||||
|
is not qualified.
|
||||||
|
Set aggregation
|
||||||
|
.Pq Do \&+ Dc termination
|
||||||
|
is not supported.
|
||||||
|
.It Ic -exit Op Ar n
|
||||||
|
This primary causes
|
||||||
|
.Nm
|
||||||
|
to stop traversing the filesystem and exit immediately if a
|
||||||
|
previous condition was met.
|
||||||
|
If no value is specified, the exit value will be 0, else
|
||||||
|
.Ar n .
|
||||||
|
Note that other primaries will be evaluated and acted upon before exiting.
|
||||||
|
.It Ic -false
|
||||||
|
This primary always evaluates to false.
|
||||||
|
This can be used following a primary that caused the
|
||||||
|
expression to be true to make the expression to be false.
|
||||||
|
This can be useful after using a
|
||||||
|
.Ic -fprint
|
||||||
|
primary so it can continue to the next expression (using an
|
||||||
|
.Cm -or
|
||||||
|
operator, for example).
|
||||||
|
.It Ic -flags Oo Fl Oc Ns Ar flags
|
||||||
|
If
|
||||||
|
.Ar flags
|
||||||
|
are preceded by a dash
|
||||||
|
.Pq Dq - ,
|
||||||
|
this primary evaluates to true
|
||||||
|
if at least all of the bits in
|
||||||
|
.Ar flags
|
||||||
|
are set in the file's flags bits.
|
||||||
|
If
|
||||||
|
.Ar flags
|
||||||
|
are not preceded by a dash, this primary evaluates to true if
|
||||||
|
the bits in
|
||||||
|
.Ar flags
|
||||||
|
exactly match the file's flags bits.
|
||||||
|
If
|
||||||
|
.Ar flags
|
||||||
|
is
|
||||||
|
.Dq none ,
|
||||||
|
files with no flags bits set are matched.
|
||||||
|
(See
|
||||||
|
.Xr chflags 1
|
||||||
|
for more information about file flags.)
|
||||||
|
.It Ic -follow
|
||||||
|
Follow symbolic links.
|
||||||
|
.It Ic -fprint Ar filename
|
||||||
|
This primary always evaluates to true.
|
||||||
|
This creates
|
||||||
|
.Ar filename
|
||||||
|
or overwrites the file if it already exists.
|
||||||
|
The file is created at startup.
|
||||||
|
It writes the pathname of the current file to this file, followed
|
||||||
|
by a newline character.
|
||||||
|
The file will be empty if no files are matched.
|
||||||
|
.It Ic -fstype Ar type
|
||||||
|
True if the file is contained in a file system of type
|
||||||
|
.Ar type .
|
||||||
|
The
|
||||||
|
.Xr sysctl 8
|
||||||
|
command can be used to find out the types of filesystems
|
||||||
|
that are available on the system:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
sysctl vfs.generic.fstypes
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
In addition, there are two pseudo-types,
|
||||||
|
.Dq local
|
||||||
|
and
|
||||||
|
.Dq rdonly .
|
||||||
|
The former matches any file system physically mounted on the system where
|
||||||
|
the
|
||||||
|
.Nm
|
||||||
|
is being executed, and the latter matches any file system which is
|
||||||
|
mounted read-only.
|
||||||
|
.It Ic -group Ar gname
|
||||||
|
True if the file belongs to the group
|
||||||
|
.Ar gname .
|
||||||
|
If
|
||||||
|
.Ar gname
|
||||||
|
is numeric and there is no such group name, then
|
||||||
|
.Ar gname
|
||||||
|
is treated as a group id.
|
||||||
|
.It Ic -iname Ar pattern
|
||||||
|
True if the last component of the pathname being examined
|
||||||
|
matches
|
||||||
|
.Ar pattern .
|
||||||
|
Case insensitive.
|
||||||
|
.It Ic -inum Ar n
|
||||||
|
True if the file has inode number
|
||||||
|
.Ar n .
|
||||||
|
.It Ic -iregex Ar regexp
|
||||||
|
True if the path name of the current file matches the case-insensitive
|
||||||
|
basic regular expression
|
||||||
|
.Pq see Xr re_format 7
|
||||||
|
.Ar regexp .
|
||||||
|
This is a match on the whole path, not a search for the regular expression
|
||||||
|
within the path.
|
||||||
|
.It Ic -links Ar n
|
||||||
|
True if the file has
|
||||||
|
.Ar n
|
||||||
|
links.
|
||||||
|
.It Ic -rm
|
||||||
|
This is an alias for
|
||||||
|
.Ic -delete .
|
||||||
|
.It Ic -ls
|
||||||
|
This primary always evaluates to true.
|
||||||
|
The following information for the current file is written to standard output:
|
||||||
|
its inode number, size in 512-byte blocks, file permissions, number of hard
|
||||||
|
links, owner, group, size in bytes, last modification time, and pathname.
|
||||||
|
If the file is a block or character special file, the major and minor numbers
|
||||||
|
will be displayed instead of the size in bytes.
|
||||||
|
If the file is a symbolic link, the pathname of the linked-to file will be
|
||||||
|
displayed preceded by
|
||||||
|
.Dq -\*[Gt] .
|
||||||
|
The format is identical to that produced by
|
||||||
|
.Dq ls -dgils .
|
||||||
|
.It Ic -maxdepth Ar n
|
||||||
|
True if the current search depth is less than or equal to what is specified in
|
||||||
|
.Ar n .
|
||||||
|
.It Ic -mindepth Ar n
|
||||||
|
True if the current search depth is at least what is specified in
|
||||||
|
.Ar n .
|
||||||
|
.It Ic -mmin Ar n
|
||||||
|
True if the difference between the file last modification time and the time
|
||||||
|
.Nm
|
||||||
|
was started, rounded up to the next full minute, is
|
||||||
|
.Ar n
|
||||||
|
minutes.
|
||||||
|
.It Ic -mtime Ar n
|
||||||
|
True if the difference between the file last modification time and the time
|
||||||
|
.Nm
|
||||||
|
was started, rounded up to the next full 24-hour period, is
|
||||||
|
.Ar n
|
||||||
|
24-hour periods.
|
||||||
|
.It Ic -ok Ar utility Oo argument ... Oc No ;
|
||||||
|
The
|
||||||
|
.Ic -ok
|
||||||
|
primary is similar to the semicolon-terminated
|
||||||
|
.Pq Dq \&;
|
||||||
|
variant of the
|
||||||
|
.Ic -exec
|
||||||
|
primary, with the exception that
|
||||||
|
.Nm
|
||||||
|
requests user affirmation for the execution of the utility by printing
|
||||||
|
a message to the terminal and reading a response.
|
||||||
|
If the response is other than
|
||||||
|
.Dq y ,
|
||||||
|
the command is not executed and the
|
||||||
|
.Ar -ok
|
||||||
|
primary evaluates to false.
|
||||||
|
Set aggregation
|
||||||
|
.Pq Do \&+ Dc termination
|
||||||
|
is not supported.
|
||||||
|
.It Ic -name Ar pattern
|
||||||
|
True if the last component of the pathname being examined matches
|
||||||
|
.Ar pattern .
|
||||||
|
Special shell pattern matching characters
|
||||||
|
.Po
|
||||||
|
.Dq \&[ ,
|
||||||
|
.Dq \&] ,
|
||||||
|
.Dq \&* ,
|
||||||
|
.Dq \&?
|
||||||
|
.Pc
|
||||||
|
may be used as part of
|
||||||
|
.Ar pattern .
|
||||||
|
These characters may be matched explicitly by escaping them with a
|
||||||
|
backslash
|
||||||
|
.Pq Dq \e .
|
||||||
|
.It Ic -newer Ar file
|
||||||
|
True if the current file has a more recent last modification time than
|
||||||
|
.Ar file .
|
||||||
|
.It Ic -nouser
|
||||||
|
True if the file belongs to an unknown user.
|
||||||
|
.It Ic -nogroup
|
||||||
|
True if the file belongs to an unknown group.
|
||||||
|
.It Ic -path Ar pattern
|
||||||
|
True if the pathname being examined matches
|
||||||
|
.Ar pattern .
|
||||||
|
Special shell pattern matching characters
|
||||||
|
.Po
|
||||||
|
.Dq \&[ ,
|
||||||
|
.Dq \&] ,
|
||||||
|
.Dq \&* ,
|
||||||
|
and
|
||||||
|
.Dq \&?
|
||||||
|
.Pc
|
||||||
|
may be used as part of
|
||||||
|
.Ar pattern .
|
||||||
|
These characters may be matched explicitly by escaping them with a
|
||||||
|
backslash
|
||||||
|
.Pq Dq \e .
|
||||||
|
Slashes
|
||||||
|
.Pq Dq /
|
||||||
|
are treated as normal characters and do not have to be
|
||||||
|
matched explicitly.
|
||||||
|
.It Ic -perm Oo Fl Oc Ns Ar mode
|
||||||
|
The
|
||||||
|
.Ar mode
|
||||||
|
may be either symbolic (see
|
||||||
|
.Xr chmod 1 )
|
||||||
|
or an octal number.
|
||||||
|
If the mode is symbolic, a starting value of zero is assumed and the
|
||||||
|
mode sets or clears permissions without regard to the process' file mode
|
||||||
|
creation mask.
|
||||||
|
If the mode is octal, only bits 07777
|
||||||
|
.Pf ( Dv S_ISUID
|
||||||
|
|
|
||||||
|
.Dv S_ISGID
|
||||||
|
|
|
||||||
|
.Dv S_ISTXT
|
||||||
|
|
|
||||||
|
.Dv S_IRWXU
|
||||||
|
|
|
||||||
|
.Dv S_IRWXG
|
||||||
|
|
|
||||||
|
.Dv S_IRWXO )
|
||||||
|
of the file's mode bits participate
|
||||||
|
in the comparison.
|
||||||
|
If the mode is preceded by a dash
|
||||||
|
.Pq Dq - ,
|
||||||
|
this primary evaluates to true
|
||||||
|
if at least all of the bits in the mode are set in the file's mode bits.
|
||||||
|
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
|
||||||
|
.Pq Dq - .
|
||||||
|
.It Ic -print
|
||||||
|
This primary always evaluates to true.
|
||||||
|
It prints the pathname of the current file to standard output, followed
|
||||||
|
by a newline character.
|
||||||
|
If none of
|
||||||
|
.Ic -exec ,
|
||||||
|
.Ic -exit ,
|
||||||
|
.Ic -fprint ,
|
||||||
|
.Ic -ls ,
|
||||||
|
.Ic -ok ,
|
||||||
|
.Ic -print0 ,
|
||||||
|
nor
|
||||||
|
.Ic -printx
|
||||||
|
is specified, the given expression shall be effectively replaced by
|
||||||
|
.Cm \&( Ns Ar given\& expression Ns Cm \&)
|
||||||
|
.Ic -print .
|
||||||
|
.It Ic -print0
|
||||||
|
This primary always evaluates to true.
|
||||||
|
It prints the pathname of the current file to standard output, followed
|
||||||
|
by a null character.
|
||||||
|
.It Ic -printx
|
||||||
|
This primary always evaluates to true.
|
||||||
|
It prints the pathname of the current file to standard output,
|
||||||
|
with each space, tab, newline, backslash, dollar sign, and single,
|
||||||
|
double, or back quotation mark prefixed by a backslash, so the output of
|
||||||
|
.Nm find
|
||||||
|
can safely be used as input to
|
||||||
|
.Nm xargs .
|
||||||
|
.It Ic -prune
|
||||||
|
This primary always evaluates to true.
|
||||||
|
It causes
|
||||||
|
.Nm
|
||||||
|
to not descend into the current file.
|
||||||
|
Note, the
|
||||||
|
.Ic -prune
|
||||||
|
primary has no effect if the
|
||||||
|
.Fl d
|
||||||
|
option was specified.
|
||||||
|
.It Ic -regex Ar regexp
|
||||||
|
True if the path name of the current file matches the case-sensitive
|
||||||
|
basic regular expression
|
||||||
|
.Pq see Xr re_format 7
|
||||||
|
.Ar regexp .
|
||||||
|
This is a match on the whole path, not a search for the regular expression
|
||||||
|
within the path.
|
||||||
|
.It Ic -size Ar n Ns Op Cm c
|
||||||
|
True if the file's size, rounded up, in 512-byte blocks is
|
||||||
|
.Ar n .
|
||||||
|
If
|
||||||
|
.Ar n
|
||||||
|
is followed by a
|
||||||
|
.Dq c ,
|
||||||
|
then the primary is true if the file's size is
|
||||||
|
.Ar n
|
||||||
|
bytes.
|
||||||
|
.It Ic -type Ar t
|
||||||
|
True if the file is of the specified type.
|
||||||
|
Possible file types are as follows:
|
||||||
|
.Pp
|
||||||
|
.Bl -tag -width flag -offset indent -compact
|
||||||
|
.It Cm b
|
||||||
|
block special
|
||||||
|
.It Cm c
|
||||||
|
character special
|
||||||
|
.It Cm d
|
||||||
|
directory
|
||||||
|
.It Cm f
|
||||||
|
regular file
|
||||||
|
.It Cm l
|
||||||
|
symbolic link
|
||||||
|
.It Cm p
|
||||||
|
FIFO
|
||||||
|
.It Cm s
|
||||||
|
socket
|
||||||
|
.It Cm W
|
||||||
|
whiteout
|
||||||
|
.It Cm w
|
||||||
|
whiteout
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
.It Ic -user Ar uname
|
||||||
|
True if the file belongs to the user
|
||||||
|
.Ar uname .
|
||||||
|
If
|
||||||
|
.Ar uname
|
||||||
|
is numeric and there is no such user name, then
|
||||||
|
.Ar uname
|
||||||
|
is treated as a user id (and considered a numeric argument).
|
||||||
|
.It Ic -xdev
|
||||||
|
This primary always evaluates to true.
|
||||||
|
It causes find not to descend past directories that have a different
|
||||||
|
device ID (st_dev, see
|
||||||
|
.Xr stat 2
|
||||||
|
S5.6.2 [POSIX.1]).
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
All primaries which take a numeric argument allow the number to be
|
||||||
|
preceded by a plus sign
|
||||||
|
.Pq Dq +
|
||||||
|
or a minus sign
|
||||||
|
.Pq Dq \- .
|
||||||
|
A preceding plus sign means
|
||||||
|
.Dq more than n ,
|
||||||
|
a preceding minus sign means
|
||||||
|
.Dq less than n ,
|
||||||
|
and neither means
|
||||||
|
.Dq exactly n .
|
||||||
|
.Sh OPERATORS
|
||||||
|
The primaries may be combined using the following operators.
|
||||||
|
The operators are listed in order of decreasing precedence.
|
||||||
|
.Bl -tag -width (expression)
|
||||||
|
.It Cm \&( Ar expression Cm \&)
|
||||||
|
This evaluates to true if the parenthesized expression evaluates to
|
||||||
|
true.
|
||||||
|
.Pp
|
||||||
|
.It Cm \&! Ar expression
|
||||||
|
This is the unary
|
||||||
|
.Tn NOT
|
||||||
|
operator.
|
||||||
|
It evaluates to true if the expression is false.
|
||||||
|
.Pp
|
||||||
|
.It Ar expression Cm -and Ar expression
|
||||||
|
.It Ar expression expression
|
||||||
|
The
|
||||||
|
.Cm -and
|
||||||
|
operator is the logical
|
||||||
|
.Tn AND
|
||||||
|
operator.
|
||||||
|
As it is implied by the juxtaposition of two expressions it does not
|
||||||
|
have to be specified.
|
||||||
|
The expression evaluates to true if both expressions are true.
|
||||||
|
The second expression is not evaluated if the first expression is false.
|
||||||
|
.Pp
|
||||||
|
.It Ar expression Cm -or Ar expression
|
||||||
|
The
|
||||||
|
.Cm -or
|
||||||
|
operator is the logical
|
||||||
|
.Tn OR
|
||||||
|
operator.
|
||||||
|
The expression evaluates to true if either the first or the second expression
|
||||||
|
is true.
|
||||||
|
The second expression is not evaluated if the first expression is true.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
All operands and primaries must be separate arguments to
|
||||||
|
.Nm .
|
||||||
|
Primaries which themselves take arguments expect each argument
|
||||||
|
to be a separate argument to
|
||||||
|
.Nm .
|
||||||
|
.Sh EXIT STATUS
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
utility normally exits 0 on success, and exits with 1 under certain
|
||||||
|
internal error conditions.
|
||||||
|
If any invokations of
|
||||||
|
.Dq Ic -exec Ar ... No +
|
||||||
|
primaries return non-zero exit-status, then
|
||||||
|
.Nm
|
||||||
|
will do so as well.
|
||||||
|
.Sh EXAMPLES
|
||||||
|
The following examples are shown as given to the shell:
|
||||||
|
.Bl -tag -width findx
|
||||||
|
.It Li "find / \e! -name \*q*.c\*q -print"
|
||||||
|
Print out a list of all the files whose names do not end in
|
||||||
|
.Dq \&.c .
|
||||||
|
.It Li "find / -newer ttt -user wnj -print"
|
||||||
|
Print out a list of all the files owned by user
|
||||||
|
.Dq wnj
|
||||||
|
that are newer than the file
|
||||||
|
.Dq ttt .
|
||||||
|
.It Li "find / \e! \e( -newer ttt -user wnj \e) -print"
|
||||||
|
Print out a list of all the files which are not both newer than
|
||||||
|
.Dq ttt
|
||||||
|
and owned by
|
||||||
|
.Dq wnj .
|
||||||
|
.It Li "find / \e( -newer ttt -or -user wnj \e) -print"
|
||||||
|
Print out a list of all the files that are either owned by
|
||||||
|
.Dq wnj
|
||||||
|
or that are newer than
|
||||||
|
.Dq ttt .
|
||||||
|
.It Li "find / \e( -newer ttt -or -user wnj \e) -exit 1"
|
||||||
|
Return immediately with a value of 1 if any files are found that are either
|
||||||
|
owned by
|
||||||
|
.Dq wnj
|
||||||
|
or that are newer than
|
||||||
|
.Dq ttt ,
|
||||||
|
but do not print them.
|
||||||
|
.It Li "find / \e( -newer ttt -or -user wnj \e) -ls -exit 1"
|
||||||
|
Same as above, but list the first file matching the criteria before exiting
|
||||||
|
with a value of 1.
|
||||||
|
.El
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr chflags 1 ,
|
||||||
|
.Xr chmod 1 ,
|
||||||
|
.Xr locate 1 ,
|
||||||
|
.Xr xargs 1 ,
|
||||||
|
.Xr stat 2 ,
|
||||||
|
.Xr fts 3 ,
|
||||||
|
.Xr getgrent 3 ,
|
||||||
|
.Xr getpwent 3 ,
|
||||||
|
.Xr strmode 3 ,
|
||||||
|
.Xr symlink 7 ,
|
||||||
|
.Xr sysctl 8
|
||||||
|
.Sh STANDARDS
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
utility syntax is a superset of the syntax specified by the
|
||||||
|
.St -p1003.2
|
||||||
|
standard.
|
||||||
|
.Pp
|
||||||
|
The options and the
|
||||||
|
.Ic -amin ,
|
||||||
|
.Ic -anewer ,
|
||||||
|
.Ic -cmin ,
|
||||||
|
.Ic -cnewer ,
|
||||||
|
.Ic -delete ,
|
||||||
|
.Ic -empty ,
|
||||||
|
.Ic -execdir ,
|
||||||
|
.Ic -follow ,
|
||||||
|
.Ic -fstype ,
|
||||||
|
.Ic -iname ,
|
||||||
|
.Ic -inum ,
|
||||||
|
.Ic -iregex ,
|
||||||
|
.Ic -links ,
|
||||||
|
.Ic -ls ,
|
||||||
|
.Ic -maxdepth ,
|
||||||
|
.Ic -mindepth ,
|
||||||
|
.Ic -mmin ,
|
||||||
|
.Ic -path ,
|
||||||
|
.Ic -print0 ,
|
||||||
|
.Ic -printx ,
|
||||||
|
.Ic -regex ,
|
||||||
|
and
|
||||||
|
.Ic -rm
|
||||||
|
primaries are extensions to
|
||||||
|
.St -p1003.2 .
|
||||||
|
.Pp
|
||||||
|
Historically, the
|
||||||
|
.Fl d ,
|
||||||
|
.Fl h ,
|
||||||
|
and
|
||||||
|
.Fl x
|
||||||
|
options were implemented using the primaries
|
||||||
|
.Dq -depth ,
|
||||||
|
.Dq -follow ,
|
||||||
|
and
|
||||||
|
.Dq -xdev .
|
||||||
|
These primaries always evaluated to true.
|
||||||
|
As they were really global variables that took effect before the traversal
|
||||||
|
began, some legal expressions could have unexpected results.
|
||||||
|
An example is the expression
|
||||||
|
.Dq -print -o -depth .
|
||||||
|
As -print always evaluates to true, the standard order of evaluation
|
||||||
|
implies that -depth would never be evaluated.
|
||||||
|
This is not the case.
|
||||||
|
.Pp
|
||||||
|
The operator
|
||||||
|
.Dq -or
|
||||||
|
was implemented as
|
||||||
|
.Dq -o ,
|
||||||
|
and the operator
|
||||||
|
.Dq -and
|
||||||
|
was implemented as
|
||||||
|
.Dq -a .
|
||||||
|
.Pp
|
||||||
|
Historic implementations of the
|
||||||
|
.Ic -exec
|
||||||
|
and
|
||||||
|
.Ic -ok
|
||||||
|
primaries did not replace the string
|
||||||
|
.Dq {}
|
||||||
|
in the utility name or the
|
||||||
|
utility arguments if it had preceding or following non-whitespace characters.
|
||||||
|
This version replaces it no matter where in the utility name or arguments
|
||||||
|
it appears.
|
||||||
|
.Pp
|
||||||
|
Support for
|
||||||
|
.Dq Ic -exec Ar ... No +
|
||||||
|
is consistent with
|
||||||
|
.Em IEEE PASC Interpretation 1003.2 #210 ,
|
||||||
|
though the feature originated in
|
||||||
|
.Tn SVR4 .
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Ic -delete
|
||||||
|
primary does not interact well with other options that cause the filesystem
|
||||||
|
tree traversal options to be changed.
|
||||||
|
.Sh HISTORY
|
||||||
|
A much simpler
|
||||||
|
.Nm find
|
||||||
|
command appeared in First Edition AT\*[Am]T Unix.
|
||||||
|
The syntax had become similar to the present version by
|
||||||
|
the time of the Fifth Edition.
|
||||||
|
.Sh BUGS
|
||||||
|
The special characters used by
|
||||||
|
.Nm
|
||||||
|
are also special characters to many shell programs.
|
||||||
|
In particular, the characters
|
||||||
|
.Dq \&* ,
|
||||||
|
.Dq \&[ ,
|
||||||
|
.Dq \&] ,
|
||||||
|
.Dq \&? ,
|
||||||
|
.Dq \&( ,
|
||||||
|
.Dq \&) ,
|
||||||
|
.Dq \&! ,
|
||||||
|
.Dq \e ,
|
||||||
|
and
|
||||||
|
.Dq \&;
|
||||||
|
may have to be escaped from the shell.
|
||||||
|
.Pp
|
||||||
|
As there is no delimiter separating options and file names or file
|
||||||
|
names and the
|
||||||
|
.Ar expression ,
|
||||||
|
it is difficult to specify files named
|
||||||
|
.Dq -xdev
|
||||||
|
or
|
||||||
|
.Dq \&! .
|
||||||
|
These problems are handled by the
|
||||||
|
.Fl f
|
||||||
|
option and the
|
||||||
|
.Xr getopt 3
|
||||||
|
.Dq --
|
||||||
|
construct.
|
284
commands/find/find.c
Normal file
284
commands/find/find.c
Normal file
|
@ -0,0 +1,284 @@
|
||||||
|
/* $NetBSD: find.c,v 1.25 2007/09/25 04:10:12 lukem Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1991, 1993, 1994
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Cimarron D. Taylor of the University of California, Berkeley.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#ifndef lint
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "from: @(#)find.c 8.5 (Berkeley) 8/5/94";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: find.c,v 1.25 2007/09/25 04:10:12 lukem Exp $");
|
||||||
|
#endif
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fts.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "find.h"
|
||||||
|
|
||||||
|
static int ftscompare(const FTSENT **, const FTSENT **);
|
||||||
|
|
||||||
|
static void sig_lock(sigset_t *);
|
||||||
|
static void sig_unlock(const sigset_t *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* find_formplan --
|
||||||
|
* process the command line and create a "plan" corresponding to the
|
||||||
|
* command arguments.
|
||||||
|
*/
|
||||||
|
PLAN *
|
||||||
|
find_formplan(char **argv)
|
||||||
|
{
|
||||||
|
PLAN *plan, *tail, *new;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* for each argument in the command line, determine what kind of node
|
||||||
|
* it is, create the appropriate node type and add the new plan node
|
||||||
|
* to the end of the existing plan. The resulting plan is a linked
|
||||||
|
* list of plan nodes. For example, the string:
|
||||||
|
*
|
||||||
|
* % find . -name foo -newer bar -print
|
||||||
|
*
|
||||||
|
* results in the plan:
|
||||||
|
*
|
||||||
|
* [-name foo]--> [-newer bar]--> [-print]
|
||||||
|
*
|
||||||
|
* in this diagram, `[-name foo]' represents the plan node generated
|
||||||
|
* by c_name() with an argument of foo and `-->' represents the
|
||||||
|
* plan->next pointer.
|
||||||
|
*/
|
||||||
|
for (plan = tail = NULL; *argv;) {
|
||||||
|
if (!(new = find_create(&argv)))
|
||||||
|
continue;
|
||||||
|
if (plan == NULL)
|
||||||
|
tail = plan = new;
|
||||||
|
else {
|
||||||
|
tail->next = new;
|
||||||
|
tail = new;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if the user didn't specify one of -print, -ok, -fprint, -exec, or
|
||||||
|
* -exit, then -print is assumed so we bracket the current expression
|
||||||
|
* with parens, if necessary, and add a -print node on the end.
|
||||||
|
*/
|
||||||
|
if (!isoutput) {
|
||||||
|
if (plan == NULL) {
|
||||||
|
new = c_print(NULL, 0);
|
||||||
|
tail = plan = new;
|
||||||
|
} else {
|
||||||
|
new = c_openparen(NULL, 0);
|
||||||
|
new->next = plan;
|
||||||
|
plan = new;
|
||||||
|
new = c_closeparen(NULL, 0);
|
||||||
|
tail->next = new;
|
||||||
|
tail = new;
|
||||||
|
new = c_print(NULL, 0);
|
||||||
|
tail->next = new;
|
||||||
|
tail = new;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* the command line has been completely processed into a search plan
|
||||||
|
* except for the (, ), !, and -o operators. Rearrange the plan so
|
||||||
|
* that the portions of the plan which are affected by the operators
|
||||||
|
* are moved into operator nodes themselves. For example:
|
||||||
|
*
|
||||||
|
* [!]--> [-name foo]--> [-print]
|
||||||
|
*
|
||||||
|
* becomes
|
||||||
|
*
|
||||||
|
* [! [-name foo] ]--> [-print]
|
||||||
|
*
|
||||||
|
* and
|
||||||
|
*
|
||||||
|
* [(]--> [-depth]--> [-name foo]--> [)]--> [-print]
|
||||||
|
*
|
||||||
|
* becomes
|
||||||
|
*
|
||||||
|
* [expr [-depth]-->[-name foo] ]--> [-print]
|
||||||
|
*
|
||||||
|
* operators are handled in order of precedence.
|
||||||
|
*/
|
||||||
|
|
||||||
|
plan = paren_squish(plan); /* ()'s */
|
||||||
|
plan = not_squish(plan); /* !'s */
|
||||||
|
plan = or_squish(plan); /* -o's */
|
||||||
|
return (plan);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ftscompare(const FTSENT **e1, const FTSENT **e2)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (strcoll((*e1)->fts_name, (*e2)->fts_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sig_lock(sigset_t *s)
|
||||||
|
{
|
||||||
|
sigset_t new;
|
||||||
|
|
||||||
|
sigemptyset(&new);
|
||||||
|
sigaddset(&new, SIGINFO); /* block SIGINFO */
|
||||||
|
sigprocmask(SIG_BLOCK, &new, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sig_unlock(const sigset_t *s)
|
||||||
|
{
|
||||||
|
|
||||||
|
sigprocmask(SIG_SETMASK, s, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
FTS *tree; /* pointer to top of FTS hierarchy */
|
||||||
|
FTSENT *g_entry; /* shared with SIGINFO handler */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* find_execute --
|
||||||
|
* take a search plan and an array of search paths and executes the plan
|
||||||
|
* over all FTSENT's returned for the given search paths.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
find_execute(PLAN *plan, char **paths)
|
||||||
|
{
|
||||||
|
PLAN *p;
|
||||||
|
int r, rval, cval;
|
||||||
|
sigset_t s;
|
||||||
|
|
||||||
|
cval = 1;
|
||||||
|
|
||||||
|
if (!(tree = fts_open(paths, ftsoptions, issort ? ftscompare : NULL)))
|
||||||
|
err(1, "ftsopen");
|
||||||
|
|
||||||
|
sig_lock(&s);
|
||||||
|
for (rval = 0; cval && (g_entry = fts_read(tree)) != NULL; sig_lock(&s)) {
|
||||||
|
sig_unlock(&s);
|
||||||
|
switch (g_entry->fts_info) {
|
||||||
|
case FTS_D:
|
||||||
|
if (isdepth)
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
case FTS_DP:
|
||||||
|
if (!isdepth)
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
case FTS_DNR:
|
||||||
|
case FTS_ERR:
|
||||||
|
case FTS_NS:
|
||||||
|
(void)fflush(stdout);
|
||||||
|
warnx("%s: %s",
|
||||||
|
g_entry->fts_path, strerror(g_entry->fts_errno));
|
||||||
|
rval = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#define BADCH " \t\n\\'\""
|
||||||
|
if (isxargs && strpbrk(g_entry->fts_path, BADCH)) {
|
||||||
|
(void)fflush(stdout);
|
||||||
|
warnx("%s: illegal path", g_entry->fts_path);
|
||||||
|
rval = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call all the functions in the execution plan until one is
|
||||||
|
* false or all have been executed. This is where we do all
|
||||||
|
* the work specified by the user on the command line.
|
||||||
|
*/
|
||||||
|
for (p = plan; p && (p->eval)(p, g_entry); p = p->next)
|
||||||
|
if (p->type == N_EXIT) {
|
||||||
|
rval = p->exit_val;
|
||||||
|
cval = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sig_unlock(&s);
|
||||||
|
if (errno)
|
||||||
|
err(1, "fts_read");
|
||||||
|
(void)fts_close(tree);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cleanup any plans with leftover state.
|
||||||
|
* Keep the last non-zero return value.
|
||||||
|
*/
|
||||||
|
if ((r = find_traverse(plan, plan_cleanup, NULL)) != 0)
|
||||||
|
rval = r;
|
||||||
|
|
||||||
|
return (rval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* find_traverse --
|
||||||
|
* traverse the plan tree and execute func() on all plans. This
|
||||||
|
* does not evaluate each plan's eval() function; it is intended
|
||||||
|
* for operations that must run on all plans, such as state
|
||||||
|
* cleanup.
|
||||||
|
*
|
||||||
|
* If any func() returns non-zero, then so will find_traverse().
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
find_traverse(plan, func, arg)
|
||||||
|
PLAN *plan;
|
||||||
|
int (*func)(PLAN *, void *);
|
||||||
|
void *arg;
|
||||||
|
{
|
||||||
|
PLAN *p;
|
||||||
|
int r, rval;
|
||||||
|
|
||||||
|
rval = 0;
|
||||||
|
for (p = plan; p; p = p->next) {
|
||||||
|
if ((r = func(p, arg)) != 0)
|
||||||
|
rval = r;
|
||||||
|
if (p->type == N_EXPR || p->type == N_OR) {
|
||||||
|
if (p->p_data[0])
|
||||||
|
if ((r = find_traverse(p->p_data[0],
|
||||||
|
func, arg)) != 0)
|
||||||
|
rval = r;
|
||||||
|
if (p->p_data[1])
|
||||||
|
if ((r = find_traverse(p->p_data[1],
|
||||||
|
func, arg)) != 0)
|
||||||
|
rval = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rval;
|
||||||
|
}
|
135
commands/find/find.h
Normal file
135
commands/find/find.h
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
/* $NetBSD: find.h,v 1.24 2007/02/06 13:25:01 elad Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1990, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Cimarron D. Taylor of the University of California, Berkeley.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* from: @(#)find.h 8.1 (Berkeley) 6/6/93
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <regex.h>
|
||||||
|
|
||||||
|
/* node type */
|
||||||
|
enum ntype {
|
||||||
|
N_AND = 1, /* must start > 0 */
|
||||||
|
N_AMIN, N_ANEWER, N_ATIME, N_CLOSEPAREN, N_CMIN, N_CNEWER, N_CTIME,
|
||||||
|
N_DEPTH, N_EMPTY, N_EXEC, N_EXECDIR, N_EXIT, N_EXPR, N_FALSE, N_FLAGS,
|
||||||
|
N_FOLLOW, N_FPRINT, N_FSTYPE, N_GROUP,
|
||||||
|
N_INAME, N_INUM, N_IREGEX, N_LINKS, N_LS, N_MINDEPTH, N_MAXDEPTH,
|
||||||
|
N_MMIN, 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_PRINT0, N_PRINTX,
|
||||||
|
N_PRUNE, N_REGEX, N_SIZE, N_TYPE, N_USER, N_XDEV, N_DELETE
|
||||||
|
};
|
||||||
|
|
||||||
|
/* node definition */
|
||||||
|
typedef struct _plandata {
|
||||||
|
struct _plandata *next; /* next node */
|
||||||
|
int (*eval)(struct _plandata *, FTSENT *);
|
||||||
|
/* node evaluation function */
|
||||||
|
#define F_EQUAL 1 /* [acm]time inum links size */
|
||||||
|
#define F_LESSTHAN 2
|
||||||
|
#define F_GREATER 3
|
||||||
|
#define F_NEEDOK 1 /* exec ok */
|
||||||
|
#define F_PLUSSET 2 /* -exec ... {} + */
|
||||||
|
#define F_MTFLAG 1 /* fstype */
|
||||||
|
#define F_MTTYPE 2
|
||||||
|
#define F_ATLEAST 1 /* perm */
|
||||||
|
int flags; /* private flags */
|
||||||
|
enum ntype type; /* plan node type */
|
||||||
|
union {
|
||||||
|
u_int32_t _f_data; /* flags */
|
||||||
|
gid_t _g_data; /* gid */
|
||||||
|
ino_t _i_data; /* inode */
|
||||||
|
mode_t _m_data; /* mode mask */
|
||||||
|
nlink_t _l_data; /* link count */
|
||||||
|
off_t _o_data; /* file size */
|
||||||
|
time_t _t_data; /* time value */
|
||||||
|
uid_t _u_data; /* uid */
|
||||||
|
short _mt_data; /* mount flags */
|
||||||
|
struct _plandata *_p_data[2]; /* PLAN trees */
|
||||||
|
struct _ex {
|
||||||
|
char **_e_argv; /* argv array */
|
||||||
|
char **_e_orig; /* original strings */
|
||||||
|
int *_e_len; /* allocated length */
|
||||||
|
char **_ep_bxp; /* ptr to 1st addt'l arg */
|
||||||
|
char *_ep_p; /* current buffer pointer */
|
||||||
|
char *_ep_bbp; /* begin buffer pointer */
|
||||||
|
char *_ep_ebp; /* end buffer pointer */
|
||||||
|
int _ep_maxargs; /* max #args */
|
||||||
|
int _ep_narg; /* # addt'l args */
|
||||||
|
int _ep_rval; /* return value */
|
||||||
|
} ex;
|
||||||
|
char *_a_data[2]; /* array of char pointers */
|
||||||
|
char *_c_data; /* char pointer */
|
||||||
|
int _exit_val; /* exit value */
|
||||||
|
int _max_data; /* tree depth */
|
||||||
|
int _min_data; /* tree depth */
|
||||||
|
regex_t _regexp_data; /* compiled regexp */
|
||||||
|
FILE *_fprint_file; /* file stream for -fprint */
|
||||||
|
} p_un;
|
||||||
|
} PLAN;
|
||||||
|
#define a_data p_un._a_data
|
||||||
|
#define c_data p_un._c_data
|
||||||
|
#define i_data p_un._i_data
|
||||||
|
#define f_data p_un._f_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
|
||||||
|
#define o_data p_un._o_data
|
||||||
|
#define p_data p_un._p_data
|
||||||
|
#define t_data p_un._t_data
|
||||||
|
#define u_data p_un._u_data
|
||||||
|
#define e_argv p_un.ex._e_argv
|
||||||
|
#define e_orig p_un.ex._e_orig
|
||||||
|
#define e_len p_un.ex._e_len
|
||||||
|
#define ep_p p_un.ex._ep_p
|
||||||
|
#define ep_bbp p_un.ex._ep_bbp
|
||||||
|
#define ep_ebp p_un.ex._ep_ebp
|
||||||
|
#define ep_bxp p_un.ex._ep_bxp
|
||||||
|
#define ep_cnt p_un.ex._ep_cnt
|
||||||
|
#define ep_maxargs p_un.ex._ep_maxargs
|
||||||
|
#define ep_nline p_un.ex._ep_nline
|
||||||
|
#define ep_narg p_un.ex._ep_narg
|
||||||
|
#define ep_rval p_un.ex._ep_rval
|
||||||
|
#define exit_val p_un._exit_val
|
||||||
|
#define max_data p_un._max_data
|
||||||
|
#define min_data p_un._min_data
|
||||||
|
#define regexp_data p_un._regexp_data
|
||||||
|
#define fprint_file p_un._fprint_file
|
||||||
|
|
||||||
|
typedef struct _option {
|
||||||
|
const char *name; /* option name */
|
||||||
|
enum ntype token; /* token type */
|
||||||
|
PLAN *(*create)(char ***, int); /* create function */
|
||||||
|
int arg; /* function needs arg */
|
||||||
|
} OPTION;
|
||||||
|
|
||||||
|
#include "extern.h"
|
1896
commands/find/function.c
Normal file
1896
commands/find/function.c
Normal file
File diff suppressed because it is too large
Load diff
123
commands/find/ls.c
Normal file
123
commands/find/ls.c
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
/* $NetBSD: ls.c,v 1.19 2006/10/11 19:51:10 apb Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1989, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#ifndef lint
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "from: @(#)ls.c 8.1 (Berkeley) 6/6/93";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: ls.c,v 1.19 2006/10/11 19:51:10 apb Exp $");
|
||||||
|
#endif
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fts.h>
|
||||||
|
#include <grp.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <tzfile.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "find.h"
|
||||||
|
|
||||||
|
/* Derived from the print routines in the ls(1) source code. */
|
||||||
|
|
||||||
|
static void printlink(char *);
|
||||||
|
static void printtime(time_t);
|
||||||
|
|
||||||
|
void
|
||||||
|
printlong(char *name, /* filename to print */
|
||||||
|
char *accpath, /* current valid path to filename */
|
||||||
|
struct stat *sb) /* stat buffer */
|
||||||
|
{
|
||||||
|
char modep[15];
|
||||||
|
|
||||||
|
(void)printf("%7lu %6lld ", (u_long)sb->st_ino,
|
||||||
|
(long long)sb->st_blocks);
|
||||||
|
(void)strmode(sb->st_mode, modep);
|
||||||
|
(void)printf("%s %3lu %-*s %-*s ", modep, (unsigned long)sb->st_nlink,
|
||||||
|
LOGIN_NAME_MAX, user_from_uid(sb->st_uid, 0), LOGIN_NAME_MAX,
|
||||||
|
group_from_gid(sb->st_gid, 0));
|
||||||
|
|
||||||
|
if (S_ISCHR(sb->st_mode) || S_ISBLK(sb->st_mode))
|
||||||
|
(void)printf("%3d,%5d ", major(sb->st_rdev),
|
||||||
|
minor(sb->st_rdev));
|
||||||
|
else
|
||||||
|
(void)printf("%9lld ", (long long)sb->st_size);
|
||||||
|
printtime(sb->st_mtime);
|
||||||
|
(void)printf("%s", name);
|
||||||
|
if (S_ISLNK(sb->st_mode))
|
||||||
|
printlink(accpath);
|
||||||
|
(void)putchar('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
printtime(time_t ftime)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *longstring;
|
||||||
|
|
||||||
|
longstring = ctime(&ftime);
|
||||||
|
for (i = 4; i < 11; ++i)
|
||||||
|
(void)putchar(longstring[i]);
|
||||||
|
|
||||||
|
#define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY)
|
||||||
|
if (ftime + SIXMONTHS > time((time_t *)NULL))
|
||||||
|
for (i = 11; i < 16; ++i)
|
||||||
|
(void)putchar(longstring[i]);
|
||||||
|
else {
|
||||||
|
(void)putchar(' ');
|
||||||
|
for (i = 20; i < 24; ++i)
|
||||||
|
(void)putchar(longstring[i]);
|
||||||
|
}
|
||||||
|
(void)putchar(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
printlink(char *name)
|
||||||
|
{
|
||||||
|
int lnklen;
|
||||||
|
char path[MAXPATHLEN + 1];
|
||||||
|
|
||||||
|
if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) {
|
||||||
|
warn("%s", name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
path[lnklen] = '\0';
|
||||||
|
(void)printf(" -> %s", path);
|
||||||
|
}
|
173
commands/find/main.c
Normal file
173
commands/find/main.c
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
/* $NetBSD: main.c,v 1.28 2008/07/21 14:19:22 lukem Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1990, 1993, 1994
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Cimarron D. Taylor of the University of California, Berkeley.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#ifndef lint
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 5/4/95";
|
||||||
|
#else
|
||||||
|
__COPYRIGHT("@(#) Copyright (c) 1990, 1993, 1994\
|
||||||
|
The Regents of the University of California. All rights reserved.");
|
||||||
|
__RCSID("$NetBSD: main.c,v 1.28 2008/07/21 14:19:22 lukem Exp $");
|
||||||
|
#endif
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <fts.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "find.h"
|
||||||
|
|
||||||
|
time_t now; /* time find was run */
|
||||||
|
int dotfd; /* starting directory */
|
||||||
|
int ftsoptions; /* options for the ftsopen(3) call */
|
||||||
|
int isdeprecated; /* using deprecated syntax */
|
||||||
|
int isdepth; /* do directories on post-order visit */
|
||||||
|
int isoutput; /* user specified output operator */
|
||||||
|
int issort; /* sort directory entries */
|
||||||
|
int isxargs; /* don't permit xargs delimiting chars */
|
||||||
|
int regcomp_flags = REG_BASIC; /* regex compilation flags */
|
||||||
|
|
||||||
|
int main(int, char **);
|
||||||
|
static void usage(void);
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct sigaction sa;
|
||||||
|
char **p, **start;
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
(void)time(&now); /* initialize the time-of-day */
|
||||||
|
(void)setlocale(LC_ALL, "");
|
||||||
|
|
||||||
|
memset(&sa, 0, sizeof(sa));
|
||||||
|
sa.sa_flags = SA_RESTART;
|
||||||
|
sa.sa_handler = show_path;
|
||||||
|
sigaction(SIGINFO, &sa, NULL);
|
||||||
|
|
||||||
|
/* array to hold dir list. at most (argc - 1) elements. */
|
||||||
|
p = start = malloc(argc * sizeof (char *));
|
||||||
|
if (p == NULL)
|
||||||
|
err(1, NULL);
|
||||||
|
|
||||||
|
ftsoptions = FTS_NOSTAT | FTS_PHYSICAL;
|
||||||
|
while ((ch = getopt(argc, argv, "HLPdEf:hsXx")) != -1)
|
||||||
|
switch (ch) {
|
||||||
|
case 'H':
|
||||||
|
ftsoptions &= ~FTS_LOGICAL;
|
||||||
|
ftsoptions |= FTS_PHYSICAL|FTS_COMFOLLOW;
|
||||||
|
break;
|
||||||
|
case 'L':
|
||||||
|
ftsoptions &= ~(FTS_COMFOLLOW|FTS_PHYSICAL);
|
||||||
|
ftsoptions |= FTS_LOGICAL;
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
ftsoptions &= ~(FTS_COMFOLLOW|FTS_LOGICAL);
|
||||||
|
ftsoptions |= FTS_PHYSICAL;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
isdepth = 1;
|
||||||
|
break;
|
||||||
|
case 'E':
|
||||||
|
regcomp_flags = REG_EXTENDED;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
*p++ = optarg;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
ftsoptions &= ~FTS_PHYSICAL;
|
||||||
|
ftsoptions |= FTS_LOGICAL;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
issort = 1;
|
||||||
|
break;
|
||||||
|
case 'X':
|
||||||
|
isxargs = 1;
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
ftsoptions |= FTS_XDEV;
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
argc -= optind;
|
||||||
|
argv += optind;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find first option to delimit the file list. The first argument
|
||||||
|
* that starts with a -, or is a ! or a ( must be interpreted as a
|
||||||
|
* part of the find expression, according to POSIX .2.
|
||||||
|
*/
|
||||||
|
for (; *argv != NULL; *p++ = *argv++) {
|
||||||
|
if (argv[0][0] == '-')
|
||||||
|
break;
|
||||||
|
if ((argv[0][0] == '!' || argv[0][0] == '(') &&
|
||||||
|
argv[0][1] == '\0')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p == start)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
*p = NULL;
|
||||||
|
|
||||||
|
if ((dotfd = open(".", O_RDONLY, 0)) == -1 ||
|
||||||
|
fcntl(dotfd, F_SETFD, FD_CLOEXEC) == -1)
|
||||||
|
err(1, ".");
|
||||||
|
|
||||||
|
exit(find_execute(find_formplan(argv), start));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
(void)fprintf(stderr,
|
||||||
|
"usage: find [-H | -L | -P] [-dEhsXx] [-f file] file [file ...] [expression]\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
151
commands/find/misc.c
Normal file
151
commands/find/misc.c
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
/* $NetBSD: misc.c,v 1.14 2006/10/11 19:51:10 apb Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1990, 1993, 1994
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Cimarron D. Taylor of the University of California, Berkeley.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#ifndef lint
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "from: @(#)misc.c 8.2 (Berkeley) 4/1/94";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: misc.c,v 1.14 2006/10/11 19:51:10 apb Exp $");
|
||||||
|
#endif
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fts.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "find.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* brace_subst --
|
||||||
|
* Replace occurrences of {} in orig with path, and place it in a malloced
|
||||||
|
* area of memory set in store.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
brace_subst(char *orig, char **store, char *path, int *len)
|
||||||
|
{
|
||||||
|
int nlen, plen, rest;
|
||||||
|
char ch, *p, *ostore;
|
||||||
|
|
||||||
|
plen = strlen(path);
|
||||||
|
for (p = *store; (ch = *orig) != '\0'; ++orig)
|
||||||
|
if (ch == '{' && orig[1] == '}') {
|
||||||
|
/* Length of string after the {}. */
|
||||||
|
rest = strlen(&orig[2]);
|
||||||
|
|
||||||
|
nlen = *len;
|
||||||
|
while ((p - *store) + plen + rest + 1 > nlen)
|
||||||
|
nlen *= 2;
|
||||||
|
|
||||||
|
if (nlen > *len) {
|
||||||
|
ostore = *store;
|
||||||
|
if ((*store = realloc(ostore, nlen)) == NULL)
|
||||||
|
err(1, "realloc");
|
||||||
|
*len = nlen;
|
||||||
|
p += *store - ostore; /* Relocate. */
|
||||||
|
}
|
||||||
|
memmove(p, path, plen);
|
||||||
|
p += plen;
|
||||||
|
++orig;
|
||||||
|
} else
|
||||||
|
*p++ = ch;
|
||||||
|
*p = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* queryuser --
|
||||||
|
* print a message to standard error and then read input from standard
|
||||||
|
* input. If the input is 'y' then 1 is returned.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
queryuser(char **argv)
|
||||||
|
{
|
||||||
|
int ch, first, nl;
|
||||||
|
|
||||||
|
(void)fprintf(stderr, "\"%s", *argv);
|
||||||
|
while (*++argv)
|
||||||
|
(void)fprintf(stderr, " %s", *argv);
|
||||||
|
(void)fprintf(stderr, "\"? ");
|
||||||
|
(void)fflush(stderr);
|
||||||
|
|
||||||
|
first = ch = getchar();
|
||||||
|
for (nl = 0;;) {
|
||||||
|
if (ch == '\n') {
|
||||||
|
nl = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ch == EOF)
|
||||||
|
break;
|
||||||
|
ch = getchar();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nl) {
|
||||||
|
(void)fprintf(stderr, "\n");
|
||||||
|
(void)fflush(stderr);
|
||||||
|
}
|
||||||
|
return (first == 'y');
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* show_path --
|
||||||
|
* called on SIGINFO
|
||||||
|
*/
|
||||||
|
/* ARGSUSED */
|
||||||
|
void
|
||||||
|
show_path(int sig)
|
||||||
|
{
|
||||||
|
extern FTSENT *g_entry;
|
||||||
|
int errno_bak;
|
||||||
|
|
||||||
|
if (g_entry == NULL) {
|
||||||
|
/*
|
||||||
|
* not initialized yet.
|
||||||
|
* assumption: pointer assignment is atomic.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno_bak = errno;
|
||||||
|
write(STDERR_FILENO, "find path: ", 11);
|
||||||
|
write(STDERR_FILENO, g_entry->fts_path, g_entry->fts_pathlen);
|
||||||
|
write(STDERR_FILENO, "\n", 1);
|
||||||
|
errno = errno_bak;
|
||||||
|
}
|
272
commands/find/operator.c
Normal file
272
commands/find/operator.c
Normal file
|
@ -0,0 +1,272 @@
|
||||||
|
/* $NetBSD: operator.c,v 1.9 2006/10/11 19:51:10 apb Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1990, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Cimarron D. Taylor of the University of California, Berkeley.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#ifndef lint
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "from: @(#)operator.c 8.1 (Berkeley) 6/6/93";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: operator.c,v 1.9 2006/10/11 19:51:10 apb Exp $");
|
||||||
|
#endif
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <err.h>
|
||||||
|
#include <fts.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "find.h"
|
||||||
|
|
||||||
|
static PLAN *yanknode(PLAN **);
|
||||||
|
static PLAN *yankexpr(PLAN **);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* yanknode --
|
||||||
|
* destructively removes the top from the plan
|
||||||
|
*/
|
||||||
|
static PLAN *
|
||||||
|
yanknode(PLAN **planp) /* pointer to top of plan (modified) */
|
||||||
|
{
|
||||||
|
PLAN *node; /* top node removed from the plan */
|
||||||
|
|
||||||
|
if ((node = (*planp)) == NULL)
|
||||||
|
return (NULL);
|
||||||
|
(*planp) = (*planp)->next;
|
||||||
|
node->next = NULL;
|
||||||
|
return (node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* yankexpr --
|
||||||
|
* Removes one expression from the plan. This is used mainly by
|
||||||
|
* paren_squish. In comments below, an expression is either a
|
||||||
|
* simple node or a N_EXPR node containing a list of simple nodes.
|
||||||
|
*/
|
||||||
|
static PLAN *
|
||||||
|
yankexpr(PLAN **planp) /* pointer to top of plan (modified) */
|
||||||
|
{
|
||||||
|
PLAN *next; /* temp node holding subexpression results */
|
||||||
|
PLAN *node; /* pointer to returned node or expression */
|
||||||
|
PLAN *tail; /* pointer to tail of subplan */
|
||||||
|
PLAN *subplan; /* pointer to head of ( ) expression */
|
||||||
|
|
||||||
|
/* first pull the top node from the plan */
|
||||||
|
if ((node = yanknode(planp)) == NULL)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the node is an '(' then we recursively slurp up expressions
|
||||||
|
* until we find its associated ')'. If it's a closing paren we
|
||||||
|
* just return it and unwind our recursion; all other nodes are
|
||||||
|
* complete expressions, so just return them.
|
||||||
|
*/
|
||||||
|
if (node->type == N_OPENPAREN)
|
||||||
|
for (tail = subplan = NULL;;) {
|
||||||
|
if ((next = yankexpr(planp)) == NULL)
|
||||||
|
err(1, "(: missing closing ')'");
|
||||||
|
/*
|
||||||
|
* If we find a closing ')' we store the collected
|
||||||
|
* subplan in our '(' node and convert the node to
|
||||||
|
* a N_EXPR. The ')' we found is ignored. Otherwise,
|
||||||
|
* we just continue to add whatever we get to our
|
||||||
|
* subplan.
|
||||||
|
*/
|
||||||
|
if (next->type == N_CLOSEPAREN) {
|
||||||
|
if (subplan == NULL)
|
||||||
|
errx(1, "(): empty inner expression");
|
||||||
|
node->p_data[0] = subplan;
|
||||||
|
node->type = N_EXPR;
|
||||||
|
node->eval = f_expr;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if (subplan == NULL)
|
||||||
|
tail = subplan = next;
|
||||||
|
else {
|
||||||
|
tail->next = next;
|
||||||
|
tail = next;
|
||||||
|
}
|
||||||
|
tail->next = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* paren_squish --
|
||||||
|
* replaces "parentheisized" plans in our search plan with "expr" nodes.
|
||||||
|
*/
|
||||||
|
PLAN *
|
||||||
|
paren_squish(PLAN *plan) /* plan with ( ) nodes */
|
||||||
|
{
|
||||||
|
PLAN *expr; /* pointer to next expression */
|
||||||
|
PLAN *tail; /* pointer to tail of result plan */
|
||||||
|
PLAN *result; /* pointer to head of result plan */
|
||||||
|
|
||||||
|
result = tail = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* the basic idea is to have yankexpr do all our work and just
|
||||||
|
* collect it's results together.
|
||||||
|
*/
|
||||||
|
while ((expr = yankexpr(&plan)) != NULL) {
|
||||||
|
/*
|
||||||
|
* if we find an unclaimed ')' it means there is a missing
|
||||||
|
* '(' someplace.
|
||||||
|
*/
|
||||||
|
if (expr->type == N_CLOSEPAREN)
|
||||||
|
errx(1, "): no beginning '('");
|
||||||
|
|
||||||
|
/* add the expression to our result plan */
|
||||||
|
if (result == NULL)
|
||||||
|
tail = result = expr;
|
||||||
|
else {
|
||||||
|
tail->next = expr;
|
||||||
|
tail = expr;
|
||||||
|
}
|
||||||
|
tail->next = NULL;
|
||||||
|
}
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* not_squish --
|
||||||
|
* compresses "!" expressions in our search plan.
|
||||||
|
*/
|
||||||
|
PLAN *
|
||||||
|
not_squish(PLAN *plan) /* plan to process */
|
||||||
|
{
|
||||||
|
PLAN *next; /* next node being processed */
|
||||||
|
PLAN *node; /* temporary node used in N_NOT processing */
|
||||||
|
PLAN *tail; /* pointer to tail of result plan */
|
||||||
|
PLAN *result; /* pointer to head of result plan */
|
||||||
|
|
||||||
|
tail = result = next = NULL;
|
||||||
|
|
||||||
|
while ((next = yanknode(&plan)) != NULL) {
|
||||||
|
/*
|
||||||
|
* if we encounter a ( expression ) then look for nots in
|
||||||
|
* the expr subplan.
|
||||||
|
*/
|
||||||
|
if (next->type == N_EXPR)
|
||||||
|
next->p_data[0] = not_squish(next->p_data[0]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if we encounter a not, then snag the next node and place
|
||||||
|
* it in the not's subplan. As an optimization we compress
|
||||||
|
* several not's to zero or one not.
|
||||||
|
*/
|
||||||
|
if (next->type == N_NOT) {
|
||||||
|
int notlevel = 1;
|
||||||
|
|
||||||
|
node = yanknode(&plan);
|
||||||
|
while (node != NULL && node->type == N_NOT) {
|
||||||
|
++notlevel;
|
||||||
|
node = yanknode(&plan);
|
||||||
|
}
|
||||||
|
if (node == NULL)
|
||||||
|
errx(1, "!: no following expression");
|
||||||
|
if (node->type == N_OR)
|
||||||
|
errx(1, "!: nothing between ! and -o");
|
||||||
|
if (node->type == N_EXPR)
|
||||||
|
node = not_squish(node);
|
||||||
|
if (notlevel % 2 != 1)
|
||||||
|
next = node;
|
||||||
|
else
|
||||||
|
next->p_data[0] = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add the node to our result plan */
|
||||||
|
if (result == NULL)
|
||||||
|
tail = result = next;
|
||||||
|
else {
|
||||||
|
tail->next = next;
|
||||||
|
tail = next;
|
||||||
|
}
|
||||||
|
tail->next = NULL;
|
||||||
|
}
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* or_squish --
|
||||||
|
* compresses -o expressions in our search plan.
|
||||||
|
*/
|
||||||
|
PLAN *
|
||||||
|
or_squish(PLAN *plan) /* plan with ors to be squished */
|
||||||
|
{
|
||||||
|
PLAN *next; /* next node being processed */
|
||||||
|
PLAN *tail; /* pointer to tail of result plan */
|
||||||
|
PLAN *result; /* pointer to head of result plan */
|
||||||
|
|
||||||
|
tail = result = next = NULL;
|
||||||
|
|
||||||
|
while ((next = yanknode(&plan)) != NULL) {
|
||||||
|
/*
|
||||||
|
* if we encounter a ( expression ) then look for or's in
|
||||||
|
* the expr subplan.
|
||||||
|
*/
|
||||||
|
if (next->type == N_EXPR)
|
||||||
|
next->p_data[0] = or_squish(next->p_data[0]);
|
||||||
|
|
||||||
|
/* if we encounter a not then look for not's in the subplan */
|
||||||
|
if (next->type == N_NOT)
|
||||||
|
next->p_data[0] = or_squish(next->p_data[0]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if we encounter an or, then place our collected plan in the
|
||||||
|
* or's first subplan and then recursively collect the
|
||||||
|
* remaining stuff into the second subplan and return the or.
|
||||||
|
*/
|
||||||
|
if (next->type == N_OR) {
|
||||||
|
if (result == NULL)
|
||||||
|
errx(1, "-o: no expression before -o");
|
||||||
|
next->p_data[0] = result;
|
||||||
|
next->p_data[1] = or_squish(plan);
|
||||||
|
if (next->p_data[1] == NULL)
|
||||||
|
errx(1, "-o: no expression after -o");
|
||||||
|
return (next);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add the node to our result plan */
|
||||||
|
if (result == NULL)
|
||||||
|
tail = result = next;
|
||||||
|
else {
|
||||||
|
tail->next = next;
|
||||||
|
tail = next;
|
||||||
|
}
|
||||||
|
tail->next = NULL;
|
||||||
|
}
|
||||||
|
return (result);
|
||||||
|
}
|
157
commands/find/option.c
Normal file
157
commands/find/option.c
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
/* $NetBSD: option.c,v 1.26 2007/02/06 15:33:22 perry Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1990, 1993, 1994
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Cimarron D. Taylor of the University of California, Berkeley.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#ifndef lint
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "from: @(#)option.c 8.2 (Berkeley) 4/16/94";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: option.c,v 1.26 2007/02/06 15:33:22 perry Exp $");
|
||||||
|
#endif
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <err.h>
|
||||||
|
#include <fts.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "find.h"
|
||||||
|
|
||||||
|
int typecompare(const void *, const void *);
|
||||||
|
static OPTION *option(char *);
|
||||||
|
|
||||||
|
/* NB: the following table must be sorted lexically. */
|
||||||
|
static OPTION const options[] = {
|
||||||
|
{ "!", N_NOT, c_not, 0 },
|
||||||
|
{ "(", N_OPENPAREN, c_openparen, 0 },
|
||||||
|
{ ")", N_CLOSEPAREN, c_closeparen, 0 },
|
||||||
|
{ "-a", N_AND, c_null, 0 },
|
||||||
|
{ "-amin", N_AMIN, c_amin, 1 },
|
||||||
|
{ "-and", N_AND, c_null, 0 },
|
||||||
|
{ "-anewer", N_ANEWER, c_anewer, 1 },
|
||||||
|
{ "-atime", N_ATIME, c_atime, 1 },
|
||||||
|
{ "-cmin", N_CMIN, c_cmin, 1 },
|
||||||
|
{ "-cnewer", N_CNEWER, c_cnewer, 1 },
|
||||||
|
{ "-ctime", N_CTIME, c_ctime, 1 },
|
||||||
|
{ "-delete", N_DELETE, c_delete, 0 },
|
||||||
|
{ "-depth", N_DEPTH, c_depth, 0 },
|
||||||
|
{ "-empty", N_EMPTY, c_empty, 0 },
|
||||||
|
{ "-exec", N_EXEC, c_exec, 1 },
|
||||||
|
{ "-execdir", N_EXECDIR, c_execdir, 1 },
|
||||||
|
{ "-exit", N_EXIT, c_exit, 0 },
|
||||||
|
{ "-false", N_FALSE, c_false, 0 },
|
||||||
|
{ "-flags", N_FLAGS, c_flags, 1 },
|
||||||
|
{ "-follow", N_FOLLOW, c_follow, 0 },
|
||||||
|
{ "-fprint", N_FPRINT, c_fprint, 1 },
|
||||||
|
{ "-fstype", N_FSTYPE, c_fstype, 1 },
|
||||||
|
{ "-group", N_GROUP, c_group, 1 },
|
||||||
|
{ "-iname", N_INAME, c_iname, 1 },
|
||||||
|
{ "-inum", N_INUM, c_inum, 1 },
|
||||||
|
{ "-iregex", N_IREGEX, c_iregex, 1 },
|
||||||
|
{ "-links", N_LINKS, c_links, 1 },
|
||||||
|
{ "-ls", N_LS, c_ls, 0 },
|
||||||
|
{ "-maxdepth", N_MAXDEPTH, c_maxdepth, 1 },
|
||||||
|
{ "-mindepth", N_MINDEPTH, c_mindepth, 1 },
|
||||||
|
{ "-mmin", N_MMIN, c_mmin, 1 },
|
||||||
|
{ "-mtime", N_MTIME, c_mtime, 1 },
|
||||||
|
{ "-name", N_NAME, c_name, 1 },
|
||||||
|
{ "-newer", N_NEWER, c_newer, 1 },
|
||||||
|
{ "-nogroup", N_NOGROUP, c_nogroup, 0 },
|
||||||
|
{ "-nouser", N_NOUSER, c_nouser, 0 },
|
||||||
|
{ "-o", N_OR, c_or, 0 },
|
||||||
|
{ "-ok", N_OK, c_exec, 1 },
|
||||||
|
{ "-or", N_OR, c_or, 0 },
|
||||||
|
{ "-path", N_PATH, c_path, 1 },
|
||||||
|
{ "-perm", N_PERM, c_perm, 1 },
|
||||||
|
{ "-print", N_PRINT, c_print, 0 },
|
||||||
|
{ "-print0", N_PRINT0, c_print0, 0 },
|
||||||
|
{ "-printx", N_PRINTX, c_printx, 0 },
|
||||||
|
{ "-prune", N_PRUNE, c_prune, 0 },
|
||||||
|
{ "-regex", N_REGEX, c_regex, 1 },
|
||||||
|
{ "-rm", N_DELETE, c_delete, 0 },
|
||||||
|
{ "-size", N_SIZE, c_size, 1 },
|
||||||
|
{ "-type", N_TYPE, c_type, 1 },
|
||||||
|
{ "-user", N_USER, c_user, 1 },
|
||||||
|
{ "-xdev", N_XDEV, c_xdev, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* find_create --
|
||||||
|
* create a node corresponding to a command line argument.
|
||||||
|
*
|
||||||
|
* TODO:
|
||||||
|
* add create/process function pointers to node, so we can skip
|
||||||
|
* this switch stuff.
|
||||||
|
*/
|
||||||
|
PLAN *
|
||||||
|
find_create(char ***argvp)
|
||||||
|
{
|
||||||
|
OPTION *p;
|
||||||
|
PLAN *new;
|
||||||
|
char **argv;
|
||||||
|
|
||||||
|
argv = *argvp;
|
||||||
|
|
||||||
|
if ((p = option(*argv)) == NULL)
|
||||||
|
errx(1, "%s: unknown option", *argv);
|
||||||
|
++argv;
|
||||||
|
if (p->arg && !*argv)
|
||||||
|
errx(1, "%s: requires additional arguments", *--argv);
|
||||||
|
|
||||||
|
new = (p->create)(&argv, p->token == N_OK);
|
||||||
|
|
||||||
|
*argvp = argv;
|
||||||
|
return (new);
|
||||||
|
}
|
||||||
|
|
||||||
|
static OPTION *
|
||||||
|
option(char *name)
|
||||||
|
{
|
||||||
|
OPTION tmp;
|
||||||
|
|
||||||
|
tmp.name = name;
|
||||||
|
return ((OPTION *)bsearch(&tmp, options,
|
||||||
|
sizeof(options)/sizeof(OPTION), sizeof(OPTION), typecompare));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
typecompare(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (strcmp(((const OPTION *)a)->name, ((const OPTION *)b)->name));
|
||||||
|
}
|
Loading…
Reference in a new issue