1 /*
2  * Copyright (C) 2015-2017 Alibaba Group Holding Limited
3  */
4 
5 #include <stdint.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <unistd.h>
9 
10 #include "ramfs_types.h"
11 #include "ramfs_api.h"
12 #include "ramfs_adapt.h"
13 
14 #define RAMFS_LL_NODE_META_SIZE (sizeof(ramfs_ll_node_t *) + \
15                                  sizeof(ramfs_ll_node_t *))
16 
17 #define RAMFS_LL_PREV_OFFSET(ll) (ll->size)
18 #define RAMFS_LL_NEXT_OFFSET(ll) (ll->size + sizeof(ramfs_ll_node_t *))
19 
20 #define RAMFS_LL_READ(ll, i) \
21     for (i = ramfs_ll_get_head(&ll); i != NULL; i = ramfs_ll_get_next(&ll, i))
22 #define RAMFS_LL_READ_BACK(ll, i) \
23     for (i = ramfs_ll_get_tail(&ll); i != NULL, u = ramfs_ll_get_prev(&ll, i))
24 
25 static ramfs_ll_t g_file_ll;
26 
27 static uint8_t g_inited = 0;
28 
29 /**
30  * @brief Set the previous node pointer of a node
31  *
32  * @param[in]  ll   pointer to linked list
33  * @param[out] act  pointer to a node which prev node pointer should be set
34  * @param[in]  prev pointer to the previous node before act
35  *
36  * @return None
37  */
ramfs_node_set_prev(ramfs_ll_t * ll,ramfs_ll_node_t * act,ramfs_ll_node_t * prev)38 static void ramfs_node_set_prev(ramfs_ll_t *ll, ramfs_ll_node_t *act,
39                                 ramfs_ll_node_t *prev)
40 {
41     memcpy(act + RAMFS_LL_PREV_OFFSET(ll), &prev, sizeof(ramfs_ll_node_t *));
42 }
43 
44 /**
45  * @brief Set the next node pointer of a node
46  *
47  * @param[in]  ll   pointer to linked list
48  * @param[out] act  poiner to a node which next node pointer should be set
49  * @param[in]  next poiner to the next node after act
50  *
51  * @return None
52  */
ramfs_node_set_next(ramfs_ll_t * ll,ramfs_ll_node_t * act,ramfs_ll_node_t * next)53 static void ramfs_node_set_next(ramfs_ll_t *ll, ramfs_ll_node_t *act,
54                                 ramfs_ll_node_t *next)
55 {
56     memcpy(act + RAMFS_LL_NEXT_OFFSET(ll), &next, sizeof(ramfs_ll_node_t *));
57 }
58 
59 /**
60  * @brief Initialize ramfs linked list
61  *
62  * @param[out] ll   pointer to the ramfs linked list
63  * @param[in]  size the size of 1 node in bytes
64  *
65  * @return None
66  */
ramfs_ll_init(ramfs_ll_t * ll,uint32_t size)67 static void ramfs_ll_init(ramfs_ll_t *ll, uint32_t size)
68 {
69     ll->head = NULL;
70     ll->tail = NULL;
71 
72     if (size & 0x3) {
73         size &= ~0x3;
74         size += 4;
75     }
76 
77     ll->size = size;
78 }
79 
80 /**
81  * @brief Add a new head to the linked list
82  *
83  * @param[in] ll pointer to the linked list
84  *
85  * @return pointer to the new head, NULL if no memory
86  */
ramfs_ll_ins_head(ramfs_ll_t * ll)87 static void *ramfs_ll_ins_head(ramfs_ll_t *ll)
88 {
89     ramfs_ll_node_t *new = NULL;
90 
91     new = ramfs_mm_alloc(ll->size + RAMFS_LL_NODE_META_SIZE);
92 
93     if (new != NULL) {
94         ramfs_node_set_prev(ll, new, NULL);     /* No prev before the new head */
95         ramfs_node_set_next(ll, new, ll->head); /* After new comes the old head */
96 
97         if (ll->head != NULL) { /* If there is old head then before it goes the new */
98             ramfs_node_set_prev(ll, ll->head, new);
99         }
100 
101         ll->head = new; /* Set the new head in the linked list */
102         if (ll->tail == NULL) { /* If there is no tail, set the tail too */
103             ll->tail = new;
104         }
105     }
106 
107     return new;
108 }
109 
110 /**
111  * @brief Return with head node of the linked list
112  *
113  * @param[in] ll pointer to the linked list
114  *
115  * @return pointer to the head of linked list
116  */
ramfs_ll_get_head(ramfs_ll_t * ll)117 void *ramfs_ll_get_head(ramfs_ll_t *ll)
118 {
119     void *head = NULL;
120 
121     if (ll->head != NULL) {
122         head = ll->head;
123     }
124 
125     return head;
126 }
127 
128 /**
129  * @brief Return with tail node of the linked list
130  *
131  * @param[in] ll pointer to the linked list
132  *
133  * @return pointer to the tail of linked list
134  */
ramfs_ll_get_tail(ramfs_ll_t * ll)135 void *ramfs_ll_get_tail(ramfs_ll_t *ll)
136 {
137     void *tail = NULL;
138 
139     if (ll->tail != NULL) {
140         tail = ll->tail;
141     }
142 
143     return tail;
144 }
145 
146 /**
147  * @brief Return with the pointer of the next node after act
148  *
149  * @param[in] ll  pointer to the linked list
150  * @param[in] act pointer to a node
151  *
152  * @return pointer to the next node
153  */
ramfs_ll_get_next(ramfs_ll_t * ll,void * act)154 void *ramfs_ll_get_next(ramfs_ll_t *ll, void *act)
155 {
156     void *next = NULL;
157 
158     ramfs_ll_node_t *node = act;
159 
160     if (ll != NULL) {
161         memcpy(&next, node + RAMFS_LL_NEXT_OFFSET(ll), sizeof(void *));
162     }
163 
164     return next;
165 }
166 
167 /**
168  * @brief Return with the pointer of the previous node after act
169  *
170  * @param[in] ll  pointer to the linked list
171  * @param[in] act pointer to a node
172  *
173  * @return pointer to the previous node
174  */
ramfs_ll_get_prev(ramfs_ll_t * ll,void * act)175 void *ramfs_ll_get_prev(ramfs_ll_t *ll, void *act)
176 {
177     void *prev = NULL;
178 
179     ramfs_ll_node_t *node = act;
180 
181     if (ll != NULL) {
182         memcpy(&prev, node + RAMFS_LL_PREV_OFFSET(ll), sizeof(void *));
183     }
184 
185     return prev;
186 }
187 
188 /**
189  * @brief Remove the node from linked list
190  *
191  * @param[in] ll   pointer to the linked list of node
192  * @param[in] node pointer to the node in linked list
193  *
194  * @return None
195  */
ramfs_ll_remove(ramfs_ll_t * ll,void * node)196 static void ramfs_ll_remove(ramfs_ll_t *ll, void *node)
197 {
198     ramfs_ll_node_t *prev;
199     ramfs_ll_node_t *next;
200 
201     if (ramfs_ll_get_head(ll) == node) {
202         ll->head = ramfs_ll_get_next(ll, node);
203 
204         if (ll->head == NULL) {
205             ll->tail = NULL;
206         } else {
207             ramfs_node_set_prev(ll, ll->head, NULL);
208         }
209 
210     } else if (ramfs_ll_get_tail(ll) == node) {
211         ll->tail = ramfs_ll_get_prev(ll, node);
212 
213         if (ll->tail == NULL) {
214             ll->head = NULL;
215         } else {
216             ramfs_node_set_next(ll, ll->tail, NULL);
217         }
218 
219     } else {
220         prev = ramfs_ll_get_prev(ll, node);
221         next = ramfs_ll_get_next(ll, node);
222 
223         ramfs_node_set_next(ll, prev, next);
224         ramfs_node_set_prev(ll, next, prev);
225     }
226 }
227 
228 /**
229  * @brief Search path in link
230  *
231  * @param[in] fn file name
232  *
233  * @return 0 if get path in link, RAMFS_ERR_FS if failed
234  */
ramfs_search_link(ramfs_entry_t * entry,char * path)235 static int ramfs_search_link(ramfs_entry_t *entry, char *path)
236 {
237     link_name_t *link_name = entry->link;
238 
239     while (link_name != NULL) {
240         if (strcmp(link_name->name, path) == 0) {
241             return RAMFS_OK;
242         } else {
243             link_name = link_name->next;
244         }
245     }
246 
247     return RAMFS_ERR_FS;
248 }
249 
250 /**
251  * @brief Search path in link
252  *
253  * @param[in] fn file name
254  *
255  * @return 0 if get path in link, RAMFS_ERR_FS if failed
256  */
ramfs_search_link_part(ramfs_entry_t * entry,char * path)257 static int ramfs_search_link_part(ramfs_entry_t *entry, char *path)
258 {
259     link_name_t *link_name = entry->link;
260 
261     while (link_name != NULL) {
262         if (strncmp(link_name->name, path, strlen(path)) == 0) {
263             return RAMFS_OK;
264         } else {
265             link_name = link_name->next;
266         }
267     }
268 
269     return RAMFS_ERR_FS;
270 }
271 
272 /**
273  * @brief Give the ramfs entry from a filename
274  *
275  * @param[in] fn file name
276  *
277  * @return pointer to the dynamically allocated entry with 'fn'.
278  *         NULL if no entry found with that name
279  */
ramfs_entry_get(const char * fn)280 static ramfs_entry_t *ramfs_entry_get(const char *fn)
281 {
282     ramfs_entry_t *entry;
283     int            ret = -1;
284 
285     RAMFS_LL_READ(g_file_ll, entry) {
286         if (strcmp(entry->fn, fn) == 0) {
287             return entry;
288         } else {
289             ret = ramfs_search_link(entry, (char *)fn);
290             if (ret == RAMFS_OK) {
291                 return entry;
292             }
293         }
294     }
295 
296     return NULL;
297 }
298 
299 /**
300  * @brief Create dir involved in path
301  *
302  * @param[in] fn file name
303  *
304  * @return poiner to the dynamically allocated new entry
305  *         NULL if no space for the entry
306  */
ramfs_entry_dir_new(const char * path)307 static int ramfs_entry_dir_new(const char *path)
308 {
309     int    i    = 0;
310     int    flag = 0;
311 
312     char dir_buf[RAMFS_PATH_MAX];
313 
314     ramfs_entry_t *new_entry = NULL;
315 
316     /* create dir involved in path, if path is "/ramfs/f1/f2/file1", then
317        create dir "/ramfs/f1" and "/ramfs/f1/f2" */
318     for(i = 1; i < strlen(path); i++) {
319         if (path[i] == '/') {
320             memset(dir_buf, 0, sizeof(dir_buf));
321             memcpy(dir_buf, path, i);
322 
323             flag = 0;
324             new_entry = NULL;
325 
326             /* if the same dir is found, ignore this dir */
327             RAMFS_LL_READ(g_file_ll, new_entry) {
328                 if ((strcmp(new_entry->fn, dir_buf) == 0) && (new_entry->is_dir == 1)) {
329                     flag = 1;
330                     break;
331                 }
332             }
333 
334             if (flag == 0) {
335                 new_entry = ramfs_ll_ins_head(&g_file_ll); /* Create a new file */
336                 if (new_entry == NULL) {
337                     return RAMFS_ERR_MALLOC;
338                 }
339 
340                 new_entry->fn = ramfs_mm_alloc(i + 1);
341                 memset(new_entry->fn, 0, (i + 1));
342                 strncpy(new_entry->fn, path, i);
343 
344                 new_entry->data       = NULL;
345                 new_entry->size       = 0;
346                 new_entry->refs       = 0;
347                 new_entry->const_data = 0;
348                 new_entry->is_dir     = 1;
349                 new_entry->link       = NULL;
350                 new_entry->link_count = 0;
351             }
352         }
353     }
354 
355     return RAMFS_OK;
356 }
357 
358 /**
359  * @brief Create a new entry with 'fn' file name
360  *
361  * @param[in] fn file name
362  *
363  * @return poiner to the dynamically allocated new entry
364  *         NULL if no space for the entry
365  */
ramfs_entry_new(const char * fn)366 static ramfs_entry_t *ramfs_entry_new(const char *fn)
367 {
368     ramfs_entry_t *new_entry = NULL;
369 
370     int ret = -1;
371 
372     /* create dir involved in path, if path is "/ramfs/f1/f2/file1", then
373        create dir "/ramfs/f1" and "/ramfs/f1/f2" */
374     ret = ramfs_entry_dir_new(fn);
375     if (ret != RAMFS_OK) {
376         return NULL;
377     }
378 
379     new_entry = ramfs_ll_ins_head(&g_file_ll); /* Create a new file */
380     if (new_entry == NULL) {
381         return NULL;
382     }
383 
384     new_entry->fn = ramfs_mm_alloc(strlen(fn) + 1);
385     strcpy(new_entry->fn, fn);
386 
387     new_entry->data       = NULL;
388     new_entry->size       = 0;
389     new_entry->refs       = 0;
390     new_entry->const_data = 0;
391     new_entry->is_dir     = 0;
392     new_entry->link       = NULL;
393     new_entry->link_count = 0;
394 
395     return new_entry;
396 }
397 
ramfs_init(void)398 void ramfs_init(void)
399 {
400     ramfs_ll_init(&g_file_ll, sizeof(ramfs_entry_t));
401 
402     g_inited = 1;
403 }
404 
ramfs_deinit(void)405 void ramfs_deinit(void)
406 {
407     if (g_inited) {
408         memset(&g_file_ll, 0 , sizeof(g_file_ll));
409         g_inited = 0;
410     }
411 }
412 
ramfs_ready(void)413 int32_t ramfs_ready(void)
414 {
415     return g_inited;
416 }
417 
ramfs_open(void * fp,const char * fn,uint32_t mode)418 int32_t ramfs_open(void *fp, const char* fn, uint32_t mode)
419 {
420     ramfs_file_t *file   = (ramfs_file_t *)fp;
421     ramfs_entry_t *entry = ramfs_entry_get(fn);
422 
423     file->entry = NULL;
424 
425     if ((entry != NULL) && (entry->is_dir == 1)) {
426         return RAMFS_ERR_NOT_EXIST;
427     }
428 
429     if (entry == NULL) {
430         if ((mode & RAMFS_MODE_WR) != 0) {
431             entry = ramfs_entry_new(fn);
432             if (entry == NULL) {
433                 return RAMFS_ERR_FULL;
434             }
435         } else {
436             return RAMFS_ERR_NOT_EXIST;
437         }
438 
439     }
440 
441     file->entry     = entry;
442     file->entry->ar = mode & RAMFS_MODE_RD ? 1 : 0;
443     file->entry->aw = mode & RAMFS_MODE_WR ? 1 : 0;
444     file->rwp       = 0;
445 
446     entry->refs++;
447 
448     return RAMFS_OK;
449 }
450 
ramfs_create_const(const char * fn,const void * data,uint32_t len)451 int32_t ramfs_create_const(const char *fn, const void *data, uint32_t len)
452 {
453     int32_t res;
454 
455     ramfs_file_t   file;
456     ramfs_entry_t *entry;
457 
458     res = ramfs_open(&file, fn, RAMFS_MODE_RD);
459     if (res == RAMFS_OK) {
460         ramfs_close(&file);
461         return RAMFS_ERR_DENIED;
462     }
463 
464     res = ramfs_open(&file, fn, RAMFS_MODE_WR);
465     if (res != RAMFS_OK) {
466         return res;
467     }
468 
469     entry = file.entry;
470 
471     if (entry->data != NULL) {
472         return RAMFS_ERR_DENIED;
473     }
474 
475     entry->data       = (void *)data;
476     entry->size       = len;
477     entry->const_data = 1;
478     entry->ar         = 1;
479     entry->aw         = 0;
480 
481     res = ramfs_close(&file);
482 
483     return res;
484 }
485 
ramfs_close(void * fp)486 int32_t ramfs_close(void *fp)
487 {
488     ramfs_file_t *file = (ramfs_file_t *)fp;
489 
490     if (file->entry == NULL) {
491         return RAMFS_OK;
492     }
493 
494     if (file->entry->refs > 0) {
495         file->entry->refs--;
496     }
497 
498     return RAMFS_OK;
499 }
500 
ramfs_remove(const char * fn)501 int32_t ramfs_remove(const char *fn)
502 {
503     ramfs_entry_t *entry = ramfs_entry_get(fn);
504 
505     link_name_t *link_name      = NULL;
506     link_name_t *link_name_next = NULL;
507 
508     if (entry == NULL) {
509         return RAMFS_ERR_NOT_EXIST;
510     }
511 
512     if (entry->is_dir == 1) {
513         return ramfs_rmdir(fn);
514     }
515 
516     if (entry->refs != 0) {
517         return RAMFS_ERR_DENIED;
518     }
519 
520     ramfs_ll_remove(&g_file_ll, entry);
521     ramfs_mm_free(entry->fn);
522     entry->fn = NULL;
523 
524     link_name = entry->link;
525     while(link_name != NULL) {
526         link_name_next = link_name->next;
527         ramfs_mm_free(link_name->name);
528         ramfs_mm_free(link_name);
529         link_name = link_name_next;
530     }
531 
532     if (entry->const_data == 0) {
533         ramfs_mm_free(entry->data);
534         entry->data = NULL;
535     }
536 
537     ramfs_mm_free(entry);
538 
539     return RAMFS_OK;
540 }
541 
ramfs_rename(const char * old,const char * new)542 int32_t ramfs_rename(const char *old, const char *new)
543 {
544     ramfs_entry_t *entry = NULL;
545 
546     entry = ramfs_entry_get(new);
547     if (entry != NULL) {
548         return RAMFS_ERR_PATH;
549     }
550 
551     entry = ramfs_entry_get(old);
552     if (entry == NULL) {
553         return RAMFS_ERR_NOT_EXIST;
554     }
555 
556     if ((entry != NULL) && (entry->is_dir == 1)) {
557         return RAMFS_ERR_PATH;
558     }
559 
560     /* rename linked name is not supported */
561     if (strcmp(entry->fn, old) != 0) {
562         return RAMFS_ERR_NOT_IMP;
563     }
564 
565     entry->fn = ramfs_mm_realloc(entry->fn, strlen(new) + 1);
566     if (entry->fn == NULL) {
567         return RAMFS_ERR_MALLOC;
568     }
569     memset(entry->fn, 0 , strlen(new) + 1);
570     strncpy(entry->fn, new, strlen(new));
571 
572     return RAMFS_OK;
573 }
574 
ramfs_read(void * fp,void * buf,uint32_t btr,uint32_t * br)575 int32_t ramfs_read(void *fp, void *buf, uint32_t btr, uint32_t *br)
576 {
577     uint8_t       *data;
578     ramfs_file_t  *file;
579     ramfs_entry_t *entry;
580 
581     file  = (ramfs_file_t *)fp;
582     entry = file->entry;
583     *br   = 0;
584 
585     if (entry->data == NULL || entry->size == 0) {
586         return RAMFS_OK;
587     } else if (entry->ar == 0) {
588         return RAMFS_ERR_DENIED;
589     }
590 
591     if (file->rwp + btr > entry->size) {
592         *br = entry->size - file->rwp;
593     } else {
594         *br = btr;
595     }
596 
597     if (entry->const_data == 0) {
598         data = (uint8_t *)entry->data;
599     } else {
600         data = entry->data;
601     }
602 
603     data += file->rwp;
604     memcpy(buf, data, *br);
605 
606     file->rwp += *br;
607 
608     return RAMFS_OK;
609 }
610 
ramfs_write(void * fp,const void * buf,uint32_t btw,uint32_t * bw)611 int32_t ramfs_write(void *fp, const void *buf, uint32_t btw, uint32_t *bw)
612 {
613     uint32_t  new_size;
614     uint8_t  *new_data;
615     uint8_t  *rwp;
616 
617     ramfs_file_t  *file;
618     ramfs_entry_t *entry;
619 
620     file  = (ramfs_file_t *)fp;
621     entry = file->entry;
622     *bw   = 0;
623 
624     if (entry->aw == 0) {
625         return RAMFS_ERR_DENIED;
626     }
627 
628     new_size = file->rwp + btw;
629     if (new_size > entry->size) {
630         new_data = ramfs_mm_realloc(entry->data, new_size);
631         if (new_data == NULL) {
632             return RAMFS_ERR_FULL;
633         }
634 
635         entry->data = new_data;
636         entry->size = new_size;
637     }
638 
639     rwp = (uint8_t *)entry->data;
640     rwp += file->rwp;
641 
642     memcpy(rwp, buf, btw);
643     *bw = btw;
644     file->rwp += *bw;
645 
646     return RAMFS_OK;
647 }
648 
ramfs_seek(void * fp,uint32_t pos)649 int32_t ramfs_seek(void *fp, uint32_t pos)
650 {
651     uint8_t *new_data;
652 
653     ramfs_file_t  *file;
654     ramfs_entry_t *entry;
655 
656     file  = (ramfs_file_t *)fp;
657     entry = file->entry;
658 
659     if (pos < entry->size) {
660         file->rwp = pos;
661     } else {
662         if (entry->aw == 0) {
663             return RAMFS_ERR_DENIED;
664         }
665 
666         new_data = ramfs_mm_realloc(entry->data, pos);
667         if (new_data == NULL) {
668             return RAMFS_ERR_FULL;
669         }
670 
671         entry->data = new_data;
672         entry->size = pos;
673         file->rwp   = pos;
674     }
675 
676     return RAMFS_OK;
677 }
678 
ramfs_tell(void * fp,uint32_t * pos)679 int32_t ramfs_tell(void *fp, uint32_t *pos)
680 {
681     *pos = ((ramfs_file_t *)fp)->rwp;
682 
683     return RAMFS_OK;
684 }
685 
ramfs_trunc(void * fp)686 int32_t ramfs_trunc(void *fp)
687 {
688     void *new_data;
689 
690     ramfs_file_t  *file;
691     ramfs_entry_t *entry;
692 
693     file  = (ramfs_file_t *)fp;
694     entry = file->entry;
695 
696     if (entry->aw == 0) {
697         return RAMFS_ERR_DENIED;
698     }
699 
700     new_data = ramfs_mm_realloc(entry->data, file->rwp);
701     if (new_data == NULL) {
702         return RAMFS_ERR_FULL;
703     }
704 
705     entry->data = new_data;
706     entry->size = file->rwp;
707 
708     return RAMFS_OK;
709 }
710 
ramfs_size(void * fp,uint32_t * size)711 int32_t ramfs_size(void *fp, uint32_t *size)
712 {
713     *size = ((ramfs_file_t *)fp)->entry->size;
714 
715     return RAMFS_OK;
716 }
717 
ramfs_access(const char * path,int32_t mode)718 int32_t ramfs_access(const char *path, int32_t mode)
719 {
720     ramfs_entry_t *entry = ramfs_entry_get(path);
721 
722     if (mode == F_OK) {
723         if (entry == NULL) {
724             return RAMFS_ERR_DENIED;
725         } else {
726             return RAMFS_OK;
727         }
728     }
729 
730     if (mode == R_OK) {
731         if (entry == NULL) {
732             return RAMFS_OK;
733         } else {
734             if (entry->ar == 1) {
735                 return RAMFS_OK;
736             } else {
737                 return RAMFS_ERR_DENIED;
738             }
739         }
740     }
741 
742     if (mode == W_OK) {
743         if (entry == NULL) {
744             return RAMFS_OK;
745         } else {
746             if (entry->aw == 1) {
747                 return RAMFS_OK;
748             } else {
749                 return RAMFS_ERR_DENIED;
750             }
751         }
752     }
753 
754     if (mode == X_OK) {
755         return RAMFS_OK;
756     }
757 
758     return RAMFS_ERR_DENIED;
759 }
760 
ramfs_mkdir(const char * path)761 int32_t ramfs_mkdir(const char *path)
762 {
763     ramfs_entry_t *entry = ramfs_entry_get(path);
764 
765     if ((entry != NULL) && (entry->is_dir == 1)) {
766         return RAMFS_ERR_EXIST;
767     }
768 
769     entry = ramfs_entry_new(path);
770     if (entry == NULL) {
771         return RAMFS_ERR_FULL;
772     }
773 
774     entry->is_dir = 1;
775 
776     return RAMFS_OK;
777 }
778 
ramfs_opendir(void * dp,const char * path)779 int32_t ramfs_opendir(void *dp, const char *path)
780 {
781     ramfs_dir_t   *ramfs_dp;
782     ramfs_entry_t *entry;
783 
784     ramfs_dp = (ramfs_dir_t *)dp;
785     entry = ramfs_entry_get(path);
786 
787     if (entry == NULL) {
788         return RAMFS_ERR_NOT_EXIST;
789     }
790 
791     if (entry->is_dir != 1) {
792         entry = ramfs_entry_get(path);
793         if (entry == NULL) {
794             return RAMFS_ERR_NOT_EXIST;
795         }
796 
797         if (entry->is_dir != 1) {
798             return RAMFS_ERR_NOT_EXIST;
799         }
800     }
801 
802     ramfs_dp->dir_name = ramfs_mm_alloc(strlen(path) + 1);
803 
804     if (ramfs_dp->dir_name == NULL) {
805         return RAMFS_ERR_FULL;
806     }
807     memset(ramfs_dp->dir_name, 0 ,strlen(path) + 1);
808 
809     strncpy(ramfs_dp->dir_name, path, strlen(path));
810     ramfs_dp->last_entry = NULL;
811 
812     return RAMFS_OK;
813 }
814 
ramfs_readdir(void * dp,char * fn)815 int32_t ramfs_readdir(void *dp, char *fn)
816 {
817     int i      = 0;
818     int len    = 0;
819     int search = 1;
820 
821     char *name = NULL;
822     char *data = NULL;
823 
824     ramfs_dir_t *ramfs_dp = (ramfs_dir_t *)dp;
825 
826     if (ramfs_dp->last_entry == NULL) {
827         ramfs_dp->last_entry = ramfs_ll_get_head(&g_file_ll);
828     }
829 
830     while ((search == 1) && (ramfs_dp->last_entry != NULL)) {
831         if ((strncmp(ramfs_dp->dir_name, ramfs_dp->last_entry->fn, strlen(ramfs_dp->dir_name)) == 0)
832           &&(*(ramfs_dp->last_entry->fn + strlen(ramfs_dp->dir_name)) != '\0')) {
833             name = ramfs_dp->last_entry->fn + strlen(ramfs_dp->dir_name) + 1;
834             data = name;
835             len  = strlen(ramfs_dp->last_entry->fn) - strlen(ramfs_dp->dir_name);
836 
837             search = 0;
838 
839             for (i = 0; i < len; i++) {
840                 if (*name == '/') {
841                     search = 1;
842                     break;
843                 }
844                 name++;
845             }
846         }
847 
848         ramfs_dp->last_entry = ramfs_ll_get_next(&g_file_ll, ramfs_dp->last_entry);
849     }
850 
851     if (ramfs_dp->last_entry != NULL) {
852         strncpy(fn, data, strlen(data));
853         fn[strlen(data)] = '\0';
854     } else {
855         return RAMFS_ERR_NOT_EXIST;
856     }
857 
858     return RAMFS_OK;
859 }
860 
ramfs_closedir(void * dp)861 int32_t ramfs_closedir(void *dp)
862 {
863     ramfs_dir_t *ramfs_dp = (ramfs_dir_t *)dp;
864 
865     if (ramfs_dp->dir_name != NULL) {
866         ramfs_mm_free(ramfs_dp->dir_name);
867     }
868 
869     return RAMFS_OK;
870 }
871 
ramfs_rmdir(const char * path)872 int32_t ramfs_rmdir(const char *path)
873 {
874     ramfs_entry_t *entry;
875     int            ret = -1;
876     int flag = 0;
877 
878     /* if file existed in the dir return error ! */
879     RAMFS_LL_READ(g_file_ll, entry) {
880         if ((strncmp(entry->fn, path, strlen(path)) == 0)
881             && (*(char*)(entry->fn + strlen(path)) == '/')) {
882             flag = 1;
883             break;
884         } else {
885             ret = ramfs_search_link_part(entry, (char *)path);
886             if (ret == RAMFS_OK) {
887                 flag = 1;
888                 break;
889             }
890         }
891     }
892 
893     if (flag == 1) {
894         return RAMFS_ERR_DENIED;
895     }
896 
897     /* if no file existed in the dir remove the dir ! */
898     RAMFS_LL_READ(g_file_ll, entry) {
899         if ((strncmp(entry->fn, path, strlen(path)) == 0) && (entry->is_dir == 1)) {
900             ramfs_ll_remove(&g_file_ll, entry);
901             ramfs_mm_free(entry->fn);
902             entry->fn = NULL;
903             ramfs_mm_free(entry);
904         }
905     }
906 
907     return RAMFS_OK;
908 }
909 
ramfs_stat(const char * path,ramfs_stat_t * st)910 int32_t ramfs_stat(const char *path, ramfs_stat_t *st)
911 {
912     ramfs_entry_t *entry = ramfs_entry_get(path);
913 
914     if (st == NULL) {
915         return RAMFS_ERR_INV_PARAM;
916     }
917 
918     if (entry != NULL) {
919         st->st_size = entry->size;
920 
921         if (entry->ar == 1) {
922             st->st_mode |= RAMFS_MODE_RD;
923         }
924 
925         if (entry->aw == 1) {
926             st->st_mode |= RAMFS_MODE_WR;
927         }
928 
929         if (entry->is_dir == 1) {
930             st->is_dir = 1;
931         }
932 
933     } else {
934         return RAMFS_ERR_NOT_EXIST;
935     }
936 
937     return RAMFS_OK;
938 }
939 
ramfs_add_link(ramfs_entry_t * entry,char * path)940 int ramfs_add_link(ramfs_entry_t *entry, char *path)
941 {
942     link_name_t *link_name   = entry->link;
943     link_name_t *link_name_c = NULL;
944 
945     link_name_c = ramfs_mm_alloc(sizeof(link_name_t));
946 
947     if (link_name_c != NULL) {
948         link_name_c->name = ramfs_mm_alloc(strlen(path) + 1);
949         if (link_name_c->name != NULL) {
950             memset(link_name_c->name, 0, strlen(path) + 1);
951             strncpy(link_name_c->name, path, strlen(path));
952             link_name_c->next = NULL;
953             entry->link_count += 1;
954         } else {
955             ramfs_mm_free(link_name_c);
956             return RAMFS_ERR_MALLOC;
957         }
958     } else {
959         return RAMFS_ERR_MALLOC;
960     }
961 
962     if (link_name == NULL) {
963         entry->link = link_name_c;
964     } else {
965         while (link_name->next != NULL) {
966             link_name = link_name->next;
967         }
968 
969         link_name->next = link_name_c;
970     }
971 
972     return 0;
973 }
974 
ramfs_remove_link(ramfs_entry_t * entry,char * path)975 int ramfs_remove_link(ramfs_entry_t *entry, char *path)
976 {
977     link_name_t *link_name   = entry->link;
978     link_name_t *link_name_c = NULL;
979     link_name_t *link_name_l = NULL;
980 
981     if (link_name == NULL) {
982          return RAMFS_ERR_INV_PARAM;
983     }
984 
985     if (strncmp(link_name->name, path, strlen(path)) == 0) {
986         ramfs_mm_free(link_name->name);
987         link_name->name = ramfs_mm_alloc(strlen(link_name->next->name) + 1);
988         if (link_name->name == NULL) {
989             return RAMFS_ERR_MALLOC;
990         }
991         memset(link_name->name, 0 , strlen(link_name->next->name) + 1);
992         strncpy(link_name->name, link_name->next->name, strlen(link_name->next->name));
993         link_name->next = link_name->next->next;
994         entry->link_count -= 1;
995     } else {
996         link_name_l = link_name;
997         link_name_c = link_name->next;
998 
999         while (link_name_c != NULL) {
1000             if (strncmp(link_name_c->name, path, strlen(path)) == 0) {
1001                 link_name_l->next = link_name_c->next;
1002                 ramfs_mm_free(link_name_c->name);
1003                 ramfs_mm_free(link_name_c);
1004                 entry->link_count -= 1;
1005             }
1006 
1007             link_name_l = link_name_c;
1008             link_name_c = link_name_c->next;
1009         }
1010     }
1011 
1012     return 0;
1013 }
1014 
ramfs_link(const char * path1,const char * path2)1015 int ramfs_link(const char *path1, const char *path2)
1016 {
1017     ramfs_entry_t *entry = NULL;
1018     int            ret = -1;
1019 
1020     entry = ramfs_entry_get(path2);
1021     if (entry != NULL) {
1022         return RAMFS_ERR_PATH;
1023     }
1024 
1025     entry = ramfs_entry_get(path1);
1026     if (entry == NULL) {
1027         return RAMFS_ERR_NOT_EXIST;
1028     }
1029 
1030     if ((entry != NULL) && (entry->is_dir == 1)) {
1031         return RAMFS_ERR_PATH;
1032     }
1033 
1034     if (entry->link_count >= RAMFS_LINK_MAX) {
1035         return RAMFS_ERR_LINK_MAX;
1036     }
1037 
1038     ret = ramfs_add_link(entry, (char *)path2);
1039     if (ret != 0) {
1040         return RAMFS_ERR_MALLOC;
1041     }
1042 
1043     return 0;
1044 }
1045 
ramfs_unlink(const char * path)1046 int ramfs_unlink(const char *path)
1047 {
1048     ramfs_entry_t *entry = NULL;
1049     int            ret = -1;
1050 
1051     entry = ramfs_entry_get(path);
1052     if (entry == NULL) {
1053         return RAMFS_ERR_PATH;
1054     }
1055 
1056     if (strncmp(entry->fn, path, strlen(path)) == 0) {
1057         ret = ramfs_remove(path);
1058     } else {
1059         ret = ramfs_remove_link(entry, (char *)path);
1060     }
1061 
1062     return ret;
1063 }
1064 
ramfs_pathconf(int32_t name)1065 int32_t ramfs_pathconf(int32_t name)
1066 {
1067     int32_t val = 0;
1068 
1069     switch (name) {
1070         case _PC_FILESIZEBITS :
1071             val = -1;
1072             break;
1073         case _PC_LINK_MAX :
1074             val = RAMFS_LINK_MAX;
1075             break;
1076         case _PC_MAX_CANON :
1077             val = -1;
1078             break;
1079         case _PC_MAX_INPUT :
1080             val = -1;
1081             break;
1082         case _PC_NAME_MAX :
1083             val = RAMFS_NAME_MAX;
1084             break;
1085         case _PC_PATH_MAX :
1086             val = RAMFS_PATH_MAX;
1087             break;
1088         case _PC_PIPE_BUF :
1089             val = -1;
1090             break;
1091         case _PC_2_SYMLINKS :
1092             val = -1;
1093             break;
1094         case _PC_ALLOC_SIZE_MIN :
1095             val = RAMFS_ALLOC_SIZE_MIN;
1096             break;
1097         case _PC_REC_INCR_XFER_SIZE :
1098             val = -1;
1099             break;
1100         case _PC_REC_MAX_XFER_SIZE :
1101             val = -1;
1102             break;
1103         case _PC_REC_MIN_XFER_SIZE :
1104             val = -1;
1105             break;
1106         case _PC_REC_XFER_ALIGN :
1107             val = -1;
1108             break;
1109         case _PC_SYMLINK_MAX :
1110             val = -1;
1111             break;
1112         case _PC_CHOWN_RESTRICTED :
1113             val = -1;
1114             break;
1115         case _PC_NO_TRUNC :
1116             val = -1;
1117             break;
1118         case _PC_VDISABLE :
1119             val = -1;
1120             break;
1121         case _PC_ASYNC_IO :
1122             val = -1;
1123             break;
1124         case _PC_PRIO_IO :
1125             val = -1;
1126             break;
1127         case _PC_SYNC_IO :
1128             val = -1;
1129             break;
1130         default:
1131             val = -1;
1132             break;
1133     }
1134 
1135     return val;
1136 }
1137