1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <fcntl.h>
7 #include <errno.h>
8 #include <string.h>
9 #include <err.h>
10 
11 /* backward compat in case it's not defined */
12 #ifndef O_TMPFILE
13 #define	O_TMPFILE	(020000000|O_DIRECTORY)
14 #endif
15 
16 /*
17  * DESCRIPTION:
18  *	Verify we can link tmpfile.
19  *
20  * STRATEGY:
21  *	1. open(2) with O_TMPFILE.
22  *	2. linkat(2).
23  *	3. freeze the pool, export and re-import the pool.
24  *	3. stat(2) the path to verify it has been created.
25  *
26  */
27 
28 static void
29 run(const char *op)
30 {
31 	int ret;
32 	char buf[50];
33 	sprintf(buf, "sudo -E zpool %s $TESTPOOL", op);
34 	if ((ret = system(buf)) != 0) {
35 		if (ret == -1)
36 			err(4, "system \"zpool %s\"", op);
37 		else
38 			errx(4, "zpool %s exited %d\n",
39 			    op, WEXITSTATUS(ret));
40 	}
41 }
42 
43 int
44 main(void)
45 {
46 	int i, fd;
47 	char spath[1024], dpath[1024];
48 	const char *penv[] = {"TESTDIR", "TESTFILE0"};
49 
50 	(void) fprintf(stdout, "Verify O_TMPFILE file can be linked.\n");
51 
52 	/*
53 	 * Get the environment variable values.
54 	 */
55 	for (i = 0; i < ARRAY_SIZE(penv); i++)
56 		if ((penv[i] = getenv(penv[i])) == NULL)
57 			errx(1, "getenv(penv[%d])", i);
58 
59 	fd = open(penv[0], O_RDWR|O_TMPFILE, 0666);
60 	if (fd < 0)
61 		err(2, "open(%s)", penv[0]);
62 
63 	snprintf(spath, 1024, "/proc/self/fd/%d", fd);
64 	snprintf(dpath, 1024, "%s/%s", penv[0], penv[1]);
65 	if (linkat(AT_FDCWD, spath, AT_FDCWD, dpath, AT_SYMLINK_FOLLOW) < 0)
66 		err(3, "linkat");
67 
68 	run("freeze");
69 
70 	close(fd);
71 
72 	run("export");
73 	run("import");
74 
75 	if (unlink(dpath) == -1) {
76 		perror("unlink");
77 		exit(5);
78 	}
79 
80 	return (0);
81 }
82