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