1 /*
2 * Copyright (C) 2015-2017 Alibaba Group Holding Limited
3 */
4
5 #include <fcntl.h>
6 #include <string.h>
7 #include <stdio.h>
8
9 #include "vfs_types.h"
10 #include "vfs_api.h"
11 #include "ramfs.h"
12
13 #include "ramfs_api.h"
14 #include "ramfs_adapt.h"
15 #include "ramfs_types.h"
16
17 #define MAX_RAMFS_FILE_NAME_BYTES 32
18
19 #define RAMFS_DEFAULT_MOUNT_PATH "/RAMFS"
20
21 typedef struct {
22 vfs_dir_t vfs_dir;
23 ramfs_dir_t ramfs_dir;
24 vfs_dirent_t vfs_dirent;
25 } ramfs_vfs_dir_t;
26
ramfs_vfs_open(vfs_file_t * fp,const char * path,int32_t flags)27 static int32_t ramfs_vfs_open(vfs_file_t *fp, const char *path, int32_t flags)
28 {
29 int32_t ret = RAMFS_ERR_NOT_IMP;
30 int32_t ramfs_flags = 0;
31
32 ramfs_file_t ramfs_file;
33
34 memset(&ramfs_file, 0, sizeof(ramfs_file));
35
36 if (flags == O_RDWR) {
37 ramfs_flags = RAMFS_MODE_WR | RAMFS_MODE_RD;
38 } else if (flags == O_RDONLY) {
39 ramfs_flags = RAMFS_MODE_RD;
40 } else if (flags == O_WRONLY) {
41 ramfs_flags = RAMFS_MODE_WR;
42 } else {
43 ramfs_flags = RAMFS_MODE_WR | RAMFS_MODE_RD;
44 }
45
46 ret = ramfs_open(&ramfs_file, path, ramfs_flags);
47
48 if (ret == 0) {
49 fp->f_arg = ramfs_file.entry;
50 }
51
52 return ret;
53 }
54
ramfs_vfs_close(vfs_file_t * fp)55 static int32_t ramfs_vfs_close(vfs_file_t *fp)
56 {
57 ramfs_file_t ramfs_file;
58
59 int32_t ret = RAMFS_ERR_NOT_IMP;
60
61 memset(&ramfs_file, 0, sizeof(ramfs_file));
62
63 ramfs_file.entry = (ramfs_entry_t *)fp->f_arg;
64
65 ret = ramfs_close(&ramfs_file);
66
67 return ret;
68 }
69
ramfs_vfs_read(vfs_file_t * fp,char * buf,uint32_t len)70 static int32_t ramfs_vfs_read(vfs_file_t *fp, char *buf, uint32_t len)
71 {
72 ramfs_file_t ramfs_file;
73
74 int32_t ret = RAMFS_ERR_NOT_IMP;
75 int32_t res = -1;
76
77 uint32_t read_bytes = 0;
78
79 memset(&ramfs_file, 0, sizeof(ramfs_file));
80
81 ramfs_file.entry = (ramfs_entry_t *)fp->f_arg;
82 ramfs_file.rwp = fp->offset;
83
84 ret = ramfs_read(&ramfs_file, buf, len, &read_bytes);
85
86 if (ret == 0) {
87 fp->offset = ramfs_file.rwp;
88 res = read_bytes;
89 } else {
90 res = -1;
91 }
92
93 return res;
94 }
95
ramfs_vfs_write(vfs_file_t * fp,const char * buf,uint32_t len)96 static int32_t ramfs_vfs_write(vfs_file_t *fp, const char *buf, uint32_t len)
97 {
98 ramfs_file_t ramfs_file;
99
100 int32_t ret = RAMFS_ERR_NOT_IMP;
101 int32_t res = -1;
102
103 uint32_t write_bytes = 0;
104
105 memset(&ramfs_file, 0, sizeof(ramfs_file));
106
107 ramfs_file.entry = (ramfs_entry_t *)fp->f_arg;
108 ramfs_file.rwp = fp->offset;
109
110 ret = ramfs_write(&ramfs_file, buf, len, &write_bytes);
111
112 if (ret == 0) {
113 fp->offset = ramfs_file.rwp;
114 res = write_bytes;
115 } else {
116 res = -1;
117 }
118
119 return res;
120 }
121
ramfs_vfs_access(vfs_file_t * fp,const char * path,int32_t amode)122 static int32_t ramfs_vfs_access(vfs_file_t *fp, const char *path, int32_t amode)
123 {
124 int32_t ret = RAMFS_ERR_NOT_IMP;
125
126 if ((amode == R_OK) || (amode == W_OK) || (amode == X_OK)) {
127 return 0;
128 }
129
130 ret = ramfs_access(path, amode);
131
132 if (ret != 0) {
133 ret = -1;
134 }
135
136 return ret;
137 }
138
ramfs_vfs_lseek(vfs_file_t * fp,int64_t off,int32_t whence)139 static uint32_t ramfs_vfs_lseek(vfs_file_t *fp, int64_t off, int32_t whence)
140 {
141 ramfs_file_t ramfs_file;
142
143 int64_t offset = 0;
144
145 memset(&ramfs_file, 0, sizeof(ramfs_file));
146
147 ramfs_file.entry = (ramfs_entry_t *)fp->f_arg;
148
149 offset = fp->offset;
150
151 if (whence == SEEK_SET) {
152 offset = off;
153 } else if (whence == SEEK_CUR) {
154 offset += off;
155 } else if (whence == SEEK_END) {
156 offset += ramfs_file.entry->size - 1;
157 }
158
159 if ((offset < ramfs_file.entry->size) && (offset >= 0)) {
160 fp->offset = offset;
161 }
162
163 return fp->offset;
164 }
165
ramfs_vfs_link(vfs_file_t * fp,const char * path1,const char * path2)166 static int32_t ramfs_vfs_link(vfs_file_t *fp, const char *path1, const char *path2)
167 {
168 return ramfs_link(path1, path2);
169 }
170
ramfs_vfs_unlink(vfs_file_t * fp,const char * path)171 static int32_t ramfs_vfs_unlink(vfs_file_t *fp, const char *path)
172 {
173 return ramfs_unlink(path);
174 }
175
ramfs_vfs_remove(vfs_file_t * fp,const char * path)176 static int32_t ramfs_vfs_remove(vfs_file_t *fp, const char *path)
177 {
178 return ramfs_remove(path);
179 }
180
ramfs_vfs_rename(vfs_file_t * fp,const char * old,const char * new)181 static int32_t ramfs_vfs_rename(vfs_file_t *fp, const char *old, const char *new)
182 {
183 return ramfs_rename(old, new);
184 }
185
ramfs_vfs_opendir(vfs_file_t * fp,const char * path)186 static vfs_dir_t *ramfs_vfs_opendir(vfs_file_t *fp, const char *path)
187 {
188 ramfs_vfs_dir_t *dp = NULL;
189 vfs_dir_t *ret = NULL;
190 int32_t res = -1;
191
192 dp = ramfs_mm_alloc(sizeof(ramfs_vfs_dir_t) + MAX_RAMFS_FILE_NAME_BYTES);
193
194 if (dp != NULL) {
195 fp->f_arg = dp;
196
197 res = ramfs_opendir(&dp->ramfs_dir, path);
198
199 if (res == 0) {
200 ret = &(dp->vfs_dir);
201 }
202 }
203
204 return ret;
205 }
206
ramfs_vfs_closedir(vfs_file_t * fp,vfs_dir_t * dir)207 static int32_t ramfs_vfs_closedir(vfs_file_t *fp, vfs_dir_t *dir)
208 {
209 ramfs_vfs_dir_t *dp;
210
211 dp = (ramfs_vfs_dir_t *)fp->f_arg;
212 if (dp != NULL) {
213 ramfs_closedir(&dp->ramfs_dir);
214 ramfs_mm_free((void*)dp);
215 }
216
217 return 0;
218 }
219
ramfs_vfs_stat(vfs_file_t * fp,const char * path,vfs_stat_t * st)220 static int32_t ramfs_vfs_stat(vfs_file_t *fp, const char *path, vfs_stat_t *st)
221 {
222 ramfs_stat_t ramfs_st;
223
224 int32_t ret = 0;
225
226 if (st == NULL) {
227 return -1;
228 }
229
230 memset(&ramfs_st, 0, sizeof(ramfs_st));
231
232 ret = ramfs_stat(path, &ramfs_st);
233
234 if (ret == 0) {
235 st->st_size = ramfs_st.st_size;
236 st->st_mode = S_IXUSR | S_IXGRP | S_IXOTH;
237
238 if ((ramfs_st.st_mode & RAMFS_MODE_RD) == RAMFS_MODE_RD) {
239 st->st_mode |= S_IRUSR | S_IRGRP | S_IROTH;
240 }
241
242 if ((ramfs_st.st_mode & RAMFS_MODE_WR) == RAMFS_MODE_WR) {
243 st->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
244 }
245
246 if (ramfs_st.is_dir == 1) {
247 st->st_mode |= S_IFDIR;
248 } else {
249 st->st_mode |= S_IFREG;
250 }
251
252 } else {
253 ret = -1;
254 }
255
256 return ret;
257 }
258
ramfs_vfs_fstat(vfs_file_t * fp,vfs_stat_t * st)259 static int32_t ramfs_vfs_fstat(vfs_file_t *fp, vfs_stat_t *st)
260 {
261 ramfs_stat_t ramfs_st;
262 ramfs_file_t ramfs_file;
263
264 int32_t ret = 0;
265
266 if (st == NULL) {
267 return -1;
268 }
269
270 memset(&ramfs_st, 0, sizeof(ramfs_st));
271 memset(&ramfs_file, 0, sizeof(ramfs_file));
272
273 ramfs_file.entry = (ramfs_entry_t *)fp->f_arg;
274
275 ret = ramfs_stat(ramfs_file.entry->fn, &ramfs_st);
276
277 if (ret == 0) {
278 st->st_size = ramfs_st.st_size;
279 st->st_mode = S_IXUSR | S_IXGRP | S_IXOTH;
280
281 if ((ramfs_st.st_mode & RAMFS_MODE_RD) == RAMFS_MODE_RD) {
282 st->st_mode |= S_IRUSR | S_IRGRP | S_IROTH;
283 }
284
285 if ((ramfs_st.st_mode & RAMFS_MODE_WR) == RAMFS_MODE_WR) {
286 st->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
287 }
288
289 if (ramfs_st.is_dir == 1) {
290 st->st_mode |= S_IFDIR;
291 } else {
292 st->st_mode |= S_IFREG;
293 }
294
295 } else {
296 ret = -1;
297 }
298
299 return ret;
300 }
301
ramfs_vfs_statfs(vfs_file_t * fp,const char * path,vfs_statfs_t * buf)302 static int32_t ramfs_vfs_statfs(vfs_file_t *fp, const char *path, vfs_statfs_t *buf)
303 {
304 if (buf == NULL) {
305 return -1;
306 }
307
308 buf->f_type = RAMFS_MAGIC;
309 buf->f_bsize = 0xFFFFFFFF;
310 buf->f_blocks = 0xFFFFFFFF;
311 buf->f_bfree = 0xFFFFFFFF;
312 buf->f_bavail = 0xFFFFFFFF;
313 buf->f_files = 0xFFFFFFFF;
314 buf->f_ffree = 0xFFFFFFFF;
315 buf->f_fsid = RAMFS_MAGIC;
316 buf->f_namelen = MAX_RAMFS_FILE_NAME_BYTES;
317
318 return 0;
319 }
320
ramfs_vfs_mkdir(vfs_file_t * fp,const char * path)321 static int32_t ramfs_vfs_mkdir(vfs_file_t *fp, const char *path)
322 {
323 return ramfs_mkdir(path);
324 }
325
ramfs_vfs_readdir(vfs_file_t * fp,vfs_dir_t * dir)326 static vfs_dirent_t *ramfs_vfs_readdir(vfs_file_t *fp, vfs_dir_t *dir)
327 {
328 ramfs_vfs_dir_t *dp = NULL;
329 vfs_dirent_t *ret = NULL;
330 int32_t res = -1;
331
332 dp = fp->f_arg;
333
334 if (dp->vfs_dirent.d_name != NULL) {
335 res = ramfs_readdir(&(dp->ramfs_dir), dp->vfs_dirent.d_name);
336
337 if (res == 0) {
338 ret = &dp->vfs_dirent;
339 }
340 }
341
342 return ret;
343 }
344
ramfs_vfs_pathconf(vfs_file_t * fp,const char * path,int32_t name)345 static int32_t ramfs_vfs_pathconf(vfs_file_t *fp, const char *path, int32_t name)
346 {
347 return ramfs_pathconf(name);
348 }
349
ramfs_vfs_fpathconf(vfs_file_t * fp,int32_t name)350 static int32_t ramfs_vfs_fpathconf(vfs_file_t *fp, int32_t name)
351 {
352 return ramfs_pathconf(name);
353 }
354
ramfs_vfs_utime(vfs_file_t * fp,const char * path,const vfs_utimbuf_t * times)355 static int32_t ramfs_vfs_utime(vfs_file_t *fp, const char *path, const vfs_utimbuf_t *times)
356 {
357 return RAMFS_ERR_NOT_IMP;
358 }
359
ramfs_vfs_rewinddir(vfs_file_t * fp,vfs_dir_t * dir)360 static void ramfs_vfs_rewinddir(vfs_file_t *fp, vfs_dir_t *dir)
361 {
362 ramfs_vfs_dir_t *dp = NULL;
363
364 dp = fp->f_arg;
365 dp->ramfs_dir.last_entry = NULL;
366 }
367
ramfs_vfs_rmdir(vfs_file_t * fp,const char * path)368 static int ramfs_vfs_rmdir(vfs_file_t *fp, const char *path)
369 {
370 return ramfs_rmdir(path);
371 }
372
ramfs_vfs_sync(vfs_file_t * fp)373 static int ramfs_vfs_sync(vfs_file_t *fp)
374 {
375 return 0;
376 }
377
378 vfs_filesystem_ops_t ramfs_ops = {
379 .open = &ramfs_vfs_open,
380 .close = &ramfs_vfs_close,
381 .read = &ramfs_vfs_read,
382 .write = &ramfs_vfs_write,
383 .access = &ramfs_vfs_access,
384 .lseek = &ramfs_vfs_lseek,
385 .sync = &ramfs_vfs_sync,
386 .stat = &ramfs_vfs_stat,
387 .fstat = &ramfs_vfs_fstat,
388 .statfs = &ramfs_vfs_statfs,
389 .link = &ramfs_vfs_link,
390 .unlink = &ramfs_vfs_unlink,
391 .remove = &ramfs_vfs_remove,
392 .rename = &ramfs_vfs_rename,
393 .opendir = &ramfs_vfs_opendir,
394 .readdir = &ramfs_vfs_readdir,
395 .closedir = &ramfs_vfs_closedir,
396 .mkdir = &ramfs_vfs_mkdir,
397 .seekdir = NULL,
398 .ioctl = NULL,
399 .pathconf = &ramfs_vfs_pathconf,
400 .fpathconf = &ramfs_vfs_fpathconf,
401 .utime = &ramfs_vfs_utime,
402 .rewinddir = &ramfs_vfs_rewinddir,
403 .rmdir = &ramfs_vfs_rmdir
404 };
405
ramfs_register(const char * mount_path)406 int32_t ramfs_register(const char *mount_path)
407 {
408 int32_t ret = RAMFS_ERR_NOT_IMP;
409
410 ramfs_init();
411
412 if (mount_path != NULL) {
413 ret = ramfs_mkdir(mount_path);
414
415 if (ret == 0) {
416 return vfs_register_fs(mount_path, &ramfs_ops, NULL);
417 }
418 } else {
419 ret = ramfs_mkdir(RAMFS_DEFAULT_MOUNT_PATH);
420
421 if (ret == 0) {
422 return vfs_register_fs(RAMFS_DEFAULT_MOUNT_PATH, &ramfs_ops, NULL);
423 }
424 }
425
426 return ret;
427 }
428
429
ramfs_vfs_rmdir_r(const char * path)430 static int32_t ramfs_vfs_rmdir_r(const char *path)
431 {
432 vfs_file_t fp;
433 vfs_dir_t *dir;
434 vfs_dirent_t *dirent;
435 int newpath_len;
436 char *newpath = NULL;
437 vfs_stat_t st;
438 int ret = 0;
439
440 dir = ramfs_vfs_opendir(&fp, path);
441 if(dir) {
442 newpath_len = strlen(path) + MAX_RAMFS_FILE_NAME_BYTES;
443 newpath = ramfs_mm_alloc(newpath_len);
444 if (NULL == newpath) {
445 ramfs_vfs_closedir(&fp, dir);
446 return -1;
447 }
448
449 while ((dirent = (ramfs_vfs_readdir(&fp, dir))) != NULL) {
450 if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0) {
451 continue;
452 } else {
453 memset(newpath, 0, newpath_len);
454 snprintf(newpath, newpath_len, "%s/%s", path, dirent->d_name);
455 memset(&st, 0, sizeof(vfs_stat_t));
456 if (!ramfs_vfs_stat(NULL, newpath, &st)) {
457 if (st.st_mode & S_IFDIR) {
458 ret = ramfs_vfs_rmdir_r(newpath);
459 if (ret) {
460 break;
461 }
462 ret = ramfs_vfs_rmdir(NULL, newpath);
463 if (ret) {
464 break;
465 }
466 } else if (st.st_mode & S_IFREG){
467 ramfs_unlink(newpath);
468 }
469 } else {
470 ret = -1;
471 break;
472 }
473 }
474 }
475
476 ramfs_mm_free(newpath);
477 ramfs_vfs_closedir(&fp, dir);
478
479 return ret;
480 }
481
482 return -1;
483 }
484
ramfs_unregister(const char * mount_path)485 int32_t ramfs_unregister(const char *mount_path)
486 {
487 int32_t ret;
488
489 if (NULL == mount_path) {
490 mount_path = RAMFS_DEFAULT_MOUNT_PATH;
491 }
492
493 // 1. recursively delete the files and dirs in ramfs
494 ret = ramfs_vfs_rmdir_r(mount_path);
495 if (ret) {
496 return ret;
497 }
498
499 // 2. unregister the fs from vfs
500 ret = vfs_unregister_fs(mount_path);
501 if (ret) {
502 return ret;
503 }
504
505 // 3. rm mount path
506 ret = ramfs_rmdir(mount_path);
507
508 // 4. deinit ramfs
509 ramfs_deinit();
510
511 return ret;
512 }
513
514