1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2020 Joyent, Inc.
14  */
15 
16 /*
17  * Test the open(2) syscall.
18  *
19  * Currently only tests O_DIRECT pass/fail based on the known support in the
20  * underlying file system.
21  *
22  * Note: there is a test for the O_DIRECTORY flag in the directory above this
23  * which could be consolidated into this code at some point.
24  */
25 
26 #include <stdio.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <sys/statvfs.h>
30 #include <sys/param.h>
31 #include <fcntl.h>
32 #include <errno.h>
33 #include <unistd.h>
34 #include <stdlib.h>
35 #include <string.h>
36 
37 static void
o_direct_test(const char * dir)38 o_direct_test(const char *dir)
39 {
40 	int fd;
41 	struct statvfs64 buf;
42 	char tmpname[MAXPATHLEN];
43 	char *path;
44 
45 	boolean_t pass;
46 
47 	(void) snprintf(tmpname, sizeof (tmpname), "%s/otstXXXXXX", dir);
48 	if ((path = mktemp(tmpname)) == NULL) {
49 		(void) printf("FAILED: unable to create temp file name\n");
50 		exit(1);
51 	}
52 
53 	if (statvfs64(dir, &buf) == -1) {
54 		perror("statvfs failed");
55 		exit(1);
56 	}
57 
58 	if (strcmp(buf.f_basetype, "zfs") == 0) {
59 		pass = B_TRUE;
60 	} else if (strcmp(buf.f_basetype, "tmpfs") == 0) {
61 		pass = B_FALSE;
62 	} else {
63 		(void) printf("SKIP: expected 'zfs' or 'tmpfs'\n");
64 		return;
65 	}
66 
67 	fd = open(path, O_WRONLY | O_CREAT | O_EXCL | O_DIRECT, 0644);
68 	if (fd >= 0) {
69 		(void) close(fd);
70 		(void) unlink(path);
71 		if (!pass) {
72 			(void) printf("FAILED: O_DIRECT on %s/tst_open is "
73 			    "expected to fail\n", dir);
74 			exit(1);
75 		}
76 	} else {
77 		if (pass) {
78 			(void) printf("FAILED: O_DIRECT on %s/tst_open is "
79 			    "expected to succeed\n", dir);
80 			exit(1);
81 		}
82 
83 		if (errno != EINVAL) {
84 			(void) printf("FAILED: expected EINVAL, got %d\n",
85 			    errno);
86 			exit(1);
87 		}
88 	}
89 }
90 
91 int
main(void)92 main(void)
93 {
94 	/* On typical illumos distros, /tmp is tmpfs, O_DIRECT should fail */
95 	o_direct_test("/tmp");
96 
97 	/* On typical illumos distros, /var is zfs, O_DIRECT should pass */
98 	o_direct_test("/var/tmp");
99 
100 	(void) printf("PASS\n");
101 	return (0);
102 }
103