/* 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
}
Пример #2
0
/* 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
}