94 lines
2.2 KiB
C
94 lines
2.2 KiB
C
/// MentOS, The Mentoring Operating system project
|
|
/// @file open.c
|
|
/// @brief
|
|
/// @copyright (c) 2014-2021 This file is distributed under the MIT License.
|
|
/// See LICENSE.md for details.
|
|
|
|
#include "process/scheduler.h"
|
|
#include "process/process.h"
|
|
#include "system/printk.h"
|
|
#include "fcntl.h"
|
|
#include "system/syscall.h"
|
|
#include "string.h"
|
|
#include "limits.h"
|
|
#include "io/debug.h"
|
|
#include "sys/errno.h"
|
|
#include "stdio.h"
|
|
#include "fs/vfs.h"
|
|
|
|
int sys_open(const char *pathname, int flags, mode_t mode)
|
|
{
|
|
// Get the current task.
|
|
task_struct *task = scheduler_get_current_process();
|
|
|
|
// Search for an unused fd.
|
|
int fd;
|
|
for (fd = 0; fd < task->max_fd; ++fd) {
|
|
if (!task->fd_list[fd].file_struct) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Check if there is not fd available.
|
|
if (fd >= MAX_OPEN_FD) {
|
|
return -EMFILE;
|
|
}
|
|
|
|
// If fd limit is reached, try to allocate more
|
|
if (fd == task->max_fd) {
|
|
if (!vfs_extend_task_fd_list(task)) {
|
|
pr_err("Failed to extend the file descriptor list.\n");
|
|
return -EMFILE;
|
|
}
|
|
}
|
|
|
|
// Try to open the file.
|
|
vfs_file_t *file = vfs_open(pathname, flags, mode);
|
|
if (file == NULL) {
|
|
return -errno;
|
|
}
|
|
|
|
// Set the file descriptor id.
|
|
task->fd_list[fd].file_struct = file;
|
|
|
|
if (!bitmask_check(flags, O_APPEND)) {
|
|
// Reset the offset.
|
|
task->fd_list[fd].file_struct->f_pos = 0;
|
|
} else {
|
|
stat_t stat;
|
|
// Stat the file.
|
|
file->fs_operations->stat_f(file, &stat);
|
|
// Point at the last character
|
|
task->fd_list[fd].file_struct->f_pos = stat.st_size;
|
|
}
|
|
|
|
// Set the flags.
|
|
task->fd_list[fd].flags_mask = flags;
|
|
|
|
// Return the file descriptor and increment it.
|
|
return fd;
|
|
}
|
|
|
|
int sys_close(int fd)
|
|
{
|
|
// Get the current task.
|
|
task_struct *task = scheduler_get_current_process();
|
|
|
|
// Check the current FD.
|
|
if (fd < 0 || fd >= task->max_fd) {
|
|
return -EMFILE;
|
|
}
|
|
|
|
// Get the file.
|
|
vfs_file_t *file = task->fd_list[fd].file_struct;
|
|
if (file == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
// Remove the reference to the file.
|
|
task->fd_list[fd].file_struct = NULL;
|
|
|
|
// Call the close function.
|
|
return vfs_close(file);
|
|
}
|