[newlib-cygwin/main] Cygwin: ACLs: Add some useful non-POSIX ACL functions from FreeBSD

Corinna Vinschen via Cygwin-cvs <[email protected]>
Newsgroups gmane.os.cygwin.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=78adc10ab819f10e1b6211b4bbc149e97f9b9e36

commit 78adc10ab819f10e1b6211b4bbc149e97f9b9e36
Author:     Corinna Vinschen <[email protected]>
AuthorDate: Mon Mar 31 10:58:26 2025 +0200
Commit:     Corinna Vinschen <[email protected]>
CommitDate: Mon Mar 31 22:03:48 2025 +0200

    Cygwin: ACLs: Add some useful non-POSIX ACL functions from FreeBSD
    
    Add the following functions:
    
      acl_get_fd_np
      acl_get_link_np
      acl_get_perm_np
      acl_is_trivial_np
      acl_set_fd_np
      acl_set_link_np
      acl_strip_np
    
    Signed-off-by: Corinna Vinschen <[email protected]>

Diff:
---
 winsup/cygwin/cygwin.din               |   7 ++
 winsup/cygwin/include/cygwin/version.h |   4 +-
 winsup/cygwin/include/sys/acl.h        |  12 +++
 winsup/cygwin/sec/posixacl.cc          | 179 ++++++++++++++++++++++++++++++---
 winsup/doc/posix.xml                   |   7 ++
 5 files changed, 193 insertions(+), 16 deletions(-)

diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din
index deac201c085c..d7a17b234a4c 100644
--- a/winsup/cygwin/cygwin.din
+++ b/winsup/cygwin/cygwin.din
@@ -179,18 +179,25 @@ acl_from_mode NOSIGFE
 acl_from_text SIGFE
 acl_get_entry NOSIGFE
 acl_get_fd SIGFE
+acl_get_fd_np SIGFE
 acl_get_file SIGFE
+acl_get_link_np SIGFE
 acl_get_perm NOSIGFE
+acl_get_perm_np = acl_get_perm NOSIGFE
 acl_get_permset NOSIGFE
 acl_get_qualifier SIGFE
 acl_get_tag_type NOSIGFE
 acl_init SIGFE
+acl_is_trivial_np SIGFE
 acl_set_fd SIGFE
+acl_set_fd_np SIGFE
 acl_set_file SIGFE
+acl_set_link_np SIGFE
 acl_set_permset NOSIGFE
 acl_set_qualifier NOSIGFE
 acl_set_tag_type NOSIGFE
 acl_size NOSIGFE
+acl_strip_np SIGFE
 acl_to_any_text SIGFE
 acl_to_text SIGFE
 acl_valid NOSIGFE
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index f341dba5b988..e4c16db43e30 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -493,12 +493,14 @@ details. */
   356: Export posix_spawn_file_actions_addchdir and
        posix_spawn_file_actions_addfchdir.
   357: Export posix_close.
+  358: Export acl_get_fd_np, acl_get_link_np, acl_get_perm_np,
+       acl_is_trivial_np, acl_set_fd_np, acl_set_link_np, acl_strip_np.
 
   Note that we forgot to bump the api for ualarm, strtoll, strtoull,
   sigaltstack, sethostname. */
 
 #define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 357
+#define CYGWIN_VERSION_API_MINOR 358
 
 /* There is also a compatibity version number associated with the shared memory
    regions.  It is incremented when incompatible changes are made to the shared
diff --git a/winsup/cygwin/include/sys/acl.h b/winsup/cygwin/include/sys/acl.h
index 74e50ba9e1d4..5789dd03a80c 100644
--- a/winsup/cygwin/include/sys/acl.h
+++ b/winsup/cygwin/include/sys/acl.h
@@ -92,6 +92,18 @@ extern ssize_t	acl_size (acl_t __acl);
 extern char    *acl_to_text (acl_t __acl, ssize_t *__len_p);
 extern int	acl_valid (acl_t __acl);
 
+/* Non-libacl extensions to POSIX.1e draft 17 */
+
+/* FreeBSD, NetBSD */
+extern acl_t	acl_get_fd_np (int __fd, acl_type_t __type);
+extern acl_t	acl_get_link_np (const char *__path_p, acl_type_t __type);
+extern int	acl_get_perm_np (acl_permset_t __permset_d, acl_perm_t __perm);
+extern int	acl_is_trivial_np (const acl_t __acl, int *__trivialp);
+extern int	acl_set_fd_np (int __fd, acl_t __acl, acl_type_t __type);
+extern int	acl_set_link_np (const char *__path_p, acl_type_t __type,
+				 acl_t __acl);
+extern acl_t	acl_strip_np (const acl_t __acl, int __recalculate_mask);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/winsup/cygwin/sec/posixacl.cc b/winsup/cygwin/sec/posixacl.cc
index 6b01ded5906b..6f3ef15ca216 100644
--- a/winsup/cygwin/sec/posixacl.cc
+++ b/winsup/cygwin/sec/posixacl.cc
@@ -322,7 +322,7 @@ acl_delete_perm (acl_permset_t permset_d, acl_perm_t perm)
     }
   __except (EINVAL) {}
   __endtry
-      return -1;
+  return -1;
 }
 
 extern "C" int
@@ -674,14 +674,11 @@ fhandler_socket_unix::acl_get (acl_type_t type)
 extern "C" acl_t
 acl_get_fd (int fd)
 {
-  cygheap_fdget cfd (fd);
-  if (cfd < 0)
-    return NULL;
-  return cfd->acl_get (ACL_TYPE_ACCESS);
+  return acl_get_fd_np (fd, ACL_TYPE_ACCESS);
 }
 
-extern "C" acl_t
-acl_get_file (const char *path_p, acl_type_t type)
+static acl_t
+__acl_get_file (const char *path_p, acl_type_t type, unsigned follow_mode)
 {
   if (type != ACL_TYPE_ACCESS && type != ACL_TYPE_DEFAULT)
     {
@@ -689,7 +686,7 @@ acl_get_file (const char *path_p, acl_type_t type)
       return NULL;
     }
   fhandler_base *fh;
-  if (!(fh = build_fh_name (path_p, PC_SYM_FOLLOW, stat_suffixes)))
+  if (!(fh = build_fh_name (path_p, follow_mode, stat_suffixes)))
     return NULL;
   if (fh->error ())
     {
@@ -701,6 +698,12 @@ acl_get_file (const char *path_p, acl_type_t type)
   return acl;
 }
 
+extern "C" acl_t
+acl_get_file (const char *path_p, acl_type_t type)
+{
+  return __acl_get_file (path_p, type, PC_SYM_FOLLOW);
+}
+
 int
 fhandler_base::acl_set (acl_t acl, acl_type_t type)
 {
@@ -844,14 +847,12 @@ fhandler_socket_unix::acl_set (acl_t acl, acl_type_t type)
 extern "C" int
 acl_set_fd (int fd, acl_t acl)
 {
-  cygheap_fdget cfd (fd);
-  if (cfd < 0)
-    return -1;
-  return cfd->acl_set (acl, ACL_TYPE_ACCESS);
+  return acl_set_fd_np (fd, acl, ACL_TYPE_ACCESS);
 }
 
-extern "C" int
-acl_set_file(const char *path_p, acl_type_t type, acl_t acl)
+static int
+__acl_set_file (const char *path_p, acl_type_t type, acl_t acl,
+		unsigned follow_mode)
 {
   if (type != ACL_TYPE_ACCESS && type != ACL_TYPE_DEFAULT)
     {
@@ -859,7 +860,7 @@ acl_set_file(const char *path_p, acl_type_t type, acl_t acl)
       return -1;
     }
   fhandler_base *fh;
-  if (!(fh = build_fh_name (path_p, PC_SYM_FOLLOW, stat_suffixes)))
+  if (!(fh = build_fh_name (path_p, follow_mode, stat_suffixes)))
     return -1;
   if (fh->error ())
     {
@@ -871,6 +872,12 @@ acl_set_file(const char *path_p, acl_type_t type, acl_t acl)
   return ret;
 }
 
+extern "C" int
+acl_set_file (const char *path_p, acl_type_t type, acl_t acl)
+{
+  return __acl_set_file (path_p, type, acl, PC_SYM_FOLLOW);
+}
+
 extern "C" int
 acl_delete_def_file (const char *path_p)
 {
@@ -1151,3 +1158,145 @@ acl_to_any_text (acl_t acl, const char *prefix, char separator, int options)
   __endtry
   return NULL;
 }
+
+/* FreeBSD extensions */
+
+extern "C" acl_t
+acl_get_fd_np (int fd, acl_type_t type)
+{
+  cygheap_fdget cfd (fd);
+  if (cfd < 0)
+    return NULL;
+  return cfd->acl_get (type);
+}
+
+extern "C" int
+acl_is_trivial_np (const acl_t acl, int *trivialp)
+{
+  __try
+    {
+      if (!(__aclcheck (acl->entry, acl->count, NULL, true)))
+	*trivialp = acl->count - acl->deleted <= MIN_ACL_ENTRIES ? 1 : 0;
+      return 0;
+    }
+  __except (EINVAL) {}
+  __endtry
+  return -1;
+}
+
+extern "C" acl_t
+acl_get_link_np (const char *path_p, acl_type_t type)
+{
+  return __acl_get_file (path_p, type, PC_SYM_NOFOLLOW);
+}
+
+extern "C" int
+acl_set_fd_np (int fd, acl_t acl, acl_type_t type)
+{
+  if (type != ACL_TYPE_ACCESS && type != ACL_TYPE_DEFAULT)
+    {
+      set_errno (EINVAL);
+      return -1;
+    }
+  cygheap_fdget cfd (fd);
+  if (cfd < 0)
+    return -1;
+  return cfd->acl_set (acl, type);
+}
+
+extern "C" int
+acl_set_link_np (const char *path_p, acl_type_t type, acl_t acl)
+{
+  return __acl_set_file (path_p, type, acl, PC_SYM_NOFOLLOW);
+}
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2001 Chris D. Faulhaber
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+extern "C" acl_t
+acl_strip_np (const acl_t acl, int recalculate_mask)
+{
+  acl_t acl_new, acl_old;
+  acl_entry_t entry, entry_new;
+  acl_tag_t tag;
+  int entry_id, have_mask_entry;
+
+  acl_old = acl_dup (acl);
+  if (acl_old == NULL)
+    return NULL;
+
+  have_mask_entry = 0;
+  acl_new = acl_init (MAX_ACL_ENTRIES);
+  if (acl_new == NULL)
+    {
+      acl_free (acl_old);
+      return NULL;
+    }
+  tag = ACL_UNDEFINED_TAG;
+
+  /* only save the default user/group/other entries */
+  entry_id = ACL_FIRST_ENTRY;
+  while (acl_get_entry (acl_old, entry_id, &entry) == 1)
+    {
+      entry_id = ACL_NEXT_ENTRY;
+
+      if (acl_get_tag_type (entry, &tag) == -1)
+	goto fail;
+
+      switch (tag)
+	{
+	  case ACL_USER_OBJ:
+	  case ACL_GROUP_OBJ:
+	  case ACL_OTHER:
+	    if (acl_create_entry (&acl_new, &entry_new) == -1)
+	      goto fail;
+	    if (acl_copy_entry (entry_new, entry) == -1)
+	      goto fail;
+	    break;
+	  case ACL_MASK:
+	    have_mask_entry = 1;
+	    break;
+	  default:
+	    break;
+	}
+    }
+
+  if (have_mask_entry && recalculate_mask)
+    {
+      if (acl_calc_mask (&acl_new) == -1)
+	goto fail;
+    }
+
+  return (acl_new);
+
+fail:
+  acl_free (acl_new);
+  acl_free (acl_old);
+
+  return NULL;
+}
diff --git a/winsup/doc/posix.xml b/winsup/doc/posix.xml
index bb5f4146dbc3..af63aa060442 100644
--- a/winsup/doc/posix.xml
+++ b/winsup/doc/posix.xml
@@ -1636,18 +1636,25 @@ ISO®/IEC DIS 9945 Information technology
     acl_from_text		(POSIX.1e draft)
     acl_get_entry		(POSIX.1e draft)
     acl_get_fd			(POSIX.1e draft)
+    acl_get_fd_np		(FreeBSD, NetBSD)
     acl_get_file		(POSIX.1e draft)
     acl_get_perm		(POSIX.1e draft)
+    acl_get_link_np		(FreeBSD, NetBSD)
+    acl_get_perm_np		(FreeBSD, NetBSD)
     acl_get_permset		(POSIX.1e draft)
     acl_get_qualifier		(POSIX.1e draft)
     acl_get_tag_type		(POSIX.1e draft)
     acl_init			(POSIX.1e draft)
+    acl_is_trivial_np		(FreeBSD, NetBSD)
     acl_set_fd			(POSIX.1e draft)
+    acl_set_fd_np		(FreeBSD, NetBSD)
     acl_set_file		(POSIX.1e draft)
+    acl_set_link_np		(FreeBSD, NetBSD)
     acl_set_permset		(POSIX.1e draft)
     acl_set_qualifier		(POSIX.1e draft)
     acl_set_tag_type		(POSIX.1e draft)
     acl_size			(POSIX.1e draft)
+    acl_strip_np		(FreeBSD, NetBSD)
     acl_to_any_text		(POSIX.1e draft)
     acl_to_text			(POSIX.1e draft)
     acl_valid			(POSIX.1e draft)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.