1 /*
2 * Copyright (c) 2020 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdio.h>
8 #include <string.h>
9 #include <zephyr/kernel.h>
10 #include <zephyr/types.h>
11 #include <errno.h>
12 #include <zephyr/init.h>
13 #include <zephyr/fs/fs.h>
14 #include <zephyr/fs/fs_sys.h>
15 #include <zephyr/sys/__assert.h>
16 #include "test_fs.h"
17
18 #define BUF_LEN 128
19 static char buffer[BUF_LEN];
20 static char *read_pos = buffer;
21 static char *cur = buffer;
22 static int file_length;
23 static struct fs_mount_t *mp[FS_TYPE_EXTERNAL_BASE];
24 static bool nospace;
25 static int opendir_result;
26
27 static
temp_open(struct fs_file_t * zfp,const char * file_name,fs_mode_t flags)28 int temp_open(struct fs_file_t *zfp, const char *file_name, fs_mode_t flags)
29 {
30 if (zfp == NULL || file_name == NULL) {
31 return -EINVAL;
32 }
33
34 if (zfp->filep) {
35 if (strcmp(zfp->filep, file_name) == 0) {
36 /* file has been opened */
37 return -EEXIST;
38 }
39 }
40
41 if (!(flags & FS_O_MASK)) {
42 return -EINVAL;
43 }
44
45 zfp->filep = (char *)file_name;
46 return 0;
47 }
48
temp_close(struct fs_file_t * zfp)49 static int temp_close(struct fs_file_t *zfp)
50 {
51 if (zfp == NULL) {
52 return -EINVAL;
53 }
54
55 if (zfp->filep) {
56 zfp->filep = NULL;
57 } else {
58 return -EIO;
59 }
60
61 return 0;
62 }
63
temp_unlink(struct fs_mount_t * mountp,const char * path)64 static int temp_unlink(struct fs_mount_t *mountp, const char *path)
65 {
66 if (mountp == NULL || path == NULL) {
67 return -EINVAL;
68 }
69
70 if (strcmp(mountp->mnt_point, path) == 0) {
71 return -EPERM;
72 }
73 return 0;
74 }
75
temp_rename(struct fs_mount_t * mountp,const char * from,const char * to)76 static int temp_rename(struct fs_mount_t *mountp, const char *from,
77 const char *to)
78 {
79 if (mountp == NULL || from == NULL || to == NULL) {
80 return -EINVAL;
81 }
82
83 if (strcmp(to, TEST_FILE_EX) == 0) {
84 return -EINVAL;
85 }
86 return 0;
87 }
88
temp_read(struct fs_file_t * zfp,void * ptr,size_t size)89 static ssize_t temp_read(struct fs_file_t *zfp, void *ptr, size_t size)
90 {
91 unsigned int br;
92
93 if (zfp == NULL || ptr == NULL) {
94 return -EINVAL;
95 }
96
97 br = size;
98 if (read_pos - buffer + br > file_length) {
99 br = file_length - (read_pos - buffer);
100 }
101 memcpy(ptr, read_pos, br);
102 read_pos += br;
103 cur = read_pos;
104
105 return br;
106 }
107
temp_write(struct fs_file_t * zfp,const void * ptr,size_t size)108 static ssize_t temp_write(struct fs_file_t *zfp, const void *ptr, size_t size)
109 {
110 unsigned int bw;
111
112 if (zfp == NULL || ptr == NULL) {
113 return -EINVAL;
114 }
115
116 if (nospace) {
117 return -ENOSPC;
118 }
119
120 bw = size;
121 if (file_length + bw > BUF_LEN) {
122 bw = BUF_LEN - file_length;
123 nospace = true;
124 }
125
126 memcpy(buffer + file_length, ptr, bw);
127 file_length += bw;
128 cur = buffer + file_length;
129
130 return bw;
131 }
132
temp_seek(struct fs_file_t * zfp,off_t offset,int whence)133 static int temp_seek(struct fs_file_t *zfp, off_t offset, int whence)
134 {
135
136 if (!zfp) {
137 return -EINVAL;
138 }
139
140 switch (whence) {
141 case FS_SEEK_SET:
142 cur = buffer + offset;
143 break;
144 case FS_SEEK_CUR:
145 cur += offset;
146 break;
147 case FS_SEEK_END:
148 cur = buffer + file_length + offset;
149 break;
150 default:
151 return -EINVAL;
152 }
153
154 if ((cur < buffer) || (cur > buffer + file_length)) {
155 return -EINVAL;
156 }
157
158 return 0;
159 }
160
temp_tell(struct fs_file_t * zfp)161 static off_t temp_tell(struct fs_file_t *zfp)
162 {
163 if (!zfp) {
164 return -EINVAL;
165 }
166
167 if (nospace) {
168 return -ENOSPC;
169 }
170
171 return cur - buffer;
172 }
173
temp_truncate(struct fs_file_t * zfp,off_t length)174 static int temp_truncate(struct fs_file_t *zfp, off_t length)
175 {
176 if (!zfp) {
177 return -EINVAL;
178 }
179
180 if (length > BUF_LEN) {
181 return -EINVAL;
182 }
183 file_length = length;
184 return 0;
185 }
186
temp_sync(struct fs_file_t * zfp)187 static int temp_sync(struct fs_file_t *zfp)
188 {
189 if (!zfp) {
190 return -EINVAL;
191 }
192
193 if (nospace) {
194 return -ENOSPC;
195 }
196
197 return 0;
198 }
199
temp_mkdir(struct fs_mount_t * mountp,const char * path)200 static int temp_mkdir(struct fs_mount_t *mountp, const char *path)
201 {
202 if (mountp == NULL || path == NULL) {
203 return -EINVAL;
204 }
205
206 if (strcmp(mountp->mnt_point, path) == 0) {
207 return -EPERM;
208 }
209 return 0;
210 }
211
mock_opendir_result(int ret)212 void mock_opendir_result(int ret)
213 {
214 opendir_result = ret;
215 }
216
temp_opendir(struct fs_dir_t * zdp,const char * path)217 static int temp_opendir(struct fs_dir_t *zdp, const char *path)
218 {
219 if (zdp == NULL || path == NULL) {
220 return -EINVAL;
221 }
222
223 if (opendir_result) {
224 return opendir_result;
225 }
226
227 zdp->dirp = (char *)path;
228 return 0;
229 }
230
231 static int i;
temp_readdir(struct fs_dir_t * zdp,struct fs_dirent * entry)232 static int temp_readdir(struct fs_dir_t *zdp, struct fs_dirent *entry)
233 {
234 if (!zdp) {
235 return -EINVAL;
236 }
237
238 if (!entry) {
239 return -ENOENT;
240 }
241
242 switch (i) {
243 case 0:
244 strcpy(entry->name, ".");
245 entry->type = FS_DIR_ENTRY_DIR;
246 i++;
247 break;
248 case 1:
249 strcpy(entry->name, "testdir");
250 entry->type = FS_DIR_ENTRY_DIR;
251 i++;
252 break;
253 case 2:
254 strcpy(entry->name, "test.txt");
255 entry->type = FS_DIR_ENTRY_FILE;
256 i++;
257 break;
258 case 3:
259 strcpy(entry->name, "..");
260 entry->type = FS_DIR_ENTRY_DIR;
261 i++;
262 break;
263 default:
264 strcpy(entry->name, "\0");
265 i = 0;
266 break;
267 }
268 return 0;
269 }
270
temp_closedir(struct fs_dir_t * zdp)271 static int temp_closedir(struct fs_dir_t *zdp)
272 {
273 if (!zdp) {
274 return -EINVAL;
275 }
276
277 if (!(zdp->dirp)) {
278 return -EIO;
279 }
280 zdp->dirp = NULL;
281 return 0;
282 }
283
temp_stat(struct fs_mount_t * mountp,const char * path,struct fs_dirent * entry)284 static int temp_stat(struct fs_mount_t *mountp,
285 const char *path, struct fs_dirent *entry)
286 {
287 if (mountp == NULL || path == NULL || entry == NULL) {
288 return -EINVAL;
289 }
290
291 return 0;
292 }
293
temp_statvfs(struct fs_mount_t * mountp,const char * path,struct fs_statvfs * stat)294 static int temp_statvfs(struct fs_mount_t *mountp,
295 const char *path, struct fs_statvfs *stat)
296 {
297 if (mountp == NULL || path == NULL || stat == NULL) {
298 return -EINVAL;
299 }
300
301 memset(stat, 0, sizeof(struct fs_statvfs));
302 stat->f_bsize = 512;
303 return 0;
304 }
305
temp_mount(struct fs_mount_t * mountp)306 static int temp_mount(struct fs_mount_t *mountp)
307 {
308 if (mountp == NULL) {
309 return -EINVAL;
310 }
311
312 size_t len = strlen(mountp->mnt_point);
313
314 if (mountp->mnt_point[len - 1] != ':') {
315 return -EINVAL;
316 }
317 mp[mountp->type] = mountp;
318 return 0;
319 }
320
temp_unmount(struct fs_mount_t * mountp)321 static int temp_unmount(struct fs_mount_t *mountp)
322 {
323 if (mountp == NULL) {
324 return -EINVAL;
325 }
326
327 if (mp[mountp->type] == NULL) {
328 return -EINVAL;
329 }
330 mp[mountp->type] = NULL;
331 return 0;
332 }
333
334 /* File system interface */
335 struct fs_file_system_t temp_fs = {
336 .open = temp_open,
337 .close = temp_close,
338 .read = temp_read,
339 .write = temp_write,
340 .lseek = temp_seek,
341 .tell = temp_tell,
342 .truncate = temp_truncate,
343 .sync = temp_sync,
344 .opendir = temp_opendir,
345 .readdir = temp_readdir,
346 .closedir = temp_closedir,
347 .mount = temp_mount,
348 .unmount = temp_unmount,
349 .unlink = temp_unlink,
350 .rename = temp_rename,
351 .mkdir = temp_mkdir,
352 .stat = temp_stat,
353 .statvfs = temp_statvfs,
354 };
355