PatchworkOS  dbbdc99
A non-POSIX operating system.
Loading...
Searching...
No Matches
devfs.c
Go to the documentation of this file.
1#include <kernel/fs/devfs.h>
2
3#include <kernel/fs/dentry.h>
4#include <kernel/fs/file.h>
6#include <kernel/fs/mount.h>
8#include <kernel/fs/path.h>
10#include <kernel/fs/vfs.h>
11#include <kernel/fs/vnode.h>
12#include <kernel/log/log.h>
13#include <kernel/log/panic.h>
14#include <kernel/sched/sched.h>
15#include <kernel/sync/lock.h>
16
17#include <assert.h>
18#include <errno.h>
19#include <stdatomic.h>
20#include <stdlib.h>
21#include <string.h>
22#include <sys/fs.h>
23#include <sys/list.h>
24
25static dentry_t* root = NULL;
26
30
31static dentry_t* devfs_mount(filesystem_t* fs, const char* options, void* data)
32{
33 UNUSED(fs);
34 UNUSED(data);
35
36 if (options != NULL)
37 {
38 errno = EINVAL;
39 return NULL;
40 }
41
42 return REF(root);
43}
44
47 .mount = devfs_mount,
48};
49
50void devfs_init(void)
51{
53 {
54 panic(NULL, "Failed to register devfs");
55 }
56
58 if (superblock == NULL)
59 {
60 panic(NULL, "Failed to create devfs superblock");
61 }
62 UNREF_DEFER(superblock);
63
64 vnode_t* vnode = vnode_new(superblock, VDIR, NULL, NULL);
65 if (vnode == NULL)
66 {
67 panic(NULL, "Failed to create devfs root vnode");
68 }
69 UNREF_DEFER(vnode);
70
71 dentry_t* dentry = dentry_new(superblock, NULL, NULL);
72 if (dentry == NULL)
73 {
74 panic(NULL, "Failed to create devfs root dentry");
75 }
76
77 dentry_make_positive(dentry, vnode);
78 superblock->root = dentry;
79 root = dentry;
80}
81
82dentry_t* devfs_dir_new(dentry_t* parent, const char* name, const vnode_ops_t* vnodeOps, void* data)
83{
84 if (name == NULL)
85 {
86 errno = EINVAL;
87 return NULL;
88 }
89
90 if (parent == NULL)
91 {
92 parent = root;
93 }
94
95 if (parent->superblock->fs != &devfs)
96 {
97 errno = EXDEV;
98 return NULL;
99 }
100
101 dentry_t* dir = dentry_new(parent->superblock, parent, name);
102 if (dir == NULL)
103 {
104 return NULL;
105 }
107
108 vnode_t* vnode = vnode_new(parent->superblock, VDIR, vnodeOps, NULL);
109 if (vnode == NULL)
110 {
111 return NULL;
112 }
113 UNREF_DEFER(vnode);
114 vnode->data = data;
115
117
118 return REF(dir);
119}
120
121dentry_t* devfs_file_new(dentry_t* parent, const char* name, const vnode_ops_t* vnodeOps, const file_ops_t* fileOps,
122 void* data)
123{
124 if (name == NULL)
125 {
126 errno = EINVAL;
127 return NULL;
128 }
129
130 if (parent == NULL)
131 {
132 parent = root;
133 }
134
135 if (parent->superblock->fs != &devfs)
136 {
137 errno = EXDEV;
138 return NULL;
139 }
140
141 dentry_t* dentry = dentry_new(parent->superblock, parent, name);
142 if (dentry == NULL)
143 {
144 return NULL;
145 }
146 UNREF_DEFER(dentry);
147
148 vnode_t* vnode = vnode_new(parent->superblock, VREG, vnodeOps, fileOps);
149 if (vnode == NULL)
150 {
151 return NULL;
152 }
153 UNREF_DEFER(vnode);
154 vnode->data = data;
155
156 dentry_make_positive(dentry, vnode);
157
158 return REF(dentry);
159}
160
161dentry_t* devfs_symlink_new(dentry_t* parent, const char* name, const vnode_ops_t* vnodeOps, void* data)
162{
163 if (parent == NULL || name == NULL || vnodeOps == NULL)
164 {
165 errno = EINVAL;
166 return NULL;
167 }
168
169 if (parent->superblock->fs != &devfs)
170 {
171 errno = EXDEV;
172 return NULL;
173 }
174
175 dentry_t* dentry = dentry_new(parent->superblock, parent, name);
176 if (dentry == NULL)
177 {
178 return NULL;
179 }
180 UNREF_DEFER(dentry);
181
182 vnode_t* vnode = vnode_new(parent->superblock, VSYMLINK, vnodeOps, NULL);
183 if (vnode == NULL)
184 {
185 return NULL;
186 }
187 UNREF_DEFER(vnode);
188 vnode->data = data;
189
190 dentry_make_positive(dentry, vnode);
191
192 return REF(dentry);
193}
194
196{
197 if (out == NULL || descs == NULL)
198 {
199 errno = EINVAL;
200 return ERR;
201 }
202
203 if (parent == NULL)
204 {
205 parent = root;
206 }
207
208 if (parent->superblock->fs != &devfs)
209 {
210 errno = EXDEV;
211 return ERR;
212 }
213
214 list_t createdList = LIST_CREATE(createdList);
215
216 uint64_t count = 0;
217 for (const devfs_file_desc_t* desc = descs; desc->name != NULL; desc++)
218 {
219 dentry_t* file = devfs_file_new(parent, desc->name, desc->vnodeOps, desc->fileOps, desc->data);
220 if (file == NULL)
221 {
222 while (!list_is_empty(&createdList))
223 {
224 UNREF(CONTAINER_OF_SAFE(list_pop_front(&createdList), dentry_t, otherEntry));
225 }
226 return ERR;
227 }
228
229 list_push_back(&createdList, &file->otherEntry);
230 count++;
231 }
232
233 if (out == NULL)
234 {
235 while (!list_is_empty(&createdList))
236 {
237 UNREF(CONTAINER_OF_SAFE(list_pop_front(&createdList), dentry_t, otherEntry));
238 }
239 return count;
240 }
241
242 while (!list_is_empty(&createdList))
243 {
244 dentry_t* file = CONTAINER_OF_SAFE(list_pop_front(&createdList), dentry_t, otherEntry);
245 list_push_back(out, &file->otherEntry);
246 }
247 return count;
248}
249
251{
252 if (files == NULL)
253 {
254 return;
255 }
256
257 while (!list_is_empty(files))
258 {
260 }
261}
static dentry_ops_t dentryOps
Definition devfs.c:27
static dentry_t * devfs_mount(filesystem_t *fs, const char *options, void *data)
Definition devfs.c:31
static filesystem_t devfs
Definition devfs.c:45
static dentry_t * root
Definition devfs.c:25
static fd_t data
Definition dwm.c:21
static dentry_t * dir
Definition fb.c:16
dentry_t * dentry_new(superblock_t *superblock, dentry_t *parent, const char *name)
Create a new dentry.
Definition dentry.c:134
uint64_t dentry_generic_iterate(dentry_t *dentry, dir_ctx_t *ctx)
Helper function for a basic iterate.
Definition dentry.c:325
void dentry_make_positive(dentry_t *dentry, vnode_t *vnode)
Make a dentry positive by associating it with an vnode.
Definition dentry.c:289
uint64_t devfs_files_new(list_t *out, dentry_t *parent, const devfs_file_desc_t *descs)
Create multiple files in a devfs directory.
Definition devfs.c:195
void devfs_init(void)
Initializes the devfs.
Definition devfs.c:50
void devfs_files_free(list_t *files)
Free all files in a list created by devfs_files_new().
Definition devfs.c:250
dentry_t * devfs_file_new(dentry_t *parent, const char *name, const vnode_ops_t *vnodeOps, const file_ops_t *fileOps, void *data)
Create a new file inside a mounted devfs instance.
Definition devfs.c:121
#define DEVFS_NAME
The name of the device filesystem.
Definition devfs.h:26
dentry_t * devfs_dir_new(dentry_t *parent, const char *name, const vnode_ops_t *vnodeOps, void *data)
Create a new directory inside a mounted devfs instance.
Definition devfs.c:82
dentry_t * devfs_symlink_new(dentry_t *parent, const char *name, const vnode_ops_t *vnodeOps, void *data)
Create a new symbolic link inside a mounted devfs instance.
Definition devfs.c:161
uint64_t filesystem_register(filesystem_t *fs)
Registers a filesystem.
Definition filesystem.c:233
superblock_t * superblock_new(filesystem_t *fs, const superblock_ops_t *ops, const dentry_ops_t *dentryOps)
Create a new superblock.
Definition superblock.c:33
vnode_t * vnode_new(superblock_t *superblock, vtype_t type, const vnode_ops_t *ops, const file_ops_t *fileOps)
Create a new vnode.
Definition vnode.c:51
NORETURN void panic(const interrupt_frame_t *frame, const char *format,...)
Panic the kernel, printing a message and halting.
Definition panic.c:292
#define UNREF_DEFER(ptr)
RAII-style cleanup for scoped references.
Definition ref.h:122
#define REF(ptr)
Increment reference count.
Definition ref.h:82
#define UNREF(ptr)
Decrement reference count.
Definition ref.h:109
#define EINVAL
Invalid argument.
Definition errno.h:142
#define EXDEV
Cross-device link.
Definition errno.h:122
#define errno
Error number variable.
Definition errno.h:27
#define UNUSED(x)
Mark a variable as unused.
Definition defs.h:96
@ VSYMLINK
Is a symbolic link.
Definition fs.h:345
@ VREG
Is a regular file.
Definition fs.h:343
@ VDIR
Is a directory.
Definition fs.h:344
static void list_push_back(list_t *list, list_entry_t *entry)
Pushes an entry to the end of the list.
Definition list.h:322
#define LIST_CREATE(name)
Creates a list initializer.
Definition list.h:163
static bool list_is_empty(list_t *list)
Checks if a list is empty.
Definition list.h:210
static list_entry_t * list_pop_back(list_t *list)
Pops the last entry from the list.
Definition list.h:386
static list_entry_t * list_pop_front(list_t *list)
Pops the first entry from the list.
Definition list.h:366
#define NULL
Pointer error value.
Definition NULL.h:25
#define ERR
Integer error value.
Definition ERR.h:17
#define CONTAINER_OF_SAFE(ptr, type, member)
Safe container of macro.
static list_t files
Definition file.c:9
static atomic_long count
Definition main.c:11
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
Dentry operations structure.
Definition dentry.h:122
uint64_t(* iterate)(dentry_t *dentry, dir_ctx_t *ctx)
Iterate over the entries in a directory dentry.
Definition dentry.h:138
Directory entry structure.
Definition dentry.h:155
char name[MAX_NAME]
The name of the dentry, immutable after creation.
Definition dentry.h:158
list_entry_t otherEntry
Made available for use by any other subsystems for convenience.
Definition dentry.h:169
superblock_t * superblock
Definition dentry.h:163
Descriptor for batch file creation.
Definition devfs.h:73
const char * name
Name of the file, NULL marks end of array.
Definition devfs.h:74
File operations structure.
Definition file.h:54
Filesystem structure, represents a filesystem type, e.g. fat32, tmpfs, devfs, etc.
Definition filesystem.h:53
const char * name
Definition filesystem.h:58
A doubly linked list.
Definition list.h:46
Superblock structure.
Definition superblock.h:33
filesystem_t * fs
Definition superblock.h:44
dentry_t * root
Root dentry of the filesystem, should not take a reference.
Definition superblock.h:40
vnode operations structure.
Definition vnode.h:69
vnode structure.
Definition vnode.h:48
void * data
Filesystem defined data.
Definition vnode.h:52
static vnode_ops_t vnodeOps
Definition tmpfs.c:195
static file_ops_t fileOps
Definition tmpfs.c:86