xref: /freebsd/sys/contrib/openzfs/tests/zfs-tests/cmd/badsend.c (revision dbd5678dca91abcefe8d046aa2f9b66497a95ffb)
1716fd348SMartin Matuska /*
2716fd348SMartin Matuska  * CDDL HEADER START
3716fd348SMartin Matuska  *
4716fd348SMartin Matuska  * The contents of this file are subject to the terms of the
5716fd348SMartin Matuska  * Common Development and Distribution License (the "License").
6716fd348SMartin Matuska  * You may not use this file except in compliance with the License.
7716fd348SMartin Matuska  *
8716fd348SMartin Matuska  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9271171e0SMartin Matuska  * or https://opensource.org/licenses/CDDL-1.0.
10716fd348SMartin Matuska  * See the License for the specific language governing permissions
11716fd348SMartin Matuska  * and limitations under the License.
12716fd348SMartin Matuska  *
13716fd348SMartin Matuska  * When distributing Covered Code, include this CDDL HEADER in each
14716fd348SMartin Matuska  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15716fd348SMartin Matuska  * If applicable, add the following below this CDDL HEADER, with the
16716fd348SMartin Matuska  * fields enclosed by brackets "[]" replaced with your own identifying
17716fd348SMartin Matuska  * information: Portions Copyright [yyyy] [name of copyright owner]
18716fd348SMartin Matuska  *
19716fd348SMartin Matuska  * CDDL HEADER END
20716fd348SMartin Matuska  */
21716fd348SMartin Matuska 
22716fd348SMartin Matuska /*
23716fd348SMartin Matuska  * Portions Copyright 2020 iXsystems, Inc.
24716fd348SMartin Matuska  */
25716fd348SMartin Matuska 
26716fd348SMartin Matuska /*
27716fd348SMartin Matuska  * Test some invalid send operations with libzfs/libzfs_core.
28716fd348SMartin Matuska  *
29716fd348SMartin Matuska  * Specifying the to and from snaps in the wrong order should return EXDEV.
30716fd348SMartin Matuska  * We are checking that the early return doesn't accidentally leave any
31716fd348SMartin Matuska  * references held, so this test is designed to trigger a panic when asserts
32716fd348SMartin Matuska  * are verified with the bug present.
33716fd348SMartin Matuska  */
34716fd348SMartin Matuska 
35716fd348SMartin Matuska #include <libzfs.h>
36716fd348SMartin Matuska #include <libzfs_core.h>
37716fd348SMartin Matuska 
38716fd348SMartin Matuska #include <fcntl.h>
39716fd348SMartin Matuska #include <stdlib.h>
40716fd348SMartin Matuska #include <string.h>
41716fd348SMartin Matuska #include <unistd.h>
42716fd348SMartin Matuska #include <sysexits.h>
43716fd348SMartin Matuska #include <err.h>
44716fd348SMartin Matuska 
45716fd348SMartin Matuska static void
usage(const char * name)46716fd348SMartin Matuska usage(const char *name)
47716fd348SMartin Matuska {
48716fd348SMartin Matuska 	fprintf(stderr, "usage: %s snap0 snap1\n", name);
49716fd348SMartin Matuska 	exit(EX_USAGE);
50716fd348SMartin Matuska }
51716fd348SMartin Matuska 
52716fd348SMartin Matuska int
main(int argc,char const * const argv[])53716fd348SMartin Matuska main(int argc, char const * const argv[])
54716fd348SMartin Matuska {
55716fd348SMartin Matuska 	sendflags_t flags = { 0 };
56716fd348SMartin Matuska 	libzfs_handle_t *zhdl;
57716fd348SMartin Matuska 	zfs_handle_t *zhp;
58716fd348SMartin Matuska 	const char *fromfull, *tofull, *fsname, *fromsnap, *tosnap, *p;
59716fd348SMartin Matuska 	uint64_t size;
60716fd348SMartin Matuska 	int fd, error;
61716fd348SMartin Matuska 
62716fd348SMartin Matuska 	if (argc != 3)
63716fd348SMartin Matuska 		usage(argv[0]);
64716fd348SMartin Matuska 
65716fd348SMartin Matuska 	fromfull = argv[1];
66716fd348SMartin Matuska 	tofull = argv[2];
67716fd348SMartin Matuska 
68716fd348SMartin Matuska 	p = strchr(fromfull, '@');
69716fd348SMartin Matuska 	if (p == NULL)
70716fd348SMartin Matuska 		usage(argv[0]);
71716fd348SMartin Matuska 	fromsnap = p + 1;
72716fd348SMartin Matuska 
73716fd348SMartin Matuska 	p = strchr(tofull, '@');
74716fd348SMartin Matuska 	if (p == NULL)
75716fd348SMartin Matuska 		usage(argv[0]);
76716fd348SMartin Matuska 	tosnap = p + 1;
77716fd348SMartin Matuska 
78716fd348SMartin Matuska 	fsname = strndup(tofull, p - tofull);
79*dbd5678dSMartin Matuska 	if (fsname == NULL) {
80*dbd5678dSMartin Matuska 		perror("strndup");
81*dbd5678dSMartin Matuska 		exit(EXIT_FAILURE);
82*dbd5678dSMartin Matuska 	}
83716fd348SMartin Matuska 	if (strncmp(fsname, fromfull, p - tofull) != 0)
84716fd348SMartin Matuska 		usage(argv[0]);
85716fd348SMartin Matuska 
86716fd348SMartin Matuska 	fd = open("/dev/null", O_WRONLY);
87716fd348SMartin Matuska 	if (fd == -1)
88716fd348SMartin Matuska 		err(EX_OSERR, "open(\"/dev/null\", O_WRONLY)");
89716fd348SMartin Matuska 
90716fd348SMartin Matuska 	zhdl = libzfs_init();
91716fd348SMartin Matuska 	if (zhdl == NULL)
92716fd348SMartin Matuska 		errx(EX_OSERR, "libzfs_init(): %s", libzfs_error_init(errno));
93716fd348SMartin Matuska 
94716fd348SMartin Matuska 	zhp = zfs_open(zhdl, fsname, ZFS_TYPE_FILESYSTEM);
95716fd348SMartin Matuska 	if (zhp == NULL)
96716fd348SMartin Matuska 		err(EX_OSERR, "zfs_open(\"%s\")", fsname);
97716fd348SMartin Matuska 
98716fd348SMartin Matuska 	/*
99716fd348SMartin Matuska 	 * Exercise EXDEV in dmu_send_obj.  The error gets translated to
100716fd348SMartin Matuska 	 * EZFS_CROSSTARGET in libzfs.
101716fd348SMartin Matuska 	 */
102716fd348SMartin Matuska 	error = zfs_send(zhp, tosnap, fromsnap, &flags, fd, NULL, NULL, NULL);
103716fd348SMartin Matuska 	if (error == 0 || libzfs_errno(zhdl) != EZFS_CROSSTARGET)
104716fd348SMartin Matuska 		errx(EX_OSERR, "zfs_send(\"%s\", \"%s\") should have failed "
105716fd348SMartin Matuska 		    "with EZFS_CROSSTARGET, not %d",
106716fd348SMartin Matuska 		    tofull, fromfull, libzfs_errno(zhdl));
107716fd348SMartin Matuska 	printf("zfs_send(\"%s\", \"%s\"): %s\n",
108716fd348SMartin Matuska 	    tofull, fromfull, libzfs_error_description(zhdl));
109716fd348SMartin Matuska 
110716fd348SMartin Matuska 	zfs_close(zhp);
111716fd348SMartin Matuska 
112716fd348SMartin Matuska 	/*
113716fd348SMartin Matuska 	 * Exercise EXDEV in dmu_send.
114716fd348SMartin Matuska 	 */
115716fd348SMartin Matuska 	error = lzc_send_resume_redacted(fromfull, tofull, fd, 0, 0, 0, NULL);
116716fd348SMartin Matuska 	if (error != EXDEV)
117716fd348SMartin Matuska 		errx(EX_OSERR, "lzc_send_resume_redacted(\"%s\", \"%s\")"
118716fd348SMartin Matuska 		    " should have failed with EXDEV, not %d",
119716fd348SMartin Matuska 		    fromfull, tofull, error);
120716fd348SMartin Matuska 	printf("lzc_send_resume_redacted(\"%s\", \"%s\"): %s\n",
121716fd348SMartin Matuska 	    fromfull, tofull, strerror(error));
122716fd348SMartin Matuska 
123716fd348SMartin Matuska 	/*
124716fd348SMartin Matuska 	 * Exercise EXDEV in dmu_send_estimate_fast.
125716fd348SMartin Matuska 	 */
126716fd348SMartin Matuska 	error = lzc_send_space_resume_redacted(fromfull, tofull, 0, 0, 0, 0,
127716fd348SMartin Matuska 	    NULL, fd, &size);
128716fd348SMartin Matuska 	if (error != EXDEV)
129716fd348SMartin Matuska 		errx(EX_OSERR, "lzc_send_space_resume_redacted(\"%s\", \"%s\")"
130716fd348SMartin Matuska 		    " should have failed with EXDEV, not %d",
131716fd348SMartin Matuska 		    fromfull, tofull, error);
132716fd348SMartin Matuska 	printf("lzc_send_space_resume_redacted(\"%s\", \"%s\"): %s\n",
133716fd348SMartin Matuska 	    fromfull, tofull, strerror(error));
134716fd348SMartin Matuska 
135716fd348SMartin Matuska 	close(fd);
136716fd348SMartin Matuska 	libzfs_fini(zhdl);
137716fd348SMartin Matuska 	free((void *)fsname);
138716fd348SMartin Matuska 
139716fd348SMartin Matuska 	return (EXIT_SUCCESS);
140716fd348SMartin Matuska }
141