13b005d3pjd/*
23b005d3pjd * CDDL HEADER START
33b005d3pjd *
43b005d3pjd * The contents of this file are subject to the terms of the
53b005d3pjd * Common Development and Distribution License (the "License").
63b005d3pjd * You may not use this file except in compliance with the License.
73b005d3pjd *
83b005d3pjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93b005d3pjd * or http://www.opensolaris.org/os/licensing.
103b005d3pjd * See the License for the specific language governing permissions
113b005d3pjd * and limitations under the License.
123b005d3pjd *
133b005d3pjd * When distributing Covered Code, include this CDDL HEADER in each
143b005d3pjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153b005d3pjd * If applicable, add the following below this CDDL HEADER, with the
163b005d3pjd * fields enclosed by brackets "[]" replaced with your own identifying
173b005d3pjd * information: Portions Copyright [yyyy] [name of copyright owner]
183b005d3pjd *
193b005d3pjd * CDDL HEADER END
203b005d3pjd */
213b005d3pjd
223b005d3pjd/*
231b03c5bpjd * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24184cebbmav * Copyright (c) 2018, Joyent, Inc. All rights reserved.
258d451edavg * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
267e5eee4mm * Copyright (c) 2012 DEY Storage Systems, Inc.  All rights reserved.
2713a03d4mav * Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved.
2813a03d4mav * Copyright (c) 2013 Martin Matuska. All rights reserved.
29ab3dbcbdelphij * Copyright (c) 2013 Steven Hartland. All rights reserved.
30eb06d29mav * Copyright (c) 2014 Integros [integros.com]
3111d282fmav * Copyright 2017 Nexenta Systems, Inc.
329765603mav * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
33ddeea94mav * Copyright 2017-2018 RackTop Systems.
3422b0eb1asomers * Copyright (c) 2019 Datto Inc.
353b005d3pjd */
363b005d3pjd
373b005d3pjd#include <ctype.h>
383b005d3pjd#include <errno.h>
393b005d3pjd#include <libintl.h>
403b005d3pjd#include <math.h>
413b005d3pjd#include <stdio.h>
423b005d3pjd#include <stdlib.h>
433b005d3pjd#include <strings.h>
443b005d3pjd#include <unistd.h>
45bbe899bpjd#include <stddef.h>
463b005d3pjd#include <zone.h>
473b005d3pjd#include <fcntl.h>
483b005d3pjd#include <sys/mntent.h>
493b005d3pjd#include <sys/mount.h>
50bbe899bpjd#include <priv.h>
51bbe899bpjd#include <pwd.h>
52bbe899bpjd#include <grp.h>
53bbe899bpjd#include <stddef.h>
541105449mav#ifdef illumos
55b2946e8mm#include <idmap.h>
561105449mav#endif
573b005d3pjd
581b03c5bpjd#include <sys/dnode.h>
593b005d3pjd#include <sys/spa.h>
603b005d3pjd#include <sys/zap.h>
61b2946e8mm#include <sys/misc.h>
623b005d3pjd#include <libzfs.h>
633b005d3pjd
643b005d3pjd#include "zfs_namecheck.h"
653b005d3pjd#include "zfs_prop.h"
663b005d3pjd#include "libzfs_impl.h"
67bbe899bpjd#include "zfs_deleg.h"
683b005d3pjd
69b2946e8mmstatic int userquota_propname_decode(const char *propname, boolean_t zoned,
70b2946e8mm    zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp);
71f2c622apjd
723b005d3pjd/*
733b005d3pjd * Given a single type (not a mask of types), return the type in a human
743b005d3pjd * readable form.
753b005d3pjd */
763b005d3pjdconst char *
773b005d3pjdzfs_type_to_name(zfs_type_t type)
783b005d3pjd{
793b005d3pjd	switch (type) {
803b005d3pjd	case ZFS_TYPE_FILESYSTEM:
813b005d3pjd		return (dgettext(TEXT_DOMAIN, "filesystem"));
823b005d3pjd	case ZFS_TYPE_SNAPSHOT:
833b005d3pjd		return (dgettext(TEXT_DOMAIN, "snapshot"));
843b005d3pjd	case ZFS_TYPE_VOLUME:
853b005d3pjd		return (dgettext(TEXT_DOMAIN, "volume"));
869765603mav	case ZFS_TYPE_POOL:
879765603mav		return (dgettext(TEXT_DOMAIN, "pool"));
889765603mav	case ZFS_TYPE_BOOKMARK:
899765603mav		return (dgettext(TEXT_DOMAIN, "bookmark"));
909765603mav	default:
919765603mav		assert(!"unhandled zfs_type_t");
923b005d3pjd	}
933b005d3pjd
943b005d3pjd	return (NULL);
953b005d3pjd}
963b005d3pjd
973b005d3pjd/*
983b005d3pjd * Validate a ZFS path.  This is used even before trying to open the dataset, to
99b2946e8mm * provide a more meaningful error message.  We call zfs_error_aux() to
100b2946e8mm * explain exactly why the name was not valid.
1013b005d3pjd */
1021b03c5bpjdint
103bbe899bpjdzfs_validate_name(libzfs_handle_t *hdl, const char *path, int type,
104bbe899bpjd    boolean_t modifying)
1053b005d3pjd{
1063b005d3pjd	namecheck_err_t why;
1073b005d3pjd	char what;
1083b005d3pjd
109ed5fb51jpaetzel	if (entity_namecheck(path, &why, &what) != 0) {
1103b005d3pjd		if (hdl != NULL) {
1113b005d3pjd			switch (why) {
1123b005d3pjd			case NAME_ERR_TOOLONG:
1133b005d3pjd				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1143b005d3pjd				    "name is too long"));
1153b005d3pjd				break;
1163b005d3pjd
1173b005d3pjd			case NAME_ERR_LEADING_SLASH:
1183b005d3pjd				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1193b005d3pjd				    "leading slash in name"));
1203b005d3pjd				break;
1213b005d3pjd
1223b005d3pjd			case NAME_ERR_EMPTY_COMPONENT:
1233b005d3pjd				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1243b005d3pjd				    "empty component in name"));
1253b005d3pjd				break;
1263b005d3pjd
1273b005d3pjd			case NAME_ERR_TRAILING_SLASH:
1283b005d3pjd				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1293b005d3pjd				    "trailing slash in name"));
1303b005d3pjd				break;
1313b005d3pjd
1323b005d3pjd			case NAME_ERR_INVALCHAR:
1333b005d3pjd				zfs_error_aux(hdl,
1343b005d3pjd				    dgettext(TEXT_DOMAIN, "invalid character "
1353b005d3pjd				    "'%c' in name"), what);
1363b005d3pjd				break;
1373b005d3pjd
138ed5fb51jpaetzel			case NAME_ERR_MULTIPLE_DELIMITERS:
1393b005d3pjd				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
140ed5fb51jpaetzel				    "multiple '@' and/or '#' delimiters in "
141ed5fb51jpaetzel				    "name"));
1423b005d3pjd				break;
1433b005d3pjd
1443b005d3pjd			case NAME_ERR_NOLETTER:
1453b005d3pjd				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1463b005d3pjd				    "pool doesn't begin with a letter"));
1473b005d3pjd				break;
1483b005d3pjd
1493b005d3pjd			case NAME_ERR_RESERVED:
1503b005d3pjd				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1513b005d3pjd				    "name is reserved"));
1523b005d3pjd				break;
1533b005d3pjd
1543b005d3pjd			case NAME_ERR_DISKLIKE:
1553b005d3pjd				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1563b005d3pjd				    "reserved disk name"));
1573b005d3pjd				break;
1589765603mav
1599765603mav			default:
1609765603mav				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1619765603mav				    "(%d) not defined"), why);
1629765603mav				break;
1633b005d3pjd			}
1643b005d3pjd		}
1653b005d3pjd
1663b005d3pjd		return (0);
1673b005d3pjd	}
1683b005d3pjd
1693b005d3pjd	if (!(type & ZFS_TYPE_SNAPSHOT) && strchr(path, '@') != NULL) {
1703b005d3pjd		if (hdl != NULL)
1713b005d3pjd			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
172ed5fb51jpaetzel			    "snapshot delimiter '@' is not expected here"));
1733b005d3pjd		return (0);
1743b005d3pjd	}
1753b005d3pjd
1763b005d3pjd	if (type == ZFS_TYPE_SNAPSHOT && strchr(path, '@') == NULL) {
1773b005d3pjd		if (hdl != NULL)
1783b005d3pjd			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1793b005d3pjd			    "missing '@' delimiter in snapshot name"));
1803b005d3pjd		return (0);
1813b005d3pjd	}
1823b005d3pjd
183ed5fb51jpaetzel	if (!(type & ZFS_TYPE_BOOKMARK) && strchr(path, '#') != NULL) {
184ed5fb51jpaetzel		if (hdl != NULL)
185ed5fb51jpaetzel			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
186ed5fb51jpaetzel			    "bookmark delimiter '#' is not expected here"));
187ed5fb51jpaetzel		return (0);
188ed5fb51jpaetzel	}
189ed5fb51jpaetzel
190ed5fb51jpaetzel	if (type == ZFS_TYPE_BOOKMARK && strchr(path, '#') == NULL) {
191ed5fb51jpaetzel		if (hdl != NULL)
192ed5fb51jpaetzel			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
193ed5fb51jpaetzel			    "missing '#' delimiter in bookmark name"));
194ed5fb51jpaetzel		return (0);
195ed5fb51jpaetzel	}
196ed5fb51jpaetzel
197bbe899bpjd	if (modifying && strchr(path, '%') != NULL) {
198bbe899bpjd		if (hdl != NULL)
199bbe899bpjd			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
200bbe899bpjd			    "invalid character %c in name"), '%');
201bbe899bpjd		return (0);
202bbe899bpjd	}
203bbe899bpjd
2043b005d3pjd	return (-1);
2053b005d3pjd}
2063b005d3pjd
2073b005d3pjdint
2083b005d3pjdzfs_name_valid(const char *name, zfs_type_t type)
2093b005d3pjd{
210bbe899bpjd	if (type == ZFS_TYPE_POOL)
211bbe899bpjd		return (zpool_name_valid(NULL, B_FALSE, name));
212bbe899bpjd	return (zfs_validate_name(NULL, name, type, B_FALSE));
2133b005d3pjd}
2143b005d3pjd
2153b005d3pjd/*
2163b005d3pjd * This function takes the raw DSL properties, and filters out the user-defined
2173b005d3pjd * properties into a separate nvlist.
2183b005d3pjd */
219bbe899bpjdstatic nvlist_t *
220bbe899bpjdprocess_user_props(zfs_handle_t *zhp, nvlist_t *props)
2213b005d3pjd{
2223b005d3pjd	libzfs_handle_t *hdl = zhp->zfs_hdl;
2233b005d3pjd	nvpair_t *elem;
2243b005d3pjd	nvlist_t *propval;
225bbe899bpjd	nvlist_t *nvl;
2263b005d3pjd
227bbe899bpjd	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
228bbe899bpjd		(void) no_memory(hdl);
229bbe899bpjd		return (NULL);
230bbe899bpjd	}
2313b005d3pjd
2323b005d3pjd	elem = NULL;
233bbe899bpjd	while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
2343b005d3pjd		if (!zfs_prop_user(nvpair_name(elem)))
2353b005d3pjd			continue;
2363b005d3pjd
2373b005d3pjd		verify(nvpair_value_nvlist(elem, &propval) == 0);
238bbe899bpjd		if (nvlist_add_nvlist(nvl, nvpair_name(elem), propval) != 0) {
239bbe899bpjd			nvlist_free(nvl);
240bbe899bpjd			(void) no_memory(hdl);
241bbe899bpjd			return (NULL);
242bbe899bpjd		}
2433b005d3pjd	}
2443b005d3pjd
245bbe899bpjd	return (nvl);
246bbe899bpjd}
247bbe899bpjd
248bbe899bpjdstatic zpool_handle_t *
249bbe899bpjdzpool_add_handle(zfs_handle_t *zhp, const char *pool_name)
250bbe899bpjd{
251bbe899bpjd	libzfs_handle_t *hdl = zhp->zfs_hdl;
252bbe899bpjd	zpool_handle_t *zph;
253bbe899bpjd
254bbe899bpjd	if ((zph = zpool_open_canfail(hdl, pool_name)) != NULL) {
255bbe899bpjd		if (hdl->libzfs_pool_handles != NULL)
256bbe899bpjd			zph->zpool_next = hdl->libzfs_pool_handles;
257bbe899bpjd		hdl->libzfs_pool_handles = zph;
258bbe899bpjd	}
259bbe899bpjd	return (zph);
260bbe899bpjd}
261bbe899bpjd
262bbe899bpjdstatic zpool_handle_t *
263bbe899bpjdzpool_find_handle(zfs_handle_t *zhp, const char *pool_name, int len)
264bbe899bpjd{
265bbe899bpjd	libzfs_handle_t *hdl = zhp->zfs_hdl;
266bbe899bpjd	zpool_handle_t *zph = hdl->libzfs_pool_handles;
267bbe899bpjd
268bbe899bpjd	while ((zph != NULL) &&
269bbe899bpjd	    (strncmp(pool_name, zpool_get_name(zph), len) != 0))
270bbe899bpjd		zph = zph->zpool_next;
271bbe899bpjd	return (zph);
272bbe899bpjd}
273bbe899bpjd
274bbe899bpjd/*
275bbe899bpjd * Returns a handle to the pool that contains the provided dataset.
276bbe899bpjd * If a handle to that pool already exists then that handle is returned.
277bbe899bpjd * Otherwise, a new handle is created and added to the list of handles.
278bbe899bpjd */
279bbe899bpjdstatic zpool_handle_t *
280bbe899bpjdzpool_handle(zfs_handle_t *zhp)
281bbe899bpjd{
282bbe899bpjd	char *pool_name;
283bbe899bpjd	int len;
284bbe899bpjd	zpool_handle_t *zph;
285bbe899bpjd
2865137277delphij	len = strcspn(zhp->zfs_name, "/@#") + 1;
287bbe899bpjd	pool_name = zfs_alloc(zhp->zfs_hdl, len);
288bbe899bpjd	(void) strlcpy(pool_name, zhp->zfs_name, len);
289bbe899bpjd
290bbe899bpjd	zph = zpool_find_handle(zhp, pool_name, len);
291bbe899bpjd	if (zph == NULL)
292bbe899bpjd		zph = zpool_add_handle(zhp, pool_name);
293bbe899bpjd
294bbe899bpjd	free(pool_name);
295