Latest coretuils basic operation of cp is failing on FreeBSD and solaris
with ENOSUP errors due to attempts to copy ACLs.

Tracing these I get:

solaris 10
 mkdir x
 src/cp -a x x.cp
  lchown("x.cp", 11003, 10000)                    = 0
  acl("x", ACE_GETACLCNT, 0, 0x00000000)          = 3
  acl("x", ACE_GETACL, 3, 0x00043490)             = 3
  acl("x", GETACLCNT, 0, 0x00000000)              = 4
  acl("x", GETACL, 4, 0x000434C0)                 = 4
  acl("x.cp", SETACL, 4, 0x000434C0)              Err#89 ENOSYS
  acl("x.cp", ACE_SETACL, 3, 0x00043490)          Err#89 ENOSYS
  acl("x.cp", ACE_GETACL, 333, 0xFFBFE130)        = 3
  acl("x.cp", ACE_SETACL, 6, 0xFFBFE0E8)          Err#89 ENOSYS
  chmod("x.cp", 040755)                           = 0

FreeBSD 9.1
 mkdir x
 src/cp -a x x.cp
  lchown(0x28417050,0x148d2,0x0,0x8056750,0xffffffff,0x28417050) = 0 (0x0)
  __acl_get_file(0xbfbfed96,0x2,0x28418000,0xbfbfe5f0,0x41ed,0x1) ERR#45 
'Operation not supported'
  madvise(0x28418000,0x1000,0x5,0x8066ea8,0x8066ea0,0x4) = 0 (0x0)
  chmod("x.cp/x",040755)               = 0 (0x0)

 touch f
 src/cp --no-preserve=mode f f.cp
 cp: setting permissions for 'f.cp': No such file or directory

All tests on FreeBSD are now passing with the attached,
though TBH I've not analyzed this deeply at all so
would appreciate separate analysis.

The crux of the patch is to set the acl_no_supported flag
when getting permissions and get such an errno.
Also I've reinstated the acl_from_mode() replacement
in set-permissions.c which was ignored due to defines in acl-internal.h

I've not tested this on solaris yet.

thanks,
Pádraig.
diff --git a/lib/acl-internal.h b/lib/acl-internal.h
index d592a75..654af1d 100644
--- a/lib/acl-internal.h
+++ b/lib/acl-internal.h
@@ -127,10 +127,16 @@ rpl_acl_set_fd (int fd, acl_t acl)
 #   define acl_extended_file(name) (-1)
 #  endif
 
-/* Linux-specific */
-#  ifndef HAVE_ACL_FROM_MODE
-#   define HAVE_ACL_FROM_MODE false
-#   define acl_from_mode(mode) (NULL)
+#  if ! defined HAVE_ACL_FROM_MODE && ! defined HAVE_ACL_FROM_TEXT
+ACL_INTERNAL_INLINE acl_t
+rpl_acl_from_mode (mode_t mode)
+{
+  (void) mode;
+  errno = ENOTSUP;
+  return NULL;
+}
+#   undef acl_from_mode
+#   define acl_from_mode rpl_acl_from_mode
 #  endif
 
 /* Set to 0 if a file's mode is stored independently from the ACL.  */
diff --git a/lib/get-permissions.c b/lib/get-permissions.c
index 6c6618d..6fe441e 100644
--- a/lib/get-permissions.c
+++ b/lib/get-permissions.c
@@ -47,7 +47,10 @@ get_permissions (const char *name, int desc, mode_t mode,
   else
     ctx->acl = acl_get_file (name, ACL_TYPE_ACCESS);
   if (ctx->acl == NULL)
-    return acl_errno_valid (errno) ? -1 : 0;
+    {
+      ctx->acls_not_supported = ! acl_errno_valid (errno);
+      return ctx->acls_not_supported ? 0 : -1;
+    }
 
   /* With POSIX ACLs, a file cannot have "no" acl; a file without
      extended permissions has a "minimal" acl which is equivalent to the
diff --git a/lib/set-permissions.c b/lib/set-permissions.c
index 3bcfd31..24a3c9c 100644
--- a/lib/set-permissions.c
+++ b/lib/set-permissions.c
@@ -504,7 +504,15 @@ set_acls (struct permission_context *ctx, const char *name, int desc,
 	    acl_free (ctx->acl);
 	  ctx->acl = acl_from_mode (ctx->mode);
 	  if (ctx->acl == NULL)
-	    ret = -1;
+            {
+              if (! acl_errno_valid (errno))
+                {
+                  ret = 0;
+                  ctx->acls_not_supported = true;
+                }
+              else
+                ret = -1;
+            }
 	}
 
       if (ret == 0 && ctx->acl)
@@ -801,10 +809,9 @@ set_permissions (struct permission_context *ctx, const char *name, int desc)
       int saved_errno = ret ? errno : 0;
 
       /* If we can't set an acl which we expect to be able to set, try setting
-	 the permissions to ctx->mode. Doe to possible inherited permissions,
-	 we cannot simply chmod.  */
+         the permissions to ctx->mode. Due to possible inherited permissions,
+         we cannot simply chmod.  */
 
-      acls_set = false;
       ret = set_acls (ctx, name, desc, true, &must_chmod, &acls_set);
       if (! acls_set)
 	must_chmod = true;

Reply via email to