Nucleus
Barry Files namespace f0dcd54 (3 years, 3 months ago)
diff --git a/vfs/files.c b/vfs/files.c
new file mode 100644
index 0000000..fffbc42
--- /dev/null
+++ b/vfs/files.c
@@ -0,0 +1,165 @@
+/*
+ * This file implements the Files object, which is the namespace for a task's
+ * files. It stores all the opened files for a task. It also implements many
+ * of the file-based system calls that need to use a file descriptor.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <nucleus/object.h>
+#include <nucleus/task.h>
+#include <nucleus/memory.h>
+#include <nucleus/vfs.h>
+
+/* Structure for a Files namespace */
+struct Files {
+ Object obj;
+ File *fd[NFILES];
+};
+
+static void files_delete(Object *);
+static void files_copy(Object *, Object *);
+
+/* Files object type */
+ObjectType filesType = {
+ .name = "FILES",
+ .size = sizeof(Files),
+ .delete = files_delete,
+ .copy = files_copy,
+};
+
+/* Destroy a Files object */
+static void
+files_delete(Object *obj)
+{
+ Files *files = (void *) obj;
+ int fd;
+ for (fd = 0; fd < NFILES; fd++)
+ if (files->fd[fd])
+ put(files->fd[fd]);
+}
+
+/* Copy a Files object */
+static void
+files_copy(Object *a, Object *b)
+{
+ Files *parent = (void *) a, *child = (void *) b;
+ File *file;
+ int fd;
+ for (fd = 0; fd < NFILES; fd++) {
+ file = parent->fd[fd];
+ if (!file)
+ continue;
+ child->fd[fd] = get(file);
+ }
+}
+
+/* Get the file described by fd */
+File *
+get_file_by_fd(int fd)
+{
+ if (fd < 0 || fd >= NFILES)
+ return NULL;
+ return current->files->fd[fd];
+}
+
+/* Allocate file descriptor */
+int
+allocate_fd(void)
+{
+ int fd;
+ for (fd = 0; fd < NFILES; fd++)
+ if (!current->files->fd[fd])
+ break;
+ if (fd == NFILES)
+ fd = -1;
+ return fd;
+}
+
+/* Install a file in a file descriptor */
+void
+install_fd(int fd, File *file)
+{
+ current->files->fd[fd] = file;
+}
+
+/* Close a file */
+int
+close(int fd)
+{
+ if (!get_file_by_fd(fd))
+ return -EBADF;
+ put(current->files->fd[fd]);
+ current->files->fd[fd] = NULL;
+ return 0;
+}
+
+/* Read a file */
+int
+read(int fd, void *buf, size_t count)
+{
+ if (!verify_access(buf, count, PROT_WRITE))
+ return -EFAULT;
+
+ File *file = get_file_by_fd(fd);
+ if (!file)
+ return -EBADF;
+
+ if (file->inode && S_ISDIR(file->inode->mode))
+ return -EISDIR;
+
+ lock(file);
+ int sz = file_read(file, buf, count);
+ unlock(file);
+ return sz;
+}
+
+/* Write a file */
+int
+write(int fd, void *buf, size_t count)
+{
+ if (!verify_access(buf, count, PROT_READ))
+ return -EFAULT;
+
+ File *file = get_file_by_fd(fd);
+ if (!file)
+ return -EBADF;
+
+ if (file->inode && S_ISDIR(file->inode->mode))
+ return -EISDIR;
+
+ lock(file);
+ int sz = file_write(file, buf, count);
+ unlock(file);
+ return sz;
+}
+
+/* Move a file's position */
+off_t
+lseek(int fd, off_t offset, int whence)
+{
+ File *file = get_file_by_fd(fd);
+ if (!file)
+ return -EBADF;
+
+ lock(file);
+ switch (whence) {
+ case SEEK_SET:
+ file->pos = offset;
+ break;
+ case SEEK_CUR:
+ file->pos += offset;
+ break;
+ case SEEK_END:
+ file->pos = file->inode->size + offset;
+ break;
+ default:
+ unlock(file);
+ return -EINVAL;
+ }
+ unlock(file);
+ return file->pos;
+}
diff --git a/vfs/namespace.c b/vfs/namespace.c
index 1cf7515..638453f 100644
--- a/vfs/namespace.c
+++ b/vfs/namespace.c
@@ -1,6 +1,6 @@
/*
* This file implements the File System object, which is the namespace for a
- * task's files. It tracks a task's root and current working directory.
+ * task's file system. It tracks a task's root and current working directory.
*/
#include <nucleus/object.h>
@@ -8,12 +8,15 @@
#include "namespace.h"
static void file_system_new(Object *);
+static void file_system_delete(Object *);
static void file_system_copy(Object *, Object *);
/* File System object type */
ObjectType fsType = {
+ .name = "FILE SYSTEM",
.size = sizeof(FileSystem),
.new = file_system_new,
+ .delete = file_system_delete,
.copy = file_system_copy,
};
@@ -25,14 +28,22 @@ file_system_new(Object *obj)
fs->cwdPath = create_list(&dirEntryType);
}
+/* Destory a File System object */
+static void
+file_system_delete(Object *obj)
+{
+ FileSystem *fs = (void *) obj;
+ put(fs->cwd);
+ destroy_list(fs->cwdPath);
+ put(fs->root);
+}
+
/* Copy a File System object */
static void
file_system_copy(Object *a, Object *b)
{
FileSystem *parent = (void *) a, *child = (void *) b;
child->cwd = get(parent->cwd);
- /* init cwd custody chain */
child->cwdPath = copy_list(parent->cwdPath);
- /* copy cwd custody chain */
child->root = get(parent->root);
}