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 O_EXCL tmpfile cannot be linked.
19  *
20  * STRATEGY:
21  *	1. open(2) with O_TMPFILE|O_EXCL.
22  *	2. linkat(2).
23  *	3. stat(2) the path to verify it wasn't created.
24  *
25  */
26 
27 int
28 main(void)
29 {
30 	int i, fd;
31 	char spath[1024], dpath[1024];
32 	const char *penv[] = {"TESTDIR", "TESTFILE0"};
33 	struct stat sbuf;
34 
35 	(void) fprintf(stdout, "Verify O_EXCL tmpfile cannot be linked.\n");
36 
37 	/*
38 	 * Get the environment variable values.
39 	 */
40 	for (i = 0; i < ARRAY_SIZE(penv); i++)
41 		if ((penv[i] = getenv(penv[i])) == NULL)
42 			errx(1, "getenv(penv[%d])", i);
43 
44 	fd = open(penv[0], O_RDWR|O_TMPFILE|O_EXCL, 0666);
45 	if (fd < 0)
46 		err(2, "open(%s)", penv[0]);
47 
48 	snprintf(spath, 1024, "/proc/self/fd/%d", fd);
49 	snprintf(dpath, 1024, "%s/%s", penv[0], penv[1]);
50 	if (linkat(AT_FDCWD, spath, AT_FDCWD, dpath, AT_SYMLINK_FOLLOW) == 0)
51 		errx(3, "linkat returned successfully\n");
52 
53 	if (stat(dpath, &sbuf) == 0)
54 		errx(4, "stat returned successfully\n");
55 
56 	return (0);
57 }
58