10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
25 * Copyright (c) 2013 by Delphix. All rights reserved.
26 * Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved.
27 * Copyright (c) 2013 Martin Matuska. All rights reserved.
28 * Copyright (c) 2013 Steven Hartland. All rights reserved.
29 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
30 */
31
32 #include <ctype.h>
33 #include <errno.h>
34 #include <libintl.h>
35 #include <math.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <strings.h>
39 #include <unistd.h>
40 #include <stddef.h>
41 #include <zone.h>
42 #include <fcntl.h>
43 #include <sys/mntent.h>
44 #include <sys/mount.h>
45 #include <priv.h>
46 #include <pwd.h>
47 #include <grp.h>
48 #include <stddef.h>
49 #include <ucred.h>
1468 /* FALLTHROUGH */
1469 default:
1470 (void) zfs_standard_error(hdl, err, errbuf);
1471 }
1472 }
1473
1474 /*
1475 * Given a property name and value, set the property for the given dataset.
1476 */
1477 int
1478 zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
1479 {
1480 zfs_cmd_t zc = { 0 };
1481 int ret = -1;
1482 prop_changelist_t *cl = NULL;
1483 char errbuf[1024];
1484 libzfs_handle_t *hdl = zhp->zfs_hdl;
1485 nvlist_t *nvl = NULL, *realprops;
1486 zfs_prop_t prop;
1487 boolean_t do_prefix = B_TRUE;
1488 int added_resv;
1489
1490 (void) snprintf(errbuf, sizeof (errbuf),
1491 dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
1492 zhp->zfs_name);
1493
1494 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 ||
1495 nvlist_add_string(nvl, propname, propval) != 0) {
1496 (void) no_memory(hdl);
1497 goto error;
1498 }
1499
1500 if ((realprops = zfs_valid_proplist(hdl, zhp->zfs_type, nvl,
1501 zfs_prop_get_int(zhp, ZFS_PROP_ZONED), zhp, errbuf)) == NULL)
1502 goto error;
1503
1504 nvlist_free(nvl);
1505 nvl = realprops;
1506
1507 prop = zfs_name_to_prop(propname);
1508
2988
2989 zfs_close(h);
2990 }
2991
2992 return (0);
2993
2994 ancestorerr:
2995 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2996 "failed to %s ancestor '%s'"), opname, target);
2997 return (-1);
2998 }
2999
3000 /*
3001 * Creates non-existing ancestors of the given path.
3002 */
3003 int
3004 zfs_create_ancestors(libzfs_handle_t *hdl, const char *path)
3005 {
3006 int prefix;
3007 char *path_copy;
3008 int rc;
3009
3010 if (check_parents(hdl, path, NULL, B_TRUE, &prefix) != 0)
3011 return (-1);
3012
3013 if ((path_copy = strdup(path)) != NULL) {
3014 rc = create_parents(hdl, path_copy, prefix);
3015 free(path_copy);
3016 }
3017 if (path_copy == NULL || rc != 0)
3018 return (-1);
3019
3020 return (0);
3021 }
3022
3023 /*
3024 * Create a new filesystem or volume.
3025 */
3026 int
3027 zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
3028 nvlist_t *props)
3610 cbp->cb_error |= zfs_destroy(zhp, B_FALSE);
3611 }
3612
3613 zfs_close(zhp);
3614 return (0);
3615 }
3616
3617 /*
3618 * Given a dataset, rollback to a specific snapshot, discarding any
3619 * data changes since then and making it the active dataset.
3620 *
3621 * Any snapshots and bookmarks more recent than the target are
3622 * destroyed, along with their dependents (i.e. clones).
3623 */
3624 int
3625 zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, boolean_t force)
3626 {
3627 rollback_data_t cb = { 0 };
3628 int err;
3629 boolean_t restore_resv = 0;
3630 uint64_t old_volsize, new_volsize;
3631 zfs_prop_t resv_prop;
3632
3633 assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM ||
3634 zhp->zfs_type == ZFS_TYPE_VOLUME);
3635
3636 /*
3637 * Destroy all recent snapshots and their dependents.
3638 */
3639 cb.cb_force = force;
3640 cb.cb_target = snap->zfs_name;
3641 cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG);
3642 (void) zfs_iter_snapshots(zhp, rollback_destroy, &cb);
3643 (void) zfs_iter_bookmarks(zhp, rollback_destroy, &cb);
3644
3645 if (cb.cb_error)
3646 return (-1);
3647
3648 /*
3649 * Now that we have verified that the snapshot is the latest,
3650 * rollback to the given snapshot.
3682 if ((zhp->zfs_type == ZFS_TYPE_VOLUME) &&
3683 (zhp = make_dataset_handle(zhp->zfs_hdl, zhp->zfs_name))) {
3684 if (restore_resv) {
3685 new_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
3686 if (old_volsize != new_volsize)
3687 err = zfs_prop_set_int(zhp, resv_prop,
3688 new_volsize);
3689 }
3690 zfs_close(zhp);
3691 }
3692 return (err);
3693 }
3694
3695 /*
3696 * Renames the given dataset.
3697 */
3698 int
3699 zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive,
3700 boolean_t force_unmount)
3701 {
3702 int ret;
3703 zfs_cmd_t zc = { 0 };
3704 char *delim;
3705 prop_changelist_t *cl = NULL;
3706 zfs_handle_t *zhrp = NULL;
3707 char *parentname = NULL;
3708 char parent[ZFS_MAXNAMELEN];
3709 libzfs_handle_t *hdl = zhp->zfs_hdl;
3710 char errbuf[1024];
3711
3712 /* if we have the same exact name, just return success */
3713 if (strcmp(zhp->zfs_name, target) == 0)
3714 return (0);
3715
3716 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3717 "cannot rename to '%s'"), target);
3718
3719 /*
3720 * Make sure the target name is valid
3721 */
3722 if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
|
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
25 * Copyright (c) 2013 by Delphix. All rights reserved.
26 * Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved.
27 * Copyright (c) 2013 Martin Matuska. All rights reserved.
28 * Copyright (c) 2013 Steven Hartland. All rights reserved.
29 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
30 * Copyright 2014 RackTop Systems.
31 */
32
33 #include <ctype.h>
34 #include <errno.h>
35 #include <libintl.h>
36 #include <math.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <strings.h>
40 #include <unistd.h>
41 #include <stddef.h>
42 #include <zone.h>
43 #include <fcntl.h>
44 #include <sys/mntent.h>
45 #include <sys/mount.h>
46 #include <priv.h>
47 #include <pwd.h>
48 #include <grp.h>
49 #include <stddef.h>
50 #include <ucred.h>
1469 /* FALLTHROUGH */
1470 default:
1471 (void) zfs_standard_error(hdl, err, errbuf);
1472 }
1473 }
1474
1475 /*
1476 * Given a property name and value, set the property for the given dataset.
1477 */
1478 int
1479 zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
1480 {
1481 zfs_cmd_t zc = { 0 };
1482 int ret = -1;
1483 prop_changelist_t *cl = NULL;
1484 char errbuf[1024];
1485 libzfs_handle_t *hdl = zhp->zfs_hdl;
1486 nvlist_t *nvl = NULL, *realprops;
1487 zfs_prop_t prop;
1488 boolean_t do_prefix = B_TRUE;
1489 int added_resv = 0;
1490
1491 (void) snprintf(errbuf, sizeof (errbuf),
1492 dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
1493 zhp->zfs_name);
1494
1495 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 ||
1496 nvlist_add_string(nvl, propname, propval) != 0) {
1497 (void) no_memory(hdl);
1498 goto error;
1499 }
1500
1501 if ((realprops = zfs_valid_proplist(hdl, zhp->zfs_type, nvl,
1502 zfs_prop_get_int(zhp, ZFS_PROP_ZONED), zhp, errbuf)) == NULL)
1503 goto error;
1504
1505 nvlist_free(nvl);
1506 nvl = realprops;
1507
1508 prop = zfs_name_to_prop(propname);
1509
2989
2990 zfs_close(h);
2991 }
2992
2993 return (0);
2994
2995 ancestorerr:
2996 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2997 "failed to %s ancestor '%s'"), opname, target);
2998 return (-1);
2999 }
3000
3001 /*
3002 * Creates non-existing ancestors of the given path.
3003 */
3004 int
3005 zfs_create_ancestors(libzfs_handle_t *hdl, const char *path)
3006 {
3007 int prefix;
3008 char *path_copy;
3009 int rc = 0;
3010
3011 if (check_parents(hdl, path, NULL, B_TRUE, &prefix) != 0)
3012 return (-1);
3013
3014 if ((path_copy = strdup(path)) != NULL) {
3015 rc = create_parents(hdl, path_copy, prefix);
3016 free(path_copy);
3017 }
3018 if (path_copy == NULL || rc != 0)
3019 return (-1);
3020
3021 return (0);
3022 }
3023
3024 /*
3025 * Create a new filesystem or volume.
3026 */
3027 int
3028 zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
3029 nvlist_t *props)
3611 cbp->cb_error |= zfs_destroy(zhp, B_FALSE);
3612 }
3613
3614 zfs_close(zhp);
3615 return (0);
3616 }
3617
3618 /*
3619 * Given a dataset, rollback to a specific snapshot, discarding any
3620 * data changes since then and making it the active dataset.
3621 *
3622 * Any snapshots and bookmarks more recent than the target are
3623 * destroyed, along with their dependents (i.e. clones).
3624 */
3625 int
3626 zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, boolean_t force)
3627 {
3628 rollback_data_t cb = { 0 };
3629 int err;
3630 boolean_t restore_resv = 0;
3631 uint64_t old_volsize = 0, new_volsize;
3632 zfs_prop_t resv_prop;
3633
3634 assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM ||
3635 zhp->zfs_type == ZFS_TYPE_VOLUME);
3636
3637 /*
3638 * Destroy all recent snapshots and their dependents.
3639 */
3640 cb.cb_force = force;
3641 cb.cb_target = snap->zfs_name;
3642 cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG);
3643 (void) zfs_iter_snapshots(zhp, rollback_destroy, &cb);
3644 (void) zfs_iter_bookmarks(zhp, rollback_destroy, &cb);
3645
3646 if (cb.cb_error)
3647 return (-1);
3648
3649 /*
3650 * Now that we have verified that the snapshot is the latest,
3651 * rollback to the given snapshot.
3683 if ((zhp->zfs_type == ZFS_TYPE_VOLUME) &&
3684 (zhp = make_dataset_handle(zhp->zfs_hdl, zhp->zfs_name))) {
3685 if (restore_resv) {
3686 new_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
3687 if (old_volsize != new_volsize)
3688 err = zfs_prop_set_int(zhp, resv_prop,
3689 new_volsize);
3690 }
3691 zfs_close(zhp);
3692 }
3693 return (err);
3694 }
3695
3696 /*
3697 * Renames the given dataset.
3698 */
3699 int
3700 zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive,
3701 boolean_t force_unmount)
3702 {
3703 int ret = -1;
3704 zfs_cmd_t zc = { 0 };
3705 char *delim;
3706 prop_changelist_t *cl = NULL;
3707 zfs_handle_t *zhrp = NULL;
3708 char *parentname = NULL;
3709 char parent[ZFS_MAXNAMELEN];
3710 libzfs_handle_t *hdl = zhp->zfs_hdl;
3711 char errbuf[1024];
3712
3713 /* if we have the same exact name, just return success */
3714 if (strcmp(zhp->zfs_name, target) == 0)
3715 return (0);
3716
3717 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3718 "cannot rename to '%s'"), target);
3719
3720 /*
3721 * Make sure the target name is valid
3722 */
3723 if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
|