Currently lzc_receive() requires that its 'snapname' argument is a snapshot name
(contains '@'). zfs receive allows to specify just a dataset name and would try
to deduce the snapshot name from the stream. I propose to allow lzc_receive()
to do the same. That is quite easy to achieve, it requires only a small amount
of logic, it does not require any additional system calls or any additional data
from the stream.
Below is a proof of concept patch that seems to work.
--- lib/libzfs_core/common/libzfs_core.c
+++ lib/libzfs_core/common/libzfs_core.c
@@ -721,9 +721,8 @@ lzc_receive
/* zc_name is name of containing filesystem */
(void) strlcpy(zc.zc_name, snapname, sizeof (zc.zc_name));
atp = strchr(zc.zc_name, '@');
- if (atp == NULL)
- return (EINVAL);
- *atp = '\0';
+ if (atp != NULL)
+ *atp = '\0';
/* if the fs does not exist, try its parent. */
if (!lzc_exists(zc.zc_name)) {
@@ -734,9 +733,6 @@ lzc_receive
}
- /* zc_value is full name of the snapshot to create */
- (void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
-
if (props != NULL) {
/* zc_nvlist_src is props to set */
packed = fnvlist_pack(props, &size);
@@ -754,6 +750,20 @@ lzc_receive
goto out;
zc.zc_begin_record = drr.drr_u.drr_begin;
+ /* zc_value is full name of the snapshot to create */
+ (void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
+
+ /* if snapshot name is not provided try to take it from the stream */
+ atp = strchr(zc.zc_value, '@');
+ if (atp == NULL) {
+ atp = strchr(zc.zc_begin_record.drr_toname, '@');
+ if (atp == NULL)
+ return (EINVAL);
+ if (strlen(zc.zc_value) + strlen(atp) >= sizeof(zc.zc_value))
+ return (ENAMETOOLONG);
+ strcat(zc.zc_value, atp);
+ }
+
/* zc_cookie is fd to read from */
zc.zc_cookie = fd;
--
Andriy Gapon
_______________________________________________
developer mailing list
[email protected]
http://lists.open-zfs.org/mailman/listinfo/developer