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
run(const char * op)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
main(void)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