1 /*
2  * Copyright (c) 2020 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <string.h>
8 #include <fcntl.h>
9 #include <zephyr/posix/unistd.h>
10 #include "test_fs.h"
11 
12 #define THE_FILE FATFS_MNTP"/the_file.txt"
13 
test_file_open_flags(void)14 static int test_file_open_flags(void)
15 {
16 	int fd = 0;
17 	int data = 0;
18 	int ret;
19 
20 	/* 1 Check opening non-existent without O_CREAT */
21 	TC_PRINT("Open of non-existent file, flags = 0\n");
22 	fd = open(THE_FILE, 0);
23 	if (fd >= 0 || errno != ENOENT) {
24 		TC_PRINT("Expected fail; fd = %d, errno = %d\n", fd, errno);
25 		close(fd);
26 		return TC_FAIL;
27 	}
28 
29 	TC_PRINT("Open on non-existent file, flags = O_RDONLY\n");
30 	fd = open(THE_FILE, O_RDONLY);
31 	if (fd >= 0 || errno != ENOENT) {
32 		TC_PRINT("Expected fail; fd = %d, errno = %d\n", fd, errno);
33 		close(fd);
34 		return TC_FAIL;
35 	}
36 	TC_PRINT("Open on non-existent file, flags = O_WRONLY\n");
37 	fd = open(THE_FILE, O_WRONLY);
38 	if (fd >= 0 || errno != ENOENT) {
39 		TC_PRINT("Expected fail; fd = %d, errno = %d\n", fd, errno);
40 		close(fd);
41 		return TC_FAIL;
42 	}
43 
44 	TC_PRINT("Open on non-existent file, flags = O_RDWR\n");
45 	fd = open(THE_FILE, O_RDWR);
46 	if (fd >= 0 || errno != ENOENT) {
47 		TC_PRINT("Expected fail; fd = %d, errno = %d\n", fd, errno);
48 		close(fd);
49 		return TC_FAIL;
50 	}
51 	/* end 1 */
52 
53 	/* 2 Create file for read only, attempt to read, attempt to write */
54 	TC_PRINT("Open on non-existent file, flags = O_CREAT | O_WRONLY\n");
55 	fd = open(THE_FILE, O_CREAT | O_WRONLY);
56 	if (fd < 0) {
57 		TC_PRINT("Expected success; fd = %d, errno = %d\n", fd, errno);
58 		return TC_FAIL;
59 	}
60 
61 	TC_PRINT("Attempt read file opened with flags = O_CREAT | O_WRONLY\n");
62 	ret = read(fd, &data, sizeof(data));
63 	if (ret > 0 || errno != EACCES) {
64 		TC_PRINT("Expected fail, ret = %d, errno = %d\n", ret, errno);
65 		close(fd);
66 		return TC_FAIL;
67 	}
68 
69 	TC_PRINT("Attempt write file opened with flags = O_CREAT | O_WRONLY\n");
70 	ret = write(fd, &data, sizeof(data));
71 	if (ret <= 0 || errno != EACCES) {
72 		TC_PRINT("Expected success, ret = %d, errno = %d\n", ret,
73 			 errno);
74 		close(fd);
75 		return TC_FAIL;
76 	}
77 
78 	close(fd);
79 	/* end 2 */
80 
81 
82 	/* 3 Attempt read/write operation on file opened with flags = 0 */
83 	TC_PRINT("Attempt open existing with flags = 0\n");
84 	fd = open(THE_FILE, 0);
85 	if (fd < 0) {
86 		TC_PRINT("Expected success, fd = %d, errno = %d\n", fd, errno);
87 		return TC_FAIL;
88 	}
89 
90 	TC_PRINT("Attempt read file opened with flags = 0\n");
91 	ret = read(fd, &data, sizeof(data));
92 	if (ret < 0) {
93 		TC_PRINT("Expected success, ret = %d, errno = %d\n", ret,
94 			 errno);
95 		close(fd);
96 		return TC_FAIL;
97 	}
98 
99 	TC_PRINT("Attempt write file opened with flags = 0\n");
100 	ret = write(fd, &data, sizeof(data));
101 	if (ret >= 0 || errno != EACCES) {
102 		TC_PRINT("Expected fail, ret = %d, errno = %d\n", ret, errno);
103 		close(fd);
104 		return TC_FAIL;
105 	}
106 
107 	close(fd);
108 	/* end 3 */
109 
110 	/* 4 Attempt read/write on file opened with flags O_RDONLY */
111 	/* File does have content after previous tests. */
112 	TC_PRINT("Attempt open existing with flags = O_RDONLY\n");
113 	fd = open(THE_FILE, O_RDONLY);
114 	if (fd < 0) {
115 		TC_PRINT("Expected success, fd = %d, errno = %d\n", fd, errno);
116 		return TC_FAIL;
117 	}
118 
119 	TC_PRINT("Attempt read file opened with flags = O_RDONLY\n");
120 	ret = read(fd, &data, sizeof(data));
121 	if (ret < 0) {
122 		TC_PRINT("Expected success, ret = %d, errno = %d\n", ret,
123 			 errno);
124 		close(fd);
125 		return TC_FAIL;
126 	}
127 
128 	TC_PRINT("Attempt write file opened with flags = O_RDONLY\n");
129 	ret = write(fd, &data, sizeof(data));
130 	if (ret >= 0 || errno != EACCES) {
131 		TC_PRINT("Expected fail, ret = %d, errno = %d\n", ret, errno);
132 		close(fd);
133 		return TC_FAIL;
134 	}
135 
136 	close(fd);
137 	/* end 4 */
138 
139 	/* 5 Attempt read/write on file opened with flags O_WRONLY */
140 	/* File does have content after previous tests. */
141 	TC_PRINT("Attempt open existing with flags = O_WRONLY\n");
142 	fd = open(THE_FILE, O_WRONLY);
143 	if (fd < 0) {
144 		TC_PRINT("Expected success, fd = %d, errno = %d\n", fd, errno);
145 		return TC_FAIL;
146 	}
147 
148 	TC_PRINT("Attempt read file opened with flags = O_WRONLY\n");
149 	ret = read(fd, &data, sizeof(data));
150 	if (ret >= 0 || errno != EACCES) {
151 		TC_PRINT("Expected fail, ret = %d, errno = %d\n", ret, errno);
152 		close(fd);
153 		return TC_FAIL;
154 	}
155 
156 	TC_PRINT("Attempt write file opened with flags = O_WRONLY\n");
157 	ret = write(fd, &data, sizeof(data));
158 	if (ret < 0) {
159 		TC_PRINT("Expected success, ret = %d, errno = %d\n", ret,
160 			 errno);
161 		close(fd);
162 		return TC_FAIL;
163 	}
164 
165 	close(fd);
166 	/* end 5 */
167 
168 	/* 6 Attempt read/write on file opened with flags O_APPEND | O_WRONLY */
169 	TC_PRINT("Attempt open existing with flags = O_APPEND | O_WRONLY\n");
170 	fd = open(THE_FILE, O_APPEND | O_WRONLY);
171 	if (fd < 0) {
172 		TC_PRINT("Expected success, fd = %d, errno = %d\n", fd, errno);
173 		return TC_FAIL;
174 	}
175 
176 	TC_PRINT("Attempt read file opened with flags = O_APPEND | O_WRONLY\n");
177 	ret = read(fd, &data, sizeof(data));
178 	if (ret >= 0 || errno != EACCES) {
179 		TC_PRINT("Expected fail, ret = %d, errno = %d\n", ret, errno);
180 		close(fd);
181 		return TC_FAIL;
182 	}
183 
184 	TC_PRINT("Attempt write to opened with flags = O_APPEND | O_WRONLY\n");
185 	ret = write(fd, &data, sizeof(data));
186 	if (ret < 0) {
187 		TC_PRINT("Expected success, ret = %d, errno = %d\n", ret,
188 			 errno);
189 		close(fd);
190 		return TC_FAIL;
191 	}
192 
193 	close(fd);
194 	/* end 6 */
195 
196 	/* 7 Attempt read/write on file opened with flags O_APPEND | O_RDWR */
197 	TC_PRINT("Attempt open existing with flags = O_APPEND | O_RDWR\n");
198 	fd = open(THE_FILE, O_APPEND | O_RDWR);
199 	if (fd < 0) {
200 		TC_PRINT("Expected success, fd = %d, errno = %d\n", fd, errno);
201 		return TC_FAIL;
202 	}
203 
204 
205 	TC_PRINT("Attempt read file opened with flags = O_APPEND | O_RDWR\n");
206 	lseek(fd, 0, SEEK_SET);
207 	ret = read(fd, &data, sizeof(data));
208 	if (ret < 0) {
209 		TC_PRINT("Expected success, ret = %d, errno = %d\n", ret,
210 			 errno);
211 		close(fd);
212 		return TC_FAIL;
213 	}
214 
215 	TC_PRINT("Attempt write file opened with flags = O_APPEND | O_RDWR\n");
216 	ret = write(fd, &data, sizeof(data));
217 	if (ret < 0) {
218 		TC_PRINT("Expected success, ret = %d, errno = %d\n", ret,
219 			 errno);
220 		close(fd);
221 		return TC_FAIL;
222 	}
223 
224 	close(fd);
225 	/* end 7 */
226 
227 	/* 8 Check if appended file is always written at the end */
228 	TC_PRINT("Attempt write to file opened with O_APPEND | O_RDWR\n");
229 	/* Clean start */
230 	unlink(THE_FILE);
231 	fd = open(THE_FILE, O_CREAT | O_WRONLY);
232 	if (fd < 0) {
233 		TC_PRINT("Expected success, fd = %d, errno = %d\n", fd, errno);
234 		return TC_FAIL;
235 	}
236 
237 	ret = write(fd, &data, sizeof(data));
238 	if (ret < 0) {
239 		TC_PRINT("Expected success, ret = %d, errno = %d\n", ret,
240 			 errno);
241 		close(fd);
242 		return TC_FAIL;
243 	}
244 
245 	close(fd);
246 
247 	fd = open(THE_FILE, O_APPEND | O_RDWR);
248 	if (fd < 0) {
249 		TC_PRINT("Expected success, fd = %d, errno = %d\n", fd, errno);
250 		return TC_FAIL;
251 	}
252 
253 	lseek(fd, 0, SEEK_SET);
254 	ret = write(fd, &data, sizeof(data));
255 	if (ret < 0) {
256 		TC_PRINT("Expected success, ret = %d, errno = %d\n", ret,
257 			 errno);
258 		close(fd);
259 		return TC_FAIL;
260 	}
261 
262 	ret = lseek(fd, 0, SEEK_END);
263 
264 	if (ret != (sizeof(data) * 2)) {
265 		TC_PRINT("Expected file size %zu, ret = %d, errno = %d\n",
266 			 sizeof(data) * 2, ret, errno);
267 		close(fd);
268 		return TC_FAIL;
269 	}
270 
271 	close(fd);
272 	/* end 8 */
273 
274 	return TC_PASS;
275 }
276 
277 /**
278  * @brief Test for POSIX open flags
279  *
280  * @details Test attempts to open file with different combinations of open
281  * flags and checks if operations on files are permitted according to flags.
282  */
ZTEST(posix_fs_test,test_fs_open_flags)283 ZTEST(posix_fs_test, test_fs_open_flags)
284 {
285 	zassert_true(test_file_open_flags() == TC_PASS);
286 }
287