feat: implement rmdir(2), unlink(2), unlinkat(2)
authorMinep <zelong56@gmail.com>
Sat, 30 Jul 2022 17:08:19 +0000 (18:08 +0100)
committerMinep <zelong56@gmail.com>
Sat, 30 Jul 2022 17:08:19 +0000 (18:08 +0100)
README.md
lunaix-os/includes/lunaix/fctrl.h
lunaix-os/includes/lunaix/fs.h
lunaix-os/includes/lunaix/fs/twifs.h
lunaix-os/includes/lunaix/status.h
lunaix-os/includes/lunaix/syscall.h
lunaix-os/kernel/asm/x86/syscall.S
lunaix-os/kernel/fs/twifs.c
lunaix-os/kernel/fs/vfs.c

index b995657869e059f8bb0a1262cd687917c3987ce9..5edd52f62db2926ebfc9b7acf401e5f6d4c51a8e 100644 (file)
--- a/README.md
+++ b/README.md
@@ -175,6 +175,9 @@ qemu-img create -f vdi machine/disk1.vdi 128M
 2. `readdir(2)`
 2. `readlink(2)`
 2. `readlinkat(2)`
+2. `rmdir(2)`
+2. `unlink(2)`
+2. `unlinkat(2)`
 
 ### LunaixOS自有
 
index 0cd2705e4d9c1ce984f66c91ff7ff118051f6794..2f58f0df1717bd08ec37d610a8df8111fcb75e61 100644 (file)
@@ -10,6 +10,9 @@ __LXSYSCALL2(int, open, const char*, path, int, options);
 __LXSYSCALL1(int, close, int, fd);
 
 __LXSYSCALL1(int, mkdir, const char*, path);
+__LXSYSCALL1(int, rmdir, const char*, pathname);
+__LXSYSCALL1(int, unlink, const char*, pathname);
+__LXSYSCALL2(int, unlinkat, int, fd, const char*, pathname);
 
 __LXSYSCALL2(int, readdir, int, fd, struct dirent*, dent);
 
index 7f05413cdb08310ddd66e41ba4afb7adf3798509..fffb26f5cd07f69db888544436dc450d14e74e18 100644 (file)
@@ -13,7 +13,7 @@
 
 #define VFS_INODE_TYPE_DIR 0x1
 #define VFS_INODE_TYPE_FILE 0x2
-#define VFS_INODE_TYPE_DEVICE 0x4
+#define VFS_INODE_TYPE_DEVICE 0x3
 
 #define VFS_ENOFS -2
 #define VFS_EBADMNT -3
@@ -108,7 +108,7 @@ struct v_inode
     uint32_t ctime;
     uint32_t mtime;
     uint64_t lb_addr;
-    uint32_t ref_count;
+    uint32_t open_count;
     uint32_t lb_usage;
     uint32_t fsize;
     void* data; // 允许底层FS绑定他的一些专有数据
@@ -118,6 +118,8 @@ struct v_inode
         int (*open)(struct v_inode* inode, struct v_file* file);
         int (*sync)(struct v_inode* inode);
         int (*mkdir)(struct v_inode* inode, struct v_dnode* dnode);
+        int (*rmdir)(struct v_inode* inode);
+        int (*unlink)(struct v_inode* inode);
         int (*dir_lookup)(struct v_inode* inode, struct v_dnode* dnode);
     } ops;
 };
index bd9dfeb63032dd4885397e28b239737df88c02a8..31875ef24fab16856de08bd40bf250ae22d709f8 100644 (file)
@@ -26,7 +26,7 @@ twifs_dir_node(struct twifs_node* parent, const char* name, int name_len);
 struct twifs_node*
 twifs_toplevel_node(const char* name, int name_len);
 
-void
+int
 twifs_rm_node(struct twifs_node* node);
 
 #endif /* __LUNAIX_TWIFS_H */
index 17b509e08e0ecfefe7c5555f4a8c80f85200819d..d6cb3eb1d57bf6290a1e8474910efe5b7f5ce141 100644 (file)
@@ -19,5 +19,9 @@
 #define ENOTSUP -14
 #define ENXIO -15
 #define ELOOP -16
+#define ENOTEMPTY -17
+#define EROFS -18
+#define EISDIR -19
+#define EBUSY -20
 
 #endif /* __LUNAIX_CODE_H */
index f5b72d36573febb15b5ee85ddf28701f34bd69f5..bccfb3bb5ec2ea67b559b1daa43a67fefed1d1bf 100644 (file)
@@ -32,6 +32,9 @@
 #define __SYSCALL_geterrno 26
 #define __SYSCALL_readlink 27
 #define __SYSCALL_readlinkat 28
+#define __SYSCALL_rmdir 29
+#define __SYSCALL_unlink 30
+#define __SYSCALL_unlinkat 31
 
 #define __SYSCALL_MAX 0x100
 
index 61b9879609f7d89397d4bcdefd11952546e56956..083f5ceec61ed9b552b6ac28c93fa999740427b0 100644 (file)
         .long __lxsys_write
         .long __lxsys_readdir
         .long __lxsys_mkdir
-        .long __lxsys_lseek          /* 25 */
+        .long __lxsys_lseek         /* 25 */
         .long __lxsys_geterrno
         .long __lxsys_readlink
         .long __lxsys_readlinkat
+        .long __lxsys_rmdir
+        .long __lxsys_unlink        /* 30 */
+        .long __lxsys_unlinkat
         2:
         .rept __SYSCALL_MAX - (2b - 1b)/4
             .long 0
index 104a2fba8e9edceb4e0ce0f68d582210f7ffd01e..a67300b81548b37bed3e5840b8bd1de55524fd51 100644 (file)
@@ -48,6 +48,7 @@ twifs_init()
     struct filesystem* twifs = vzalloc(sizeof(struct filesystem));
     twifs->fs_name = HSTR("twifs", 5);
     twifs->mount = __twifs_mount;
+    twifs->types = FSTYPE_ROFS;
 
     fsm_register(twifs);
 
@@ -71,15 +72,16 @@ __twifs_new_node(struct twifs_node* parent, const char* name, int name_len)
     return node;
 }
 
-void
+int
 twifs_rm_node(struct twifs_node* node)
 {
-    if ((node->itype & VFS_INODE_TYPE_DIR)) {
-        // TODO recursivly delete any sub-directories.
+    if ((node->itype & VFS_INODE_TYPE_DIR) && !llist_empty(&node->children)) {
+        return ENOTEMPTY;
     }
     llist_delete(&node->siblings);
     vfs_i_free(node->inode);
     cake_release(twi_pile, node);
+    return 0;
 }
 
 struct twifs_node*
@@ -151,9 +153,11 @@ __twifs_create_inode(struct twifs_node* twi_node)
                                .lb_usage = 0,
                                .data = twi_node,
                                .mtime = 0,
-                               .ref_count = 0 };
+                               .open_count = 0 };
     inode->ops.dir_lookup = __twifs_dirlookup;
     inode->ops.mkdir = __twifs_mkdir;
+    inode->ops.unlink = __twifs_rmstuff;
+    inode->ops.rmdir = __twifs_rmstuff;
     inode->ops.open = __twifs_openfile;
 
     return inode;
@@ -175,6 +179,13 @@ __twifs_get_node(struct twifs_node* parent, struct hstr* name)
     return NULL;
 }
 
+int
+__twifs_rmstuff(struct v_inode* inode)
+{
+    struct twifs_node* twi_node = (struct twifs_node*)inode->data;
+    return twifs_rm_node(twi_node);
+}
+
 int
 __twifs_dirlookup(struct v_inode* inode, struct v_dnode* dnode)
 {
index 4c0324088d0a60eaddd486e90a7cc7676cbd5cfc..0fbf6529df93295f851e13b690f827479daa5d69 100644 (file)
@@ -295,6 +295,7 @@ vfs_open(struct v_dnode* dnode, struct v_file** file)
 
     vfile->dnode = dnode;
     vfile->inode = dnode->inode;
+    dnode->inode->open_count++;
 
     int errno = dnode->inode->ops.open(dnode->inode, vfile);
     if (errno) {
@@ -314,6 +315,9 @@ vfs_close(struct v_file* file)
 
     int errno = file->ops.close(file);
     if (!errno) {
+        if (file->inode->open_count) {
+            file->inode->open_count--;
+        }
         cake_release(file_pile, file);
     }
     return errno;
@@ -393,6 +397,8 @@ vfs_i_free(struct v_inode* inode)
     cake_release(inode_pile, inode);
 }
 
+/* ---- System call definition and support ---- */
+
 int
 __vfs_do_open(struct v_file** file_out, const char* path, int options)
 {
@@ -668,6 +674,87 @@ __DEFINE_LXSYSCALL4(int,
         return errno;
     }
 
+    __current->k_status = errno;
+    return SYSCALL_ESTATUS(errno);
+}
+
+__DEFINE_LXSYSCALL1(int, rmdir, const char*, pathname)
+{
+    int errno;
+    struct v_dnode* dnode;
+    if ((errno = vfs_walk(NULL, pathname, &dnode, NULL, 0))) {
+        goto done;
+    }
+    if ((dnode->super_block->fs->types & FSTYPE_ROFS)) {
+        errno = EROFS;
+        goto done;
+    }
+
+    if (dnode->inode->open_count) {
+        errno = EBUSY;
+        goto done;
+    }
+
+    if (dnode->inode->itype == VFS_INODE_TYPE_DIR) {
+        errno = dnode->inode->ops.rmdir(dnode->inode);
+    } else {
+        errno = ENOTDIR;
+    }
+
+done:
+    __current->k_status = errno;
+    return SYSCALL_ESTATUS(errno);
+}
+
+int
+__vfs_do_unlink(struct v_inode* inode)
+{
+    int errno;
+    if (inode->open_count) {
+        errno = EBUSY;
+    } else if (inode->itype != VFS_INODE_TYPE_DIR) {
+        // TODO handle symbolic link and type other than regular file
+        errno = inode->ops.unlink(inode);
+    } else {
+        errno = EISDIR;
+    }
+
+    return errno;
+}
+
+__DEFINE_LXSYSCALL1(int, unlink, const char*, pathname)
+{
+    int errno;
+    struct v_dnode* dnode;
+    if ((errno = vfs_walk(NULL, pathname, &dnode, NULL, 0))) {
+        goto done;
+    }
+    if ((dnode->super_block->fs->types & FSTYPE_ROFS)) {
+        errno = EROFS;
+        goto done;
+    }
+
+    errno = __vfs_do_unlink(dnode->inode);
+
+done:
+    __current->k_status = errno;
+    return SYSCALL_ESTATUS(errno);
+}
+
+__DEFINE_LXSYSCALL2(int, unlinkat, int, fd, const char*, pathname)
+{
+    int errno;
+    struct v_fd* fd_s;
+    if (!GET_FD(fd, fd_s)) {
+        errno = EBADF;
+    } else {
+        struct v_dnode* dnode;
+        if (!(errno = vfs_walk(fd_s->file->dnode, pathname, &dnode, NULL, 0))) {
+            errno = __vfs_do_unlink(dnode->inode);
+        }
+    }
+
+done:
     __current->k_status = errno;
     return SYSCALL_ESTATUS(errno);
 }
\ No newline at end of file