Skip to content

Commit

Permalink
Merge pull request #34 from fischerling/implement_dup
Browse files Browse the repository at this point in the history
Implement dup syscall
  • Loading branch information
Galfurian committed Feb 29, 2024
2 parents 7b6076b + cf87813 commit bd864fe
Show file tree
Hide file tree
Showing 11 changed files with 161 additions and 40 deletions.
2 changes: 1 addition & 1 deletion doc/syscall.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ If the column is empty it means that it's not implemented yet.
| 38 | sys_rename | | const char * | const char * | - | - | - |
2 | 39 | sys_mkdir | fs/namei.c | const char * | int | - | - | - |
2 | 40 | sys_rmdir | fs/namei.c | const char * | - | - | - | - |
| 41 | sys_dup | | unsigned int | - | - | - | - |
1 | 41 | sys_dup | fs/vfs.c | unsigned int | - | - | - | - |
| 42 | sys_pipe | | unsigned long * | - | - | - | - |
| 43 | sys_times | | struct tms * | - | - | - | - |
2 | 45 | sys_brk | mem/kheap.c | unsigned long | - | - | - | - |
Expand Down
1 change: 1 addition & 0 deletions libc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# Add the library.
add_library(
libc
${CMAKE_SOURCE_DIR}/libc/src/unistd/dup.c
${CMAKE_SOURCE_DIR}/libc/src/stdio.c
${CMAKE_SOURCE_DIR}/libc/src/ctype.c
${CMAKE_SOURCE_DIR}/libc/src/string.c
Expand Down
6 changes: 6 additions & 0 deletions libc/inc/sys/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,12 @@ int fchdir(int fd);
/// appropriately.
ssize_t getdents(int fd, dirent_t *dirp, unsigned int count);

/// @brief Return a new file descriptor
/// @param fd The fd pointing to the opened file.
/// @return On success, a new file descriptor is returned.
/// On error, -1 is returned, and errno is set appropriately.
int dup(int fd);

/// @brief Send signal to calling thread after desired seconds.
/// @param seconds the amount of seconds.
/// @return If there is a previous alarm() request with time remaining, alarm()
Expand Down
10 changes: 10 additions & 0 deletions libc/src/unistd/dup.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/// @file dup.c
/// @brief
/// @copyright (c) 2024 This file is distributed under the MIT License.
/// See LICENSE.md for details.

#include "sys/unistd.h"
#include "system/syscall_types.h"
#include "sys/errno.h"

_syscall1(int, dup, int, fd)
8 changes: 8 additions & 0 deletions mentos/inc/fs/vfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,11 @@ int vfs_dup_task(struct task_struct *new_task, struct task_struct *old_task);
/// @param task The task for which we destroy the file descriptor list.
/// @return 0 on fail, 1 on success.
int vfs_destroy_task(struct task_struct *task);

/// @brief Find the smallest available fd.
/// @return -errno on fail, fd on success.
int get_unused_fd(void);

/// @brief Return new smallest available file desriptor.
/// @return -errno on fail, fd on success.
int sys_dup(int fd);
22 changes: 3 additions & 19 deletions mentos/src/fs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,9 @@ int sys_creat(const char *path, mode_t mode)
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;
}
}
int fd = get_unused_fd();
if (fd < 0)
return fd;

// Try to open the file.
vfs_file_t *file = vfs_creat(path, mode);
Expand Down
22 changes: 3 additions & 19 deletions mentos/src/fs/open.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,9 @@ int sys_open(const char *pathname, int flags, mode_t mode)
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;
}
}
int fd = get_unused_fd();
if (fd < 0)
return fd;

// Try to open the file.
vfs_file_t *file = vfs_open(pathname, flags, mode);
Expand Down
62 changes: 62 additions & 0 deletions mentos/src/fs/vfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -604,3 +604,65 @@ int vfs_destroy_task(task_struct *task)
}
return 1;
}

int get_unused_fd(void)
{
// 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;
}
}

return fd;
}

int sys_dup(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 descriptor.
vfs_file_descriptor_t *vfd = &task->fd_list[fd];
vfs_file_t *file = vfd->file_struct;

// Check the file.
if (file == NULL) {
return -ENOSYS;
}

fd = get_unused_fd();
if (fd < 0)
return fd;

// Increment file reference counter.
file->count += 1;

// Install the new fd
task->fd_list[fd].file_struct = file;
task->fd_list[fd].flags_mask = vfd->flags_mask;

return fd;
}
3 changes: 2 additions & 1 deletion mentos/src/system/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include "descriptor_tables/isr.h"
#include "devices/fpu.h"
#include "fs/vfs.h"
#include "fs/ioctl.h"
#include "hardware/timer.h"
#include "kernel.h"
Expand Down Expand Up @@ -91,7 +92,7 @@ void syscall_init(void)
sys_call_table[__NR_rename] = (SystemCall)sys_ni_syscall;
sys_call_table[__NR_mkdir] = (SystemCall)sys_mkdir;
sys_call_table[__NR_rmdir] = (SystemCall)sys_rmdir;
sys_call_table[__NR_dup] = (SystemCall)sys_ni_syscall;
sys_call_table[__NR_dup] = (SystemCall)sys_dup;
sys_call_table[__NR_pipe] = (SystemCall)sys_ni_syscall;
sys_call_table[__NR_times] = (SystemCall)sys_ni_syscall;
sys_call_table[__NR_brk] = (SystemCall)sys_brk;
Expand Down
1 change: 1 addition & 0 deletions programs/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# List of programs.
set(TEST_LIST
t_dup.c
t_creat.c
t_write_read.c
t_gid.c
Expand Down
64 changes: 64 additions & 0 deletions programs/tests/t_dup.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/// @file t_dup.c
/// @brief Test the dup syscall
/// @copyright (c) 2024 This file is distributed under the MIT License.
/// See LICENSE.md for details.

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/unistd.h>
#include <strerror.h>
#include <string.h>

int main(int argc, char *argv[])
{
char *file = "t_dup_file";
int fd1, fd2;
int flags = O_WRONLY | O_CREAT | O_TRUNC;
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;

fd1 = open(file, flags, mode);
if (fd1 < 0) {
printf("Failed to open file %s: %s\n", file, strerror(errno));
exit(1);
}

fd2 = dup(fd1);
if (fd2 < 0) {
printf("Failed to dup fd %d: %s\n", fd1, strerror(errno));
exit(1);
}

if (write(fd1, "foo", 3) != 3) {
printf("Writing to fd %d failed: %s\n", fd1, strerror(errno));
exit(1);
}
close(fd1);

if (write(fd2, "bar", 3) != 3) {
printf("Writing to fd %d failed: %s\n", fd2, strerror(errno));
exit(1);
}
close(fd2);

fd1 = open(file, O_RDONLY, 0);
if (fd1 < 0) {
printf("Failed to open file %s: %s\n", file, strerror(errno));
exit(1);
}

char buf[7];
buf[6] = 0;
if (read(fd1, &buf, 6) < 0) {
printf("Reading from fd %d failed: %s\n", fd1, strerror(errno));
exit(1);
}

if (strcmp(buf, "foobar") != 0) {
printf("Unexpected file content: %s\n", buf);
exit(1);
}

unlink(file);
return 0;
}

0 comments on commit bd864fe

Please sign in to comment.