bug-gnulib
[Top][All Lists]
Advanced

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

acl: finish support for MacOS X


From: Bruno Haible
Subject: acl: finish support for MacOS X
Date: Sun, 8 Jun 2008 05:06:39 +0200
User-agent: KMail/1.5.4

On MacOS X the testsuite still fails:

  file_has_acl("tmpfile0") returned no, expected yes
  FAIL: test-file-has-acl.sh
  PASS: test-set-mode-acl.sh
  PASS: test-copy-acl.sh

The reason is that on MacOS X, the ACL types ACL_TYPE_ACCESS and 
ACL_TYPE_DEFAULT
are not supported; only ACL_TYPE_EXTENDED works. More precisely, I found out
through some testing that:

      On MacOS X,  acl_get_file (name, ACL_TYPE_ACCESS)
      and          acl_get_file (name, ACL_TYPE_DEFAULT)
      always return NULL / EINVAL.  You have to use
                   acl_get_file (name, ACL_TYPE_EXTENDED)
      or           acl_get_fd (open (name, ...))
      to retrieve an ACL.
      On the other hand,
                   acl_set_file (name, ACL_TYPE_ACCESS, acl)
      and          acl_set_file (name, ACL_TYPE_DEFAULT, acl)
      have the same effect as
                   acl_set_file (name, ACL_TYPE_EXTENDED, acl):
      Each of these calls sets the file's ACL.

In my first attempt, I had code that uses all both ACL_TYPE_ACCESS and
ACL_TYPE_EXTENDED. But this is overkill: It only makes useless system calls.
Better use ACL_TYPE_EXTENDED _only_.

Please review (although I commit it immediately, because more patches are
coming.)


2008-06-07  Bruno Haible  <address@hidden>

        Add support for MacOS X ACLs.
        * lib/file-has-acl.c (file_has_acl): Use ACL_TYPE_EXTENDED instead of
        ACL_TYPE_ACCESS and ACL_TYPE_DEFAULT.
        * lib/set-mode-acl.c (qset_acl): Likewise.
        * lib/copy-acl.c (qcopy_acl): Likewise.

*** lib/file-has-acl.c.orig     2008-06-08 04:56:25.000000000 +0200
--- lib/file-has-acl.c  2008-06-08 04:56:11.000000000 +0200
***************
*** 127,135 ****
        int ret;
  
        if (HAVE_ACL_EXTENDED_FILE)
!       ret = acl_extended_file (name);
        else
        {
          acl_t acl = acl_get_file (name, ACL_TYPE_ACCESS);
          if (acl)
            {
--- 127,155 ----
        int ret;
  
        if (HAVE_ACL_EXTENDED_FILE)
!       {
!         /* On Linux, acl_extended_file is an optimized function: It only
!            makes two calls to getxattr(), one for ACL_TYPE_ACCESS, one for
!            ACL_TYPE_DEFAULT.  */
!         ret = acl_extended_file (name);
!       }
        else
        {
+ #  if HAVE_ACL_TYPE_EXTENDED /* MacOS X */
+         /* On MacOS X, acl_get_file (name, ACL_TYPE_ACCESS)
+            and acl_get_file (name, ACL_TYPE_DEFAULT)
+            always return NULL / EINVAL.  There is no point in making
+            these two useless calls.  The real ACL is retrieved through
+            acl_get_file (name, ACL_TYPE_EXTENDED).  */
+         acl_t acl = acl_get_file (name, ACL_TYPE_EXTENDED);
+         if (acl)
+           {
+             ret = (0 < acl_entries (acl));
+             acl_free (acl);
+           }
+         else
+           ret = -1;
+ #  else /* FreeBSD, IRIX, Tru64 */
          acl_t acl = acl_get_file (name, ACL_TYPE_ACCESS);
          if (acl)
            {
***************
*** 153,158 ****
--- 173,179 ----
            }
          else
            ret = -1;
+ #  endif
        }
        if (ret < 0)
        return ACL_NOT_WELL_SUPPORTED (errno) ? 0 : -1;
***************
*** 179,185 ****
      }
  #endif
  
!   /* FIXME: Add support for AIX, Irix, and Tru64.  Please see Samba's
       source/lib/sysacls.c file for fix-related ideas.  */
  
    return 0;
--- 200,206 ----
      }
  #endif
  
!   /* FIXME: Add support for AIX.  Please see Samba's
       source/lib/sysacls.c file for fix-related ideas.  */
  
    return 0;
*** lib/set-mode-acl.c.orig     2008-06-08 04:56:25.000000000 +0200
--- lib/set-mode-acl.c  2008-06-08 04:56:11.000000000 +0200
***************
*** 143,148 ****
--- 143,165 ----
  #  else /* !MODE_INSIDE_ACL */
    /* MacOS X */
  
+ #   if !HAVE_ACL_TYPE_EXTENDED
+ #    error Must have ACL_TYPE_EXTENDED
+ #   endif
+ 
+   /* On MacOS X,  acl_get_file (name, ACL_TYPE_ACCESS)
+      and          acl_get_file (name, ACL_TYPE_DEFAULT)
+      always return NULL / EINVAL.  You have to use
+                 acl_get_file (name, ACL_TYPE_EXTENDED)
+      or           acl_get_fd (open (name, ...))
+      to retrieve an ACL.
+      On the other hand,
+                 acl_set_file (name, ACL_TYPE_ACCESS, acl)
+      and          acl_set_file (name, ACL_TYPE_DEFAULT, acl)
+      have the same effect as
+                 acl_set_file (name, ACL_TYPE_EXTENDED, acl):
+      Each of these calls sets the file's ACL.  */
+ 
    acl_t acl;
    int ret;
  
***************
*** 150,156 ****
    if (HAVE_ACL_GET_FD && desc != -1)
      acl = acl_get_fd (desc);
    else
!     acl = acl_get_file (name, ACL_TYPE_ACCESS);
    if (acl)
      {
        acl_free (acl);
--- 167,173 ----
    if (HAVE_ACL_GET_FD && desc != -1)
      acl = acl_get_fd (desc);
    else
!     acl = acl_get_file (name, ACL_TYPE_EXTENDED);
    if (acl)
      {
        acl_free (acl);
***************
*** 161,167 ****
          if (HAVE_ACL_SET_FD && desc != -1)
            ret = acl_set_fd (desc, acl);
          else
!           ret = acl_set_file (name, ACL_TYPE_ACCESS, acl);
          if (ret != 0)
            {
              int saved_errno = errno;
--- 178,184 ----
          if (HAVE_ACL_SET_FD && desc != -1)
            ret = acl_set_fd (desc, acl);
          else
!           ret = acl_set_file (name, ACL_TYPE_EXTENDED, acl);
          if (ret != 0)
            {
              int saved_errno = errno;
*** lib/copy-acl.c.orig 2008-06-08 04:56:25.000000000 +0200
--- lib/copy-acl.c      2008-06-08 04:56:11.000000000 +0200
***************
*** 42,47 ****
--- 42,49 ----
  #if USE_ACL && HAVE_ACL_GET_FILE
    /* POSIX 1003.1e (draft 17 -- abandoned) specific version.  */
    /* Linux, FreeBSD, MacOS X, IRIX, Tru64 */
+ # if MODE_INSIDE_ACL
+   /* Linux, FreeBSD, IRIX, Tru64 */
  
    acl_t acl;
    int ret;
***************
*** 82,88 ****
    else
      acl_free (acl);
  
!   if (!MODE_INSIDE_ACL || (mode & (S_ISUID | S_ISGID | S_ISVTX)))
      {
        /* We did not call chmod so far, and either the mode and the ACL are
         separate or special bits are to be set which don't fit into ACLs.  */
--- 84,90 ----
    else
      acl_free (acl);
  
!   if (mode & (S_ISUID | S_ISGID | S_ISVTX))
      {
        /* We did not call chmod so far, and either the mode and the ACL are
         separate or special bits are to be set which don't fit into ACLs.  */
***************
*** 110,115 ****
--- 112,181 ----
      }
    return 0;
  
+ # else /* !MODE_INSIDE_ACL */
+   /* MacOS X */
+ 
+ #  if !HAVE_ACL_TYPE_EXTENDED
+ #   error Must have ACL_TYPE_EXTENDED
+ #  endif
+ 
+   /* On MacOS X,  acl_get_file (name, ACL_TYPE_ACCESS)
+      and          acl_get_file (name, ACL_TYPE_DEFAULT)
+      always return NULL / EINVAL.  You have to use
+                 acl_get_file (name, ACL_TYPE_EXTENDED)
+      or           acl_get_fd (open (name, ...))
+      to retrieve an ACL.
+      On the other hand,
+                 acl_set_file (name, ACL_TYPE_ACCESS, acl)
+      and          acl_set_file (name, ACL_TYPE_DEFAULT, acl)
+      have the same effect as
+                 acl_set_file (name, ACL_TYPE_EXTENDED, acl):
+      Each of these calls sets the file's ACL.  */
+ 
+   acl_t acl;
+   int ret;
+ 
+   if (HAVE_ACL_GET_FD && source_desc != -1)
+     acl = acl_get_fd (source_desc);
+   else
+     acl = acl_get_file (src_name, ACL_TYPE_EXTENDED);
+   if (acl == NULL)
+     {
+       if (ACL_NOT_WELL_SUPPORTED (errno))
+       return qset_acl (dst_name, dest_desc, mode);
+       else
+         return -2;
+     }
+ 
+   if (HAVE_ACL_SET_FD && dest_desc != -1)
+     ret = acl_set_fd (dest_desc, acl);
+   else
+     ret = acl_set_file (dst_name, ACL_TYPE_EXTENDED, acl);
+   if (ret != 0)
+     {
+       int saved_errno = errno;
+ 
+       if (ACL_NOT_WELL_SUPPORTED (errno) && !(acl_entries (acl) > 0))
+         {
+         acl_free (acl);
+         return chmod_or_fchmod (dst_name, dest_desc, mode);
+       }
+       else
+       {
+         acl_free (acl);
+         chmod_or_fchmod (dst_name, dest_desc, mode);
+         errno = saved_errno;
+         return -1;
+       }
+     }
+   else
+     acl_free (acl);
+ 
+   /* Since !MODE_INSIDE_ACL, we have to call chmod explicitly.  */
+   return chmod_or_fchmod (dst_name, dest_desc, mode);
+ 
+ # endif
+ 
  #elif USE_ACL && defined ACL_NO_TRIVIAL
    /* Solaris 10 NFSv4 ACLs.  */
  





reply via email to

[Prev in Thread] Current Thread [Next in Thread]