#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
#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();
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);
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);
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;
};
* @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.
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)
{
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
{
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
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,
/* ---- 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)
}
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;
}
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;
}
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);
+#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/lunaix.h>
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);
}
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);
}