feat: ability to manipulate extended attribute
authorMinep <zelong56@gmail.com>
Sat, 20 Aug 2022 16:30:33 +0000 (17:30 +0100)
committerMinep <zelong56@gmail.com>
Sat, 20 Aug 2022 16:30:33 +0000 (17:30 +0100)
chore: minor refactoring and fix.

12 files changed:
README.md
lunaix-os/includes/lib/hash.h
lunaix-os/includes/lunaix/ds/hstr.h
lunaix-os/includes/lunaix/fctrl.h
lunaix-os/includes/lunaix/fs.h
lunaix-os/includes/lunaix/status.h
lunaix-os/includes/lunaix/syscall.h
lunaix-os/kernel/asm/x86/syscall.S
lunaix-os/kernel/fs/path_walk.c [new file with mode: 0644]
lunaix-os/kernel/fs/vfs.c
lunaix-os/kernel/fs/xattr.c [new file with mode: 0644]
lunaix-os/libs/hash.c

index ebaf251be08bcc551e433941d279924012145205..1a71e5753cedf56bdbffe52481d6e55df8979526 100644 (file)
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@ LunaixOS - 一个简单的,详细的,POSIX兼容的(但愿!),带有
 + 内存管理与按需分页(Demand Paging)
 + 键盘输入
 + 多进程
-+ 40个常见的Linux/POSIX系统调用([附录1](#appendix1))
++ 44个常见的Linux/POSIX系统调用([附录1](#appendix1))
 + 用户模式
 + 信号机制
 + PCI 3.0
@@ -148,7 +148,7 @@ qemu-img create -f vdi machine/disk0.vdi 128M
 
 ## 附录1:支持的系统调用<a id="appendix1"></a>
 
-### Unix/Linux/POSIX
+**Unix/Linux/POSIX**
 1. `sleep(3)`
 1. `wait(2)`
 1. `waitpid(2)`
@@ -170,32 +170,38 @@ qemu-img create -f vdi machine/disk0.vdi 128M
 2. `write(2)`
 2. `open(2)`
 2. `close(2)`
-2. `mkdir(2)`
+2. `mkdir(2)`
 2. `lseek(2)`
 2. `readdir(2)`
-2. `readlink(2)`
-2. `readlinkat(2)`
-2. `rmdir(2)`
-2. `unlink(2)`
-2. `unlinkat(2)`
-2. `link(2)`
-2. `fsync(2)`
+2. `readlink(2)`
+2. `readlinkat(2)`
+2. `rmdir(2)`
+2. `unlink(2)`
+2. `unlinkat(2)`
+2. `link(2)`
+2. `fsync(2)`
 2. `dup(2)`
 2. `dup2(2)`
-2. `symlink(2)`
+2. `symlink(2)`
 2. `chdir(2)`
 2. `fchdir(2)`
 2. `getcwd(2)`
-2. `rename(2)`
+2. `rename(2)`
 2. `mount(2)`
-2. `unmount` (a.k.a `umount(2)`)
+2. `unmount` (a.k.a `umount(2)`)※
+2. `getxattr(2)`※
+2. `setxattr(2)`※
+2. `fgetxattr(2)`※
+2. `fsetxattr(2)`※
 
-### LunaixOS自有
+**LunaixOS自有**
 
 1. `yield`
 2. `geterrno`
 3. `realpathat`
 
+( **※**:该系统调用暂未经过测试 )
+
 ## 附录2:编译gcc作为交叉编译器<a id="appendix2"></a>
 
 注意,gcc需要从源码构建,并配置为交叉编译器,即目标平台为`i686-elf`。你可以使用本项目提供的[自动化脚本](slides/c0-workspace/gcc-build.sh),这将会涵盖gcc和binutils源码的下载,配置和编译(没什么时间去打磨脚本,目前只知道在笔者的Ubuntu系统上可以运行)。
index 22998f78ac7c0804142b613bc307b6ea4a3dc7b8..f98fe28e24200d07e6792749d8ae1ca6f844527d 100644 (file)
@@ -6,7 +6,7 @@
 #define HASH_SIZE_BITS 32
 
 uint32_t
-strhash_32(char* str, uint32_t truncate_to);
+strhash_32(const char* str, uint32_t truncate_to);
 
 /**
  * @brief Simple generic hash function
@@ -18,7 +18,7 @@ strhash_32(char* str, uint32_t truncate_to);
  * @return uint32_t
  */
 inline uint32_t
-hash_32(uint32_t val, uint32_t truncate_to)
+hash_32(const uint32_t val, uint32_t truncate_to)
 {
     return (val * 0x61C88647u) >> (HASH_SIZE_BITS - truncate_to);
 }
index 4b6947e62a1b7194cf9a0868c5b7a13582a84655..5dab1cbbeb559a9ebb8a6c484e1322ade1a4ded6 100644 (file)
@@ -9,7 +9,7 @@ struct hstr
 {
     uint32_t hash;
     uint32_t len;
-    char* value;
+    const char* value;
 };
 
 #define HSTR(str, length)                                                      \
index 85f49aca73e67e1d0cfd419bcaf226fe188857ae..8a46058b8764e015edf8a657a0e18629ee454479 100644 (file)
@@ -36,4 +36,48 @@ __LXSYSCALL3(int,
 
 __LXSYSCALL1(int, unmount, const char*, target)
 
+__LXSYSCALL4(int,
+             getxattr,
+             const char*,
+             path,
+             const char*,
+             name,
+             void*,
+             value,
+             size_t,
+             len)
+
+__LXSYSCALL4(int,
+             setxattr,
+             const char*,
+             path,
+             const char*,
+             name,
+             void*,
+             value,
+             size_t,
+             len)
+
+__LXSYSCALL4(int,
+             fgetxattr,
+             int,
+             fd,
+             const char*,
+             name,
+             void*,
+             value,
+             size_t,
+             len)
+
+__LXSYSCALL4(int,
+             fsetxattr,
+             int,
+             fd,
+             const char*,
+             name,
+             void*,
+             value,
+             size_t,
+             len)
+
 #endif /* __LUNAIX_FCTRL_H */
index d43293be06075be91f99f368c1205480bb87f263..c86c6bc3aed5a27ecd7d8b6236a55fae40d5b9c6 100644 (file)
@@ -9,6 +9,7 @@
 #include <lunaix/ds/llist.h>
 #include <lunaix/ds/lru.h>
 #include <lunaix/ds/mutex.h>
+#include <lunaix/process.h>
 #include <lunaix/status.h>
 #include <stdatomic.h>
 
@@ -31,6 +32,8 @@
 #define VFS_HASH_MASK (VFS_HASHTABLE_SIZE - 1)
 #define VFS_HASHBITS (32 - VFS_HASHTABLE_BITS)
 
+#define VFS_PATH_DELIM '/'
+
 #define FSTYPE_ROFS 0x1
 
 #define DO_STATUS(errno) SYSCALL_ESTATUS(__current->k_status = errno)
      ('0' <= (chr) && (chr) <= '9') || (chr) == '.' || (chr) == '_' ||         \
      (chr) == '-')
 
+#define unlock_inode(inode) mutex_unlock(&inode->lock)
+#define lock_inode(inode)                                                      \
+    ({                                                                         \
+        mutex_lock(&inode->lock);                                              \
+        lru_use_one(inode_lru, &inode->lru);                                   \
+    })
+
+#define unlock_dnode(dnode) mutex_unlock(&dnode->lock)
+#define lock_dnode(dnode)                                                      \
+    ({                                                                         \
+        mutex_lock(&dnode->lock);                                              \
+        lru_use_one(dnode_lru, &dnode->lru);                                   \
+    })
+
 typedef uint32_t inode_t;
 
 struct v_dnode;
@@ -53,6 +70,7 @@ struct v_file_ops;
 struct v_inode_ops;
 struct v_fd;
 struct pcache;
+struct v_xattr_entry;
 
 extern struct v_file_ops default_file_ops;
 extern struct v_inode_ops default_inode_ops;
@@ -122,6 +140,17 @@ struct v_inode_ops
     int (*rename)(struct v_inode* from_inode,
                   struct v_dnode* from_dnode,
                   struct v_dnode* to_dnode);
+    int (*getxattr)(struct v_inode* this, struct v_xattr_entry* entry);
+    int (*setxattr)(struct v_inode* this, struct v_xattr_entry* entry);
+    int (*delxattr)(struct v_inode* this, struct v_xattr_entry* entry);
+};
+
+struct v_xattr_entry
+{
+    struct llist_header entries;
+    struct hstr name;
+    const void* value;
+    size_t len;
 };
 
 struct v_file
@@ -153,6 +182,7 @@ struct v_inode
     uint32_t link_count;
     uint32_t lb_usage;
     uint32_t fsize;
+    struct llist_header xattrs;
     struct v_superblock* sb;
     struct hlist_node hash_list;
     struct lru_node lru;
@@ -241,6 +271,12 @@ vfs_dcache_lookup(struct v_dnode* parent, struct hstr* str);
 void
 vfs_dcache_add(struct v_dnode* parent, struct v_dnode* dnode);
 
+void
+vfs_dcache_rehash(struct v_dnode* new_parent, struct v_dnode* dnode);
+
+void
+vfs_dcache_remove(struct v_dnode* dnode);
+
 int
 vfs_walk(struct v_dnode* start,
          const char* path,
@@ -248,6 +284,12 @@ vfs_walk(struct v_dnode* start,
          struct hstr* component,
          int walk_options);
 
+int
+vfs_walk_proc(const char* path,
+              struct v_dnode** dentry,
+              struct hstr* component,
+              int options);
+
 int
 vfs_mount(const char* target, const char* fs_name, struct device* device);
 
@@ -304,6 +346,9 @@ vfs_i_free(struct v_inode* inode);
 int
 vfs_dup_fd(struct v_fd* old, struct v_fd** new);
 
+int
+vfs_getfd(int fd, struct v_fd** fd_s);
+
 void
 pcache_init(struct pcache* pcache);
 
@@ -397,4 +442,13 @@ default_inode_rmdir(struct v_inode* this, struct v_dnode* dir);
 int
 default_inode_mkdir(struct v_inode* this, struct v_dnode* dir);
 
+struct v_xattr_entry*
+xattr_new(struct hstr* name);
+
+struct v_xattr_entry*
+xattr_getcache(struct v_inode* inode, struct hstr* name);
+
+void
+xattr_addcache(struct v_inode* inode, struct v_xattr_entry* xattr);
+
 #endif /* __LUNAIX_VFS_H */
index a108ea26070728b5c127457b9cf65e5d35ae0020..2368156726bf615e31bffbb9312ea5fc9ee0a0c1 100644 (file)
 #define EISDIR -19
 #define EBUSY -20
 #define EXDEV -21
-#define ELOOP -22
-#define ENODEV -23
-#define ERANGE -24
+#define ENODEV -22
+#define ERANGE -23
 #define ENOMEM LXOUTOFMEM
-#define ENOTDEV -25
+#define ENOTDEV -24
 
 #endif /* __LUNAIX_CODE_H */
index 5e0272fdd77c978d8813fcfd3dcb4b7447cf83be..98f5585a16fb202a931765f5716d2773ef17071e 100644 (file)
 #define __SYSCALL_rename 41
 #define __SYSCALL_mount 42
 #define __SYSCALL_unmount 43
+#define __SYSCALL_getxattr 44
+#define __SYSCALL_setxattr 45
+#define __SYSCALL_fgetxattr 46
+#define __SYSCALL_fsetxattr 47
 
 #define __SYSCALL_MAX 0x100
 
index 2d78828a4f9dd72cb9bc047f9943f2a2ccc496a9..b8d021973cbec4eda95d8daf7c78d6c53a86ad36 100644 (file)
         .long __lxsys_rename
         .long __lxsys_mount
         .long __lxsys_unmount
+        .long __lxsys_getxattr
+        .long __lxsys_setxattr      /* 45 */
+        .long __lxsys_fgetxattr
+        .long __lxsys_fsetxattr
         2:
         .rept __SYSCALL_MAX - (2b - 1b)/4
             .long 0
diff --git a/lunaix-os/kernel/fs/path_walk.c b/lunaix-os/kernel/fs/path_walk.c
new file mode 100644 (file)
index 0000000..0ffbabb
--- /dev/null
@@ -0,0 +1,187 @@
+#include <lunaix/fs.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/spike.h>
+
+#include <klibc/string.h>
+
+#define VFS_SYMLINK_DEPTH 16
+
+extern struct lru_zone *dnode_lru, *inode_lru;
+
+int
+__vfs_walk(struct v_dnode* start,
+           const char* path,
+           struct v_dnode** dentry,
+           struct hstr* component,
+           int walk_options,
+           size_t depth,
+           char* fname_buffer)
+{
+    int errno = 0;
+    int i = 0, j = 0;
+
+    if (depth >= VFS_SYMLINK_DEPTH) {
+        return ENAMETOOLONG;
+    }
+
+    if (path[0] == VFS_PATH_DELIM || !start) {
+        if ((walk_options & VFS_WALK_FSRELATIVE) && start) {
+            start = start->super_block->root;
+        } else {
+            start = vfs_sysroot;
+            if (!vfs_sysroot->mnt) {
+                panick("vfs: no root");
+            }
+        }
+        i++;
+    }
+
+    struct v_dnode* dnode;
+    struct v_inode* current_inode;
+    struct v_dnode* current_level = start;
+
+    struct hstr name = HSTR(fname_buffer, 0);
+
+    char current = path[i++], lookahead;
+    while (current && current_level) {
+        lookahead = path[i++];
+        if (current != VFS_PATH_DELIM) {
+            if (j >= VFS_NAME_MAXLEN - 1) {
+                return ENAMETOOLONG;
+            }
+            if (!VFS_VALID_CHAR(current)) {
+                return EINVAL;
+            }
+            fname_buffer[j++] = current;
+            if (lookahead) {
+                goto cont;
+            }
+        }
+
+        // handling cases like /^.*(\/+).*$/
+        if (lookahead == VFS_PATH_DELIM) {
+            goto cont;
+        }
+
+        fname_buffer[j] = 0;
+        name.len = j;
+        hstr_rehash(&name, HSTR_FULL_HASH);
+
+        if (!lookahead && (walk_options & VFS_WALK_PARENT)) {
+            if (component) {
+                component->hash = name.hash;
+                component->len = j;
+                strcpy(component->value, fname_buffer);
+            }
+            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);
+
+        if (!dnode) {
+            dnode = vfs_d_alloc(current_level, &name);
+
+            if (!dnode) {
+                errno = ENOMEM;
+                goto error;
+            }
+
+            lock_inode(current_inode);
+
+            errno = current_inode->ops->dir_lookup(current_inode, dnode);
+
+            if (errno == ENOENT && (walk_options & VFS_WALK_MKPARENT)) {
+                if (!current_inode->ops->mkdir) {
+                    errno = ENOTSUP;
+                } else {
+                    errno = current_inode->ops->mkdir(current_inode, dnode);
+                }
+            }
+
+            vfs_dcache_add(current_level, dnode);
+            unlock_inode(current_inode);
+
+            if (errno) {
+                unlock_dnode(current_level);
+                goto cleanup;
+            }
+        }
+
+        unlock_dnode(current_level);
+
+        j = 0;
+        current_level = dnode;
+    cont:
+        current = lookahead;
+    };
+
+    *dentry = current_level;
+    return 0;
+
+cleanup:
+    vfs_d_free(dnode);
+error:
+    *dentry = NULL;
+    return errno;
+}
+
+int
+vfs_walk(struct v_dnode* start,
+         const char* path,
+         struct v_dnode** dentry,
+         struct hstr* component,
+         int options)
+{
+    // allocate a file name stack for path walking and recursion to resolve
+    // symlink
+    char* name_buffer = valloc(2048);
+
+    int errno =
+      __vfs_walk(start, path, dentry, component, options, 0, name_buffer);
+
+    vfree(name_buffer);
+    return errno;
+}
+
+int
+vfs_walk_proc(const char* path,
+              struct v_dnode** dentry,
+              struct hstr* component,
+              int options)
+{
+    return vfs_walk(__current->cwd, path, dentry, component, options);
+}
\ No newline at end of file
index c13b8d3d9663cdddf88865c666b7744e5dc2ec28..a69803ef6a3be08d68e9ea2ad6d784b44c10b3b5 100644 (file)
 
 #include <lunaix/fs/twifs.h>
 
-#define PATH_DELIM '/'
-
-#define unlock_inode(inode) mutex_unlock(&inode->lock)
-#define lock_inode(inode)                                                      \
-    ({                                                                         \
-        mutex_lock(&inode->lock);                                              \
-        lru_use_one(inode_lru, &inode->lru);                                   \
-    })
-
-#define unlock_dnode(dnode) mutex_unlock(&dnode->lock)
-#define lock_dnode(dnode)                                                      \
-    ({                                                                         \
-        mutex_lock(&dnode->lock);                                              \
-        lru_use_one(dnode_lru, &dnode->lru);                                   \
-    })
-
 static struct cake_pile* dnode_pile;
 static struct cake_pile* inode_pile;
 static struct cake_pile* file_pile;
@@ -81,7 +65,7 @@ static struct cake_pile* fd_pile;
 struct v_dnode* vfs_sysroot;
 static struct hbucket* dnode_cache;
 
-static struct lru_zone *dnode_lru, *inode_lru;
+struct lru_zone *dnode_lru, *inode_lru;
 
 struct hstr vfs_ddot = HSTR("..", 2);
 struct hstr vfs_dot = HSTR(".", 1);
@@ -194,176 +178,6 @@ vfs_dcache_rehash(struct v_dnode* new_parent, struct v_dnode* dnode)
     vfs_dcache_add(new_parent, dnode);
 }
 
-#define VFS_SYMLINK_DEPTH 16
-
-int
-__vfs_walk(struct v_dnode* start,
-           const char* path,
-           struct v_dnode** dentry,
-           struct hstr* component,
-           int walk_options,
-           size_t depth,
-           char* fname_buffer)
-{
-    int errno = 0;
-    int i = 0, j = 0;
-
-    if (depth >= VFS_SYMLINK_DEPTH) {
-        return ENAMETOOLONG;
-    }
-
-    if (path[0] == PATH_DELIM || !start) {
-        if ((walk_options & VFS_WALK_FSRELATIVE) && start) {
-            start = start->super_block->root;
-        } else {
-            start = vfs_sysroot;
-            if (!vfs_sysroot->mnt) {
-                panick("vfs: no root");
-            }
-        }
-        i++;
-    }
-
-    struct v_dnode* dnode;
-    struct v_inode* current_inode;
-    struct v_dnode* current_level = start;
-
-    struct hstr name = HSTR(fname_buffer, 0);
-
-    char current = path[i++], lookahead;
-    while (current && current_level) {
-        lookahead = path[i++];
-        if (current != PATH_DELIM) {
-            if (j >= VFS_NAME_MAXLEN - 1) {
-                return ENAMETOOLONG;
-            }
-            if (!VFS_VALID_CHAR(current)) {
-                return EINVAL;
-            }
-            fname_buffer[j++] = current;
-            if (lookahead) {
-                goto cont;
-            }
-        }
-
-        // handling cases like /^.*(\/+).*$/
-        if (lookahead == PATH_DELIM) {
-            goto cont;
-        }
-
-        fname_buffer[j] = 0;
-        name.len = j;
-        hstr_rehash(&name, HSTR_FULL_HASH);
-
-        if (!lookahead && (walk_options & VFS_WALK_PARENT)) {
-            if (component) {
-                component->hash = name.hash;
-                component->len = j;
-                strcpy(component->value, fname_buffer);
-            }
-            break;
-        }
-
-        current_inode = current_level->inode;
-
-        if ((current_inode->itype & VFS_IFSYMLINK)) {
-            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);
-
-        if (!dnode) {
-            dnode = vfs_d_alloc(current_level, &name);
-
-            if (!dnode) {
-                errno = ENOMEM;
-                goto error;
-            }
-
-            lock_inode(current_inode);
-
-            errno = current_inode->ops->dir_lookup(current_inode, dnode);
-
-            if (errno == ENOENT && (walk_options & VFS_WALK_MKPARENT)) {
-                if (!current_inode->ops->mkdir) {
-                    errno = ENOTSUP;
-                } else {
-                    errno = current_inode->ops->mkdir(current_inode, dnode);
-                }
-            }
-
-            vfs_dcache_add(current_level, dnode);
-            unlock_inode(current_inode);
-
-            if (errno) {
-                unlock_dnode(current_level);
-                goto cleanup;
-            }
-        }
-
-        unlock_dnode(current_level);
-
-        j = 0;
-        current_level = dnode;
-    cont:
-        current = lookahead;
-    };
-
-    *dentry = current_level;
-    return 0;
-
-cleanup:
-    vfs_d_free(dnode);
-error:
-    *dentry = NULL;
-    return errno;
-}
-
-int
-vfs_walk(struct v_dnode* start,
-         const char* path,
-         struct v_dnode** dentry,
-         struct hstr* component,
-         int options)
-{
-    // allocate a file name stack for path walking and recursion to resolve
-    // symlink
-    char* name_buffer = valloc(2048);
-
-    int errno =
-      __vfs_walk(start, path, dentry, component, options, 0, name_buffer);
-
-    vfree(name_buffer);
-    return errno;
-}
-
 int
 vfs_open(struct v_dnode* dnode, struct v_file** file)
 {
@@ -614,6 +428,7 @@ vfs_i_alloc(struct v_superblock* sb)
 
     memset(inode, 0, sizeof(*inode));
     mutex_init(&inode->lock);
+    llist_init_head(&inode->xattrs);
 
     sb->ops.init_inode(sb, inode);
 
@@ -644,7 +459,7 @@ vfs_i_free(struct v_inode* inode)
 #define FLOCATE_CREATE_EMPTY 1
 
 int
-__vfs_getfd(int fd, struct v_fd** fd_s)
+vfs_getfd(int fd, struct v_fd** fd_s)
 {
     if (TEST_FD(fd) && (*fd_s = __current->fdtable->fds[fd])) {
         return 0;
@@ -730,7 +545,7 @@ __DEFINE_LXSYSCALL1(int, close, int, fd)
 {
     struct v_fd* fd_s;
     int errno = 0;
-    if ((errno = __vfs_getfd(fd, &fd_s))) {
+    if ((errno = vfs_getfd(fd, &fd_s))) {
         goto done_err;
     }
 
@@ -764,7 +579,7 @@ __DEFINE_LXSYSCALL2(int, readdir, int, fd, struct dirent*, dent)
     struct v_fd* fd_s;
     int errno;
 
-    if ((errno = __vfs_getfd(fd, &fd_s))) {
+    if ((errno = vfs_getfd(fd, &fd_s))) {
         goto done;
     }
 
@@ -805,7 +620,7 @@ __DEFINE_LXSYSCALL3(int, read, int, fd, void*, buf, size_t, count)
 {
     int errno = 0;
     struct v_fd* fd_s;
-    if ((errno = __vfs_getfd(fd, &fd_s))) {
+    if ((errno = vfs_getfd(fd, &fd_s))) {
         goto done;
     }
 
@@ -843,7 +658,7 @@ __DEFINE_LXSYSCALL3(int, write, int, fd, void*, buf, size_t, count)
 {
     int errno = 0;
     struct v_fd* fd_s;
-    if ((errno = __vfs_getfd(fd, &fd_s))) {
+    if ((errno = vfs_getfd(fd, &fd_s))) {
         goto done;
     }
 
@@ -881,7 +696,7 @@ __DEFINE_LXSYSCALL3(int, lseek, int, fd, int, offset, int, options)
 {
     int errno = 0;
     struct v_fd* fd_s;
-    if ((errno = __vfs_getfd(fd, &fd_s))) {
+    if ((errno = vfs_getfd(fd, &fd_s))) {
         goto done;
     }
 
@@ -933,7 +748,7 @@ vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth)
     len += cpy_size;
 
     if (len < size) {
-        buf[len++] = PATH_DELIM;
+        buf[len++] = VFS_PATH_DELIM;
     }
 
     return len;
@@ -960,7 +775,7 @@ __DEFINE_LXSYSCALL3(int, realpathat, int, fd, char*, buf, size_t, size)
 {
     int errno;
     struct v_fd* fd_s;
-    if ((errno = __vfs_getfd(fd, &fd_s))) {
+    if ((errno = vfs_getfd(fd, &fd_s))) {
         goto done;
     }
 
@@ -1004,7 +819,7 @@ __DEFINE_LXSYSCALL4(int,
 {
     int errno;
     struct v_fd* fd_s;
-    if ((errno = __vfs_getfd(dirfd, &fd_s))) {
+    if ((errno = vfs_getfd(dirfd, &fd_s))) {
         goto done;
     }
 
@@ -1176,7 +991,7 @@ __DEFINE_LXSYSCALL2(int, unlinkat, int, fd, const char*, pathname)
 {
     int errno;
     struct v_fd* fd_s;
-    if ((errno = __vfs_getfd(fd, &fd_s))) {
+    if ((errno = vfs_getfd(fd, &fd_s))) {
         goto done;
     }
 
@@ -1211,7 +1026,7 @@ __DEFINE_LXSYSCALL1(int, fsync, int, fildes)
 {
     int errno;
     struct v_fd* fd_s;
-    if (!(errno = __vfs_getfd(fildes, &fd_s))) {
+    if (!(errno = vfs_getfd(fildes, &fd_s))) {
         errno = vfs_fsync(fd_s->file);
     }
 
@@ -1242,7 +1057,7 @@ vfs_dup2(int oldfd, int newfd)
 
     int errno;
     struct v_fd *oldfd_s, *newfd_s;
-    if ((errno = __vfs_getfd(oldfd, &oldfd_s))) {
+    if ((errno = vfs_getfd(oldfd, &oldfd_s))) {
         goto done;
     }
 
@@ -1274,7 +1089,7 @@ __DEFINE_LXSYSCALL1(int, dup, int, oldfd)
 {
     int errno, newfd;
     struct v_fd *oldfd_s, *newfd_s;
-    if ((errno = __vfs_getfd(oldfd, &oldfd_s))) {
+    if ((errno = vfs_getfd(oldfd, &oldfd_s))) {
         goto done;
     }
 
@@ -1366,7 +1181,7 @@ __DEFINE_LXSYSCALL1(int, fchdir, int, fd)
     struct v_fd* fd_s;
     int errno = 0;
 
-    if ((errno = __vfs_getfd(fd, &fd_s))) {
+    if ((errno = vfs_getfd(fd, &fd_s))) {
         goto done;
     }
 
@@ -1388,7 +1203,7 @@ __DEFINE_LXSYSCALL2(char*, getcwd, char*, buf, size_t, size)
     size_t len = 0;
 
     if (!__current->cwd) {
-        *buf = PATH_DELIM;
+        *buf = VFS_PATH_DELIM;
         len = 1;
     } else {
         len = vfs_get_path(__current->cwd, buf, size, 0);
diff --git a/lunaix-os/kernel/fs/xattr.c b/lunaix-os/kernel/fs/xattr.c
new file mode 100644 (file)
index 0000000..94f85b7
--- /dev/null
@@ -0,0 +1,257 @@
+#include <klibc/string.h>
+#include <lunaix/fs.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/syscall.h>
+
+struct v_xattr_entry*
+xattr_new(struct hstr* name)
+{
+    struct v_xattr_entry* entry = valloc(sizeof(*entry));
+    if (!entry) {
+        return NULL;
+    }
+    *entry =
+      (struct v_xattr_entry){ .name = HHSTR(valloc(VFS_NAME_MAXLEN), 0, 0) };
+
+    hstrcpy(&entry->name, name);
+    return entry;
+}
+
+void
+xattr_free(struct v_xattr_entry* entry)
+{
+    vfree(entry->name.value);
+    vfree(entry);
+}
+
+struct v_xattr_entry*
+xattr_getcache(struct v_inode* inode, struct hstr* name)
+{
+    struct v_xattr_entry *pos, *n;
+    llist_for_each(pos, n, &inode->xattrs, entries)
+    {
+        if (HSTR_EQ(&pos->name, name)) {
+            return pos;
+        }
+    }
+
+    return NULL;
+}
+
+void
+xattr_addcache(struct v_inode* inode, struct v_xattr_entry* xattr)
+{
+    llist_append(&inode->xattrs, &xattr->entries);
+}
+
+void
+xattr_delcache(struct v_inode* inode, struct v_xattr_entry* xattr)
+{
+    llist_delete(&xattr->entries);
+}
+
+int
+__vfs_getxattr(struct v_inode* inode,
+               struct v_xattr_entry** xentry,
+               const char* name)
+{
+    if (!inode->ops->getxattr) {
+        return ENOTSUP;
+    }
+
+    int errno = 0;
+    size_t len = strlen(name);
+
+    if (len > VFS_NAME_MAXLEN) {
+        return ERANGE;
+    }
+
+    struct hstr hname = HSTR(name, len);
+
+    hstr_rehash(&hname, HSTR_FULL_HASH);
+
+    struct v_xattr_entry* entry = xattr_getcache(inode, &hname);
+    if (!entry) {
+        if (!(entry = xattr_new(&hname))) {
+            return ENOMEM;
+        }
+    }
+
+    if (!(errno = inode->ops->getxattr(inode, entry))) {
+        *xentry = entry;
+        xattr_addcache(inode, entry);
+    } else {
+        xattr_free(entry);
+    }
+    return errno;
+}
+
+int
+__vfs_setxattr(struct v_inode* inode,
+               const char* name,
+               const void* data,
+               size_t len)
+{
+    if (!inode->ops->setxattr || !inode->ops->delxattr) {
+        return ENOTSUP;
+    }
+
+    int errno = 0;
+    size_t slen = strlen(name);
+
+    if (slen > VFS_NAME_MAXLEN) {
+        return ERANGE;
+    }
+
+    struct hstr hname = HSTR(name, slen);
+
+    hstr_rehash(&hname, HSTR_FULL_HASH);
+
+    struct v_xattr_entry* entry = xattr_getcache(inode, &hname);
+    if (!entry) {
+        if (!(entry = xattr_new(&hname))) {
+            return ENOMEM;
+        }
+    } else {
+        xattr_delcache(inode, entry);
+    }
+
+    if ((errno = inode->ops->delxattr(inode, entry))) {
+        xattr_free(entry);
+        goto done;
+    }
+
+    entry->value = data;
+    entry->len = len;
+
+    if ((errno = inode->ops->setxattr(inode, entry))) {
+        xattr_free(entry);
+        goto done;
+    }
+
+    xattr_addcache(inode, entry);
+done:
+    return errno;
+}
+
+__DEFINE_LXSYSCALL4(int,
+                    getxattr,
+                    const char*,
+                    path,
+                    const char*,
+                    name,
+                    void*,
+                    value,
+                    size_t,
+                    len)
+{
+    struct v_dnode* dnode;
+    struct v_xattr_entry* xattr;
+    int errno = 0;
+
+    if ((errno = vfs_walk_proc(path, &dnode, NULL, 0))) {
+        goto done;
+    }
+
+    if ((errno = __vfs_getxattr(dnode->inode, &xattr, name))) {
+        goto done;
+    }
+
+    if (len < xattr->len) {
+        errno = ERANGE;
+        goto done;
+    }
+
+    memcpy(value, xattr->value, len);
+
+done:
+    return DO_STATUS(errno);
+}
+
+__DEFINE_LXSYSCALL4(int,
+                    setxattr,
+                    const char*,
+                    path,
+                    const char*,
+                    name,
+                    void*,
+                    value,
+                    size_t,
+                    len)
+{
+    struct v_dnode* dnode;
+    struct v_xattr_entry* xattr;
+    int errno = 0;
+
+    if ((errno = vfs_walk_proc(path, &dnode, NULL, 0))) {
+        goto done;
+    }
+
+    if ((errno = __vfs_setxattr(dnode->inode, name, value, len))) {
+        goto done;
+    }
+
+done:
+    return DO_STATUS(errno);
+}
+
+__DEFINE_LXSYSCALL4(int,
+                    fgetxattr,
+                    int,
+                    fd,
+                    const char*,
+                    name,
+                    void*,
+                    value,
+                    size_t,
+                    len)
+{
+    struct v_fd* fd_s;
+    struct v_xattr_entry* xattr;
+    int errno = 0;
+
+    if ((errno = vfs_getfd(fd, &fd_s))) {
+        goto done;
+    }
+
+    if ((errno = __vfs_getxattr(fd_s->file->inode, &xattr, name))) {
+        goto done;
+    }
+
+    if (len < xattr->len) {
+        errno = ERANGE;
+        goto done;
+    }
+
+    memcpy(value, xattr->value, len);
+
+done:
+    return DO_STATUS(errno);
+}
+
+__DEFINE_LXSYSCALL4(int,
+                    fsetxattr,
+                    int,
+                    fd,
+                    const char*,
+                    name,
+                    void*,
+                    value,
+                    size_t,
+                    len)
+{
+    struct v_fd* fd_s;
+    struct v_xattr_entry* xattr;
+    int errno = 0;
+
+    if ((errno = vfs_getfd(fd, &fd_s))) {
+        goto done;
+    }
+
+    if ((errno = __vfs_setxattr(fd_s->file->inode, name, value, len))) {
+        goto done;
+    }
+
+done:
+    return DO_STATUS(errno);
+}
\ No newline at end of file
index 277efb32eaf8370fc8f265ef8038ce4d1960004f..dc1b3ccb1c1af2f9e537457a6fc8b01637b472c5 100644 (file)
@@ -9,7 +9,7 @@
  * @return unsigned int
  */
 uint32_t
-strhash_32(char* str, uint32_t truncate_to)
+strhash_32(const char* str, uint32_t truncate_to)
 {
     if (!str)
         return 0;