PatchworkOS  19e446b
A non-POSIX operating system.
Loading...
Searching...
No Matches
file_table.c
Go to the documentation of this file.
2
3#include <kernel/fs/path.h>
6
7#include <sys/bitmap.h>
8
10{
11 for (uint64_t i = 0; i < CONFIG_MAX_FD; i++)
12 {
13 table->files[i] = NULL;
14 }
15 BITMAP_DEFINE_INIT(table->bitmap, CONFIG_MAX_FD);
16 lock_init(&table->lock);
17}
18
20{
21 LOCK_SCOPE(&table->lock);
22
23 for (uint64_t i = 0; i < CONFIG_MAX_FD; i++)
24 {
25 if (table->files[i] != NULL)
26 {
27 UNREF(table->files[i]);
28 table->files[i] = NULL;
29 }
30 }
31}
32
34{
35 if (table == NULL)
36 {
37 errno = EINVAL;
38 return NULL;
39 }
40
41 LOCK_SCOPE(&table->lock);
42
43 if (fd >= CONFIG_MAX_FD || table->files[fd] == NULL)
44 {
45 errno = EBADF;
46 return NULL;
47 }
48
49 return REF(table->files[fd]);
50}
51
53{
54 if (table == NULL || file == NULL)
55 {
56 errno = EINVAL;
57 return ERR;
58 }
59
60 LOCK_SCOPE(&table->lock);
61
62 uint64_t index = bitmap_find_first_clear(&table->bitmap, 0, CONFIG_MAX_FD);
63 if (index >= CONFIG_MAX_FD)
64 {
65 errno = EMFILE;
66 return ERR;
67 }
68
69 table->files[index] = REF(file);
70 bitmap_set(&table->bitmap, index);
71 return (fd_t)index;
72}
73
75{
76 if (table == NULL)
77 {
78 errno = EINVAL;
79 return ERR;
80 }
81
82 LOCK_SCOPE(&table->lock);
83
84 if (fd >= CONFIG_MAX_FD || table->files[fd] == NULL)
85 {
86 errno = EBADF;
87 return ERR;
88 }
89
90 UNREF(table->files[fd]);
91 table->files[fd] = NULL;
92 bitmap_clear(&table->bitmap, fd);
93 return 0;
94}
95
97{
98 if (table == NULL)
99 {
100 return;
101 }
102
103 LOCK_SCOPE(&table->lock);
104
105 for (uint64_t i = 0; i < CONFIG_MAX_FD; i++)
106 {
107 if (table->files[i] != NULL)
108 {
109 UNREF(table->files[i]);
110 table->files[i] = NULL;
111 bitmap_clear(&table->bitmap, i);
112 }
113 }
114}
115
117{
118 if (table == NULL)
119 {
120 return;
121 }
122
123 LOCK_SCOPE(&table->lock);
124
125 for (uint64_t i = 0; i < CONFIG_MAX_FD; i++)
126 {
127 if (table->files[i] != NULL && (table->files[i]->mode & mode))
128 {
129 UNREF(table->files[i]);
130 table->files[i] = NULL;
131 bitmap_clear(&table->bitmap, i);
132 }
133 }
134}
135
137{
138 if (table == NULL)
139 {
140 errno = EINVAL;
141 return ERR;
142 }
143
144 LOCK_SCOPE(&table->lock);
145
146 for (fd_t fd = min; fd < max && fd < CONFIG_MAX_FD; fd++)
147 {
148 if (table->files[fd] != NULL)
149 {
150 UNREF(table->files[fd]);
151 table->files[fd] = NULL;
152 bitmap_clear(&table->bitmap, fd);
153 }
154 }
155
156 return 0;
157}
158
160{
161 if (table == NULL || file == NULL)
162 {
163 errno = EINVAL;
164 return ERR;
165 }
166
167 LOCK_SCOPE(&table->lock);
168
169 if (fd >= CONFIG_MAX_FD)
170 {
171 errno = EBADF;
172 return ERR;
173 }
174
175 if (table->files[fd] != NULL)
176 {
177 UNREF(table->files[fd]);
178 table->files[fd] = NULL;
179 }
180
181 table->files[fd] = REF(file);
182 bitmap_set(&table->bitmap, fd);
183 return fd;
184}
185
187{
188 if (table == NULL)
189 {
190 errno = EINVAL;
191 return ERR;
192 }
193
194 LOCK_SCOPE(&table->lock);
195
196 if (oldFd >= CONFIG_MAX_FD || table->files[oldFd] == NULL)
197 {
198 errno = EBADF;
199 return ERR;
200 }
201
202 uint64_t index = bitmap_find_first_clear(&table->bitmap, 0, CONFIG_MAX_FD);
203 if (index >= CONFIG_MAX_FD)
204 {
205 errno = EMFILE;
206 return ERR;
207 }
208
209 table->files[index] = REF(table->files[oldFd]);
210 bitmap_set(&table->bitmap, index);
211 return (fd_t)index;
212}
213
215{
216 if (table == NULL)
217 {
218 errno = EINVAL;
219 return ERR;
220 }
221
222 LOCK_SCOPE(&table->lock);
223
224 if (oldFd >= CONFIG_MAX_FD || newFd >= CONFIG_MAX_FD || table->files[oldFd] == NULL)
225 {
226 errno = EBADF;
227 return ERR;
228 }
229
230 if (oldFd == newFd)
231 {
232 return newFd;
233 }
234
235 if (table->files[newFd] != NULL)
236 {
237 UNREF(table->files[newFd]);
238 table->files[newFd] = NULL;
239 }
240
241 table->files[newFd] = REF(table->files[oldFd]);
242 bitmap_set(&table->bitmap, newFd);
243 return newFd;
244}
245
247{
248 if (dest == NULL || src == NULL)
249 {
250 errno = EINVAL;
251 return ERR;
252 }
253
254 LOCK_SCOPE(&src->lock);
255 LOCK_SCOPE(&dest->lock);
256
257 for (fd_t i = min; i < max && i < CONFIG_MAX_FD; i++)
258 {
259 if (src->files[i] == NULL)
260 {
261 continue;
262 }
263
264 if (dest->files[i] != NULL)
265 {
266 UNREF(dest->files[i]);
267 dest->files[i] = NULL;
268 }
269
270 dest->files[i] = REF(src->files[i]);
271 bitmap_set(&dest->bitmap, i);
272 }
273
274 return 0;
275}
276
278{
279 return file_table_close(&process_current()->fileTable, fd);
280}
281
283{
284 return file_table_dup(&process_current()->fileTable, oldFd);
285}
286
288{
289 return file_table_dup2(&process_current()->fileTable, oldFd, newFd);
290}
#define CONFIG_MAX_FD
Maximum file descriptor configuration.
Definition config.h:51
#define SYSCALL_DEFINE(num, returnType,...)
Macro to define a syscall.
Definition syscall.h:172
@ SYS_CLOSE
Definition syscall.h:76
@ SYS_DUP
Definition syscall.h:89
@ SYS_DUP2
Definition syscall.h:90
fd_t file_table_dup2(file_table_t *table, fd_t oldFd, fd_t newFd)
Duplicate a file descriptor to a specific file descriptor.
Definition file_table.c:214
uint64_t file_table_close(file_table_t *table, fd_t fd)
Free a file descriptor.
Definition file_table.c:74
file_t * file_table_get(file_table_t *table, fd_t fd)
Get a file from its file descriptor.
Definition file_table.c:33
void file_table_close_mode(file_table_t *table, mode_t mode)
Close all files in the file table with the specified mode.
Definition file_table.c:116
uint64_t file_table_close_range(file_table_t *table, fd_t min, fd_t max)
Free a range of file descriptors.
Definition file_table.c:136
fd_t file_table_open(file_table_t *table, file_t *file)
Allocate a new file descriptor for a file.
Definition file_table.c:52
uint64_t file_table_copy(file_table_t *dest, file_table_t *src, fd_t min, fd_t max)
Copy a file table, closing any overlapping file descriptors.
Definition file_table.c:246
void file_table_close_all(file_table_t *table)
Close all files in the file table.
Definition file_table.c:96
void file_table_init(file_table_t *table)
Initialize a file table.
Definition file_table.c:9
fd_t file_table_set(file_table_t *table, fd_t fd, file_t *file)
Set a specific file descriptor to a file.
Definition file_table.c:159
void file_table_deinit(file_table_t *table)
Deinitialize a file table.
Definition file_table.c:19
fd_t file_table_dup(file_table_t *table, fd_t oldFd)
Duplicate a file descriptor.
Definition file_table.c:186
mode_t
Path flags and permissions.
Definition path.h:79
static process_t * process_current(void)
Retrieves the process of the currently running thread.
Definition process.h:131
static void lock_init(lock_t *lock)
Initializes a lock.
Definition lock.h:79
#define LOCK_SCOPE(lock)
Acquires a lock for the reminder of the current scope.
Definition lock.h:58
#define REF(ptr)
Increment reference count.
Definition ref.h:82
#define UNREF(ptr)
Decrement reference count.
Definition ref.h:109
#define EINVAL
Invalid argument.
Definition errno.h:142
#define EMFILE
Too many open files.
Definition errno.h:152
#define errno
Error number variable.
Definition errno.h:27
#define EBADF
Bad file number.
Definition errno.h:77
static uint64_t bitmap_find_first_clear(bitmap_t *map, uint64_t startIdx, uint64_t endIdx)
Find the first clear bit in the bitmap.
Definition bitmap.h:306
static void bitmap_clear(bitmap_t *map, uint64_t index)
Clear a bit in the bitmap.
Definition bitmap.h:244
static void bitmap_set(bitmap_t *map, uint64_t index)
Set a bit in the bitmap.
Definition bitmap.h:190
#define BITMAP_DEFINE_INIT(name, bits)
Initialize a bitmap defined with BITMAP_DEFINE.
Definition bitmap.h:117
#define NULL
Pointer error value.
Definition NULL.h:25
#define ERR
Integer error value.
Definition ERR.h:17
__UINT64_TYPE__ fd_t
File descriptor type.
Definition fd_t.h:10
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
File structure.
Definition file.h:39
mode_t mode
Definition file.h:42
File table structure.
Definition file_table.h:24
file_t * files[CONFIG_MAX_FD]
Definition file_table.h:25
lock_t lock
Definition file_table.h:27