From: Minep Date: Sun, 25 Jun 2023 15:47:55 +0000 (+0100) Subject: feat: refine symbolic link support. X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/commitdiff_plain/f8bd95b7a13dfe54d800e2d7ecdb0329f0798289 feat: refine symbolic link support. --- diff --git a/lunaix-os/includes/lunaix/fs.h b/lunaix-os/includes/lunaix/fs.h index 4b28881..add7798 100644 --- a/lunaix-os/includes/lunaix/fs.h +++ b/lunaix-os/includes/lunaix/fs.h @@ -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 diff --git a/lunaix-os/includes/lunaix/fs/ramfs.h b/lunaix-os/includes/lunaix/fs/ramfs.h index f7f8e27..4c77906 100644 --- a/lunaix-os/includes/lunaix/fs/ramfs.h +++ b/lunaix-os/includes/lunaix/fs/ramfs.h @@ -1,6 +1,20 @@ #ifndef __LUNAIX_RAMFS_H #define __LUNAIX_RAMFS_H +#include + +#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(); diff --git a/lunaix-os/kernel/fs/path_walk.c b/lunaix-os/kernel/fs/path_walk.c index cd0ac01..f3dc8dd 100644 --- a/lunaix-os/kernel/fs/path_walk.c +++ b/lunaix-os/kernel/fs/path_walk.c @@ -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; }; diff --git a/lunaix-os/kernel/fs/ramfs/ramfs.c b/lunaix-os/kernel/fs/ramfs/ramfs.c index decc080..37f8869 100644 --- a/lunaix-os/kernel/fs/ramfs/ramfs.c +++ b/lunaix-os/kernel/fs/ramfs/ramfs.c @@ -8,9 +8,11 @@ * @copyright Copyright (c) 2022 * */ +#include #include #include #include +#include /* 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, diff --git a/lunaix-os/kernel/fs/vfs.c b/lunaix-os/kernel/fs/vfs.c index 6f94b5a..7959fc3 100644 --- a/lunaix-os/kernel/fs/vfs.c +++ b/lunaix-os/kernel/fs/vfs.c @@ -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); diff --git a/lunaix-os/uprog/init.c b/lunaix-os/uprog/init.c index a7265c0..82e3ea3 100644 --- a/lunaix-os/uprog/init.c +++ b/lunaix-os/uprog/init.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -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); } diff --git a/lunaix-os/uprog/ls.c b/lunaix-os/uprog/ls.c index accc7f7..da4cca3 100644 --- a/lunaix-os/uprog/ls.c +++ b/lunaix-os/uprog/ls.c @@ -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); }