From 1197797ee1358e41922c9b1c8ef03c53e4382e8c Mon Sep 17 00:00:00 2001 From: "Enrico Fraccaroli (Galfurian)" Date: Fri, 1 Sep 2023 11:17:40 -0400 Subject: [PATCH] Add symlink function (not yet implemented in ext2) --- libc/inc/sys/unistd.h | 6 ++++++ libc/src/unistd/symlink.c | 10 ++++++++++ mentos/inc/fs/vfs.h | 6 ++++++ mentos/inc/fs/vfs_types.h | 4 ++++ mentos/inc/system/syscall.h | 6 ++++++ mentos/src/drivers/ata.c | 8 +++++--- mentos/src/fs/ext2.c | 9 +++++---- mentos/src/fs/namei.c | 5 +++++ mentos/src/fs/procfs.c | 8 +++++--- mentos/src/fs/vfs.c | 28 ++++++++++++++++++++++++++++ mentos/src/io/proc_feedback.c | 8 +++++--- mentos/src/io/proc_ipc.c | 9 +++++---- mentos/src/io/proc_running.c | 8 +++++--- mentos/src/io/proc_system.c | 8 +++++--- mentos/src/io/proc_video.c | 8 +++++--- mentos/src/system/syscall.c | 2 +- 16 files changed, 106 insertions(+), 27 deletions(-) create mode 100644 libc/src/unistd/symlink.c diff --git a/libc/inc/sys/unistd.h b/libc/inc/sys/unistd.h index a7aeb82..348b196 100644 --- a/libc/inc/sys/unistd.h +++ b/libc/inc/sys/unistd.h @@ -54,6 +54,12 @@ off_t lseek(int fd, off_t offset, int whence); /// @return int unlink(const char *path); +/// @brief Creates a symbolic link. +/// @param linkname the name of the link. +/// @param path the entity it is linking to. +/// @return 0 on success, a negative number if fails and errno is set. +int symlink(const char *linkname, const char *path); + /// @brief Wrapper for exit system call. /// @param status The exit status. extern void exit(int status); diff --git a/libc/src/unistd/symlink.c b/libc/src/unistd/symlink.c new file mode 100644 index 0000000..1ed4cc5 --- /dev/null +++ b/libc/src/unistd/symlink.c @@ -0,0 +1,10 @@ +/// @file unlink.c +/// @brief +/// @copyright (c) 2014-2023 This file is distributed under the MIT License. +/// See LICENSE.md for details. + +#include "sys/unistd.h" +#include "sys/errno.h" +#include "system/syscall_types.h" + +_syscall2(int, symlink, const char *, linkname, const char *, path) diff --git a/mentos/inc/fs/vfs.h b/mentos/inc/fs/vfs.h index 6258b7b..a07c9cb 100644 --- a/mentos/inc/fs/vfs.h +++ b/mentos/inc/fs/vfs.h @@ -119,6 +119,12 @@ int vfs_rmdir(const char *path); /// It is equivalent to: open(path, O_WRONLY|O_CREAT|O_TRUNC, mode) vfs_file_t *vfs_creat(const char *path, mode_t mode); +/// @brief Creates a symbolic link. +/// @param linkname the name of the link. +/// @param path the entity it is linking to. +/// @return 0 on success, a negative number if fails and errno is set. +int vfs_symlink(const char *linkname, const char *path); + /// @brief Stat the file at the given path. /// @param path Path to the file for which we are retrieving the statistics. /// @param buf Buffer where we are storing the statistics. diff --git a/mentos/inc/fs/vfs_types.h b/mentos/inc/fs/vfs_types.h index 20d8b03..c00f230 100644 --- a/mentos/inc/fs/vfs_types.h +++ b/mentos/inc/fs/vfs_types.h @@ -44,6 +44,8 @@ typedef int (*vfs_stat_callback)(const char *, stat_t *); typedef int (*vfs_fstat_callback)(vfs_file_t *, stat_t *); /// Function used to perform ioctl on files. typedef int (*vfs_ioctl_callback)(vfs_file_t *, int, void *); +/// Function for creating symbolic links. +typedef int (*vfs_symlink_callback)(const char *, const char *); /// @brief Filesystem information. typedef struct file_system_type { @@ -65,6 +67,8 @@ typedef struct vfs_sys_operations_t { vfs_stat_callback stat_f; /// File creation function. vfs_creat_callback creat_f; + /// Symbolic link creation function. + vfs_symlink_callback symlink_f; } vfs_sys_operations_t; /// @brief Set of functions used to perform operations on files. diff --git a/mentos/inc/system/syscall.h b/mentos/inc/system/syscall.h index a1e7778..dd00328 100644 --- a/mentos/inc/system/syscall.h +++ b/mentos/inc/system/syscall.h @@ -217,6 +217,12 @@ int sys_rmdir(const char *path); /// It is equivalent to: open(path, O_WRONLY|O_CREAT|O_TRUNC, mode) int sys_creat(const char *path, mode_t mode); +/// @brief Creates a symbolic link. +/// @param linkname the name of the link. +/// @param path the entity it is linking to. +/// @return 0 on success, a negative number if fails and errno is set. +int sys_symlink(const char *linkname, const char *path); + /// Provide access to the directory entries. /// @param fd The file descriptor of the directory for which we accessing /// the entries. diff --git a/mentos/src/drivers/ata.c b/mentos/src/drivers/ata.c index 25369e2..c2df4b6 100644 --- a/mentos/src/drivers/ata.c +++ b/mentos/src/drivers/ata.c @@ -1114,9 +1114,11 @@ static int ata_stat(const char *path, stat_t *stat) // == VFS ENTRY GENERATION ==================================================== /// Filesystem general operations. static vfs_sys_operations_t ata_sys_operations = { - .mkdir_f = NULL, - .rmdir_f = NULL, - .stat_f = ata_stat + .mkdir_f = NULL, + .rmdir_f = NULL, + .stat_f = ata_stat, + .creat_f = NULL, + .symlink_f = NULL, }; /// ATA filesystem file operations. diff --git a/mentos/src/fs/ext2.c b/mentos/src/fs/ext2.c index 1cc9690..73ed1a9 100644 --- a/mentos/src/fs/ext2.c +++ b/mentos/src/fs/ext2.c @@ -391,10 +391,11 @@ static vfs_file_t *ext2_mount(vfs_file_t *block_device, const char *path); /// Filesystem general operations. static vfs_sys_operations_t ext2_sys_operations = { - .mkdir_f = ext2_mkdir, - .rmdir_f = ext2_rmdir, - .stat_f = ext2_stat, - .creat_f = ext2_creat + .mkdir_f = ext2_mkdir, + .rmdir_f = ext2_rmdir, + .stat_f = ext2_stat, + .creat_f = ext2_creat, + .symlink_f = NULL, }; /// Filesystem file operations. diff --git a/mentos/src/fs/namei.c b/mentos/src/fs/namei.c index 0ea5078..56fe750 100644 --- a/mentos/src/fs/namei.c +++ b/mentos/src/fs/namei.c @@ -61,3 +61,8 @@ int sys_creat(const char *path, mode_t mode) // Return the file descriptor and increment it. return fd; } + +int sys_symlink(const char *linkname, const char *path) +{ + return vfs_symlink(linkname, path); +} diff --git a/mentos/src/fs/procfs.c b/mentos/src/fs/procfs.c index c0f722c..932ec15 100644 --- a/mentos/src/fs/procfs.c +++ b/mentos/src/fs/procfs.c @@ -98,9 +98,11 @@ static ssize_t procfs_getdents(vfs_file_t *file, dirent_t *dirp, off_t doff, siz /// Filesystem general operations. static vfs_sys_operations_t procfs_sys_operations = { - .mkdir_f = procfs_mkdir, - .rmdir_f = procfs_rmdir, - .stat_f = procfs_stat + .mkdir_f = procfs_mkdir, + .rmdir_f = procfs_rmdir, + .stat_f = procfs_stat, + .creat_f = NULL, + .symlink_f = NULL, }; /// Filesystem file operations. diff --git a/mentos/src/fs/vfs.c b/mentos/src/fs/vfs.c index 2436068..79478e6 100644 --- a/mentos/src/fs/vfs.c +++ b/mentos/src/fs/vfs.c @@ -331,6 +331,34 @@ vfs_file_t *vfs_creat(const char *path, mode_t mode) return file; } +int vfs_symlink(const char *linkname, const char *path) +{ + // Allocate a variable for the path. + char absolute_path[PATH_MAX]; + // If the first character is not the '/' then get the absolute path. + if (!realpath(linkname, absolute_path, sizeof(absolute_path))) { + pr_err("vfs_symlink(%s, %s): Cannot get the absolute path.", linkname, path); + return -ENODEV; + } + super_block_t *sb = vfs_get_superblock(absolute_path); + if (sb == NULL) { + pr_err("vfs_symlink(%s, %s): Cannot find the superblock!\n"); + return -ENODEV; + } + vfs_file_t *sb_root = sb->root; + if (sb_root == NULL) { + pr_err("vfs_symlink(%s, %s): Cannot find the superblock root.", linkname, path); + return -ENOENT; + } + // Check if the function is implemented. + if (sb_root->sys_operations->symlink_f == NULL) { + pr_err("vfs_symlink(%s, %s): Function not supported in current filesystem.", linkname, path); + return -ENOSYS; + } + pr_alert("vfs_symlink(%s, %s)", linkname, path); + return 0; +} + int vfs_stat(const char *path, stat_t *buf) { // Allocate a variable for the path. diff --git a/mentos/src/io/proc_feedback.c b/mentos/src/io/proc_feedback.c index c906320..3e23f1c 100644 --- a/mentos/src/io/proc_feedback.c +++ b/mentos/src/io/proc_feedback.c @@ -23,9 +23,11 @@ static ssize_t procfb_read(vfs_file_t *file, char *buf, off_t offset, size_t nby /// Filesystem general operations. static vfs_sys_operations_t procfb_sys_operations = { - .mkdir_f = NULL, - .rmdir_f = NULL, - .stat_f = NULL + .mkdir_f = NULL, + .rmdir_f = NULL, + .stat_f = NULL, + .creat_f = NULL, + .symlink_f = NULL, }; /// Filesystem file operations. diff --git a/mentos/src/io/proc_ipc.c b/mentos/src/io/proc_ipc.c index 7e9a586..63721d1 100644 --- a/mentos/src/io/proc_ipc.c +++ b/mentos/src/io/proc_ipc.c @@ -12,7 +12,6 @@ #include "sys/sem.h" #include "sys/shm.h" - extern ssize_t procipc_msg_read(vfs_file_t *file, char *buf, off_t offset, size_t nbyte); extern ssize_t procipc_sem_read(vfs_file_t *file, char *buf, off_t offset, size_t nbyte); @@ -21,9 +20,11 @@ extern ssize_t procipc_shm_read(vfs_file_t *file, char *buf, off_t offset, size_ /// Filesystem general operations. static vfs_sys_operations_t procipc_sys_operations = { - .mkdir_f = NULL, - .rmdir_f = NULL, - .stat_f = NULL + .mkdir_f = NULL, + .rmdir_f = NULL, + .stat_f = NULL, + .creat_f = NULL, + .symlink_f = NULL, }; /// Filesystem file operations for message queues. diff --git a/mentos/src/io/proc_running.c b/mentos/src/io/proc_running.c index aece47a..63e34f3 100644 --- a/mentos/src/io/proc_running.c +++ b/mentos/src/io/proc_running.c @@ -407,9 +407,11 @@ static inline ssize_t __procr_read(vfs_file_t *file, char *buffer, off_t offset, /// Filesystem general operations. static vfs_sys_operations_t procr_sys_operations = { - .mkdir_f = NULL, - .rmdir_f = NULL, - .stat_f = NULL + .mkdir_f = NULL, + .rmdir_f = NULL, + .stat_f = NULL, + .creat_f = NULL, + .symlink_f = NULL, }; /// Filesystem file operations. diff --git a/mentos/src/io/proc_system.c b/mentos/src/io/proc_system.c index fbfdb87..c5e73aa 100644 --- a/mentos/src/io/proc_system.c +++ b/mentos/src/io/proc_system.c @@ -69,9 +69,11 @@ static ssize_t procs_read(vfs_file_t *file, char *buf, off_t offset, size_t nbyt /// Filesystem general operations. static vfs_sys_operations_t procs_sys_operations = { - .mkdir_f = NULL, - .rmdir_f = NULL, - .stat_f = NULL + .mkdir_f = NULL, + .rmdir_f = NULL, + .stat_f = NULL, + .creat_f = NULL, + .symlink_f = NULL, }; /// Filesystem file operations. diff --git a/mentos/src/io/proc_video.c b/mentos/src/io/proc_video.c index d0f4a5b..11b8a3f 100644 --- a/mentos/src/io/proc_video.c +++ b/mentos/src/io/proc_video.c @@ -212,9 +212,11 @@ static int procv_ioctl(vfs_file_t *file, int request, void *data) /// Filesystem general operations. static vfs_sys_operations_t procv_sys_operations = { - .mkdir_f = NULL, - .rmdir_f = NULL, - .stat_f = NULL + .mkdir_f = NULL, + .rmdir_f = NULL, + .stat_f = NULL, + .creat_f = NULL, + .symlink_f = NULL, }; /// Filesystem file operations. diff --git a/mentos/src/system/syscall.c b/mentos/src/system/syscall.c index 46fa791..18a7ea1 100644 --- a/mentos/src/system/syscall.c +++ b/mentos/src/system/syscall.c @@ -123,7 +123,7 @@ void syscall_init() sys_call_table[__NR_settimeofday] = (SystemCall)sys_ni_syscall; sys_call_table[__NR_getgroups] = (SystemCall)sys_ni_syscall; sys_call_table[__NR_setgroups] = (SystemCall)sys_ni_syscall; - sys_call_table[__NR_symlink] = (SystemCall)sys_ni_syscall; + sys_call_table[__NR_symlink] = (SystemCall)sys_symlink; sys_call_table[__NR_lstat] = (SystemCall)sys_ni_syscall; sys_call_table[__NR_readlink] = (SystemCall)sys_ni_syscall; sys_call_table[__NR_uselib] = (SystemCall)sys_ni_syscall;