chore: minor refactoring and fix.
+ 内存管理与按需分页(Demand Paging)
+ 键盘输入
+ 多进程
-+ 40个常见的Linux/POSIX系统调用([附录1](#appendix1))
++ 44个常见的Linux/POSIX系统调用([附录1](#appendix1))
+ 用户模式
+ 信号机制
+ PCI 3.0
## 附录1:支持的系统调用<a id="appendix1"></a>
-### Unix/Linux/POSIX
+**Unix/Linux/POSIX**
1. `sleep(3)`
1. `wait(2)`
1. `waitpid(2)`
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系统上可以运行)。
#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
* @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);
}
{
uint32_t hash;
uint32_t len;
- char* value;
+ const char* value;
};
#define HSTR(str, length) \
__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 */
#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>
#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;
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;
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
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;
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,
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);
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);
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 */
#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 */
#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
.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
--- /dev/null
+#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
#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;
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);
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)
{
memset(inode, 0, sizeof(*inode));
mutex_init(&inode->lock);
+ llist_init_head(&inode->xattrs);
sb->ops.init_inode(sb, 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;
{
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;
}
struct v_fd* fd_s;
int errno;
- if ((errno = __vfs_getfd(fd, &fd_s))) {
+ if ((errno = vfs_getfd(fd, &fd_s))) {
goto done;
}
{
int errno = 0;
struct v_fd* fd_s;
- if ((errno = __vfs_getfd(fd, &fd_s))) {
+ if ((errno = vfs_getfd(fd, &fd_s))) {
goto done;
}
{
int errno = 0;
struct v_fd* fd_s;
- if ((errno = __vfs_getfd(fd, &fd_s))) {
+ if ((errno = vfs_getfd(fd, &fd_s))) {
goto done;
}
{
int errno = 0;
struct v_fd* fd_s;
- if ((errno = __vfs_getfd(fd, &fd_s))) {
+ if ((errno = vfs_getfd(fd, &fd_s))) {
goto done;
}
len += cpy_size;
if (len < size) {
- buf[len++] = PATH_DELIM;
+ buf[len++] = VFS_PATH_DELIM;
}
return len;
{
int errno;
struct v_fd* fd_s;
- if ((errno = __vfs_getfd(fd, &fd_s))) {
+ if ((errno = vfs_getfd(fd, &fd_s))) {
goto done;
}
{
int errno;
struct v_fd* fd_s;
- if ((errno = __vfs_getfd(dirfd, &fd_s))) {
+ if ((errno = vfs_getfd(dirfd, &fd_s))) {
goto done;
}
{
int errno;
struct v_fd* fd_s;
- if ((errno = __vfs_getfd(fd, &fd_s))) {
+ if ((errno = vfs_getfd(fd, &fd_s))) {
goto done;
}
{
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);
}
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;
}
{
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;
}
struct v_fd* fd_s;
int errno = 0;
- if ((errno = __vfs_getfd(fd, &fd_s))) {
+ if ((errno = vfs_getfd(fd, &fd_s))) {
goto done;
}
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);
--- /dev/null
+#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
* @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;