diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libzfs/libzfs_dataset.c | 5 | ||||
-rw-r--r-- | lib/libzfs/libzfs_sendrecv.c | 44 | ||||
-rw-r--r-- | lib/libzfs/libzfs_util.c | 5 |
3 files changed, 41 insertions, 13 deletions
diff --git a/lib/libzfs/libzfs_dataset.c b/lib/libzfs/libzfs_dataset.c index 6445c9d7a..be86e5692 100644 --- a/lib/libzfs/libzfs_dataset.c +++ b/lib/libzfs/libzfs_dataset.c @@ -3809,11 +3809,6 @@ zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type, "no such parent '%s'"), parent); return (zfs_error(hdl, EZFS_NOENT, errbuf)); - case EINVAL: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "parent '%s' is not a filesystem"), parent); - return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); - case ENOTSUP: zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be upgraded to set this " diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c index ae24454d7..1d8292101 100644 --- a/lib/libzfs/libzfs_sendrecv.c +++ b/lib/libzfs/libzfs_sendrecv.c @@ -28,7 +28,7 @@ * Copyright (c) 2013 Steven Hartland. All rights reserved. * Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved. * Copyright 2016 Igor Kozhukhov <[email protected]> - * Copyright (c) 2017, loli10K <[email protected]>. All rights reserved. + * Copyright (c) 2018, loli10K <[email protected]>. All rights reserved. */ #include <assert.h> @@ -3912,6 +3912,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap, * - we are resuming a failed receive. */ if (stream_wantsnewfs) { + boolean_t is_volume = drrb->drr_type == DMU_OST_ZVOL; if (!flags->force) { zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "destination '%s' exists\n" @@ -3928,6 +3929,24 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap, err = zfs_error(hdl, EZFS_EXISTS, errbuf); goto out; } + if (is_volume && strrchr(name, '/') == NULL) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "destination %s is the root dataset\n" + "cannot overwrite with a ZVOL"), + name); + err = zfs_error(hdl, EZFS_EXISTS, errbuf); + goto out; + } + if (is_volume && + ioctl(hdl->libzfs_fd, ZFS_IOC_DATASET_LIST_NEXT, + &zc) == 0) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "destination has children (eg. %s)\n" + "cannot overwrite with a ZVOL"), + zc.zc_name); + err = zfs_error(hdl, EZFS_WRONG_PARENT, errbuf); + goto out; + } } if ((zhp = zfs_open(hdl, name, @@ -4051,6 +4070,20 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap, goto out; } + /* validate parent */ + zhp = zfs_open(hdl, name, ZFS_TYPE_DATASET); + if (zhp == NULL) { + err = zfs_error(hdl, EZFS_BADRESTORE, errbuf); + goto out; + } + if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "parent '%s' is not a filesystem"), name); + err = zfs_error(hdl, EZFS_WRONG_PARENT, errbuf); + zfs_close(zhp); + goto out; + } + /* * It is invalid to receive a properties stream that was * unencrypted on the send side as a child of an encrypted @@ -4068,23 +4101,18 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap, zfs_prop_to_name(ZFS_PROP_ENCRYPTION))) { uint64_t crypt; - zhp = zfs_open(hdl, name, ZFS_TYPE_DATASET); - if (zhp == NULL) { - err = zfs_error(hdl, EZFS_BADRESTORE, errbuf); - goto out; - } - crypt = zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION); - zfs_close(zhp); if (crypt != ZIO_CRYPT_OFF) { zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "parent '%s' must not be encrypted to " "receive unenecrypted property"), name); err = zfs_error(hdl, EZFS_BADPROP, errbuf); + zfs_close(zhp); goto out; } } + zfs_close(zhp); newfs = B_TRUE; *cp = '/'; diff --git a/lib/libzfs/libzfs_util.c b/lib/libzfs/libzfs_util.c index d7401cdf4..4ed885880 100644 --- a/lib/libzfs/libzfs_util.c +++ b/lib/libzfs/libzfs_util.c @@ -290,6 +290,8 @@ libzfs_error_description(libzfs_handle_t *hdl) case EZFS_NO_INITIALIZE: return (dgettext(TEXT_DOMAIN, "there is no active " "initialization")); + case EZFS_WRONG_PARENT: + return (dgettext(TEXT_DOMAIN, "invalid parent dataset")); case EZFS_UNKNOWN: return (dgettext(TEXT_DOMAIN, "unknown error")); default: @@ -471,6 +473,9 @@ zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) case ZFS_ERR_IOC_ARG_BADTYPE: zfs_verror(hdl, EZFS_IOC_NOTSUPPORTED, fmt, ap); break; + case ZFS_ERR_WRONG_PARENT: + zfs_verror(hdl, EZFS_WRONG_PARENT, fmt, ap); + break; default: zfs_error_aux(hdl, strerror(error)); zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap); |