summaryrefslogtreecommitdiffstats
path: root/usr.bin/find
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1996-10-04 12:54:07 +0000
committerpeter <peter@FreeBSD.org>1996-10-04 12:54:07 +0000
commit342c1e079401a7b0174ba0bb6b4c4cbc9839e9e3 (patch)
tree6a961baf6e584072dd782aa7ea6833a44a7bc50b /usr.bin/find
parent76b116d2fd0e0fd77244ae0eeeedb0d944ecf0ee (diff)
downloadFreeBSD-src-342c1e079401a7b0174ba0bb6b4c4cbc9839e9e3.zip
FreeBSD-src-342c1e079401a7b0174ba0bb6b4c4cbc9839e9e3.tar.gz
Implement a -delete option to find. The code is extremely paranoid and
goes to a fair degree of trouble to enable something like this to be safe: cd /tmp && find . -mtime +7 -delete It removes both files and directories. It does not attempt to remove immutable files (an earlier version I showed to a few people did a chflags and tried to blow away even immutable files. Too risky..) It is thought to be safe because it forces the fts(3) driven descent to only do "minimal risk" stuff. specifically, -follow is disabled, it does checking to see that it chdir'ed to the directory it thought it was going to, it will *not* pass a pathname with a '/' character in it to unlink(), so it should be totally immune to symlink tree races. If it runs into something "fishy", it bails out rather than blunder ahead.. It's better to do that if somebody is trying to compromise security rather than risk giving them an opportunity. Since the unlink()/rmdir() is being called from within the current working directory during the tree descent, there are no fork/exec overheads or races. As a side effect of this paranoia, you cannot do a "find /somewhere/dir -delete", as the last argument to rmdir() is "/somewhere/dir", and the checking won't allow it. Besides, one would use rm -rf for that case anyway. :-) Reviewed by: pst (some time ago, but I've removed the immutable file deletion code that he complained about since he last saw it)
Diffstat (limited to 'usr.bin/find')
-rw-r--r--usr.bin/find/extern.h1
-rw-r--r--usr.bin/find/find.115
-rw-r--r--usr.bin/find/find.h2
-rw-r--r--usr.bin/find/function.c53
-rw-r--r--usr.bin/find/option.c1
5 files changed, 70 insertions, 2 deletions
diff --git a/usr.bin/find/extern.h b/usr.bin/find/extern.h
index c9aba6f..eb63ecd 100644
--- a/usr.bin/find/extern.h
+++ b/usr.bin/find/extern.h
@@ -49,6 +49,7 @@ int queryuser __P((char **));
PLAN *c_atime __P((char *));
PLAN *c_ctime __P((char *));
+PLAN *c_delete __P((void));
PLAN *c_depth __P((void));
PLAN *c_exec __P((char ***, int));
PLAN *c_follow __P((void));
diff --git a/usr.bin/find/find.1 b/usr.bin/find/find.1
index 66f3b59..42ec96f 100644
--- a/usr.bin/find/find.1
+++ b/usr.bin/find/find.1
@@ -33,7 +33,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)find.1 8.4 (Berkeley) 4/1/94
-.\" $Id$
+.\" $Id: find.1,v 1.3 1996/08/29 18:05:51 wosch Exp $
.\"
.Dd April 1, 1994
.Dt FIND 1
@@ -143,6 +143,13 @@ information and the time
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 ``/''
+character in it's pathname relative to "." for security reasons.
+Depth\-first traversal processing is implied by this option.
.It Ic -exec Ar utility Op argument ... ;
True if the program named
.Ar utility
@@ -414,6 +421,7 @@ and
options and the
.Ic -inum ,
.Ic -print0 ,
+.Ic -delete ,
and
.Ic -ls
primaries are extensions to
@@ -461,6 +469,11 @@ These problems are handled by the
option and the
.Xr getopt 3
``--'' construct.
+.Pp
+The
+.Ic -delete
+primary do not interact well with other options that cause the filesystem
+tree traversal options to be changed.
.Sh HISTORY
A
.Nm
diff --git a/usr.bin/find/find.h b/usr.bin/find/find.h
index 8066d37..ff007e7 100644
--- a/usr.bin/find/find.h
+++ b/usr.bin/find/find.h
@@ -43,7 +43,7 @@ enum ntype {
N_FSTYPE, N_GROUP, N_INUM, N_LINKS, N_LS, 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_PRUNE, N_SIZE, N_TYPE, N_USER, N_XDEV,
- N_PRINT0
+ N_PRINT0, N_DELETE
};
/* node definition */
diff --git a/usr.bin/find/function.c b/usr.bin/find/function.c
index ffd7ff1..d5bd5fa 100644
--- a/usr.bin/find/function.c
+++ b/usr.bin/find/function.c
@@ -937,6 +937,59 @@ c_type(typestring)
}
/*
+ * -delete functions --
+ *
+ * True always. Makes it's best shot and continues on regardless.
+ */
+int
+f_delete(plan, entry)
+ PLAN *plan;
+ FTSENT *entry;
+{
+ /* ignore these from fts */
+ if (strcmp(entry->fts_accpath, ".") == 0 ||
+ strcmp(entry->fts_accpath, "..") == 0)
+ return (1);
+
+ /* sanity check */
+ if (isdepth == 0 || /* depth off */
+ (ftsoptions & FTS_NOSTAT) || /* not stat()ing */
+ !(ftsoptions & FTS_PHYSICAL) || /* physical off */
+ (ftsoptions & FTS_LOGICAL)) /* or finally, logical on */
+ errx(1, "-delete: insecure options got turned on");
+
+ /* Potentially unsafe - do not accept relative paths whatsoever */
+ if (strchr(entry->fts_accpath, '/') != NULL)
+ errx(1, "-delete: %s: relative path potentially not safe",
+ entry->fts_accpath);
+
+ /* rmdir directories, unlink everything else */
+ if (S_ISDIR(entry->fts_statp->st_mode)) {
+ if (rmdir(entry->fts_accpath) < 0)
+ warn("-delete: rmdir(%s)", entry->fts_path);
+ } else {
+ if (unlink(entry->fts_accpath) < 0)
+ warn("-delete: unlink(%s)", entry->fts_path);
+ }
+
+ /* "succeed" */
+ return (1);
+}
+
+PLAN *
+c_delete()
+{
+
+ ftsoptions &= ~FTS_NOSTAT; /* no optimise */
+ ftsoptions |= FTS_PHYSICAL; /* disable -follow */
+ ftsoptions &= ~FTS_LOGICAL; /* disable -follow */
+ isoutput = 1; /* possible output */
+ isdepth = 1; /* -depth implied */
+
+ return (palloc(N_DELETE, f_delete));
+}
+
+/*
* -user uname functions --
*
* True if the file belongs to the user uname. If uname is numeric and
diff --git a/usr.bin/find/option.c b/usr.bin/find/option.c
index 66596c3..c316d4a 100644
--- a/usr.bin/find/option.c
+++ b/usr.bin/find/option.c
@@ -60,6 +60,7 @@ static OPTION const options[] = {
{ "-and", N_AND, NULL, O_NONE },
{ "-atime", N_ATIME, c_atime, O_ARGV },
{ "-ctime", N_CTIME, c_ctime, O_ARGV },
+ { "-delete", N_DELETE, c_delete, O_ZERO },
{ "-depth", N_DEPTH, c_depth, O_ZERO },
{ "-exec", N_EXEC, c_exec, O_ARGVP },
{ "-follow", N_FOLLOW, c_follow, O_ZERO },
OpenPOWER on IntegriCloud