mirror of
				https://git.proxmox.com/git/mirror_zfs
				synced 2025-10-31 20:33:04 +00:00 
			
		
		
		
	 861166b027
			
		
	
	
		861166b027
		
	
	
	
	
		
			
			bcopy() has a confusing argument order and is actually a move, not a copy; they're all deprecated since POSIX.1-2001 and removed in -2008, and we shim them out to mem*() on Linux anyway Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz> Closes #12996
		
			
				
	
	
		
			223 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			223 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2008, 2009 Edward Tomasz Napierała <trasz@FreeBSD.org>
 | |
|  *
 | |
|  * Redistribution and use in source and binary forms, with or without
 | |
|  * modification, are permitted provided that the following conditions
 | |
|  * are met:
 | |
|  * 1. Redistributions of source code must retain the above copyright
 | |
|  *    notice, this list of conditions and the following disclaimer.
 | |
|  * 2. Redistributions in binary form must reproduce the above copyright
 | |
|  *    notice, this list of conditions and the following disclaimer in the
 | |
|  *    documentation and/or other materials provided with the distribution.
 | |
|  *
 | |
|  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 | |
|  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | |
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | |
|  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 | |
|  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | |
|  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | |
|  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | |
|  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | |
|  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | |
|  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | |
|  * SUCH DAMAGE.
 | |
|  */
 | |
| 
 | |
| #include <sys/cdefs.h>
 | |
| __FBSDID("$FreeBSD$");
 | |
| 
 | |
| #include <sys/types.h>
 | |
| #include <sys/param.h>
 | |
| #include <sys/systm.h>
 | |
| #include <sys/types.h>
 | |
| #include <sys/malloc.h>
 | |
| #include <sys/errno.h>
 | |
| #include <sys/zfs_acl.h>
 | |
| #include <sys/acl.h>
 | |
| 
 | |
| struct zfs2bsd {
 | |
| 	uint32_t	zb_zfs;
 | |
| 	int		zb_bsd;
 | |
| };
 | |
| 
 | |
| static const struct zfs2bsd perms[] = {{ACE_READ_DATA, ACL_READ_DATA},
 | |
| 			{ACE_WRITE_DATA, ACL_WRITE_DATA},
 | |
| 			{ACE_EXECUTE, ACL_EXECUTE},
 | |
| 			{ACE_APPEND_DATA, ACL_APPEND_DATA},
 | |
| 			{ACE_DELETE_CHILD, ACL_DELETE_CHILD},
 | |
| 			{ACE_DELETE, ACL_DELETE},
 | |
| 			{ACE_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
 | |
| 			{ACE_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
 | |
| 			{ACE_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
 | |
| 			{ACE_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
 | |
| 			{ACE_READ_ACL, ACL_READ_ACL},
 | |
| 			{ACE_WRITE_ACL, ACL_WRITE_ACL},
 | |
| 			{ACE_WRITE_OWNER, ACL_WRITE_OWNER},
 | |
| 			{ACE_SYNCHRONIZE, ACL_SYNCHRONIZE},
 | |
| 			{0, 0}};
 | |
| 
 | |
| static const struct zfs2bsd flags[] = {{ACE_FILE_INHERIT_ACE,
 | |
| 			    ACL_ENTRY_FILE_INHERIT},
 | |
| 			{ACE_DIRECTORY_INHERIT_ACE,
 | |
| 			    ACL_ENTRY_DIRECTORY_INHERIT},
 | |
| 			{ACE_NO_PROPAGATE_INHERIT_ACE,
 | |
| 			    ACL_ENTRY_NO_PROPAGATE_INHERIT},
 | |
| 			{ACE_INHERIT_ONLY_ACE,
 | |
| 			    ACL_ENTRY_INHERIT_ONLY},
 | |
| 			{ACE_INHERITED_ACE,
 | |
| 			    ACL_ENTRY_INHERITED},
 | |
| 			{ACE_SUCCESSFUL_ACCESS_ACE_FLAG,
 | |
| 			    ACL_ENTRY_SUCCESSFUL_ACCESS},
 | |
| 			{ACE_FAILED_ACCESS_ACE_FLAG,
 | |
| 			    ACL_ENTRY_FAILED_ACCESS},
 | |
| 			{0, 0}};
 | |
| 
 | |
| static int
 | |
| _bsd_from_zfs(uint32_t zfs, const struct zfs2bsd *table)
 | |
| {
 | |
| 	const struct zfs2bsd *tmp;
 | |
| 	int bsd = 0;
 | |
| 
 | |
| 	for (tmp = table; tmp->zb_zfs != 0; tmp++) {
 | |
| 		if (zfs & tmp->zb_zfs)
 | |
| 			bsd |= tmp->zb_bsd;
 | |
| 	}
 | |
| 
 | |
| 	return (bsd);
 | |
| }
 | |
| 
 | |
| static uint32_t
 | |
| _zfs_from_bsd(int bsd, const struct zfs2bsd *table)
 | |
| {
 | |
| 	const struct zfs2bsd *tmp;
 | |
| 	uint32_t zfs = 0;
 | |
| 
 | |
| 	for (tmp = table; tmp->zb_bsd != 0; tmp++) {
 | |
| 		if (bsd & tmp->zb_bsd)
 | |
| 			zfs |= tmp->zb_zfs;
 | |
| 	}
 | |
| 
 | |
| 	return (zfs);
 | |
| }
 | |
| 
 | |
| int
 | |
| acl_from_aces(struct acl *aclp, const ace_t *aces, int nentries)
 | |
| {
 | |
| 	int i;
 | |
| 	struct acl_entry *entry;
 | |
| 	const ace_t *ace;
 | |
| 
 | |
| 	if (nentries < 1) {
 | |
| 		printf("acl_from_aces: empty ZFS ACL; returning EINVAL.\n");
 | |
| 		return (EINVAL);
 | |
| 	}
 | |
| 
 | |
| 	if (nentries > ACL_MAX_ENTRIES) {
 | |
| 		/*
 | |
| 		 * I believe it may happen only when moving a pool
 | |
| 		 * from SunOS to FreeBSD.
 | |
| 		 */
 | |
| 		printf("acl_from_aces: ZFS ACL too big to fit "
 | |
| 		    "into 'struct acl'; returning EINVAL.\n");
 | |
| 		return (EINVAL);
 | |
| 	}
 | |
| 
 | |
| 	memset(aclp, 0, sizeof (*aclp));
 | |
| 	aclp->acl_maxcnt = ACL_MAX_ENTRIES;
 | |
| 	aclp->acl_cnt = nentries;
 | |
| 
 | |
| 	for (i = 0; i < nentries; i++) {
 | |
| 		entry = &(aclp->acl_entry[i]);
 | |
| 		ace = &(aces[i]);
 | |
| 
 | |
| 		if (ace->a_flags & ACE_OWNER)
 | |
| 			entry->ae_tag = ACL_USER_OBJ;
 | |
| 		else if (ace->a_flags & ACE_GROUP)
 | |
| 			entry->ae_tag = ACL_GROUP_OBJ;
 | |
| 		else if (ace->a_flags & ACE_EVERYONE)
 | |
| 			entry->ae_tag = ACL_EVERYONE;
 | |
| 		else if (ace->a_flags & ACE_IDENTIFIER_GROUP)
 | |
| 			entry->ae_tag = ACL_GROUP;
 | |
| 		else
 | |
| 			entry->ae_tag = ACL_USER;
 | |
| 
 | |
| 		if (entry->ae_tag == ACL_USER || entry->ae_tag == ACL_GROUP)
 | |
| 			entry->ae_id = ace->a_who;
 | |
| 		else
 | |
| 			entry->ae_id = ACL_UNDEFINED_ID;
 | |
| 
 | |
| 		entry->ae_perm = _bsd_from_zfs(ace->a_access_mask, perms);
 | |
| 		entry->ae_flags = _bsd_from_zfs(ace->a_flags, flags);
 | |
| 
 | |
| 		switch (ace->a_type) {
 | |
| 		case ACE_ACCESS_ALLOWED_ACE_TYPE:
 | |
| 			entry->ae_entry_type = ACL_ENTRY_TYPE_ALLOW;
 | |
| 			break;
 | |
| 		case ACE_ACCESS_DENIED_ACE_TYPE:
 | |
| 			entry->ae_entry_type = ACL_ENTRY_TYPE_DENY;
 | |
| 			break;
 | |
| 		case ACE_SYSTEM_AUDIT_ACE_TYPE:
 | |
| 			entry->ae_entry_type = ACL_ENTRY_TYPE_AUDIT;
 | |
| 			break;
 | |
| 		case ACE_SYSTEM_ALARM_ACE_TYPE:
 | |
| 			entry->ae_entry_type = ACL_ENTRY_TYPE_ALARM;
 | |
| 			break;
 | |
| 		default:
 | |
| 			panic("acl_from_aces: a_type is 0x%x", ace->a_type);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return (0);
 | |
| }
 | |
| 
 | |
| void
 | |
| aces_from_acl(ace_t *aces, int *nentries, const struct acl *aclp)
 | |
| {
 | |
| 	int i;
 | |
| 	const struct acl_entry *entry;
 | |
| 	ace_t *ace;
 | |
| 
 | |
| 	memset(aces, 0, sizeof (*aces) * aclp->acl_cnt);
 | |
| 
 | |
| 	*nentries = aclp->acl_cnt;
 | |
| 
 | |
| 	for (i = 0; i < aclp->acl_cnt; i++) {
 | |
| 		entry = &(aclp->acl_entry[i]);
 | |
| 		ace = &(aces[i]);
 | |
| 
 | |
| 		ace->a_who = entry->ae_id;
 | |
| 
 | |
| 		if (entry->ae_tag == ACL_USER_OBJ)
 | |
| 			ace->a_flags = ACE_OWNER;
 | |
| 		else if (entry->ae_tag == ACL_GROUP_OBJ)
 | |
| 			ace->a_flags = (ACE_GROUP | ACE_IDENTIFIER_GROUP);
 | |
| 		else if (entry->ae_tag == ACL_GROUP)
 | |
| 			ace->a_flags = ACE_IDENTIFIER_GROUP;
 | |
| 		else if (entry->ae_tag == ACL_EVERYONE)
 | |
| 			ace->a_flags = ACE_EVERYONE;
 | |
| 		else /* ACL_USER */
 | |
| 			ace->a_flags = 0;
 | |
| 
 | |
| 		ace->a_access_mask = _zfs_from_bsd(entry->ae_perm, perms);
 | |
| 		ace->a_flags |= _zfs_from_bsd(entry->ae_flags, flags);
 | |
| 
 | |
| 		switch (entry->ae_entry_type) {
 | |
| 		case ACL_ENTRY_TYPE_ALLOW:
 | |
| 			ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
 | |
| 			break;
 | |
| 		case ACL_ENTRY_TYPE_DENY:
 | |
| 			ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
 | |
| 			break;
 | |
| 		case ACL_ENTRY_TYPE_ALARM:
 | |
| 			ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE;
 | |
| 			break;
 | |
| 		case ACL_ENTRY_TYPE_AUDIT:
 | |
| 			ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE;
 | |
| 			break;
 | |
| 		default:
 | |
| 			panic("aces_from_acl: ae_entry_type is 0x%x",
 | |
| 			    entry->ae_entry_type);
 | |
| 		}
 | |
| 	}
 | |
| }
 |