feat: a pseudo shell environment for basic interacting and testing purpose
[lunaix-os.git] / lunaix-os / kernel / fs / ramfs / ramfs.c
1 /**
2  * @file ramfs.c
3  * @author Lunaixsky
4  * @brief RamFS - a file system sit in RAM
5  * @version 0.1
6  * @date 2022-08-18
7  *
8  * @copyright Copyright (c) 2022
9  *
10  */
11 #include <lunaix/fs.h>
12 #include <lunaix/fs/ramfs.h>
13 #include <lunaix/mm/valloc.h>
14
15 /*
16     A RAM FS will play a role of being a root.
17
18     This is an temporary meaure as we don't have any concrete fs
19     yet. In the near future, we will have an ISO-9660 as our first
20     fs and mount our boot medium as root. And similar thing could
21     be done when we have installed our OS into hard disk, in that
22     case, our rootfs will be something like ext2.
23
24     RamFS vs. TwiFS: Indeed, they are both fs that lives in RAM so
25     there is no foundmentally differences. However, TwiFS is designed
26     to be a 'virtual FIlesystem for KERnel space' (FIKER), so other
27     kernel sub-modules can just create node and attach their own
28     implementation of read/write, without brothering to create a
29     full featured concrete filesystem. This particularly useful for
30     kernel state exposure. In Lunaix, TwiFS is summation of procfs,
31     sysfs and kernfs in Linux world.
32
33     However, there is a smell of bad-design in the concept of TwiFS.
34     Since it tries to integrate too much responsibility. The TwiFS may
35     be replaced by more specific fs in the future.
36
37     On the other hand, RamFS is designed to be act like a dummy fs
38     that just ensure 'something there at least' and thus provide basic
39     'mountibility' for other fs.
40 */
41
42 volatile static inode_t ino = 0;
43
44 extern const struct v_inode_ops ramfs_inode_ops;
45 extern const struct v_file_ops ramfs_file_ops;
46
47 int
48 ramfs_readdir(struct v_file* file, struct dir_context* dctx)
49 {
50     int i = 0;
51     struct v_dnode *pos, *n;
52     llist_for_each(pos, n, &file->dnode->children, siblings)
53     {
54         if (i++ >= dctx->index) {
55             dctx->read_complete_callback(
56               dctx, pos->name.value, pos->name.len, 0);
57             return 1;
58         }
59     }
60     return 0;
61 }
62
63 int
64 ramfs_mkdir(struct v_inode* this, struct v_dnode* dnode)
65 {
66     struct v_inode* inode = vfs_i_alloc(dnode->super_block);
67     inode->itype = VFS_IFDIR;
68
69     vfs_i_addhash(inode);
70     vfs_assign_inode(dnode, inode);
71
72     return 0;
73 }
74
75 int
76 ramfs_create(struct v_inode* this, struct v_dnode* dnode)
77 {
78     struct v_inode* inode = vfs_i_alloc(dnode->super_block);
79     inode->itype = VFS_IFFILE;
80
81     vfs_i_addhash(inode);
82     vfs_assign_inode(dnode, inode);
83
84     return 0;
85 }
86
87 void
88 ramfs_inode_init(struct v_superblock* vsb, struct v_inode* inode)
89 {
90     inode->id = ino++;
91     inode->ops = &ramfs_inode_ops;
92     inode->default_fops = &ramfs_file_ops;
93 }
94
95 int
96 ramfs_mount(struct v_superblock* vsb, struct v_dnode* mount_point)
97 {
98     vsb->ops.init_inode = ramfs_inode_init;
99
100     struct v_inode* inode = vfs_i_alloc(vsb);
101     inode->itype = VFS_IFDIR;
102
103     vfs_i_addhash(inode);
104     vfs_assign_inode(mount_point, inode);
105
106     return 0;
107 }
108
109 int
110 ramfs_unmount(struct v_superblock* vsb)
111 {
112     return 0;
113 }
114
115 void
116 ramfs_init()
117 {
118     struct filesystem* ramfs = fsm_new_fs("ramfs", 5);
119     ramfs->mount = ramfs_mount;
120     ramfs->unmount = ramfs_unmount;
121
122     fsm_register(ramfs);
123 }
124
125 const struct v_inode_ops ramfs_inode_ops = { .mkdir = ramfs_mkdir,
126                                              .rmdir = default_inode_rmdir,
127                                              .dir_lookup =
128                                                default_inode_dirlookup,
129                                              .create = ramfs_create,
130                                              .open = default_inode_open,
131                                              .rename = default_inode_rename };
132
133 const struct v_file_ops ramfs_file_ops = { .readdir = ramfs_readdir,
134                                            .close = default_file_close,
135                                            .read = default_file_read,
136                                            .write = default_file_write,
137                                            .seek = default_file_seek };