[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

find -delete



this patch adds the "-delete" functionality to find. it removes all the
found files and directories and implies -depth. the code is from
freebsd.

diff -uN find.orig/extern.h find/extern.h
--- find.orig/extern.h	2003-06-26 17:27:29.000000000 +1000
+++ find/extern.h	2004-01-10 14:22:20.000000000 +1000
@@ -52,6 +52,7 @@
 PLAN	*c_cmin(char *, char ***, int);
 PLAN	*c_cnewer(char *, char ***, int);
 PLAN	*c_ctime(char *, char ***, int);
+PLAN	*c_delete(char *, char ***, int);
 PLAN	*c_depth(char *, char ***, int);
 PLAN	*c_empty(char *, char ***, int);
 PLAN	*c_exec(char *, char ***, int);
diff -uN find.orig/find.1 find/find.1
--- find.orig/find.1	2003-09-03 04:50:06.000000000 +1000
+++ find/find.1	2004-01-10 14:22:20.000000000 +1000
@@ -168,6 +168,9 @@
 was started, rounded up to the next full 24-hour period, is
 .Ar n
 24-hour periods.
+.It Ic -delete
+Delete the found files and directories. Always true. Implies
+.Fl d .
 .It Ic -empty
 True if the current file or directory is empty.
 .It Ic -exec Ar utility Op argument ... ;
@@ -500,8 +503,7 @@
 .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
+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
@@ -511,8 +513,7 @@
 .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
+or that are newer than
 .Dq ttt .
 .It Li "$ find  /  \e!  -fstype  local  -prune  -or  -name '*.core' -print"
 Print out a list of all core files on local file systems.
diff -uN find.orig/find.h find/find.h
--- find.orig/find.h	2003-06-26 17:27:29.000000000 +1000
+++ find/find.h	2004-01-10 14:22:20.000000000 +1000
@@ -37,7 +37,7 @@
 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_EXPR,
+	N_DELETE, N_DEPTH, N_EMPTY, N_EXEC, N_EXECDIR, N_EXPR,
 	N_FLAGS, N_FOLLOW, N_FSTYPE, N_GROUP, N_INAME, N_INUM, N_LINKS, N_LS,
 	N_MMIN, N_MAXDEPTH,
 	N_MINDEPTH, N_MTIME, N_NAME, N_NEWER, N_NOGROUP, N_NOT, N_NOUSER,
diff -uN find.orig/function.c find/function.c
--- find.orig/function.c	2003-06-26 17:27:29.000000000 +1000
+++ find/function.c	2004-01-10 16:33:53.000000000 +1000
@@ -115,6 +115,7 @@
 int	f_expr(PLAN *, FTSENT *);
 int	f_not(PLAN *, FTSENT *);
 int	f_or(PLAN *, FTSENT *);
+int	f_delete(PLAN *, FTSENT *);
 
 extern int dotfd;
 extern time_t now;
@@ -292,6 +293,62 @@
 }
 
 /*
+ * -delete functions --
+ *
+ *	True always.  Makes its best shot and continues on regardless.
+ */
+int
+f_delete(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);
+
+	/* Turn off user immutable bits if running as root */
+	if ((entry->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
+	    !(entry->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
+	    geteuid() == 0)
+		chflags(entry->fts_accpath,
+		       entry->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE));
+
+	/* rmdir directories, unlink everything else */
+	if (S_ISDIR(entry->fts_statp->st_mode)) {
+		if (rmdir(entry->fts_accpath) < 0 && errno != ENOTEMPTY)
+			warn("-delete: rmdir(%s)", entry->fts_path);
+	} else {
+		if (unlink(entry->fts_accpath) < 0)
+			warn("-delete: unlink(%s)", entry->fts_path);
+	}
+
+	return (1);
+}
+
+PLAN *
+c_delete(char *ignore, char ***ignored, int unused)
+{
+	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));
+}
+
+/*
  * -depth functions --
  *
  *	Always true, causes descent of the directory hierarchy to be done
diff -uN find.orig/option.c find/option.c
--- find.orig/option.c	2003-07-03 07:04:10.000000000 +1000
+++ find/option.c	2004-01-10 14:22:21.000000000 +1000
@@ -64,6 +64,7 @@
 	{ "-cmin",	N_CMIN,		c_cmin,		O_ARGV },
 	{ "-cnewer",	N_CNEWER,	c_cnewer,	O_ARGV },
 	{ "-ctime",	N_CTIME,	c_ctime,	O_ARGV },
+	{ "-delete",	N_DELETE,	c_delete,	O_ZERO },
 	{ "-depth",	N_DEPTH,	c_depth,	O_ZERO },
 	{ "-empty",	N_EMPTY,	c_empty,	O_ZERO },
 	{ "-exec",	N_EXEC,		c_exec,		O_ARGVP },



Visit your host, monkey.org