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 
10 /* backward compat in case it's not defined */
11 #ifndef O_TMPFILE
12 #define	O_TMPFILE	(020000000|O_DIRECTORY)
13 #endif
14 
15 /*
16  * DESCRIPTION:
17  *	Verify O_EXCL tmpfile cannot be linked.
18  *
19  * STRATEGY:
20  *	1. open(2) with O_TMPFILE|O_EXCL.
21  *	2. linkat(2).
22  *	3. stat(2) the path to verify it wasn't created.
23  *
24  */
25 
26 int
27 main(int argc, char *argv[])
28 {
29 	int i, fd;
30 	char spath[1024], dpath[1024];
31 	char *penv[] = {"TESTDIR", "TESTFILE0"};
32 	struct stat sbuf;
33 
34 	(void) fprintf(stdout, "Verify O_EXCL tmpfile cannot be linked.\n");
35 
36 	/*
37 	 * Get the environment variable values.
38 	 */
39 	for (i = 0; i < sizeof (penv) / sizeof (char *); i++) {
40 		if ((penv[i] = getenv(penv[i])) == NULL) {
41 			(void) fprintf(stderr, "getenv(penv[%d])\n", i);
42 			exit(1);
43 		}
44 	}
45 
46 	fd = open(penv[0], O_RDWR|O_TMPFILE|O_EXCL, 0666);
47 	if (fd < 0) {
48 		perror("open");
49 		exit(2);
50 	}
51 
52 	snprintf(spath, 1024, "/proc/self/fd/%d", fd);
53 	snprintf(dpath, 1024, "%s/%s", penv[0], penv[1]);
54 	if (linkat(AT_FDCWD, spath, AT_FDCWD, dpath, AT_SYMLINK_FOLLOW) == 0) {
55 		fprintf(stderr, "linkat returns successfully\n");
56 		close(fd);
57 		exit(3);
58 	}
59 
60 	if (stat(dpath, &sbuf) == 0) {
61 		fprintf(stderr, "stat returns successfully\n");
62 		close(fd);
63 		exit(4);
64 	}
65 	close(fd);
66 
67 	return (0);
68 }
69