feat: refine symbolic link support.
authorMinep <lunaixsky@qq.com>
Sun, 25 Jun 2023 15:47:55 +0000 (16:47 +0100)
committerMinep <lunaixsky@qq.com>
Sun, 25 Jun 2023 15:47:55 +0000 (16:47 +0100)
lunaix-os/includes/lunaix/fs.h
lunaix-os/includes/lunaix/fs/ramfs.h
lunaix-os/kernel/fs/path_walk.c
lunaix-os/kernel/fs/ramfs/ramfs.c
lunaix-os/kernel/fs/vfs.c
lunaix-os/uprog/init.c
lunaix-os/uprog/ls.c

index 4b2888157d59003569801d30fbcf6d13c32565f6..add77983b5fd1008857374f6b767152d2593dbb1 100644 (file)
@@ -19,7 +19,7 @@
 #define VFS_IFFILE 0x2
 #define VFS_IFSEQDEV 0x4
 #define VFS_IFVOLDEV 0x8
-#define VFS_IFSYMLINK 0x16
+#define VFS_IFSYMLINK 0x10
 
 #define VFS_WALK_MKPARENT 0x1
 #define VFS_WALK_FSRELATIVE 0x2
index f7f8e270a96066f8b226f8af5be5b2efac70fbf6..4c77906bf449e75a16b0d1412a077c657d8bd1fa 100644 (file)
@@ -1,6 +1,20 @@
 #ifndef __LUNAIX_RAMFS_H
 #define __LUNAIX_RAMFS_H
 
+#include <lunaix/types.h>
+
+#define RAMF_FILE 0
+#define RAMF_DIR 1
+#define RAMF_SYMLINK 2
+
+struct ram_inode
+{
+    u32_t flags;
+    char* symlink;
+};
+
+#define RAM_INODE(data) ((struct ram_inode*)(data))
+
 void
 ramfs_init();
 
index cd0ac01565e4616ca68901a8ccaa7ed2938b244b..f3dc8dd1bae87941bc926b095c7c817eaf26c569 100644 (file)
@@ -43,8 +43,8 @@ __vfs_walk(struct v_dnode* start,
     assert(start);
 
     struct v_dnode* dnode;
-    struct v_inode* current_inode;
     struct v_dnode* current_level = start;
+    struct v_inode* current_inode = current_level->inode;
 
     struct hstr name = HSTR(fname_buffer, 0);
 
@@ -80,38 +80,6 @@ __vfs_walk(struct v_dnode* start,
             break;
         }
 
-        current_inode = current_level->inode;
-
-        if ((current_inode->itype & VFS_IFSYMLINK) &&
-            !(walk_options & VFS_WALK_NOFOLLOW)) {
-            const char* link;
-
-            lock_inode(current_inode);
-            if ((errno =
-                   current_inode->ops->read_symlink(current_inode, &link))) {
-                unlock_inode(current_inode);
-                goto error;
-            }
-            unlock_inode(current_inode);
-
-            errno = __vfs_walk(current_level->parent,
-                               link,
-                               &dnode,
-                               NULL,
-                               0,
-                               depth + 1,
-                               fname_buffer + name.len + 1);
-
-            if (errno) {
-                goto error;
-            }
-
-            // reposition the resolved subtree pointed by symlink
-            // vfs_dcache_rehash(current_level->parent, dnode);
-            current_level = dnode;
-            current_inode = dnode->inode;
-        }
-
         lock_dnode(current_level);
 
         dnode = vfs_dcache_lookup(current_level, &name);
@@ -149,6 +117,43 @@ __vfs_walk(struct v_dnode* start,
 
         j = 0;
         current_level = dnode;
+        current_inode = current_level->inode;
+
+        if ((current_inode->itype & VFS_IFSYMLINK) &&
+            !(walk_options & VFS_WALK_NOFOLLOW)) {
+            const char* link;
+
+            if (!current_inode->ops->read_symlink) {
+                errno = ENOTSUP;
+                goto error;
+            }
+
+            lock_inode(current_inode);
+            if ((errno =
+                   current_inode->ops->read_symlink(current_inode, &link))) {
+                unlock_inode(current_inode);
+                goto error;
+            }
+            unlock_inode(current_inode);
+
+            errno = __vfs_walk(current_level->parent,
+                               link,
+                               &dnode,
+                               NULL,
+                               0,
+                               depth + 1,
+                               fname_buffer + name.len + 1);
+
+            if (errno) {
+                goto error;
+            }
+
+            // reposition the resolved subtree pointed by symlink
+            // vfs_dcache_rehash(current_level->parent, dnode);
+            current_level = dnode;
+            current_inode = dnode->inode;
+        }
+
     cont:
         current = lookahead;
     };
index decc0806d082ac0cfc8699fdf42ea98b4606ace7..37f8869ac6ca3ec322d3f87e4dc4a610adcaa4a3 100644 (file)
@@ -8,9 +8,11 @@
  * @copyright Copyright (c) 2022
  *
  */
+#include <klibc/string.h>
 #include <lunaix/fs.h>
 #include <lunaix/fs/ramfs.h>
 #include <lunaix/mm/valloc.h>
+#include <lunaix/spike.h>
 
 /*
     A RAM FS will play a role of being a root.
@@ -44,6 +46,45 @@ volatile static inode_t ino = 0;
 extern const struct v_inode_ops ramfs_inode_ops;
 extern const struct v_file_ops ramfs_file_ops;
 
+static int
+__ramfs_mknod(struct v_dnode* dnode, struct v_inode** nod_out, u32_t flags)
+{
+    struct v_inode* inode = vfs_i_alloc(dnode->super_block);
+
+    if (!inode) {
+        return ENOMEM;
+    }
+
+    struct ram_inode* rinode = valloc(sizeof(struct ram_inode));
+
+    if (!rinode) {
+        vfs_i_free(inode);
+        return ENOMEM;
+    }
+
+    rinode->flags = flags;
+    inode->data = rinode;
+
+    if ((flags & RAMF_DIR)) {
+        inode->itype = VFS_IFDIR;
+    } else {
+        inode->itype = VFS_IFFILE;
+    }
+
+    if ((flags & RAMF_SYMLINK)) {
+        inode->itype |= VFS_IFSYMLINK;
+    }
+
+    if (nod_out) {
+        *nod_out = inode;
+    }
+
+    vfs_i_addhash(inode);
+    vfs_assign_inode(dnode, inode);
+
+    return 0;
+}
+
 int
 ramfs_readdir(struct v_file* file, struct dir_context* dctx)
 {
@@ -65,25 +106,13 @@ ramfs_readdir(struct v_file* file, struct dir_context* dctx)
 int
 ramfs_mkdir(struct v_inode* this, struct v_dnode* dnode)
 {
-    struct v_inode* inode = vfs_i_alloc(dnode->super_block);
-    inode->itype = VFS_IFDIR;
-
-    vfs_i_addhash(inode);
-    vfs_assign_inode(dnode, inode);
-
-    return 0;
+    return __ramfs_mknod(dnode, NULL, RAMF_DIR);
 }
 
 int
 ramfs_create(struct v_inode* this, struct v_dnode* dnode)
 {
-    struct v_inode* inode = vfs_i_alloc(dnode->super_block);
-    inode->itype = VFS_IFFILE;
-
-    vfs_i_addhash(inode);
-    vfs_assign_inode(dnode, inode);
-
-    return 0;
+    return __ramfs_mknod(dnode, NULL, RAMF_FILE);
 }
 
 void
@@ -99,13 +128,7 @@ ramfs_mount(struct v_superblock* vsb, struct v_dnode* mount_point)
 {
     vsb->ops.init_inode = ramfs_inode_init;
 
-    struct v_inode* inode = vfs_i_alloc(vsb);
-    inode->itype = VFS_IFDIR;
-
-    vfs_i_addhash(inode);
-    vfs_assign_inode(mount_point, inode);
-
-    return 0;
+    return __ramfs_mknod(mount_point, NULL, RAMF_DIR);
 }
 
 int
@@ -124,12 +147,69 @@ ramfs_init()
     fsm_register(ramfs);
 }
 
+int
+ramfs_mksymlink(struct v_inode* this, const char* target)
+{
+    struct ram_inode* rinode = RAM_INODE(this->data);
+
+    assert(!(rinode->flags & RAMF_SYMLINK));
+
+    size_t len = strlen(target);
+    char* symlink = valloc(len);
+
+    if (!symlink) {
+        return ENOMEM;
+    }
+
+    memcpy(symlink, target, len);
+
+    this->itype |= VFS_IFSYMLINK;
+    rinode->flags |= RAMF_SYMLINK;
+    rinode->symlink = symlink;
+
+    return 0;
+}
+
+int
+ramfs_read_symlink(struct v_inode* this, const char** path_out)
+{
+    struct ram_inode* rinode = RAM_INODE(this->data);
+
+    if (!(rinode->flags & RAMF_SYMLINK)) {
+        return EINVAL;
+    }
+
+    *path_out = rinode->symlink;
+
+    return 0;
+}
+
+int
+ramfs_unlink(struct v_inode* this)
+{
+    struct ram_inode* rinode = RAM_INODE(this->data);
+
+    if ((rinode->flags & RAMF_SYMLINK)) {
+        rinode->flags &= ~RAMF_SYMLINK;
+        this->itype &= ~VFS_IFSYMLINK;
+        vfree(rinode->symlink);
+        return;
+    }
+
+    // TODO
+
+    return 0;
+}
+
 const struct v_inode_ops ramfs_inode_ops = { .mkdir = ramfs_mkdir,
                                              .rmdir = default_inode_rmdir,
                                              .dir_lookup =
                                                default_inode_dirlookup,
                                              .create = ramfs_create,
                                              .open = default_inode_open,
+                                             .unlink = ramfs_unlink,
+                                             .set_symlink = ramfs_mksymlink,
+                                             .read_symlink = ramfs_read_symlink,
                                              .rename = default_inode_rename };
 
 const struct v_file_ops ramfs_file_ops = { .readdir = ramfs_readdir,
index 6f94b5a7c98a7cbce2d84cb00bd4e671077c179a..7959fc3ffc3cce0cc58d79ec40ec777666480e5f 100644 (file)
@@ -515,6 +515,7 @@ vfs_i_free(struct v_inode* inode)
 /* ---- System call definition and support ---- */
 
 #define FLOCATE_CREATE_EMPTY 1
+#define FLOCATE_CREATE_ONLY 2
 
 int
 vfs_getfd(int fd, struct v_fd** fd_s)
@@ -541,7 +542,13 @@ __vfs_try_locate_file(const char* path,
     }
 
     errno = vfs_walk(*fdir, name.value, file, NULL, 0);
-    if (errno != ENOENT || !(options & FLOCATE_CREATE_EMPTY)) {
+
+    if (errno != ENOENT && (options & FLOCATE_CREATE_ONLY)) {
+        return EEXIST;
+    }
+
+    if (errno != ENOENT ||
+        !(options & (FLOCATE_CREATE_EMPTY | FLOCATE_CREATE_ONLY))) {
         return errno;
     }
 
@@ -821,7 +828,7 @@ vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth)
 
     size_t cpy_size = MIN(dnode->name.len, size - len);
     strncpy(buf + len, dnode->name.value, cpy_size);
-    len += cpy_size + !!cpy_size;
+    len += cpy_size;
 
     return len;
 }
@@ -1201,25 +1208,26 @@ __DEFINE_LXSYSCALL2(int,
                     link_target)
 {
     int errno;
-    struct v_dnode* dnode;
-    if ((errno = vfs_walk_proc(pathname, &dnode, NULL, 0))) {
+    struct v_dnode *dnode, *file;
+    if ((errno = __vfs_try_locate_file(
+           pathname, &dnode, &file, FLOCATE_CREATE_ONLY))) {
         goto done;
     }
 
-    if (errno = vfs_check_writable(dnode)) {
+    if (errno = vfs_check_writable(file)) {
         goto done;
     }
 
-    if (!dnode->inode->ops->set_symlink) {
+    if (!file->inode->ops->set_symlink) {
         errno = ENOTSUP;
         goto done;
     }
 
-    lock_inode(dnode->inode);
+    lock_inode(file->inode);
 
-    errno = dnode->inode->ops->set_symlink(dnode->inode, link_target);
+    errno = file->inode->ops->set_symlink(file->inode, link_target);
 
-    unlock_inode(dnode->inode);
+    unlock_inode(file->inode);
 
 done:
     return DO_STATUS(errno);
index a7265c0e350c4c9b54187d5d7a2b94d77c8faf8b..82e3ea32ec1b694b5e5729baa55e2c210ae94109 100644 (file)
@@ -1,3 +1,4 @@
+#include <errno.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <sys/lunaix.h>
@@ -6,24 +7,29 @@
 int
 main(int argc, const char** argv)
 {
-    int errno = 0;
+    int err = 0;
 
-    if ((errno = open("/dev/tty", 0)) < 0) {
+    if ((err = open("/dev/tty", 0)) < 0) {
         syslog(2, "fail to open tty (%d)\n", errno);
         return 0;
     }
 
-    if ((errno = dup(errno)) < 0) {
+    if ((err = dup(err)) < 0) {
         syslog(2, "fail to setup tty i/o (%d)\n", errno);
         return 0;
     }
 
     printf("(%p) user space!\n", (void*)main);
 
+    if ((err = symlink("/usr", "/mnt/lunaix-os/usr"))) {
+        syslog(2, "symlink /usr:/mnt/lunaix-os/usr (%d)\n", errno);
+        return 0;
+    }
+
     pid_t pid;
     if (!(pid = fork())) {
-        int err = execve("/mnt/lunaix-os/usr/sh", NULL, NULL);
-        printf("fail to execute (%d)\n", err);
+        err = execve("/mnt/lunaix-os/usr/sh", NULL, NULL);
+        printf("fail to execute (%d)\n", errno);
         _exit(err);
     }
 
index accc7f7fb9758c0e0cc6377665d38d60ad2c60ba..da4cca36de2398879793992438125707f59b6c19 100644 (file)
@@ -21,6 +21,8 @@ main(int argc, const char* argv[])
     while ((dent = readdir(dir))) {
         if (dent->d_type == DT_DIR) {
             printf(" \033[3m%s\033[39;49m\n", dent->d_name);
+        } else if (dent->d_type == DT_SYMLINK) {
+            printf(" \033[13m%s@\033[39;49m\n", dent->d_name);
         } else {
             printf(" %s\n", dent->d_name);
         }