xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/open/open12.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
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