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