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