git: e4b646ce1610 - main - find: Add -readable, -writable & -executable options

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Mon, 22 Jan 2024 01:35:46 UTC
The branch main has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=e4b646ce16105efc943bc8ac2242a2220dfe18d8

commit e4b646ce16105efc943bc8ac2242a2220dfe18d8
Author:     Ricardo Branco <rbranco@suse.de>
AuthorDate: 2024-01-21 19:53:05 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2024-01-22 01:33:46 +0000

    find: Add -readable, -writable & -executable options
    
    Reviewed by:    jhb, Mina Galić
    Pull Request:   https://github.com/freebsd/freebsd-src/pull/1080
---
 usr.bin/find/extern.h   |  3 +++
 usr.bin/find/find.1     | 20 +++++++++++++++++++-
 usr.bin/find/function.c | 39 +++++++++++++++++++++++++++++++++++++++
 usr.bin/find/option.c   |  3 +++
 4 files changed, 64 insertions(+), 1 deletion(-)

diff --git a/usr.bin/find/extern.h b/usr.bin/find/extern.h
index a1bd5e6d16a5..feb2e0202056 100644
--- a/usr.bin/find/extern.h
+++ b/usr.bin/find/extern.h
@@ -86,6 +86,7 @@ exec_f	f_delete;
 exec_f	f_depth;
 exec_f	f_empty;
 exec_f	f_exec;
+exec_f	f_executable;
 exec_f	f_expr;
 exec_f	f_false;
 exec_f	f_flags;
@@ -107,11 +108,13 @@ exec_f	f_print;
 exec_f	f_print0;
 exec_f	f_prune;
 exec_f	f_quit;
+exec_f	f_readable;
 exec_f	f_regex;
 exec_f	f_size;
 exec_f	f_sparse;
 exec_f	f_type;
 exec_f	f_user;
+exec_f	f_writable;
 
 extern int ftsoptions, ignore_readdir_race, isdepth, isoutput;
 extern int issort, isxargs;
diff --git a/usr.bin/find/find.1 b/usr.bin/find/find.1
index 856961d02395..635d42656bad 100644
--- a/usr.bin/find/find.1
+++ b/usr.bin/find/find.1
@@ -28,7 +28,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd January 15, 2024
+.Dd January 21, 2024
 .Dt FIND 1
 .Os
 .Sh NAME
@@ -465,6 +465,12 @@ if at least one invocation of
 returns a non-zero exit status,
 .Nm
 will return a non-zero exit status.
+.It Ic -executable
+Matches files which are executable by the current user.
+This test makes use of the
+.Xr access 2
+system call, and so can be fooled by NFS servers which do UID mapping (or root-squashing).
+This is a GNU find extension.
 .It Ic -flags Oo Cm - Ns | Ns Cm + Oc Ns Ar flags , Ns Ar notflags
 The flags are specified using symbolic names (see
 .Xr chflags 1 ) .
@@ -829,6 +835,12 @@ option was specified.
 Causes
 .Nm
 to terminate immediately.
+.It Ic -readable
+Matches files which are readable by the current user.
+This test makes use of the
+.Xr access 2
+system call, and so can be fooled by NFS servers which do UID mapping (or root-squashing).
+This is a GNU find extension.
 .It Ic -regex Ar pattern
 True if the whole path of the file matches
 .Ar pattern
@@ -925,6 +937,12 @@ is treated as a user ID.
 The same thing as
 .Ic -path ,
 for GNU find compatibility.
+.It Ic -writable
+Matches files which are writable by the current user.
+This test makes use of the
+.Xr access 2
+system call, and so can be fooled by NFS servers which do UID mapping (or root-squashing).
+This is a GNU find extension.
 .El
 .Sh OPERATORS
 The primaries may be combined using the following operators.
diff --git a/usr.bin/find/function.c b/usr.bin/find/function.c
index f96a086cbda3..ef610903cc00 100644
--- a/usr.bin/find/function.c
+++ b/usr.bin/find/function.c
@@ -1808,3 +1808,42 @@ f_quit(PLAN *plan __unused, FTSENT *entry __unused)
 }
 
 /* c_quit == c_simple */
+
+/*
+ * -readable
+ *
+ *  	File is readable
+ */
+int
+f_readable(PLAN *plan __unused, FTSENT *entry)
+{
+	return (access(entry->fts_path, R_OK) == 0);
+}
+
+/* c_readable == c_simple */
+
+/*
+ * -writable
+ *
+ *  	File is writable
+ */
+int
+f_writable(PLAN *plan __unused, FTSENT *entry)
+{
+	return (access(entry->fts_path, W_OK) == 0);
+}
+
+/* c_writable == c_simple */
+
+/*
+ * -executable
+ *
+ *  	File is executable
+ */
+int
+f_executable(PLAN *plan __unused, FTSENT *entry)
+{
+	return (access(entry->fts_path, X_OK) == 0);
+}
+
+/* c_executable == c_simple */
diff --git a/usr.bin/find/option.c b/usr.bin/find/option.c
index 166fc75e9c51..99c67eed8cd9 100644
--- a/usr.bin/find/option.c
+++ b/usr.bin/find/option.c
@@ -75,6 +75,7 @@ static OPTION const options[] = {
 	{ "-empty",	c_empty,	f_empty,	0 },
 	{ "-exec",	c_exec,		f_exec,		0 },
 	{ "-execdir",	c_exec,		f_exec,		F_EXECDIR },
+	{ "-executable", c_simple,	f_executable,	0 },
 	{ "-false",	c_simple,	f_false,	0 },
 #if HAVE_STRUCT_STAT_ST_FLAGS
 	{ "-flags",	c_flags,	f_flags,	0 },
@@ -149,6 +150,7 @@ static OPTION const options[] = {
 // -printf
 	{ "-prune",	c_simple,	f_prune,	0 },
 	{ "-quit",	c_simple,	f_quit,		0 },
+	{ "-readable",	c_simple,	f_readable,	0 },
 	{ "-regex",	c_regex,	f_regex,	0 },
 	{ "-samefile",	c_samefile,	f_inum,		0 },
 	{ "-size",	c_size,		f_size,		0 },
@@ -158,6 +160,7 @@ static OPTION const options[] = {
 	{ "-uid",	c_user,		f_user,		0 },
 	{ "-user",	c_user,		f_user,		0 },
 	{ "-wholename",	c_name,		f_path,		0 },
+	{ "-writable",	c_simple,	f_writable,	0 },
 	{ "-xdev",	c_xdev,		f_always_true,	0 },
 // -xtype
 };