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)

Reply via email to