1 /*
2 * Copyright (c) 2014 Fujitsu Ltd.
3 * Author: Zeng Linggang <[email protected]>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program.
15 */
16 /*
17 * DESCRIPTION
18 * This test case will verify basic function of open(2) with the flags
19 * O_APPEND, O_NOATIME, O_CLOEXEC and O_LARGEFILE.
20 */
21
22 #define _GNU_SOURCE
23
24 #include <stdio.h>
25 #include <sys/types.h>
26 #include <sys/wait.h>
27 #include <unistd.h>
28 #include <mntent.h>
29 #include <errno.h>
30 #include "test.h"
31 #include "safe_macros.h"
32 #include "lapi/fcntl.h"
33 #include "lapi/mount.h"
34
35 #define MNTPOINT "mntpoint"
36 #define TEST_FILE MNTPOINT"/test_file"
37 #define LARGE_FILE "large_file"
38
39 #define DIR_MODE 0755
40
41 char *TCID = "open12";
42
43 static const char *device;
44 static unsigned int mount_flag, skip_noatime;
45
46 static void setup(void);
47 static void cleanup(void);
48 static void test_append(void);
49 static void test_noatime(void);
50 static void test_cloexec(void);
51 static void test_largefile(void);
52
53 static void (*test_func[])(void) = { test_append, test_noatime, test_cloexec,
54 test_largefile };
55
56 int TST_TOTAL = ARRAY_SIZE(test_func);
57
main(int argc,char ** argv)58 int main(int argc, char **argv)
59 {
60 int lc;
61 int i;
62
63 tst_parse_opts(argc, argv, NULL, NULL);
64
65 setup();
66
67 for (lc = 0; TEST_LOOPING(lc); lc++) {
68 tst_count = 0;
69 for (i = 0; i < TST_TOTAL; i++)
70 (*test_func[i])();
71 }
72
73 cleanup();
74 tst_exit();
75 }
76
setup(void)77 static void setup(void)
78 {
79 const char *mount_flags[] = {"noatime", "relatime", NULL};
80
81 TEST_PAUSE;
82
83 tst_sig(FORK, DEF_HANDLER, cleanup);
84
85 tst_tmpdir();
86
87 SAFE_MKDIR(cleanup, MNTPOINT, DIR_MODE);
88
89 if (tst_path_has_mnt_flags(cleanup, NULL, mount_flags)) {
90 const char *fs_type;
91
92 fs_type = tst_dev_fs_type();
93 device = tst_acquire_device(cleanup);
94
95 if (!device) {
96 tst_resm(TINFO, "Failed to obtain block device");
97 skip_noatime = 1;
98 goto end;
99 }
100
101 tst_mkfs(cleanup, device, fs_type, NULL, NULL);
102
103 SAFE_MOUNT(cleanup, device, MNTPOINT, fs_type, MS_STRICTATIME, NULL);
104 mount_flag = 1;
105 }
106
107 end:
108 SAFE_FILE_PRINTF(cleanup, TEST_FILE, TEST_FILE);
109 }
110
test_append(void)111 static void test_append(void)
112 {
113 off_t len1, len2;
114
115 TEST(open(TEST_FILE, O_RDWR | O_APPEND, 0777));
116
117 if (TEST_RETURN == -1) {
118 tst_resm(TFAIL | TTERRNO, "open failed");
119 return;
120 }
121
122 len1 = SAFE_LSEEK(cleanup, TEST_RETURN, 0, SEEK_CUR);
123 SAFE_WRITE(cleanup, SAFE_WRITE_ALL, TEST_RETURN, TEST_FILE,
124 sizeof(TEST_FILE));
125 len2 = SAFE_LSEEK(cleanup, TEST_RETURN, 0, SEEK_CUR);
126 SAFE_CLOSE(cleanup, TEST_RETURN);
127
128 if (len2 > len1)
129 tst_resm(TPASS, "test O_APPEND for open success");
130 else
131 tst_resm(TFAIL, "test O_APPEND for open failed");
132 }
133
test_noatime(void)134 static void test_noatime(void)
135 {
136 char read_buf;
137 struct stat old_stat, new_stat;
138
139 if (skip_noatime) {
140 tst_resm(TCONF,
141 "test O_NOATIME flag for open needs filesystems which "
142 "is mounted without noatime and relatime");
143 return;
144 }
145
146 SAFE_STAT(cleanup, TEST_FILE, &old_stat);
147
148 sleep(1);
149
150 TEST(open(TEST_FILE, O_RDONLY | O_NOATIME, 0777));
151
152 if (TEST_RETURN == -1) {
153 tst_resm(TFAIL | TTERRNO, "open failed");
154 return;
155 }
156 SAFE_READ(cleanup, 1, TEST_RETURN, &read_buf, 1);
157 SAFE_CLOSE(cleanup, TEST_RETURN);
158 SAFE_STAT(cleanup, TEST_FILE, &new_stat);
159
160 if (old_stat.st_atime == new_stat.st_atime)
161 tst_resm(TPASS, "test O_NOATIME for open success");
162 else
163 tst_resm(TFAIL, "test O_NOATIME for open failed");
164 }
165
test_cloexec(void)166 static void test_cloexec(void)
167 {
168 pid_t pid;
169 int status;
170 char buf[20];
171
172 TEST(open(TEST_FILE, O_RDWR | O_APPEND | O_CLOEXEC, 0777));
173
174 if (TEST_RETURN == -1) {
175 tst_resm(TFAIL | TTERRNO, "open failed");
176 return;
177 }
178
179 sprintf(buf, "%ld", TEST_RETURN);
180
181 pid = tst_fork();
182 if (pid < 0)
183 tst_brkm(TBROK | TERRNO, cleanup, "fork() failed");
184
185 if (pid == 0) {
186 if (execlp("open12_child", "open12_child", buf, NULL))
187 exit(2);
188 }
189
190 SAFE_CLOSE(cleanup, TEST_RETURN);
191
192 if (wait(&status) != pid)
193 tst_brkm(TBROK | TERRNO, cleanup, "wait() failed");
194
195 if (WIFEXITED(status)) {
196 switch ((int8_t)WEXITSTATUS(status)) {
197 case 0:
198 tst_resm(TPASS, "test O_CLOEXEC for open success");
199 break;
200 case 1:
201 tst_resm(TFAIL, "test O_CLOEXEC for open failed");
202 break;
203 default:
204 tst_brkm(TBROK, cleanup, "execlp() failed");
205 }
206 } else {
207 tst_brkm(TBROK, cleanup,
208 "open12_child exits with unexpected error");
209 }
210 }
211
test_largefile(void)212 static void test_largefile(void)
213 {
214 int fd;
215 off_t offset;
216
217 fd = SAFE_OPEN(cleanup, LARGE_FILE,
218 O_LARGEFILE | O_RDWR | O_CREAT, 0777);
219
220 offset = lseek(fd, 4.1*1024*1024*1024, SEEK_SET);
221 if (offset == -1)
222 tst_brkm(TBROK | TERRNO, cleanup, "lseek failed");
223
224 SAFE_WRITE(cleanup, SAFE_WRITE_ALL, fd, LARGE_FILE,
225 sizeof(LARGE_FILE));
226
227 SAFE_CLOSE(cleanup, fd);
228
229 TEST(open(LARGE_FILE, O_LARGEFILE | O_RDONLY, 0777));
230
231 if (TEST_RETURN == -1) {
232 tst_resm(TFAIL, "test O_LARGEFILE for open failed");
233 } else {
234 tst_resm(TPASS, "test O_LARGEFILE for open success");
235 SAFE_CLOSE(cleanup, TEST_RETURN);
236 }
237 }
238
cleanup(void)239 static void cleanup(void)
240 {
241 if (mount_flag && tst_umount(MNTPOINT) == -1)
242 tst_brkm(TWARN | TERRNO, NULL, "umount(2) failed");
243
244 if (device)
245 tst_release_device(device);
246
247 tst_rmdir();
248 }
249