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