PatchworkOS
Loading...
Searching...
No Matches
vfs_ctx.c
Go to the documentation of this file.
1#include <kernel/fs/vfs_ctx.h>
2
3#include <kernel/fs/vfs.h>
4#include <kernel/log/log.h>
6
7#include <assert.h>
8#include <string.h>
9#include <sys/io.h>
10
11void vfs_ctx_init(vfs_ctx_t* ctx, const path_t* cwd)
12{
13 ctx->cwd = PATH_EMPTY;
14
15 if (cwd != NULL)
16 {
17 path_copy(&ctx->cwd, cwd);
18 }
19
20 for (uint64_t i = 0; i < CONFIG_MAX_FD; i++)
21 {
22 ctx->files[i] = NULL;
23 }
25 memset(ctx->allocBitmapBuffer, 0, sizeof(ctx->allocBitmapBuffer));
26 lock_init(&ctx->lock);
27 ctx->initalized = true;
28}
29
31{
32 LOCK_SCOPE(&ctx->lock);
33
34 path_put(&ctx->cwd);
35
36 for (uint64_t i = 0; i < CONFIG_MAX_FD; i++)
37 {
38 if (ctx->files[i] != NULL)
39 {
40 DEREF(ctx->files[i]);
41 ctx->files[i] = NULL;
42 }
43 }
44
45 ctx->initalized = false;
46}
47
49{
50 LOCK_SCOPE(&ctx->lock);
51
52 if (!ctx->initalized)
53 {
54 errno = EBUSY;
55 return NULL;
56 }
57
58 if (fd >= CONFIG_MAX_FD || ctx->files[fd] == NULL)
59 {
60 errno = EBADF;
61 return NULL;
62 }
63
64 return REF(ctx->files[fd]);
65}
66
68{
69 LOCK_SCOPE(&ctx->lock);
70
71 if (!ctx->initalized)
72 {
73 errno = EBUSY;
74 return ERR;
75 }
76
77 if (ctx->cwd.dentry == NULL || ctx->cwd.mount == NULL)
78 {
79 assert(ctx->cwd.dentry == NULL && ctx->cwd.mount == NULL);
80 namespace_t* kernelNs = &process_get_kernel()->namespace;
81
82 if (namespace_get_root_path(kernelNs, outCwd) == ERR)
83 {
84 return ERR;
85 }
86 return 0;
87 }
88
89 path_copy(outCwd, &ctx->cwd);
90 return 0;
91}
92
94{
95 LOCK_SCOPE(&ctx->lock);
96
97 if (!ctx->initalized)
98 {
99 errno = EBUSY;
100 return ERR;
101 }
102
103 if (cwd == NULL || cwd->dentry == NULL || cwd->dentry->inode == NULL)
104 {
105 errno = EINVAL;
106 return ERR;
107 }
108
109 if (cwd->dentry->inode->type != INODE_DIR)
110 {
111 errno = ENOTDIR;
112 return ERR;
113 }
114
115 path_put(&ctx->cwd);
116 path_copy(&ctx->cwd, cwd);
117
118 return 0;
119}
120
121SYSCALL_DEFINE(SYS_CHDIR, uint64_t, const char* pathString)
122{
123 thread_t* thread = sched_thread();
124 process_t* process = thread->process;
125
126 pathname_t pathname;
127 if (thread_copy_from_user_pathname(thread, &pathname, pathString) == ERR)
128 {
129 return ERR;
130 }
131
132 path_t path = PATH_EMPTY;
133 if (vfs_walk(&path, &pathname, WALK_NONE, process) == ERR)
134 {
135 return ERR;
136 }
137 PATH_DEFER(&path);
138
139 return vfs_ctx_set_cwd(&process->vfsCtx, &path);
140}
141
143{
144 LOCK_SCOPE(&ctx->lock);
145
146 if (!ctx->initalized)
147 {
148 errno = EBUSY;
149 return ERR;
150 }
151
153 if (index < CONFIG_MAX_FD)
154 {
155 ctx->files[index] = REF(file);
156 bitmap_set(&ctx->allocBitmap, index);
157 return (fd_t)index;
158 }
159
160 errno = EMFILE;
161 return ERR;
162}
163
165{
166 LOCK_SCOPE(&ctx->lock);
167
168 if (!ctx->initalized)
169 {
170 errno = EBUSY;
171 return ERR;
172 }
173
174 if (fd >= CONFIG_MAX_FD)
175 {
176 errno = EINVAL;
177 return ERR;
178 }
179
180 if (ctx->files[fd] != NULL)
181 {
182 DEREF(ctx->files[fd]);
183 ctx->files[fd] = NULL;
184 }
185
186 ctx->files[fd] = REF(file);
187 bitmap_set(&ctx->allocBitmap, fd);
188 return fd;
189}
190
192{
193 LOCK_SCOPE(&ctx->lock);
194
195 if (!ctx->initalized)
196 {
197 errno = EBUSY;
198 return ERR;
199 }
200
201 if (fd >= CONFIG_MAX_FD || ctx->files[fd] == NULL)
202 {
203 errno = EBADF;
204 return ERR;
205 }
206
207 DEREF(ctx->files[fd]);
208 ctx->files[fd] = NULL;
209 bitmap_clear(&ctx->allocBitmap, fd);
210 return 0;
211}
212
214{
215 return vfs_ctx_free_fd(&sched_process()->vfsCtx, fd);
216}
217
219{
220 LOCK_SCOPE(&ctx->lock);
221
222 if (!ctx->initalized)
223 {
224 errno = EBUSY;
225 return ERR;
226 }
227
228 if (oldFd >= CONFIG_MAX_FD || ctx->files[oldFd] == NULL)
229 {
230 errno = EBADF;
231 return ERR;
232 }
233
235 if (index < CONFIG_MAX_FD)
236 {
237 ctx->files[index] = REF(ctx->files[oldFd]);
238 bitmap_set(&ctx->allocBitmap, index);
239 return (fd_t)index;
240 }
241
242 errno = EMFILE;
243 return ERR;
244}
245
247{
248 return vfs_ctx_dup(&sched_process()->vfsCtx, oldFd);
249}
250
252{
253 if (oldFd == newFd)
254 {
255 return newFd;
256 }
257
258 LOCK_SCOPE(&ctx->lock);
259
260 if (!ctx->initalized)
261 {
262 errno = EBUSY;
263 return ERR;
264 }
265
266 if (oldFd >= CONFIG_MAX_FD || newFd >= CONFIG_MAX_FD || ctx->files[oldFd] == NULL)
267 {
268 errno = EBADF;
269 return ERR;
270 }
271
272 if (ctx->files[newFd] != NULL)
273 {
274 DEREF(ctx->files[newFd]);
275 ctx->files[newFd] = NULL;
276 }
277
278 ctx->files[newFd] = REF(ctx->files[oldFd]);
279 bitmap_set(&ctx->allocBitmap, newFd);
280 return newFd;
281}
282
284{
285 return vfs_ctx_dup2(&sched_process()->vfsCtx, oldFd, newFd);
286}
#define assert(expression)
Definition assert.h:29
#define SYS_CHDIR
Definition syscalls.h:38
#define SYS_DUP
Definition syscalls.h:47
#define SYSCALL_DEFINE(num, returnType,...)
Macro to define a syscall.
Definition syscalls.h:100
#define SYS_CLOSE
Definition syscalls.h:33
#define SYS_DUP2
Definition syscalls.h:48
uint64_t namespace_get_root_path(namespace_t *ns, path_t *outPath)
Get the root path of a namespace.
Definition namespace.c:274
void path_put(path_t *path)
Put a path.
Definition path.c:257
#define PATH_DEFER(path)
Defer path put.
Definition path.h:53
void path_copy(path_t *dest, const path_t *src)
Copy a path.
Definition path.c:232
#define PATH_EMPTY
Helper to create an empty path.
Definition path.h:182
@ WALK_NONE
No flags.
Definition path.h:101
void vfs_ctx_deinit(vfs_ctx_t *ctx)
Deinitialize a VFS context.
Definition vfs_ctx.c:30
fd_t vfs_ctx_set_fd(vfs_ctx_t *ctx, fd_t fd, file_t *file)
Allocate a specific file descriptor in a VFS context.
Definition vfs_ctx.c:164
fd_t vfs_ctx_dup(vfs_ctx_t *ctx, fd_t oldFd)
Duplicate a file descriptor in a VFS context.
Definition vfs_ctx.c:218
void vfs_ctx_init(vfs_ctx_t *ctx, const path_t *cwd)
Initialize a VFS context.
Definition vfs_ctx.c:11
uint64_t vfs_ctx_get_cwd(vfs_ctx_t *ctx, path_t *outCwd)
Definition vfs_ctx.c:67
fd_t vfs_ctx_alloc_fd(vfs_ctx_t *ctx, file_t *file)
Allocate a new file descriptor in a VFS context.
Definition vfs_ctx.c:142
fd_t vfs_ctx_dup2(vfs_ctx_t *ctx, fd_t oldFd, fd_t newFd)
Duplicate a file descriptor in a VFS context to a specific file descriptor.
Definition vfs_ctx.c:251
uint64_t vfs_ctx_free_fd(vfs_ctx_t *ctx, fd_t fd)
Free a file descriptor in a VFS context.
Definition vfs_ctx.c:191
uint64_t vfs_ctx_set_cwd(vfs_ctx_t *ctx, const path_t *cwd)
Set the current working directory of a VFS context.
Definition vfs_ctx.c:93
file_t * vfs_ctx_get_file(vfs_ctx_t *ctx, fd_t fd)
Get a file from a VFS context.
Definition vfs_ctx.c:48
uint64_t vfs_walk(path_t *outPath, const pathname_t *pathname, walk_flags_t flags, process_t *process)
Walk a pathname to a path, starting from the current process's working directory.
Definition vfs.c:341
process_t * process_get_kernel(void)
Gets the kernel process.
Definition process.c:594
uint64_t thread_copy_from_user_pathname(thread_t *thread, pathname_t *pathname, const char *userPath)
Safely copy a string from user space and use it to initialize a pathname.
Definition thread.c:307
process_t * sched_process(void)
Retrieves the process of the currently running thread.
Definition sched.c:164
thread_t * sched_thread(void)
Retrieves the currently running thread.
Definition sched.c:157
static void lock_init(lock_t *lock)
Initializes a lock.
Definition lock.h:80
#define LOCK_SCOPE(lock)
Acquires a lock for the reminder of the current scope.
Definition lock.h:57
#define REF(ptr)
Increment reference count.
Definition ref.h:65
#define DEREF(ptr)
Decrement reference count.
Definition ref.h:80
#define CONFIG_MAX_FD
Maximum file descriptor configuration.
Definition config.h:47
#define EINVAL
Invalid argument.
Definition errno.h:142
#define EMFILE
Too many open files.
Definition errno.h:152
#define EBUSY
Device or resource busy.
Definition errno.h:112
#define ENOTDIR
Not a directory.
Definition errno.h:132
#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)
Find the first clear bit in the bitmap.
Definition bitmap.h:283
static void bitmap_clear(bitmap_t *map, uint64_t index)
Clear a bit in the bitmap.
Definition bitmap.h:186
static void bitmap_set(bitmap_t *map, uint64_t index)
Set a bit in the bitmap.
Definition bitmap.h:106
static void bitmap_init(bitmap_t *map, void *buffer, uint64_t length)
Initialize a bitmap.
Definition bitmap.h:74
@ INODE_DIR
Is a directory.
Definition io.h:346
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
__UINT64_TYPE__ fd_t
A file descriptor.
Definition fd_t.h:12
static dentry_t * file
Definition log_file.c:17
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
_PUBLIC void * memset(void *s, int c, size_t n)
Definition memset.c:4
inode_t * inode
Definition dentry.h:87
File structure.
Definition file.h:37
inode_type_t type
Constant after creation.
Definition inode.h:57
Path structure.
Definition path.h:110
mount_t * mount
Definition path.h:111
dentry_t * dentry
Definition path.h:112
Pathname structure.
Definition path.h:122
Process structure.
Definition process.h:53
vfs_ctx_t vfsCtx
Definition process.h:61
Thread of execution structure.
Definition thread.h:55
process_t * process
The parent process that the thread executes within.
Definition thread.h:57
VFS context structure.
Definition vfs_ctx.h:31
bitmap_t allocBitmap
Bitmap tracking allocated file descriptors.
Definition vfs_ctx.h:34
lock_t lock
Definition vfs_ctx.h:36
path_t cwd
Definition vfs_ctx.h:32
file_t * files[CONFIG_MAX_FD]
Definition vfs_ctx.h:33
bool initalized
Definition vfs_ctx.h:37
uint64_t allocBitmapBuffer[BITMAP_BITS_TO_QWORDS(CONFIG_MAX_FD)]
Definition vfs_ctx.h:35