aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/vfs_syscalls.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/vfs_syscalls.c')
-rw-r--r--sys/kern/vfs_syscalls.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 937ae87..77070ab 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -34,6 +34,7 @@
#include <sys/errno.h>
#include <sys/sio.h>
#include <sys/filedesc.h>
+#include <sys/atomic.h>
#include <sys/namei.h>
#include <sys/proc.h>
#include <sys/limits.h>
@@ -141,6 +142,40 @@ sys_open(struct syscall_args *scargs)
/*
* arg0: fd
+ */
+scret_t
+sys_close(struct syscall_args *args)
+{
+ struct filedesc *filedes;
+ struct proc *td;
+ int fd = args->arg0;
+
+ if ((filedes = fd_get(fd)) == NULL) {
+ return -EBADF;
+ }
+
+ /* Return if other threads still hold a ref */
+ if (atomic_dec_int(&filedes->refcnt) > 0) {
+ return 0;
+ }
+
+ td = this_td();
+
+ /*
+ * Each file descriptor structure references a vnode,
+ * we want to reclaim it or at the very least drop
+ * one of its references. After we've cleaned up within
+ * the file descriptor, we can clear it from the fd table
+ * and free up the memory for it.
+ */
+ vfs_release_vnode(filedes->vp);
+ td->fds[fd] = NULL;
+ dynfree(filedes);
+ return 0;
+}
+
+/*
+ * arg0: fd
* arg1: buf
* arg2: count
*/