/* Copy the permissions of src_path to dst_path. This includes the file mode permission bits and ACLs. File ownership is not copied. */ int perm_copy_fd (const char *src_path, int src_fd, const char *dst_path, int dst_fd, struct error_context *ctx) { #if defined(HAVE_ACL_GET_FD) && defined(HAVE_ACL_SET_FD) acl_t acl; #endif struct stat st; int ret = 0; ret = fstat(src_fd, &st); if (ret != 0) { const char *qpath = quote (ctx, src_path); error (ctx, "%s", qpath); quote_free (ctx, qpath); return -1; } #if defined(HAVE_ACL_GET_FD) && defined(HAVE_ACL_SET_FD) /* POSIX 1003.1e draft 17 (abandoned) specific version. */ acl = acl_get_fd (src_fd); if (acl == NULL) { ret = -1; if (errno == ENOSYS || errno == ENOTSUP) ret = set_acl_fd (dst_path, dst_fd, st.st_mode, ctx); else { const char *qpath = quote (ctx, src_path); error (ctx, "%s", qpath); quote_free (ctx, qpath); } return ret; } if (acl_set_fd (dst_fd, acl) != 0) { int saved_errno = errno; __apply_mask_to_mode(&st.st_mode, acl); ret = fchmod (dst_fd, st.st_mode); if ((errno != ENOSYS && errno != ENOTSUP) || acl_entries (acl) != 3) { const char *qpath = quote (ctx, dst_path); errno = saved_errno; error (ctx, _("preserving permissions for %s"), qpath); quote_free (ctx, qpath); ret = -1; } } (void) acl_free (acl); return ret; #else /* POSIX.1 version. */ ret = fchmod (dst_fd, st.st_mode); if (ret != 0) { const char *qpath = quote (ctx, dst_path); error (ctx, _("setting permissions for %s"), qpath); quote_free (ctx, qpath); } return ret; #endif }
/* Copy the permissions of src_path to dst_path. This includes the file mode permission bits and ACLs. File ownership is not copied. */ int perm_copy_file (const char *src_path, const char *dst_path, struct error_context *ctx) { #if defined(HAVE_ACL_GET_FILE) && defined(HAVE_ACL_SET_FILE) acl_t acl; #endif struct stat st; int ret = 0; ret = stat(src_path, &st); if (ret != 0) { const char *qpath = quote (ctx, src_path); error (ctx, "%s", qpath); quote_free (ctx, qpath); return -1; } #if defined(HAVE_ACL_GET_FILE) && defined(HAVE_ACL_SET_FILE) /* POSIX 1003.1e draft 17 (abandoned) specific version. */ acl = acl_get_file (src_path, ACL_TYPE_ACCESS); if (acl == NULL) { ret = -1; if (errno == ENOSYS || errno == ENOTSUP) ret = set_acl (dst_path, st.st_mode, ctx); else { const char *qpath = quote (ctx, src_path); error (ctx, "%s", qpath); quote_free (ctx, qpath); } return ret; } if (acl_set_file (dst_path, ACL_TYPE_ACCESS, acl) != 0) { int saved_errno = errno; __apply_mask_to_mode(&st.st_mode, acl); ret = chmod (dst_path, st.st_mode); if ((errno != ENOSYS && errno != ENOTSUP) || acl_entries (acl) != 3) { const char *qpath = quote (ctx, dst_path); errno = saved_errno; error (ctx, _("preserving permissions for %s"), qpath); quote_free (ctx, qpath); ret = -1; } } (void) acl_free (acl); if (ret == 0 && S_ISDIR (st.st_mode)) { acl = acl_get_file (src_path, ACL_TYPE_DEFAULT); if (acl == NULL) { const char *qpath = quote (ctx, src_path); error (ctx, "%s", qpath); quote_free (ctx, qpath); return -1; } # if defined(HAVE_ACL_DELETE_DEF_FILE) if (acl_entries(acl) == 0) ret = acl_delete_def_file(dst_path); else ret = acl_set_file (dst_path, ACL_TYPE_DEFAULT, acl); # else ret = acl_set_file (dst_path, ACL_TYPE_DEFAULT, acl); # endif if (ret != 0) { const char *qpath = quote (ctx, dst_path); error (ctx, _("preserving permissions for %s"), qpath); quote_free (ctx, qpath); } (void) acl_free(acl); } return ret; #else /* POSIX.1 version. */ ret = chmod (dst_path, st.st_mode); if (ret != 0) { const char *qpath = quote (ctx, dst_path); error (ctx, _("setting permissions for %s"), qpath); quote_free (ctx, qpath); } return ret; #endif }