/* Copy access control lists from one file to another. If SOURCE_DESC is
a valid file descriptor, use file descriptor operations, else use
filename based operations on SRC_NAME. Likewise for DEST_DESC and
- DEST_NAME.
+ DST_NAME.
If access control lists are not available, fchmod the target file to
MODE. Also sets the non-permission bits of the destination file
(S_ISUID, S_ISGID, S_ISVTX) to those from MODE if any are set.
- System call return value semantics. */
+ Return 0 if successful, otherwise output a diagnostic and return -1. */
int
copy_acl (const char *src_name, int source_desc, const char *dst_name,
/* On most hosts an ACL is trivial if n == 3, and it cannot be
less than 3. On IRIX 6.5 it is also trivial if n == -1.
For simplicity and safety, assume the ACL is trivial if n <= 3.
- Also see file_has_acl.c for some of the other possibilities;
+ Also see file-has-acl.c for some of the other possibilities;
it's not clear whether that complexity is needed here. */
if (n <= 3)
{
acl_free (acl);
}
return 0;
+
#else
- ret = chmod_or_fchmod (dst_name, dest_desc, mode);
+
+# if USE_ACL && defined ACL_NO_TRIVIAL
+ /* Solaris 10 NFSv4 ACLs. */
+ acl_t *aclp = NULL;
+ ret = (source_desc < 0
+ ? acl_get (src_name, ACL_NO_TRIVIAL, &aclp)
+ : facl_get (source_desc, ACL_NO_TRIVIAL, &aclp));
+ if (ret != 0 && errno != ENOSYS)
+ {
+ error (0, errno, "%s", quote (src_name));
+ return ret;
+ }
+# endif
+
+ ret = qset_acl (dst_name, dest_desc, mode);
if (ret != 0)
error (0, errno, _("preserving permissions for %s"), quote (dst_name));
+
+# if USE_ACL && defined ACL_NO_TRIVIAL
+ if (ret == 0 && aclp)
+ {
+ ret = (dest_desc < 0
+ ? acl_set (dst_name, aclp)
+ : facl_set (dest_desc, aclp));
+ if (ret != 0)
+ error (0, errno, _("preserving permissions for %s"), quote (dst_name));
+ acl_free (aclp);
+ }
+# endif
+
return ret;
#endif
}
semantics. */
int
-set_acl (char const *name, int desc, mode_t mode)
+qset_acl (char const *name, int desc, mode_t mode)
{
#if USE_ACL && HAVE_ACL_SET_FILE && HAVE_ACL_FREE
/* POSIX 1003.1e draft 17 (abandoned) specific version. */
{
acl = acl_from_mode (mode);
if (!acl)
- {
- error (0, errno, "%s", quote (name));
- return -1;
- }
+ return -1;
}
else
{
acl = acl_from_text (acl_text);
if (!acl)
- {
- error (0, errno, "%s", quote (name));
- return -1;
- }
+ return -1;
}
if (HAVE_ACL_SET_FD && desc != -1)
ret = acl_set_fd (desc, acl);
else
return 0;
}
- error (0, saved_errno, _("setting permissions for %s"), quote (name));
+ errno = saved_errno;
return -1;
}
else
acl_free (acl);
if (S_ISDIR (mode) && acl_delete_def_file (name))
- {
- error (0, errno, _("setting permissions for %s"), quote (name));
- return -1;
- }
+ return -1;
if (mode & (S_ISUID | S_ISGID | S_ISVTX))
{
been set. */
if (chmod_or_fchmod (name, desc, mode))
- {
- error (0, errno, _("preserving permissions for %s"), quote (name));
- return -1;
- }
+ return -1;
}
return 0;
#else
- int ret = chmod_or_fchmod (name, desc, mode);
- if (ret)
- error (0, errno, _("setting permissions for %s"), quote (name));
- return ret;
+
+# if USE_ACL && defined ACL_NO_TRIVIAL
+
+ /* Solaris 10, with NFSv4 ACLs. */
+ acl_t *aclp;
+ char acl_text[] = "user::---,group::---,mask:---,other:---";
+
+ if (mode & S_IRUSR) acl_text[ 6] = 'r';
+ if (mode & S_IWUSR) acl_text[ 7] = 'w';
+ if (mode & S_IXUSR) acl_text[ 8] = 'x';
+ if (mode & S_IRGRP) acl_text[17] = acl_text[26] = 'r';
+ if (mode & S_IWGRP) acl_text[18] = acl_text[27] = 'w';
+ if (mode & S_IXGRP) acl_text[19] = acl_text[28] = 'x';
+ if (mode & S_IROTH) acl_text[36] = 'r';
+ if (mode & S_IWOTH) acl_text[37] = 'w';
+ if (mode & S_IXOTH) acl_text[38] = 'x';
+
+ if (acl_fromtext (acl_text, &aclp) != 0)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ else
+ {
+ int acl_result = (desc < 0 ? acl_set (name, aclp) : facl_set (desc, aclp));
+ int acl_errno = errno;
+ acl_free (aclp);
+ if (acl_result == 0 || acl_errno != ENOSYS)
+ {
+ errno = acl_errno;
+ return acl_result;
+ }
+ }
+# endif
+
+ return chmod_or_fchmod (name, desc, mode);
+
#endif
}
+
+/* As with qset_acl, but also output a diagnostic on failure. */
+
+int
+set_acl (char const *name, int desc, mode_t mode)
+{
+ int r = qset_acl (name, desc, mode);
+ if (r != 0)
+ error (0, errno, _("setting permissions for %s"), quote (name));
+ return r;
+}