PatchworkOS  621ae6b
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/inode.h>
7#include <kernel/fs/mount.h>
9#include <kernel/fs/path.h>
11#include <kernel/fs/vfs.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/io.h>
23#include <sys/list.h>
24
25static dentry_t* root = NULL;
26
29};
30
34
35static dentry_t* devfs_mount(filesystem_t* fs, block_device_t* device, void* private)
36{
37 UNUSED(fs);
38 UNUSED(device);
39 UNUSED(private);
40
41 return REF(root);
42}
43
46 .mount = devfs_mount,
47};
48
49void devfs_init(void)
50{
52 {
53 panic(NULL, "Failed to register devfs");
54 }
55
57 if (superblock == NULL)
58 {
59 panic(NULL, "Failed to create devfs superblock");
60 }
61 UNREF_DEFER(superblock);
62
63 inode_t* inode = inode_new(superblock, vfs_id_get(), INODE_DIR, NULL, &dirOps);
64 if (inode == NULL)
65 {
66 panic(NULL, "Failed to create devfs root inode");
67 }
68 UNREF_DEFER(inode);
69
70 dentry_t* dentry = dentry_new(superblock, NULL, NULL);
71 if (dentry == NULL)
72 {
73 panic(NULL, "Failed to create devfs root dentry");
74 }
75
76 dentry_make_positive(dentry, inode);
77 superblock->root = dentry;
78 root = dentry;
79}
80
81dentry_t* devfs_dir_new(dentry_t* parent, const char* name, const inode_ops_t* inodeOps, void* private)
82{
83 if (name == NULL)
84 {
85 errno = EINVAL;
86 return NULL;
87 }
88
89 if (parent == NULL)
90 {
91 parent = root;
92 }
93
94 if (parent->superblock->fs != &devfs)
95 {
96 errno = EXDEV;
97 return NULL;
98 }
99
100 dentry_t* dir = dentry_new(parent->superblock, parent, name);
101 if (dir == NULL)
102 {
103 return NULL;
104 }
106
108 if (inode == NULL)
109 {
110 return NULL;
111 }
112 UNREF_DEFER(inode);
113 inode->private = private;
114
116
117 return REF(dir);
118}
119
120dentry_t* devfs_file_new(dentry_t* parent, const char* name, const inode_ops_t* inodeOps, const file_ops_t* fileOps,
121 void* private)
122{
123 if (name == NULL)
124 {
125 errno = EINVAL;
126 return NULL;
127 }
128
129 if (parent == NULL)
130 {
131 parent = root;
132 }
133
134 if (parent->superblock->fs != &devfs)
135 {
136 errno = EXDEV;
137 return NULL;
138 }
139
140 dentry_t* dentry = dentry_new(parent->superblock, parent, name);
141 if (dentry == NULL)
142 {
143 return NULL;
144 }
145 UNREF_DEFER(dentry);
146
148 if (inode == NULL)
149 {
150 return NULL;
151 }
152 UNREF_DEFER(inode);
153 inode->private = private;
154
155 dentry_make_positive(dentry, inode);
156
157 return REF(dentry);
158}
159
160dentry_t* devfs_symlink_new(dentry_t* parent, const char* name, const inode_ops_t* inodeOps, void* private)
161{
162 if (parent == NULL || name == NULL || inodeOps == NULL)
163 {
164 errno = EINVAL;
165 return NULL;
166 }
167
168 if (parent->superblock->fs != &devfs)
169 {
170 errno = EXDEV;
171 return NULL;
172 }
173
174 dentry_t* dentry = dentry_new(parent->superblock, parent, name);
175 if (dentry == NULL)
176 {
177 return NULL;
178 }
179 UNREF_DEFER(dentry);
180
182 if (inode == NULL)
183 {
184 return NULL;
185 }
186 UNREF_DEFER(inode);
187 inode->private = private;
188
189 dentry_make_positive(dentry, inode);
190
191 return REF(dentry);
192}
193
195{
196 if (out == NULL || descs == NULL)
197 {
198 errno = EINVAL;
199 return ERR;
200 }
201
202 if (parent == NULL)
203 {
204 parent = root;
205 }
206
207 if (parent->superblock->fs != &devfs)
208 {
209 errno = EXDEV;
210 return ERR;
211 }
212
214
215 for (const devfs_file_desc_t* desc = descs; desc->name != NULL; desc++)
216 {
217 dentry_t* file = devfs_file_new(parent, desc->name, desc->inodeOps, desc->fileOps, desc->private);
218 if (file == NULL)
219 {
220 while (!list_is_empty(&createdList))
221 {
223 }
224 return ERR;
225 }
226
228 }
229
231
232 if (out == NULL)
233 {
234 while (!list_is_empty(&createdList))
235 {
237 }
238 return count;
239 }
240
241 while (!list_is_empty(&createdList))
242 {
245 }
246 return count;
247}
248
250{
251 if (files == NULL)
252 {
253 return;
254 }
255
256 while (!list_is_empty(files))
257 {
259 }
260}
int64_t y
Definition main.c:153
dentry_t * devfs_dir_new(dentry_t *parent, const char *name, const inode_ops_t *inodeOps, void *private)
Create a new directory inside a mounted devfs instance.
Definition devfs.c:81
static dentry_ops_t dentryOps
Definition devfs.c:31
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:194
static filesystem_t devfs
Definition devfs.c:44
dentry_t * devfs_symlink_new(dentry_t *parent, const char *name, const inode_ops_t *inodeOps, void *private)
Create a new symbolic link inside a mounted devfs instance.
Definition devfs.c:160
static dentry_t * devfs_mount(filesystem_t *fs, block_device_t *device, void *private)
Definition devfs.c:35
dentry_t * devfs_file_new(dentry_t *parent, const char *name, const inode_ops_t *inodeOps, const file_ops_t *fileOps, void *private)
Create a new file inside a mounted devfs instance.
Definition devfs.c:120
void devfs_init(void)
Initializes the devfs.
Definition devfs.c:49
void devfs_files_free(list_t *files)
Free all files in a list created by devfs_files_new().
Definition devfs.c:249
static dentry_t * root
Definition devfs.c:25
static file_ops_t dirOps
Definition devfs.c:27
#define DEVFS_NAME
The name of the device filesystem.
Definition devfs.h:23
static dentry_t * dir
Definition fb.c:16
void dentry_make_positive(dentry_t *dentry, inode_t *inode)
Make a dentry positive by associating it with an inode.
Definition dentry.c:277
dentry_t * dentry_new(superblock_t *superblock, dentry_t *parent, const char *name)
Create a new dentry.
Definition dentry.c:116
uint64_t dentry_generic_iterate(dentry_t *dentry, dir_ctx_t *ctx)
Helper function for a basic iterate.
Definition dentry.c:313
size_t file_generic_seek(file_t *file, ssize_t offset, seek_origin_t origin)
Helper function for basic seeking.
Definition file.c:69
uint64_t filesystem_register(filesystem_t *fs)
Registers a filesystem.
Definition filesystem.c:40
inode_t * inode_new(superblock_t *superblock, ino_t number, itype_t type, const inode_ops_t *ops, const file_ops_t *fileOps)
Create a new inode.
Definition inode.c:41
superblock_t * superblock_new(filesystem_t *fs, block_device_t *device, const superblock_ops_t *ops, const dentry_ops_t *dentryOps)
Create a new superblock.
Definition superblock.c:33
NORETURN void panic(const interrupt_frame_t *frame, const char *format,...)
Panic the kernel, printing a message and halting.
Definition panic.c:267
#define UNREF_DEFER(ptr)
RAII-style cleanup for scoped references.
Definition ref.h:69
#define REF(ptr)
Increment reference count.
Definition ref.h:80
#define UNREF(ptr)
Decrement reference count.
Definition ref.h:95
uint64_t vfs_id_get(void)
Generates a new unique ID, to be used for any VFS object.
Definition vfs.c:1277
#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:100
@ INODE_FILE
Is a file.
Definition io.h:342
@ INODE_DIR
Is a directory.
Definition io.h:343
@ INODE_SYMLINK
Is a symbolic link.
Definition io.h:344
static uint64_t list_length(list_t *list)
Gets the length of the list.
Definition list.h:232
static void list_push_back(list_t *list, list_entry_t *entry)
Pushes an entry to the end of the list.
Definition list.h:324
#define LIST_CREATE(name)
Creates a list initializer.
Definition list.h:165
static bool list_is_empty(list_t *list)
Checks if a list is empty.
Definition list.h:214
static list_entry_t * list_pop_back(list_t *list)
Pops the last entry from the list.
Definition list.h:374
static list_entry_t * list_pop_front(list_t *list)
Pops the first entry from the list.
Definition list.h:354
#define NULL
Pointer error value.
Definition NULL.h:23
#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
Block device type.
Definition superblock.h:40
Dentry operations structure.
Definition dentry.h:121
uint64_t(* iterate)(dentry_t *dentry, dir_ctx_t *ctx)
Iterate over the entries in a directory dentry.
Definition dentry.h:137
Directory entry structure.
Definition dentry.h:153
char name[MAX_NAME]
Constant after creation.
Definition dentry.h:156
list_entry_t otherEntry
Made available for use by any other subsystems for convenience.
Definition dentry.h:166
superblock_t * superblock
Definition dentry.h:161
Descriptor for batch file creation.
Definition devfs.h:74
const char * name
Name of the file, NULL marks end of array.
Definition devfs.h:75
File operations structure.
Definition file.h:54
size_t(* seek)(file_t *file, ssize_t offset, seek_origin_t origin)
Definition file.h:60
Filesystem structure, represents a filesystem type, e.g. fat32, tmpfs, devfs, etc.
Definition filesystem.h:33
const char * name
Definition filesystem.h:37
Inode operations structure.
Definition inode.h:74
Inode structure.
Definition inode.h:49
void * private
Definition inode.h:60
A doubly linked list.
Definition list.h:47
Superblock structure.
Definition superblock.h:49
filesystem_t * fs
Definition superblock.h:60
dentry_t * root
Root dentry of the filesystem, should not take a reference.
Definition superblock.h:56
static inode_ops_t inodeOps
Definition tmpfs.c:195
static file_ops_t fileOps
Definition tmpfs.c:86