git: 551f4b478bf8 - stable/14 - find: Add -readable, -writable & -executable options

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Mon, 08 Apr 2024 19:04:15 UTC
The branch stable/14 has been updated by jhb:

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

commit 551f4b478bf833aa8b268299cad90508b1ff4311
Author:     Ricardo Branco <rbranco@suse.de>
AuthorDate: 2024-01-21 19:53:05 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2024-04-08 17:34:32 +0000

    find: Add -readable, -writable & -executable options
    
    Reviewed by:    jhb, Mina Galić
    Pull Request:   https://github.com/freebsd/freebsd-src/pull/1080
    
    (cherry picked from commit e4b646ce16105efc943bc8ac2242a2220dfe18d8)
---
 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 8c98a6d86bcd..3436f8cf07bf 100644
--- a/usr.bin/find/extern.h
+++ b/usr.bin/find/extern.h
@@ -88,6 +88,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;
@@ -109,11 +110,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 a73196180e7c..def6a82d0a97 100644
--- a/usr.bin/find/find.1
+++ b/usr.bin/find/find.1
@@ -30,7 +30,7 @@
 .\"
 .\"	@(#)find.1	8.7 (Berkeley) 5/9/95
 .\"
-.Dd January 15, 2024
+.Dd January 21, 2024
 .Dt FIND 1
 .Os
 .Sh NAME
@@ -467,6 +467,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 ) .
@@ -831,6 +837,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
@@ -927,6 +939,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 9c1fd4df8731..d28c0edced9e 100644
--- a/usr.bin/find/function.c
+++ b/usr.bin/find/function.c
@@ -1813,3 +1813,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 c5b461f3389b..dc5e5003b3fb 100644
--- a/usr.bin/find/option.c
+++ b/usr.bin/find/option.c
@@ -80,6 +80,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 },
@@ -154,6 +155,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 },
@@ -163,6 +165,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
 };