PatchworkOS  621ae6b
A non-POSIX operating system.
Loading...
Searching...
No Matches
netfs.c
Go to the documentation of this file.
1#include <kernel/fs/ctl.h>
2#include <kernel/fs/dentry.h>
3#include <kernel/fs/devfs.h>
5#include <kernel/fs/mount.h>
6#include <kernel/fs/netfs.h>
7#include <kernel/fs/path.h>
8#include <kernel/fs/vfs.h>
9#include <kernel/log/log.h>
10#include <kernel/log/panic.h>
12#include <kernel/proc/process.h>
13#include <kernel/sched/sched.h>
14#include <kernel/sync/rwmutex.h>
15
16#include <sys/io.h>
17#include <sys/list.h>
18
21
23{
24 if (socket == NULL)
25 {
26 return;
27 }
28
29 rwmutex_write_acquire(&socket->family->mutex);
30 if (list_contains_entry(&socket->family->sockets, &socket->listEntry))
31 {
32 list_remove(&socket->family->sockets, &socket->listEntry);
33 }
34 rwmutex_write_release(&socket->family->mutex);
35
36 socket->family->deinit(socket);
37 free(socket);
38}
39
41{
43
44 socket_t* socket = malloc(sizeof(socket_t));
45 if (socket == NULL)
46 {
47 errno = ENOMEM;
48 return NULL;
49 }
50
52 list_entry_init(&socket->listEntry);
54 socket->family = family;
55 socket->type = type;
56 socket->state = SOCKET_NEW;
57 weak_ptr_set(&socket->ownerNs, NULL, NULL, NULL);
58 socket->private = NULL;
59 mutex_init(&socket->mutex);
60
61 if (socket->family->init(socket) == ERR)
62 {
63 free(socket);
64 return NULL;
65 }
66
67 return socket;
68}
69
70typedef struct socket_file
71{
72 const char* name;
75
77{
78 socket_t* sock = file->inode->private;
79 assert(sock != NULL);
80
81 file->private = REF(sock);
82 return 0;
83}
84
85static void netfs_data_close(file_t* file)
86{
87 socket_t* sock = file->private;
88 if (sock == NULL)
89 {
90 return;
91 }
92
93 UNREF(sock);
94}
95
96static size_t netfs_data_read(file_t* file, void* buf, size_t count, size_t* offset)
97{
98 socket_t* sock = file->private;
99 assert(sock != NULL);
100
101 if (sock->family->recv == NULL)
102 {
103 errno = ENOSYS;
104 return 0;
105 }
106
107 MUTEX_SCOPE(&sock->mutex);
108
109 if (sock->state != SOCKET_CONNECTED)
110 {
111 errno = ENOTCONN;
112 return ERR;
113 }
114
115 return sock->family->recv(sock, buf, count, offset, file->mode);
116}
117
118static size_t netfs_data_write(file_t* file, const void* buf, size_t count, size_t* offset)
119{
120 socket_t* sock = file->private;
121 assert(sock != NULL);
122
123 if (sock->family->send == NULL)
124 {
125 errno = ENOSYS;
126 return 0;
127 }
128
129 MUTEX_SCOPE(&sock->mutex);
130
131 if (sock->state != SOCKET_CONNECTED)
132 {
133 errno = ENOTCONN;
134 return ERR;
135 }
136
137 return sock->family->send(sock, buf, count, offset, file->mode);
138}
139
141{
142 socket_t* sock = file->private;
143 assert(sock != NULL);
144
145 if (sock->family->poll == NULL)
146 {
147 errno = ENOSYS;
148 return NULL;
149 }
150
151 MUTEX_SCOPE(&sock->mutex);
152
153 return sock->family->poll(sock, revents);
154}
155
158 .close = netfs_data_close,
159 .read = netfs_data_read,
160 .write = netfs_data_write,
161 .poll = netfs_data_poll,
162};
163
165{
166 socket_t* sock = file->inode->private;
167 assert(sock != NULL);
168
169 if (sock->family->accept == NULL)
170 {
171 errno = ENOSYS;
172 return ERR;
173 }
174
175 MUTEX_SCOPE(&sock->mutex);
176
177 if (sock->state != SOCKET_LISTENING)
178 {
179 errno = EINVAL;
180 return ERR;
181 }
182
183 socket_t* newSock = socket_new(sock->family, sock->type);
184 if (newSock == NULL)
185 {
186 return ERR;
187 }
188
189 if (sock->family->accept(sock, newSock, file->mode) == ERR)
190 {
192 return ERR;
193 }
194
195 newSock->state = SOCKET_CONNECTED;
196 file->private = newSock;
197 file->ops = &dataOps;
198 return 0;
199}
200
204
205static uint64_t netfs_ctl_bind(file_t* file, uint64_t argc, const char** argv)
206{
207 UNUSED(argc);
208
209 socket_t* sock = file->inode->private;
210 assert(sock != NULL);
211
212 if (sock->family->bind == NULL)
213 {
214 errno = ENOSYS;
215 return ERR;
216 }
217
218 MUTEX_SCOPE(&sock->mutex);
219
220 if (sock->state != SOCKET_NEW)
221 {
222 errno = EINVAL;
223 return ERR;
224 }
225
226 strncpy(sock->address, argv[1], sizeof(sock->address));
227 sock->address[sizeof(sock->address) - 1] = '\0';
228
229 if (sock->family->bind(sock) == ERR)
230 {
231 return ERR;
232 }
233
234 sock->state = SOCKET_BOUND;
235 return 0;
236}
237
238static uint64_t netfs_ctl_listen(file_t* file, uint64_t argc, const char** argv)
239{
240 UNUSED(argc);
241
243 if (argc == 2)
244 {
245 if (sscanf(argv[1], "%llu", &backlog) != 1)
246 {
247 errno = EINVAL;
248 return ERR;
249 }
250
251 if (backlog == 0)
252 {
253 errno = EINVAL;
254 return ERR;
255 }
256 }
257
258 socket_t* sock = file->inode->private;
259 assert(sock != NULL);
260
261 if (sock->family->listen == NULL)
262 {
263 errno = ENOSYS;
264 return ERR;
265 }
266
267 MUTEX_SCOPE(&sock->mutex);
268
269 if (sock->state != SOCKET_BOUND)
270 {
271 errno = EINVAL;
272 return ERR;
273 }
274
275 if (sock->family->listen(sock, backlog) == ERR)
276 {
277 return ERR;
278 }
279
280 sock->state = SOCKET_LISTENING;
281 return 0;
282}
283
284static uint64_t netfs_ctl_connect(file_t* file, uint64_t argc, const char** argv)
285{
286 UNUSED(argc);
287
288 socket_t* sock = file->inode->private;
289 assert(sock != NULL);
290
291 if (sock->family->connect == NULL)
292 {
293 errno = ENOSYS;
294 return ERR;
295 }
296
297 MUTEX_SCOPE(&sock->mutex);
298
299 if (sock->state != SOCKET_NEW && sock->state != SOCKET_BOUND)
300 {
301 errno = EINVAL;
302 return ERR;
303 }
304
305 strncpy(sock->address, argv[1], sizeof(sock->address));
306 sock->address[sizeof(sock->address) - 1] = '\0';
307
308 if (sock->family->connect(sock) == ERR)
309 {
310 return ERR;
311 }
312
313 sock->state = SOCKET_CONNECTED;
314 return 0;
315}
316
318 {
319 {"bind", netfs_ctl_bind, 2, 2},
320 {"listen", netfs_ctl_listen, 1, 2},
321 {"connect", netfs_ctl_connect, 2, 2},
322 {0},
323 });
324
326 {.name = "data", .fileOps = &dataOps},
327 {.name = "accept", .fileOps = &acceptOps},
328 {.name = "ctl", .fileOps = &ctlOps},
329};
330
332{
333 for (size_t i = 0; i < ARRAY_SIZE(socketFiles); i++)
334 {
335 if (strcmp(socketFiles[i].name, dentry->name) != 0)
336 {
337 continue;
338 }
339
342 if (inode == NULL)
343 {
344 return ERR;
345 }
346 UNREF_DEFER(inode);
347 inode->private = dir->private; // No reference
348
349 dentry_make_positive(dentry, inode);
350 return 0;
351 }
352
353 return 0;
354}
355
356static void netfs_socket_cleanup(inode_t* inode)
357{
358 socket_t* socket = (socket_t*)inode->private;
359 if (socket == NULL)
360 {
361 return;
362 }
363
364 UNREF(socket);
365}
366
368{
369 if (!dentry_iterate_dots(dentry, ctx))
370 {
371 return 0;
372 }
373
374 for (size_t i = 0; i < ARRAY_SIZE(socketFiles); i++)
375 {
376 if (ctx->index++ < ctx->pos)
377 {
378 continue;
379 }
380
381 if (!ctx->emit(ctx, socketFiles[i].name, ino_gen(dentry->inode->number, socketFiles[i].name), INODE_FILE))
382 {
383 return 0;
384 }
385 }
386
387 return 0;
388}
389
394
398
405
411
412static void socket_weak_ptr_callback(void* arg)
413{
414 socket_t* socket = (socket_t*)arg;
415 UNREF(socket);
416}
417
419{
421 assert(ctx != NULL);
422 dentry_t* root = file->inode->superblock->root;
423 assert(root != NULL);
424
426 if (socket == NULL)
427 {
428 return ERR;
429 }
431
433 list_push_back(&ctx->family->sockets, &socket->listEntry);
435
437 if (ns == NULL)
438 {
439 return ERR;
440 }
441 UNREF_DEFER(ns);
442
444
445 file->private = REF(socket);
446 return 0;
447}
448
449static void netfs_factory_close(file_t* file)
450{
451 socket_t* socket = file->private;
452 if (socket == NULL)
453 {
454 return;
455 }
456
457 UNREF(socket);
458}
459
460static size_t netfs_factory_read(file_t* file, void* buffer, size_t count, size_t* offset)
461{
462 socket_t* socket = file->private;
463 if (socket == NULL)
464 {
465 return 0;
466 }
467
468 return BUFFER_READ(buffer, count, offset, socket->id, strlen(socket->id));
469}
470
473 .close = netfs_factory_close,
474 .read = netfs_factory_read,
475};
476
477static size_t netfs_addrs_read(file_t* file, void* buffer, size_t count, size_t* offset)
478{
480 assert(ctx != NULL);
481
483
484 if (list_is_empty(&ctx->family->sockets))
485 {
486 return 0;
487 }
488
489 char* string = malloc(list_length(&ctx->family->sockets) * (MAX_PATH + 1));
490 if (string == NULL)
491 {
492 errno = ENOMEM;
493 return ERR;
494 }
495
496 size_t length = 0;
498 LIST_FOR_EACH(socket, &ctx->family->sockets, listEntry)
499 {
500 if (socket->family != ctx->family)
501 {
502 continue;
503 }
504
505 if (socket->state != SOCKET_LISTENING)
506 {
507 continue;
508 }
509
510 length += snprintf(string + length, MAX_PATH, "%s\n", socket->address);
511 }
512
513 size_t bytesRead = BUFFER_READ(buffer, count, offset, string, length);
514 free(string);
515 return bytesRead;
516}
517
521
523 {.name = "stream", .type = SOCKET_STREAM, .fileOps = &factoryFileOps},
524 {.name = "dgram", .type = SOCKET_DGRAM, .fileOps = &factoryFileOps},
525 {.name = "seqpacket", .type = SOCKET_SEQPACKET, .fileOps = &factoryFileOps},
526 {.name = "raw", .type = SOCKET_RAW, .fileOps = &factoryFileOps},
527 {.name = "rdm", .type = SOCKET_RDM, .fileOps = &factoryFileOps},
528 {.name = "addrs", .type = 0, .fileOps = &addrsFileOps},
529};
530
531static void netfs_file_cleanup(inode_t* inode)
532{
533 netfs_family_file_ctx_t* ctx = inode->private;
534 if (ctx == NULL)
535 {
536 return;
537 }
538
539 free(ctx);
540 inode->private = NULL;
541}
542
546
548{
549 netfs_family_t* family = dir->private;
550 assert(family != NULL);
551
552 for (size_t i = 0; i < ARRAY_SIZE(familyFiles); i++)
553 {
554 if (strcmp(familyFiles[i].name, dentry->name) != 0)
555 {
556 continue;
557 }
558
561 if (inode == NULL)
562 {
563 return ERR;
564 }
565 UNREF_DEFER(inode);
566
568 if (ctx == NULL)
569 {
570 return ERR;
571 }
572 ctx->family = family;
573 ctx->fileInfo = &familyFiles[i];
574 inode->private = ctx;
575
576 dentry_make_positive(dentry, inode);
577 return 0;
578 }
579
580 RWMUTEX_READ_SCOPE(&family->mutex);
581
582 if (list_is_empty(&family->sockets))
583 {
584 return 0;
585 }
586
588 if (ns == NULL)
589 {
590 return ERR;
591 }
592 UNREF_DEFER(ns);
593
595 LIST_FOR_EACH(socket, &family->sockets, listEntry)
596 {
597 if (strcmp(socket->id, dentry->name) != 0)
598 {
599 continue;
600 }
601
602 namespace_t* ownerNs = weak_ptr_get(&socket->ownerNs);
603 if (ownerNs == NULL)
604 {
605 continue;
606 }
607 UNREF_DEFER(ownerNs);
608
609 if (ownerNs != ns)
610 {
611 continue;
612 }
613
615 if (inode == NULL)
616 {
617 return ERR;
618 }
619 UNREF_DEFER(inode);
620 inode->private = REF(socket);
621
622 dentry->ops = &socketDentryOps;
623
624 dentry_make_positive(dentry, inode);
625 return 0;
626 }
627
628 return 0;
629}
630
632{
633 netfs_family_t* family = dentry->inode->private;
634 assert(family != NULL);
635
636 if (!dentry_iterate_dots(dentry, ctx))
637 {
638 return 0;
639 }
640
641 for (size_t i = 0; i < ARRAY_SIZE(familyFiles); i++)
642 {
643 if (ctx->index++ < ctx->pos)
644 {
645 continue;
646 }
647
648 if (!ctx->emit(ctx, familyFiles[i].name, ino_gen(dentry->inode->number, familyFiles[i].name), INODE_FILE))
649 {
650 return 0;
651 }
652 }
653
654 RWMUTEX_READ_SCOPE(&family->mutex);
655
656 if (list_is_empty(&family->sockets))
657 {
658 return 0;
659 }
660
662 if (ns == NULL)
663 {
664 return ERR;
665 }
666 UNREF_DEFER(ns);
667
669 LIST_FOR_EACH(socket, &family->sockets, listEntry)
670 {
671 namespace_t* ownerNs = weak_ptr_get(&socket->ownerNs);
672 if (ownerNs == NULL)
673 {
674 continue;
675 }
676 UNREF_DEFER(ownerNs);
677
678 if (ownerNs != ns)
679 {
680 continue;
681 }
682
683 if (ctx->index++ < ctx->pos)
684 {
685 continue;
686 }
687
688 if (!ctx->emit(ctx, socket->id, ino_gen(dentry->inode->number, socket->id), INODE_DIR))
689 {
690 return 0;
691 }
692 }
693
694 return 0;
695}
696
700
704
706{
708
709 netfs_family_t* family;
710 LIST_FOR_EACH(family, &families, listEntry)
711 {
712 if (strcmp(family->name, dentry->name) != 0)
713 {
714 continue;
715 }
716
717 inode_t* inode =
719 if (inode == NULL)
720 {
721 return ERR;
722 }
723 UNREF_DEFER(inode);
724 inode->private = family;
725
726 dentry->ops = &familyDentryOps;
727
728 dentry_make_positive(dentry, inode);
729 return 0;
730 }
731
732 return 0;
733}
734
736{
737 if (!dentry_iterate_dots(dentry, ctx))
738 {
739 return 0;
740 }
741
743
744 netfs_family_t* family;
745 LIST_FOR_EACH(family, &families, listEntry)
746 {
747 if (ctx->index++ < ctx->pos)
748 {
749 continue;
750 }
751
752 if (!ctx->emit(ctx, family->name, ino_gen(dentry->inode->number, family->name), INODE_DIR))
753 {
754 return 0;
755 }
756 }
757
758 return 0;
759}
760
764
768
769static dentry_t* netfs_mount(filesystem_t* fs, block_device_t* device, void* private)
770{
771 UNUSED(private);
772
773 superblock_t* superblock = superblock_new(fs, device, NULL, NULL);
774 if (superblock == NULL)
775 {
776 return NULL;
777 }
778 UNREF_DEFER(superblock);
779
780 inode_t* inode = inode_new(superblock, 0, INODE_DIR, &netInodeOps, NULL);
781 if (inode == NULL)
782 {
783 return NULL;
784 }
785 UNREF_DEFER(inode);
786
787 dentry_t* dentry = dentry_new(superblock, NULL, NULL);
788 if (dentry == NULL)
789 {
790 return NULL;
791 }
792 dentry->ops = &netDentryOps;
793
794 dentry_make_positive(dentry, inode);
795
796 superblock->root = dentry;
797 return superblock->root;
798}
799
801 .name = NETFS_NAME,
802 .mount = netfs_mount,
803};
804
805void netfs_init(void)
806{
808 {
809 panic(NULL, "Failed to register netfs filesystem");
810 }
811}
812
814{
815 if (family == NULL || family->init == NULL || family->deinit == NULL)
816 {
817 errno = EINVAL;
818 return ERR;
819 }
820
821 list_entry_init(&family->listEntry);
822 list_init(&family->sockets);
823 rwmutex_init(&family->mutex);
824
828
829 return 0;
830}
831
#define MAX_PATH
Maximum length of filepaths.
Definition MAX_PATH.h:11
#define assert(expression)
Definition assert.h:29
int64_t y
Definition main.c:153
static dentry_t * root
Definition devfs.c:25
static dentry_t * dir
Definition fb.c:16
#define CTL_STANDARD_OPS_DEFINE(name,...)
Helper macro to define a standard ctl file operations structure.
Definition ctl.h:54
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
bool dentry_iterate_dots(dentry_t *dentry, dir_ctx_t *ctx)
Helper function to iterate over the special entries "." and "..".
Definition dentry.c:292
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
ino_t ino_gen(ino_t parentNumber, const char *name)
Helper to generate a consistent inode number for an entry in a directory.
Definition inode.c:134
#define NETFS_NAME
The name of the networking filesystem.
Definition netfs.h:85
#define NETFS_BACKLOG_DEFAULT
The default backlog size for listening sockets.
Definition netfs.h:90
socket_type_t
Socket types.
Definition netfs.h:97
uint64_t netfs_family_register(netfs_family_t *family)
Register a network family.
Definition netfs.c:813
void netfs_init(void)
Initialize the networking filesystem.
Definition netfs.c:805
void netfs_family_unregister(netfs_family_t *family)
Unregister a network family.
Definition netfs.c:832
@ SOCKET_LISTENING
Definition netfs.h:114
@ SOCKET_CONNECTED
Definition netfs.h:116
@ SOCKET_NEW
Definition netfs.h:112
@ SOCKET_BOUND
Definition netfs.h:113
@ SOCKET_RDM
A reliable datagram layer that does not guarantee ordering.
Definition netfs.h:102
@ SOCKET_STREAM
A sequenced, reliable, two-way connection-based byte stream.
Definition netfs.h:98
@ SOCKET_SEQPACKET
A sequenced, reliable, two-way connection-based packet stream.
Definition netfs.h:100
@ SOCKET_DGRAM
A connectionless, unreliable datagram service.
Definition netfs.h:99
@ SOCKET_RAW
Provides raw network protocol access.
Definition netfs.h:101
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
namespace_t * process_get_ns(process_t *process)
Gets the namespace of a process.
Definition process.c:164
process_t * sched_process(void)
Retrieves the process of the currently running thread.
Definition sched.c:620
void mutex_init(mutex_t *mtx)
Initializes a mutex.
Definition mutex.c:14
#define MUTEX_SCOPE(mutex)
Acquires a mutex for the reminder of the current scope.
Definition mutex.h:23
void rwmutex_write_acquire(rwmutex_t *mtx)
Acquires a rwmutex for writing, blocking until it is available.
Definition rwmutex.c:85
void rwmutex_init(rwmutex_t *mtx)
Initializes a rwmutex.
Definition rwmutex.c:10
#define RWMUTEX_READ_SCOPE(mutex)
Acquires a rwmutex for reading for the reminder of the current scope.
Definition rwmutex.h:21
#define RWMUTEX_CREATE(name)
Create a rwmutex initializer.
Definition rwmutex.h:58
void rwmutex_deinit(rwmutex_t *mtx)
Deinitializes a rwmutex.
Definition rwmutex.c:20
void rwmutex_write_release(rwmutex_t *mtx)
Releases a rwmutex from writing.
Definition rwmutex.c:124
static void weak_ptr_set(weak_ptr_t *wp, ref_t *ref, void(*callback)(void *), void *arg)
Set a weak pointer.
Definition ref.h:204
#define UNREF_DEFER(ptr)
RAII-style cleanup for scoped references.
Definition ref.h:69
static void * weak_ptr_get(weak_ptr_t *wp)
Upgrade a weak pointer to a strong pointer.
Definition ref.h:268
#define REF(ptr)
Increment reference count.
Definition ref.h:80
static void ref_init(ref_t *ref, void *callback)
Initialize a reference counter.
Definition ref.h:107
#define UNREF(ptr)
Decrement reference count.
Definition ref.h:95
#define BUFFER_READ(buffer, count, offset, src, size)
Helper macros for implementing file operations dealing with simple buffers.
Definition vfs.h:206
#define EINVAL
Invalid argument.
Definition errno.h:142
#define ENOSYS
Function not implemented.
Definition errno.h:222
#define ENOMEM
Out of memory.
Definition errno.h:92
#define errno
Error number variable.
Definition errno.h:27
#define ENOTCONN
Transport endpoint is not connected.
Definition errno.h:562
#define ARRAY_SIZE(x)
Get the number of elements in a static array.
Definition defs.h:108
#define UNUSED(x)
Mark a variable as unused.
Definition defs.h:100
poll_events_t
Poll events type.
Definition io.h:285
@ INODE_FILE
Is a file.
Definition io.h:342
@ INODE_DIR
Is a directory.
Definition io.h:343
#define LIST_FOR_EACH(elem, list, member)
Iterates over a list.
Definition list.h:60
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 void list_remove(list_t *list, list_entry_t *entry)
Removes a list entry from its current list.
Definition list.h:297
static bool list_is_empty(list_t *list)
Checks if a list is empty.
Definition list.h:214
static void list_entry_init(list_entry_t *entry)
Initializes a list entry.
Definition list.h:172
static bool list_contains_entry(list_t *list, list_entry_t *entry)
Check if an entry belongs to a specific list.
Definition list.h:200
static void list_init(list_t *list)
Initializes a list.
Definition list.h:185
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
static uint64_t offset
Definition screen.c:19
EFI_PHYSICAL_ADDRESS buffer
Definition mem.c:15
static void netfs_socket_cleanup(inode_t *inode)
Definition netfs.c:356
static file_ops_t acceptOps
Definition netfs.c:201
static dentry_ops_t familyDentryOps
Definition netfs.c:701
static uint64_t netfs_ctl_listen(file_t *file, uint64_t argc, const char **argv)
Definition netfs.c:238
static void socket_weak_ptr_callback(void *arg)
Definition netfs.c:412
static netfs_family_file_t familyFiles[]
Definition netfs.c:522
static uint64_t netfs_ctl_bind(file_t *file, uint64_t argc, const char **argv)
Definition netfs.c:205
static uint64_t netfs_ctl_connect(file_t *file, uint64_t argc, const char **argv)
Definition netfs.c:284
static size_t netfs_addrs_read(file_t *file, void *buffer, size_t count, size_t *offset)
Definition netfs.c:477
static rwmutex_t familiesMutex
Definition netfs.c:20
static dentry_ops_t socketDentryOps
Definition netfs.c:395
static uint64_t netfs_factory_open(file_t *file)
Definition netfs.c:418
static socket_file_t socketFiles[]
Definition netfs.c:325
static wait_queue_t * netfs_data_poll(file_t *file, poll_events_t *revents)
Definition netfs.c:140
static inode_ops_t socketInodeOps
Definition netfs.c:390
static uint64_t netfs_socket_iterate(dentry_t *dentry, dir_ctx_t *ctx)
Definition netfs.c:367
static socket_t * socket_new(netfs_family_t *family, socket_type_t type)
Definition netfs.c:40
static size_t netfs_data_read(file_t *file, void *buf, size_t count, size_t *offset)
Definition netfs.c:96
static uint64_t netfs_data_open(file_t *file)
Definition netfs.c:76
static inode_ops_t familyFileInodeOps
Definition netfs.c:543
static uint64_t netfs_iterate(dentry_t *dentry, dir_ctx_t *ctx)
Definition netfs.c:735
static list_t families
Definition netfs.c:19
static file_ops_t dataOps
Definition netfs.c:156
static size_t netfs_data_write(file_t *file, const void *buf, size_t count, size_t *offset)
Definition netfs.c:118
static dentry_t * netfs_mount(filesystem_t *fs, block_device_t *device, void *private)
Definition netfs.c:769
static uint64_t netfs_family_lookup(inode_t *dir, dentry_t *dentry)
Definition netfs.c:547
static filesystem_t netfs
Definition netfs.c:800
static void netfs_file_cleanup(inode_t *inode)
Definition netfs.c:531
static size_t netfs_factory_read(file_t *file, void *buffer, size_t count, size_t *offset)
Definition netfs.c:460
static uint64_t netfs_accept_open(file_t *file)
Definition netfs.c:164
static inode_ops_t familyInodeOps
Definition netfs.c:697
static dentry_ops_t netDentryOps
Definition netfs.c:765
static uint64_t netfs_lookup(inode_t *dir, dentry_t *dentry)
Definition netfs.c:705
static file_ops_t addrsFileOps
Definition netfs.c:518
static uint64_t netfs_family_iterate(dentry_t *dentry, dir_ctx_t *ctx)
Definition netfs.c:631
static uint64_t netfs_socket_lookup(inode_t *dir, dentry_t *dentry)
Definition netfs.c:331
static void socket_free(socket_t *socket)
Definition netfs.c:22
static file_ops_t factoryFileOps
Definition netfs.c:471
static inode_ops_t netInodeOps
Definition netfs.c:761
static void netfs_data_close(file_t *file)
Definition netfs.c:85
static void netfs_factory_close(file_t *file)
Definition netfs.c:449
static atomic_long count
Definition main.c:11
@ memory_order_relaxed
Definition stdatomic.h:116
#define atomic_fetch_add_explicit(object, operand, order)
Definition stdatomic.h:259
#define _Atomic(T)
Definition stdatomic.h:59
#define ATOMIC_VAR_INIT(value)
Definition stdatomic.h:74
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
_PUBLIC int sscanf(const char *_RESTRICT s, const char *_RESTRICT format,...)
Definition sscanf.c:4
_PUBLIC int snprintf(char *_RESTRICT s, size_t n, const char *_RESTRICT format,...)
Definition snprintf.c:3
_PUBLIC void * malloc(size_t size)
Definition malloc.c:5
_PUBLIC void free(void *ptr)
Definition free.c:11
_PUBLIC char * strncpy(char *_RESTRICT s1, const char *_RESTRICT s2, size_t n)
Definition strncpy.c:3
_PUBLIC size_t strlen(const char *s)
Definition strlen.c:3
_PUBLIC int strcmp(const char *s1, const char *s2)
Definition strcmp.c:3
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
inode_t * inode
Will be NULL if the dentry is negative, once positive it will never be modified.
Definition dentry.h:157
char name[MAX_NAME]
Constant after creation.
Definition dentry.h:156
dentry_id_t id
Definition dentry.h:155
const dentry_ops_t * ops
Definition dentry.h:162
void * private
Definition dentry.h:163
superblock_t * superblock
Definition dentry.h:161
Directory context used to iterate over directory entries.
Definition dentry.h:96
size_t index
An index that the filesystem can use for its own purposes.
Definition dentry.h:113
bool(* emit)(dir_ctx_t *ctx, const char *name, ino_t number, itype_t type)
Emit function.
Definition dentry.h:110
size_t pos
The current position in the directory, can be used to skip entries.
Definition dentry.h:111
File operations structure.
Definition file.h:54
size_t(* read)(file_t *file, void *buffer, size_t count, size_t *offset)
Definition file.h:58
uint64_t(* open)(file_t *file)
Definition file.h:55
File structure.
Definition file.h:39
const file_ops_t * ops
Definition file.h:45
mode_t mode
Definition file.h:42
inode_t * inode
Definition file.h:43
void * private
Definition file.h:46
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
void(* cleanup)(inode_t *inode)
Cleanup function called when the inode is being freed.
Definition inode.h:143
uint64_t(* lookup)(inode_t *dir, dentry_t *target)
Look up a dentry in a directory inode.
Definition inode.h:85
Inode structure.
Definition inode.h:49
void * private
Definition inode.h:60
ino_t number
Definition inode.h:51
superblock_t * superblock
Definition inode.h:61
A doubly linked list.
Definition list.h:47
Namespace structure.
Definition namespace.h:57
ref_t ref
Definition namespace.h:58
netfs_family_t * family
Definition netfs.c:408
netfs_family_file_t * fileInfo
Definition netfs.c:409
const char * name
Definition netfs.c:401
file_ops_t * fileOps
Definition netfs.c:403
socket_type_t type
Definition netfs.c:402
Socket Family structure.
Definition netfs.h:144
uint64_t(* init)(socket_t *sock)
Initialize a socket.
Definition netfs.h:152
list_entry_t listEntry
Definition netfs.h:224
void(* deinit)(socket_t *sock)
Deinitialize a socket.
Definition netfs.h:158
rwmutex_t mutex
Definition netfs.h:226
const char * name
Definition netfs.h:145
list_t sockets
Definition netfs.h:225
Read-Write Mutex structure.
Definition rwmutex.h:42
const char * name
Definition netfs.c:72
file_ops_t * fileOps
Definition netfs.c:73
Socket structure.
Definition netfs.h:126
Superblock structure.
Definition superblock.h:49
dentry_t * root
Root dentry of the filesystem, should not take a reference.
Definition superblock.h:56
The primitive that threads block on.
Definition wait.h:182