PatchworkOS  dbbdc99
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/fs.h>
17#include <sys/list.h>
18
21
22static void socket_free(socket_t* socket)
23{
24 if (socket == NULL)
25 {
26 return;
27 }
28
30 list_remove(&socket->listEntry);
32
33 socket->family->deinit(socket);
34 free(socket);
35}
36
38{
39 static _Atomic(uint64_t) nextId = ATOMIC_VAR_INIT(0);
40
41 socket_t* socket = malloc(sizeof(socket_t));
42 if (socket == NULL)
43 {
44 errno = ENOMEM;
45 return NULL;
46 }
47
48 ref_init(&socket->ref, socket_free);
49 list_entry_init(&socket->listEntry);
50 snprintf(socket->id, sizeof(socket->id), "%llu", atomic_fetch_add_explicit(&nextId, 1, memory_order_relaxed));
51 socket->family = family;
52 socket->type = type;
53 socket->state = SOCKET_NEW;
54 weak_ptr_set(&socket->ownerNs, NULL, NULL, NULL);
55 socket->data = NULL;
56 mutex_init(&socket->mutex);
57
58 if (socket->family->init(socket) == ERR)
59 {
60 free(socket);
61 return NULL;
62 }
63
64 return socket;
65}
66
67typedef struct socket_file
68{
69 const char* name;
72
74{
75 socket_t* sock = file->vnode->data;
76 assert(sock != NULL);
77
78 file->data = REF(sock);
79 return 0;
80}
81
82static void netfs_data_close(file_t* file)
83{
84 socket_t* sock = file->data;
85 if (sock == NULL)
86 {
87 return;
88 }
89
90 UNREF(sock);
91}
92
93static size_t netfs_data_read(file_t* file, void* buf, size_t count, size_t* offset)
94{
95 socket_t* sock = file->data;
96 assert(sock != NULL);
97
98 if (sock->family->recv == NULL)
99 {
100 errno = ENOSYS;
101 return 0;
102 }
103
104 MUTEX_SCOPE(&sock->mutex);
105
106 if (sock->state != SOCKET_CONNECTED)
107 {
108 errno = ENOTCONN;
109 return ERR;
110 }
111
112 return sock->family->recv(sock, buf, count, offset, file->mode);
113}
114
115static size_t netfs_data_write(file_t* file, const void* buf, size_t count, size_t* offset)
116{
117 socket_t* sock = file->data;
118 assert(sock != NULL);
119
120 if (sock->family->send == NULL)
121 {
122 errno = ENOSYS;
123 return 0;
124 }
125
126 MUTEX_SCOPE(&sock->mutex);
127
128 if (sock->state != SOCKET_CONNECTED)
129 {
130 errno = ENOTCONN;
131 return ERR;
132 }
133
134 return sock->family->send(sock, buf, count, offset, file->mode);
135}
136
138{
139 socket_t* sock = file->data;
140 assert(sock != NULL);
141
142 if (sock->family->poll == NULL)
143 {
144 errno = ENOSYS;
145 return NULL;
146 }
147
148 MUTEX_SCOPE(&sock->mutex);
149
150 return sock->family->poll(sock, revents);
151}
152
155 .close = netfs_data_close,
156 .read = netfs_data_read,
157 .write = netfs_data_write,
158 .poll = netfs_data_poll,
159};
160
162{
163 socket_t* sock = file->vnode->data;
164 assert(sock != NULL);
165
166 if (sock->family->accept == NULL)
167 {
168 errno = ENOSYS;
169 return ERR;
170 }
171
172 MUTEX_SCOPE(&sock->mutex);
173
174 if (sock->state != SOCKET_LISTENING)
175 {
176 errno = EINVAL;
177 return ERR;
178 }
179
180 socket_t* newSock = socket_new(sock->family, sock->type);
181 if (newSock == NULL)
182 {
183 return ERR;
184 }
185
186 if (sock->family->accept(sock, newSock, file->mode) == ERR)
187 {
188 socket_free(newSock);
189 return ERR;
190 }
191
192 newSock->state = SOCKET_CONNECTED;
193 file->data = newSock;
194 file->ops = &dataOps;
195 return 0;
196}
197
201
202static uint64_t netfs_ctl_bind(file_t* file, uint64_t argc, const char** argv)
203{
204 UNUSED(argc);
205
206 socket_t* sock = file->vnode->data;
207 assert(sock != NULL);
208
209 if (sock->family->bind == NULL)
210 {
211 errno = ENOSYS;
212 return ERR;
213 }
214
215 MUTEX_SCOPE(&sock->mutex);
216
217 if (sock->state != SOCKET_NEW)
218 {
219 errno = EINVAL;
220 return ERR;
221 }
222
223 strncpy(sock->address, argv[1], sizeof(sock->address));
224 sock->address[sizeof(sock->address) - 1] = '\0';
225
226 if (sock->family->bind(sock) == ERR)
227 {
228 return ERR;
229 }
230
231 sock->state = SOCKET_BOUND;
232 return 0;
233}
234
235static uint64_t netfs_ctl_listen(file_t* file, uint64_t argc, const char** argv)
236{
237 UNUSED(argc);
238
240 if (argc == 2)
241 {
242 if (sscanf(argv[1], "%llu", &backlog) != 1)
243 {
244 errno = EINVAL;
245 return ERR;
246 }
247
248 if (backlog == 0)
249 {
250 errno = EINVAL;
251 return ERR;
252 }
253 }
254
255 socket_t* sock = file->vnode->data;
256 assert(sock != NULL);
257
258 if (sock->family->listen == NULL)
259 {
260 errno = ENOSYS;
261 return ERR;
262 }
263
264 MUTEX_SCOPE(&sock->mutex);
265
266 if (sock->state != SOCKET_BOUND)
267 {
268 errno = EINVAL;
269 return ERR;
270 }
271
272 if (sock->family->listen(sock, backlog) == ERR)
273 {
274 return ERR;
275 }
276
277 sock->state = SOCKET_LISTENING;
278 return 0;
279}
280
281static uint64_t netfs_ctl_connect(file_t* file, uint64_t argc, const char** argv)
282{
283 UNUSED(argc);
284
285 socket_t* sock = file->vnode->data;
286 assert(sock != NULL);
287
288 if (sock->family->connect == NULL)
289 {
290 errno = ENOSYS;
291 return ERR;
292 }
293
294 MUTEX_SCOPE(&sock->mutex);
295
296 if (sock->state != SOCKET_NEW && sock->state != SOCKET_BOUND)
297 {
298 errno = EINVAL;
299 return ERR;
300 }
301
302 strncpy(sock->address, argv[1], sizeof(sock->address));
303 sock->address[sizeof(sock->address) - 1] = '\0';
304
305 if (sock->family->connect(sock) == ERR)
306 {
307 return ERR;
308 }
309
310 sock->state = SOCKET_CONNECTED;
311 return 0;
312}
313
315 {
316 {"bind", netfs_ctl_bind, 2, 2},
317 {"listen", netfs_ctl_listen, 1, 2},
318 {"connect", netfs_ctl_connect, 2, 2},
319 {0},
320 });
321
323 {.name = "data", .fileOps = &dataOps},
324 {.name = "accept", .fileOps = &acceptOps},
325 {.name = "ctl", .fileOps = &ctlOps},
326};
327
329{
330 for (size_t i = 0; i < ARRAY_SIZE(socketFiles); i++)
331 {
332 if (strcmp(socketFiles[i].name, dentry->name) != 0)
333 {
334 continue;
335 }
336
338 if (vnode == NULL)
339 {
340 return ERR;
341 }
342 UNREF_DEFER(vnode);
343 vnode->data = dir->data; // No reference
344
345 dentry_make_positive(dentry, vnode);
346 return 0;
347 }
348
349 return 0;
350}
351
352static void netfs_socket_cleanup(vnode_t* vnode)
353{
354 socket_t* socket = (socket_t*)vnode->data;
355 if (socket == NULL)
356 {
357 return;
358 }
359
360 UNREF(socket);
361}
362
364{
365 if (!dentry_iterate_dots(dentry, ctx))
366 {
367 return 0;
368 }
369
370 for (size_t i = 0; i < ARRAY_SIZE(socketFiles); i++)
371 {
372 if (ctx->index++ < ctx->pos)
373 {
374 continue;
375 }
376
377 if (!ctx->emit(ctx, socketFiles[i].name, VREG))
378 {
379 return 0;
380 }
381 }
382
383 return 0;
384}
385
390
394
395typedef struct netfs_family_file
396{
397 const char* name;
401
407
408static void socket_weak_ptr_callback(void* arg)
409{
410 socket_t* socket = (socket_t*)arg;
411 UNREF(socket);
412}
413
415{
416 netfs_family_file_ctx_t* ctx = file->vnode->data;
417 assert(ctx != NULL);
418 dentry_t* root = file->vnode->superblock->root;
419 assert(root != NULL);
420
421 socket_t* socket = socket_new(ctx->family, ctx->fileInfo->type);
422 if (socket == NULL)
423 {
424 return ERR;
425 }
426 UNREF_DEFER(socket);
427
429 list_push_back(&ctx->family->sockets, &socket->listEntry);
431
433 if (ns == NULL)
434 {
435 return ERR;
436 }
437 UNREF_DEFER(ns);
438
439 weak_ptr_set(&socket->ownerNs, &ns->ref, socket_weak_ptr_callback, REF(socket));
440
441 file->data = REF(socket);
442 return 0;
443}
444
445static void netfs_factory_close(file_t* file)
446{
447 socket_t* socket = file->data;
448 if (socket == NULL)
449 {
450 return;
451 }
452
453 UNREF(socket);
454}
455
456static size_t netfs_factory_read(file_t* file, void* buffer, size_t count, size_t* offset)
457{
458 socket_t* socket = file->data;
459 if (socket == NULL)
460 {
461 return 0;
462 }
463
464 return BUFFER_READ(buffer, count, offset, socket->id, strlen(socket->id));
465}
466
469 .close = netfs_factory_close,
470 .read = netfs_factory_read,
471};
472
473static size_t netfs_addrs_read(file_t* file, void* buffer, size_t count, size_t* offset)
474{
475 netfs_family_file_ctx_t* ctx = file->vnode->data;
476 assert(ctx != NULL);
477
479
480 if (list_is_empty(&ctx->family->sockets))
481 {
482 return 0;
483 }
484
485 char* string = malloc(list_size(&ctx->family->sockets) * (MAX_PATH + 1));
486 if (string == NULL)
487 {
488 errno = ENOMEM;
489 return ERR;
490 }
491
492 size_t length = 0;
493 socket_t* socket;
494 LIST_FOR_EACH(socket, &ctx->family->sockets, listEntry)
495 {
496 if (socket->family != ctx->family)
497 {
498 continue;
499 }
500
501 if (socket->state != SOCKET_LISTENING)
502 {
503 continue;
504 }
505
506 length += snprintf(string + length, MAX_PATH, "%s\n", socket->address);
507 }
508
509 size_t bytesRead = BUFFER_READ(buffer, count, offset, string, length);
510 free(string);
511 return bytesRead;
512}
513
517
519 {.name = "stream", .type = SOCKET_STREAM, .fileOps = &factoryFileOps},
520 {.name = "dgram", .type = SOCKET_DGRAM, .fileOps = &factoryFileOps},
521 {.name = "seqpacket", .type = SOCKET_SEQPACKET, .fileOps = &factoryFileOps},
522 {.name = "raw", .type = SOCKET_RAW, .fileOps = &factoryFileOps},
523 {.name = "rdm", .type = SOCKET_RDM, .fileOps = &factoryFileOps},
524 {.name = "addrs", .type = 0, .fileOps = &addrsFileOps},
525};
526
527static void netfs_file_cleanup(vnode_t* vnode)
528{
529 netfs_family_file_ctx_t* ctx = vnode->data;
530 if (ctx == NULL)
531 {
532 return;
533 }
534
535 free(ctx);
536 vnode->data = NULL;
537}
538
542
544{
545 netfs_family_t* family = dir->data;
546 assert(family != NULL);
547
548 for (size_t i = 0; i < ARRAY_SIZE(familyFiles); i++)
549 {
550 if (strcmp(familyFiles[i].name, dentry->name) != 0)
551 {
552 continue;
553 }
554
556 if (vnode == NULL)
557 {
558 return ERR;
559 }
560 UNREF_DEFER(vnode);
561
563 if (ctx == NULL)
564 {
565 return ERR;
566 }
567 ctx->family = family;
568 ctx->fileInfo = &familyFiles[i];
569 vnode->data = ctx;
570
571 dentry_make_positive(dentry, vnode);
572 return 0;
573 }
574
575 RWMUTEX_READ_SCOPE(&family->mutex);
576
577 if (list_is_empty(&family->sockets))
578 {
579 return 0;
580 }
581
583 if (ns == NULL)
584 {
585 return ERR;
586 }
587 UNREF_DEFER(ns);
588
589 socket_t* socket;
590 LIST_FOR_EACH(socket, &family->sockets, listEntry)
591 {
592 if (strcmp(socket->id, dentry->name) != 0)
593 {
594 continue;
595 }
596
597 namespace_t* ownerNs = weak_ptr_get(&socket->ownerNs);
598 if (ownerNs == NULL)
599 {
600 continue;
601 }
602 UNREF_DEFER(ownerNs);
603
604 if (ownerNs != ns)
605 {
606 continue;
607 }
608
610 if (vnode == NULL)
611 {
612 return ERR;
613 }
614 UNREF_DEFER(vnode);
615 vnode->data = REF(socket);
616
617 dentry->ops = &socketDentryOps;
618
619 dentry_make_positive(dentry, vnode);
620 return 0;
621 }
622
623 return 0;
624}
625
627{
628 netfs_family_t* family = dentry->vnode->data;
629 assert(family != NULL);
630
631 if (!dentry_iterate_dots(dentry, ctx))
632 {
633 return 0;
634 }
635
636 for (size_t i = 0; i < ARRAY_SIZE(familyFiles); i++)
637 {
638 if (ctx->index++ < ctx->pos)
639 {
640 continue;
641 }
642
643 if (!ctx->emit(ctx, familyFiles[i].name, VREG))
644 {
645 return 0;
646 }
647 }
648
649 RWMUTEX_READ_SCOPE(&family->mutex);
650
651 if (list_is_empty(&family->sockets))
652 {
653 return 0;
654 }
655
657 if (ns == NULL)
658 {
659 return ERR;
660 }
661 UNREF_DEFER(ns);
662
663 socket_t* socket;
664 LIST_FOR_EACH(socket, &family->sockets, listEntry)
665 {
666 namespace_t* ownerNs = weak_ptr_get(&socket->ownerNs);
667 if (ownerNs == NULL)
668 {
669 continue;
670 }
671 UNREF_DEFER(ownerNs);
672
673 if (ownerNs != ns)
674 {
675 continue;
676 }
677
678 if (ctx->index++ < ctx->pos)
679 {
680 continue;
681 }
682
683 if (!ctx->emit(ctx, socket->id, VDIR))
684 {
685 return 0;
686 }
687 }
688
689 return 0;
690}
691
695
699
701{
703
704 netfs_family_t* family;
705 LIST_FOR_EACH(family, &families, listEntry)
706 {
707 if (strcmp(family->name, dentry->name) != 0)
708 {
709 continue;
710 }
711
713 if (vnode == NULL)
714 {
715 return ERR;
716 }
717 UNREF_DEFER(vnode);
718 vnode->data = family;
719
720 dentry->ops = &familyDentryOps;
721
722 dentry_make_positive(dentry, vnode);
723 return 0;
724 }
725
726 return 0;
727}
728
730{
731 if (!dentry_iterate_dots(dentry, ctx))
732 {
733 return 0;
734 }
735
737
738 netfs_family_t* family;
739 LIST_FOR_EACH(family, &families, listEntry)
740 {
741 if (ctx->index++ < ctx->pos)
742 {
743 continue;
744 }
745
746 if (!ctx->emit(ctx, family->name, VDIR))
747 {
748 return 0;
749 }
750 }
751
752 return 0;
753}
754
758
762
763static dentry_t* netfs_mount(filesystem_t* fs, const char* options, void* data)
764{
765 UNUSED(data);
766
767 if (options != NULL)
768 {
769 errno = EINVAL;
770 return NULL;
771 }
772
773 superblock_t* superblock = superblock_new(fs, NULL, NULL);
774 if (superblock == NULL)
775 {
776 return NULL;
777 }
778 UNREF_DEFER(superblock);
779
780 vnode_t* vnode = vnode_new(superblock, VDIR, &netVnodeOps, NULL);
781 if (vnode == NULL)
782 {
783 return NULL;
784 }
785 UNREF_DEFER(vnode);
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, vnode);
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
EFI_PHYSICAL_ADDRESS buffer
Definition main.c:237
static dentry_t * root
Definition devfs.c:25
static fd_t data
Definition dwm.c:21
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
dentry_t * dentry_new(superblock_t *superblock, dentry_t *parent, const char *name)
Create a new dentry.
Definition dentry.c:134
void dentry_make_positive(dentry_t *dentry, vnode_t *vnode)
Make a dentry positive by associating it with an vnode.
Definition dentry.c:289
bool dentry_iterate_dots(dentry_t *dentry, dir_ctx_t *ctx)
Helper function to iterate over the special entries "." and "..".
Definition dentry.c:304
uint64_t filesystem_register(filesystem_t *fs)
Registers a filesystem.
Definition filesystem.c:233
#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, 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
static process_t * process_current(void)
Retrieves the process of the currently running thread.
Definition process.h:131
namespace_t * process_get_ns(process_t *process)
Gets the namespace of a process.
Definition process.c:206
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:252
#define UNREF_DEFER(ptr)
RAII-style cleanup for scoped references.
Definition ref.h:122
static void * weak_ptr_get(weak_ptr_t *wp)
Upgrade a weak pointer to a strong pointer.
Definition ref.h:316
#define REF(ptr)
Increment reference count.
Definition ref.h:82
static void ref_init(ref_t *ref, void *callback)
Initialize a reference counter.
Definition ref.h:130
#define UNREF(ptr)
Decrement reference count.
Definition ref.h:109
#define BUFFER_READ(buffer, count, offset, src, size)
Helper macros for implementing file operations dealing with simple buffers.
Definition vfs.h:209
#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:111
#define UNUSED(x)
Mark a variable as unused.
Definition defs.h:96
poll_events_t
Poll events type.
Definition fs.h:286
@ VREG
Is a regular file.
Definition fs.h:343
@ VDIR
Is a directory.
Definition fs.h:344
#define LIST_FOR_EACH(elem, list, member)
Iterates over a list.
Definition list.h:58
static void list_remove(list_entry_t *entry)
Removes a list entry from its current list.
Definition list.h:290
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 uint64_t list_size(list_t *list)
Gets the size of the list.
Definition list.h:478
static void list_entry_init(list_entry_t *entry)
Initializes a list entry.
Definition list.h:173
static void list_init(list_t *list)
Initializes a list.
Definition list.h:185
#define NULL
Pointer error value.
Definition NULL.h:25
#define ERR
Integer error value.
Definition ERR.h:17
static uint64_t offset
Definition screen.c:19
static file_ops_t acceptOps
Definition netfs.c:198
static uint64_t netfs_lookup(vnode_t *dir, dentry_t *dentry)
Definition netfs.c:700
static dentry_ops_t familyDentryOps
Definition netfs.c:696
static uint64_t netfs_ctl_listen(file_t *file, uint64_t argc, const char **argv)
Definition netfs.c:235
static void socket_weak_ptr_callback(void *arg)
Definition netfs.c:408
static netfs_family_file_t familyFiles[]
Definition netfs.c:518
static uint64_t netfs_ctl_bind(file_t *file, uint64_t argc, const char **argv)
Definition netfs.c:202
static uint64_t netfs_ctl_connect(file_t *file, uint64_t argc, const char **argv)
Definition netfs.c:281
static size_t netfs_addrs_read(file_t *file, void *buffer, size_t count, size_t *offset)
Definition netfs.c:473
static rwmutex_t familiesMutex
Definition netfs.c:20
static dentry_ops_t socketDentryOps
Definition netfs.c:391
static vnode_ops_t familyVnodeOps
Definition netfs.c:692
static uint64_t netfs_factory_open(file_t *file)
Definition netfs.c:414
static socket_file_t socketFiles[]
Definition netfs.c:322
static wait_queue_t * netfs_data_poll(file_t *file, poll_events_t *revents)
Definition netfs.c:137
static uint64_t netfs_socket_iterate(dentry_t *dentry, dir_ctx_t *ctx)
Definition netfs.c:363
static socket_t * socket_new(netfs_family_t *family, socket_type_t type)
Definition netfs.c:37
static size_t netfs_data_read(file_t *file, void *buf, size_t count, size_t *offset)
Definition netfs.c:93
static dentry_t * netfs_mount(filesystem_t *fs, const char *options, void *data)
Definition netfs.c:763
static uint64_t netfs_data_open(file_t *file)
Definition netfs.c:73
static uint64_t netfs_iterate(dentry_t *dentry, dir_ctx_t *ctx)
Definition netfs.c:729
static vnode_ops_t socketVnodeOps
Definition netfs.c:386
static list_t families
Definition netfs.c:19
static file_ops_t dataOps
Definition netfs.c:153
static void netfs_socket_cleanup(vnode_t *vnode)
Definition netfs.c:352
static size_t netfs_data_write(file_t *file, const void *buf, size_t count, size_t *offset)
Definition netfs.c:115
static filesystem_t netfs
Definition netfs.c:800
static size_t netfs_factory_read(file_t *file, void *buffer, size_t count, size_t *offset)
Definition netfs.c:456
static uint64_t netfs_accept_open(file_t *file)
Definition netfs.c:161
static dentry_ops_t netDentryOps
Definition netfs.c:759
static file_ops_t addrsFileOps
Definition netfs.c:514
static uint64_t netfs_socket_lookup(vnode_t *dir, dentry_t *dentry)
Definition netfs.c:328
static uint64_t netfs_family_iterate(dentry_t *dentry, dir_ctx_t *ctx)
Definition netfs.c:626
static void socket_free(socket_t *socket)
Definition netfs.c:22
static uint64_t netfs_family_lookup(vnode_t *dir, dentry_t *dentry)
Definition netfs.c:543
static file_ops_t factoryFileOps
Definition netfs.c:467
static vnode_ops_t netVnodeOps
Definition netfs.c:755
static void netfs_data_close(file_t *file)
Definition netfs.c:82
static void netfs_factory_close(file_t *file)
Definition netfs.c:445
static void netfs_file_cleanup(vnode_t *vnode)
Definition netfs.c:527
static vnode_ops_t familyFileVnodeOps
Definition netfs.c:539
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
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
const dentry_ops_t * ops
Definition dentry.h:164
void * data
Definition dentry.h:165
vnode_t * vnode
Will be NULL if the dentry is negative, once positive it will never be modified.
Definition dentry.h:159
superblock_t * superblock
Definition dentry.h:163
Directory context used to iterate over directory entries.
Definition dentry.h:97
size_t index
An index that the filesystem can use for its own purposes.
Definition dentry.h:114
size_t pos
The current position in the directory, can be used to skip entries.
Definition dentry.h:112
bool(* emit)(dir_ctx_t *ctx, const char *name, vtype_t type)
Emit function.
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
void * data
Definition file.h:46
const file_ops_t * ops
Definition file.h:45
mode_t mode
Definition file.h:42
vnode_t * vnode
Definition file.h:43
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
Namespace structure.
Definition namespace.h:57
ref_t ref
Definition namespace.h:58
netfs_family_t * family
Definition netfs.c:404
netfs_family_file_t * fileInfo
Definition netfs.c:405
const char * name
Definition netfs.c:397
file_ops_t * fileOps
Definition netfs.c:399
socket_type_t type
Definition netfs.c:398
Socket Family structure.
Definition netfs.h:144
uint64_t(* connect)(socket_t *sock)
Connect a socket to its address.
Definition netfs.h:184
wait_queue_t *(* poll)(socket_t *sock, poll_events_t *revents)
Poll a socket for events.
Definition netfs.h:223
uint64_t(* init)(socket_t *sock)
Initialize a socket.
Definition netfs.h:152
list_entry_t listEntry
Definition netfs.h:224
uint64_t(* bind)(socket_t *sock)
Bind a socket to its address.
Definition netfs.h:167
void(* deinit)(socket_t *sock)
Deinitialize a socket.
Definition netfs.h:158
rwmutex_t mutex
Definition netfs.h:226
size_t(* recv)(socket_t *sock, void *buffer, size_t count, size_t *offset, mode_t mode)
Receive data on a socket.
Definition netfs.h:215
uint64_t(* listen)(socket_t *sock, uint32_t backlog)
Listen for incoming connections on a socket.
Definition netfs.h:175
const char * name
Definition netfs.h:145
size_t(* send)(socket_t *sock, const void *buffer, size_t count, size_t *offset, mode_t mode)
Send data on a socket.
Definition netfs.h:204
uint64_t(* accept)(socket_t *sock, socket_t *newSock, mode_t mode)
Accept an incoming connection on a listening socket.
Definition netfs.h:193
list_t sockets
Definition netfs.h:225
Read-Write Mutex structure.
Definition rwmutex.h:42
const char * name
Definition netfs.c:69
file_ops_t * fileOps
Definition netfs.c:70
Socket structure.
Definition netfs.h:126
netfs_family_t * family
Definition netfs.h:131
char address[MAX_PATH]
Definition netfs.h:130
ref_t ref
Definition netfs.h:127
socket_type_t type
Definition netfs.h:132
socket_state_t state
Definition netfs.h:133
list_entry_t listEntry
Definition netfs.h:128
char id[MAX_NAME]
Definition netfs.h:129
weak_ptr_t ownerNs
A weak pointer to the namespace that created the socket.
Definition netfs.h:134
void * data
Definition netfs.h:135
mutex_t mutex
Definition netfs.h:136
Superblock structure.
Definition superblock.h:33
dentry_t * root
Root dentry of the filesystem, should not take a reference.
Definition superblock.h:40
vnode operations structure.
Definition vnode.h:69
void(* cleanup)(vnode_t *vnode)
Cleanup function called when the vnode is being freed.
Definition vnode.h:138
uint64_t(* lookup)(vnode_t *dir, dentry_t *target)
Look up a dentry in a directory vnode.
Definition vnode.h:80
vnode structure.
Definition vnode.h:48
superblock_t * superblock
Definition vnode.h:54
void * data
Filesystem defined data.
Definition vnode.h:52
The primitive that threads block on.
Definition wait.h:185