1 /*
2  * Copyright (C) 2015-2017 Alibaba Group Holding Limited
3  */
4 
5 #include <stdio.h>
6 #include <stddef.h>
7 #include <stdint.h>
8 
9 #include "vfs_types.h"
10 #include "vfs_conf.h"
11 
12 #include "vfs_file.h"
13 
14 static vfs_file_t g_files[VFS_MAX_FILE_NUM];
15 static uint32_t   g_opened_fd_bitmap[(VFS_MAX_FILE_NUM + 31) / 32];
16 
17 extern void vfs_inode_ref(vfs_inode_t *node);
18 extern void vfs_inode_unref(vfs_inode_t *node);
19 
vfs_fd_get(vfs_file_t * file)20 int32_t vfs_fd_get(vfs_file_t *file)
21 {
22     return (file - g_files) + VFS_FD_OFFSET;
23 }
24 
vfs_file_get_helper(int32_t fd,int explore)25 static vfs_file_t *vfs_file_get_helper(int32_t fd, int explore)
26 {
27     int32_t rfd, real_fd, real_rfd;
28     vfs_file_t *f;
29 
30     real_fd = fd - VFS_FD_OFFSET;
31 
32     if ((real_fd < 0) || (real_fd >= VFS_MAX_FILE_NUM) || (!vfs_fd_is_open(fd)))
33     {
34         return NULL;
35     }
36 
37     f = &g_files[real_fd];
38 
39     if (!explore)
40     {
41         return f;
42     }
43 
44     /* fd redirect logic */
45     rfd = f->redirect_fd;
46     real_rfd = rfd - VFS_FD_OFFSET;
47     while (real_rfd >= 0) {
48         if (real_rfd >= VFS_MAX_FILE_NUM || !vfs_fd_is_open(rfd))
49         {
50             return NULL;
51         }
52         else
53         {
54             f = &g_files[real_rfd];
55             rfd = f->redirect_fd;
56             real_rfd = rfd - VFS_FD_OFFSET;
57         }
58     }
59 
60     return f->node ? f : NULL;
61 }
62 
vfs_file_get(int32_t fd)63 vfs_file_t *vfs_file_get(int32_t fd)
64 {
65     return vfs_file_get_helper(fd, 1);
66 }
67 
vfs_file_get2(int32_t fd)68 vfs_file_t *vfs_file_get2(int32_t fd)
69 {
70     return vfs_file_get_helper(fd, 0);
71 }
72 
vfs_file_new(vfs_inode_t * node)73 vfs_file_t *vfs_file_new(vfs_inode_t *node)
74 {
75     int32_t     idx;
76     vfs_file_t *f;
77 
78     for (idx = 0; idx < VFS_MAX_FILE_NUM; idx++) {
79         f = &g_files[idx];
80 
81         if (f->node == NULL) {
82             goto got_file;
83         }
84     }
85 
86     printf("[vfs_warn]: Failed to open file, too many files open now in system!\r\n");
87     return NULL;
88 
89 got_file:
90     f->redirect_fd = -1;
91     f->node     = node;
92     f->f_arg    = NULL;
93     f->offset   = 0;
94     /* do NOT really use node if it is for redirect fd (i.e. -1 as node) */
95     if (node && node != (vfs_inode_t *)(-1))
96 	{
97 		vfs_inode_ref(node);
98 	}
99 
100     return f;
101 }
102 
vfs_file_del(vfs_file_t * file)103 void vfs_file_del(vfs_file_t *file)
104 {
105     /* do NOT really use node if it is for redirect fd (i.e. -1 as node) */
106     if (file && file->node && file->node != (vfs_inode_t *)(-1)) {
107         vfs_inode_unref(file->node);
108     }
109 
110     file->node  = NULL;
111     file->redirect_fd = -1;
112 }
113 
vfs_fd_mark_open(int32_t fd)114 int32_t vfs_fd_mark_open(int32_t fd)
115 {
116     int word, bit;
117 
118     fd -= VFS_FD_OFFSET;
119 
120     /* invalid fd */
121     if (fd < 0) {
122         return -1;
123     }
124 
125     word = fd / 32;
126     bit = fd % 32;
127 
128     if (g_opened_fd_bitmap[word] & (1 << bit))
129     {
130         /* fd has been opened */
131         return 1;
132     }
133     else
134     {
135         g_opened_fd_bitmap[word] |= (1 << bit);
136     }
137 
138     return 0;
139 }
140 
vfs_fd_mark_close(int32_t fd)141 int32_t vfs_fd_mark_close(int32_t fd)
142 {
143     int word, bit;
144 
145     fd -= VFS_FD_OFFSET;
146 
147     /* invalid fd */
148     if (fd < 0) {
149         return -1;
150     }
151 
152     word = fd / 32;
153     bit = fd % 32;
154 
155     if (g_opened_fd_bitmap[word] & (1 << bit))
156     {
157         g_opened_fd_bitmap[word] &= ~(1 << bit);
158     }
159     else
160     {
161         /* fd has been close */
162         return 1;
163     }
164 
165     return 0;
166 }
167 
vfs_fd_is_open(int32_t fd)168 int32_t vfs_fd_is_open(int32_t fd)
169 {
170     int word, bit;
171 
172     fd -= VFS_FD_OFFSET;
173 
174     /* invalid fd */
175     if (fd < 0) {
176         return -1;
177     }
178 
179     word = fd / 32;
180     bit = fd % 32;
181 
182     return g_opened_fd_bitmap[word] & (1 << bit);
183 }
184 
185