aboutsummaryrefslogtreecommitdiff
path: root/src/caio
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi92@disroot.org>2025-07-07 13:22:53 +0200
committerXavier Del Campo Romero <xavi92@disroot.org>2025-11-11 00:08:15 +0100
commit7861a52adf92a083bb2aed4c35f98d8035dce032 (patch)
tree28cd3c40e4c878f730f5df3c1d93bdf91af490c3 /src/caio
parent7fc48e9216ff809da5f8055a50b0be17628ef1df (diff)
downloadwnix-7861a52adf92a083bb2aed4c35f98d8035dce032.tar.gz
Setup project skeleton
Diffstat (limited to 'src/caio')
-rw-r--r--src/caio/CMakeLists.txt23
-rw-r--r--src/caio/include/caio.h43
-rw-r--r--src/caio/private_include/caio/routines.h27
-rw-r--r--src/caio/private_include/caio/types.h46
-rw-r--r--src/caio/src/CMakeLists.txt27
-rw-r--r--src/caio/src/cache.c38
-rw-r--r--src/caio/src/close.c44
-rw-r--r--src/caio/src/eof.c25
-rw-r--r--src/caio/src/open.c79
-rw-r--r--src/caio/src/read.c154
-rw-r--r--src/caio/src/readdebugmsg.c170
-rw-r--r--src/caio/src/readnodebug.c152
-rw-r--r--src/caio/src/seek.c35
-rw-r--r--src/caio/src/set_caches.c78
-rw-r--r--src/caio/src/tell.c26
-rw-r--r--src/caio/src/write.c29
16 files changed, 996 insertions, 0 deletions
diff --git a/src/caio/CMakeLists.txt b/src/caio/CMakeLists.txt
new file mode 100644
index 0000000..980d21b
--- /dev/null
+++ b/src/caio/CMakeLists.txt
@@ -0,0 +1,23 @@
+# wnix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(caio)
+add_subdirectory(src)
+target_include_directories(caio PUBLIC include PRIVATE private_include)
+target_link_libraries(caio PUBLIC aio fs state PRIVATE loop)
+# Even if PRIVATE, there are cyclical dependencies among libraries that
+# make LINK_INTERFACE_MULTIPLICITY to exceed its default value (2).
+set_target_properties(caio PROPERTIES LINK_INTERFACE_MULTIPLICITY 3)
diff --git a/src/caio/include/caio.h b/src/caio/include/caio.h
new file mode 100644
index 0000000..284224a
--- /dev/null
+++ b/src/caio/include/caio.h
@@ -0,0 +1,43 @@
+/*
+ * wnix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef CAIO_H
+#define CAIO_H
+
+#include <aio.h>
+#include <stddef.h>
+
+struct caio_open
+{
+ const char *path;
+ int flags;
+ uid_t uid;
+ gid_t gid;
+};
+
+struct caio *caio_open(const struct caio_open *op, const struct aio_done *d);
+int caio_set_caches(struct caio *a, size_t n);
+int caio_read(struct caio *a, void *buf, size_t n, const struct aio_done *d);
+int caio_write(struct caio *a, const void *buf, size_t n,
+ const struct aio_done *d);
+int caio_seek(struct caio *a, off_t offset);
+int caio_tell(const struct caio *a, off_t *offset);
+int caio_eof(const struct caio *a);
+int caio_close(struct caio *a);
+
+#endif
diff --git a/src/caio/private_include/caio/routines.h b/src/caio/private_include/caio/routines.h
new file mode 100644
index 0000000..a83043a
--- /dev/null
+++ b/src/caio/private_include/caio/routines.h
@@ -0,0 +1,27 @@
+/*
+ * wnix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef CAIO_ROUTINES_H
+#define CAIO_ROUTINES_H
+
+#include <caio/types.h>
+#include <sys/types.h>
+
+struct caio_cache *caio_cache(struct caio *a);
+
+#endif
diff --git a/src/caio/private_include/caio/types.h b/src/caio/private_include/caio/types.h
new file mode 100644
index 0000000..001a4d3
--- /dev/null
+++ b/src/caio/private_include/caio/types.h
@@ -0,0 +1,46 @@
+/*
+ * wnix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef CAIO_TYPES_H
+#define CAIO_TYPES_H
+
+#include <caio.h>
+#include <aio.h>
+#include <fs/fs.h>
+#include <sys/types.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+struct caio_cache
+{
+ off_t offset;
+ size_t available;
+ char buf[2048];
+ struct caio_cache *prev, *next;
+};
+
+struct caio
+{
+ struct aio_done done;
+ struct aio *aio;
+ struct fs_fd fd;
+ struct caio_cache *caches;
+ off_t offset;
+};
+
+#endif
diff --git a/src/caio/src/CMakeLists.txt b/src/caio/src/CMakeLists.txt
new file mode 100644
index 0000000..91b95d4
--- /dev/null
+++ b/src/caio/src/CMakeLists.txt
@@ -0,0 +1,27 @@
+# wnix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(caio PRIVATE
+ cache.c
+ close.c
+ eof.c
+ open.c
+ read.c
+ seek.c
+ set_caches.c
+ tell.c
+ write.c
+)
diff --git a/src/caio/src/cache.c b/src/caio/src/cache.c
new file mode 100644
index 0000000..edd462c
--- /dev/null
+++ b/src/caio/src/cache.c
@@ -0,0 +1,38 @@
+/*
+ * wnix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <caio.h>
+#include <caio/routines.h>
+#include <caio/types.h>
+#include <sys/types.h>
+#include <stddef.h>
+
+struct caio_cache *caio_cache(struct caio *const a)
+{
+ for (struct caio_cache *c = a->caches; c; c = c->next)
+ {
+ const off_t offset = a->offset;
+
+ if (c->available
+ && offset >= c->offset
+ && offset < c->offset + sizeof c->buf)
+ return c;
+ }
+
+ return NULL;
+}
diff --git a/src/caio/src/close.c b/src/caio/src/close.c
new file mode 100644
index 0000000..253aaa7
--- /dev/null
+++ b/src/caio/src/close.c
@@ -0,0 +1,44 @@
+/*
+ * wnix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <caio.h>
+#include <caio/types.h>
+#include <aio.h>
+#include <fs/fs.h>
+#include <stdlib.h>
+
+int caio_close(struct caio *const caio)
+{
+ if (!caio)
+ return 0;
+ else
+ aio_free(caio->aio);
+
+ for (struct caio_cache *c = caio->caches; c;)
+ {
+ struct caio_cache *const next = c->next;
+
+ free(c);
+ c = next;
+ }
+
+ aio_close(&caio->fd);
+ free(caio);
+ /* TODO */
+ return -1;
+}
diff --git a/src/caio/src/eof.c b/src/caio/src/eof.c
new file mode 100644
index 0000000..a631546
--- /dev/null
+++ b/src/caio/src/eof.c
@@ -0,0 +1,25 @@
+/*
+ * wnix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <caio.h>
+#include <caio/types.h>
+
+int caio_eof(const struct caio *const a)
+{
+ return a->offset >= a->fd.size;
+}
diff --git a/src/caio/src/open.c b/src/caio/src/open.c
new file mode 100644
index 0000000..c12432c
--- /dev/null
+++ b/src/caio/src/open.c
@@ -0,0 +1,79 @@
+/*
+ * wnix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <caio.h>
+#include <caio/types.h>
+#include <aio.h>
+#include <loop.h>
+#include <fs/fs.h>
+#include <stdlib.h>
+
+static int done(const enum state state, void *const args)
+{
+ struct caio *const a = args;
+ const struct aio_done *const d = &a->done;
+
+ if (loop_rm_aio(a->aio))
+ return -1;
+
+ aio_free(a->aio);
+ a->aio = NULL;
+ return d->f ? d->f(state, d->args) : 0;
+}
+
+struct caio *caio_open(const struct caio_open *op,
+ const struct aio_done *const d)
+{
+ struct aio *aio = NULL;
+ struct caio *const ret = malloc(sizeof *ret);
+
+ if (!ret)
+ goto failure;
+
+ const struct fs_open aio_op =
+ {
+ .flags = op->flags,
+ .path = op->path,
+ .uid = op->uid,
+ .gid = op->gid,
+ .fd = &ret->fd,
+ };
+
+ const struct aio_done dd =
+ {
+ .f = done,
+ .args = ret
+ };
+
+ *ret = (const struct caio){0};
+
+ if (caio_set_caches(ret, 1)
+ || !(aio = aio_open(&aio_op, &dd))
+ || loop_add_aio(aio))
+ goto failure;
+ else if (d)
+ ret->done = *d;
+
+ ret->aio = aio;
+ return ret;
+
+failure:
+ aio_free(aio);
+ free(ret);
+ return NULL;
+}
diff --git a/src/caio/src/read.c b/src/caio/src/read.c
new file mode 100644
index 0000000..e1e85b6
--- /dev/null
+++ b/src/caio/src/read.c
@@ -0,0 +1,154 @@
+/*
+ * wnix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <caio.h>
+#include <caio/routines.h>
+#include <caio/types.h>
+#include <aio.h>
+#include <fs/fs.h>
+#include <loop.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int done(const enum state s, void *const args)
+{
+ struct caio *const a = args;
+ const struct aio_done *const d = &a->done;
+
+ if (loop_rm_aio(a->aio))
+ return -1;
+
+ aio_free(a->aio);
+ a->aio = NULL;
+ return d->f ? d->f(s, d->args) : 0;
+}
+
+static size_t read_cache(struct caio *const a, struct caio_cache *const c,
+ void *const buf, size_t n)
+{
+ char *p = buf;
+ size_t i = a->offset % sizeof c->buf;
+
+ while (i < c->available && n)
+ {
+ *p++ = c->buf[i++];
+ n--;
+ }
+
+ const size_t ret = p - (const char *)buf;
+
+ a->offset += ret;
+ return ret;
+}
+
+static size_t getrem(const struct caio *const a)
+{
+ const struct fs_fd *const fd = &a->fd;
+ const off_t n = fd->size - fd->offset;
+ const size_t sz = sizeof a->caches->buf / sizeof *a->caches->buf;
+
+ return n < sz ? n : sz;
+}
+
+static struct caio_cache *rotate(struct caio *const a)
+{
+ const struct fs_fd *const fd = &a->fd;
+ long long maxdiff = LLONG_MAX;
+ struct caio_cache *ret = a->caches;
+
+ for (struct caio_cache *c = a->caches; c; c = c->next)
+ {
+ if (!c->available)
+ return c;
+
+ const long long diff = (long long)c->offset - (long long)fd->offset,
+ adiff = llabs(diff);
+
+ if (adiff < maxdiff)
+ {
+ maxdiff = adiff;
+ ret = c;
+ }
+ }
+
+ return ret;
+}
+
+static int setup_cache(struct caio *const a, const struct aio_done *const d)
+{
+ const size_t rem = getrem(a);
+
+ if (!rem)
+ return 0;
+
+ struct aio *aio = NULL;
+ struct caio_cache *const c = rotate(a);
+ const struct fs_read r =
+ {
+ .fd = &a->fd,
+ .buf = c->buf,
+ .n = rem
+ };
+
+ const struct aio_done dd =
+ {
+ .f = done,
+ .args = a
+ };
+
+ const off_t offset = (a->offset / sizeof c->buf) * sizeof c->buf;
+
+ a->fd.offset = offset;
+
+ if (!(aio = aio_read(&r, &dd)) || loop_add_aio(aio))
+ goto failure;
+ else if (d)
+ a->done = *d;
+ else
+ a->done = (const struct aio_done){0};
+
+ a->aio = aio;
+ c->offset = offset;
+ c->available = rem;
+ return 0;
+
+failure:
+ aio_free(aio);
+ return -1;
+}
+
+int caio_read(struct caio *const a, void *const buf, const size_t n,
+ const struct aio_done *const d)
+{
+ if (a->offset >= a->fd.size)
+ return 0;
+
+ struct caio_cache *const c = caio_cache(a);
+
+ if (c)
+ {
+ const size_t cr = read_cache(a, c, buf, n);
+
+ if (cr)
+ return cr;
+ }
+
+ return setup_cache(a, d);
+}
diff --git a/src/caio/src/readdebugmsg.c b/src/caio/src/readdebugmsg.c
new file mode 100644
index 0000000..11493ba
--- /dev/null
+++ b/src/caio/src/readdebugmsg.c
@@ -0,0 +1,170 @@
+/*
+ * wnix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <caio.h>
+#include <caio/routines.h>
+#include <caio/types.h>
+#include <aio.h>
+#include <fs/fs.h>
+#include <loop.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#include <drv/ps1/bios.h>
+static int done(const enum state s, void *const args)
+{
+ struct caio *const a = args;
+ const struct aio_done *const d = &a->done;
+
+ if (loop_rm_aio(a->aio))
+ return -1;
+
+ aio_free(a->aio);
+ a->aio = NULL;
+ Printf("finished preparing cache\n");
+ return d->f ? d->f(s, d->args) : 0;
+}
+
+static size_t read_cache(struct caio *const a, struct caio_cache *const c,
+ void *const buf, size_t n)
+{
+ char *p = buf;
+ size_t i = a->offset % sizeof c->buf, start = i;
+ unsigned char checksum = 0;
+
+ while (i < c->available && n)
+ {
+ const unsigned char b = c->buf[i++];
+
+ *p++ = b;
+ checksum += b;
+ n--;
+ }
+
+ const size_t ret = p - (const char *)buf;
+
+ if (ret)
+ Printf("%s: read %lu bytes from cache %p (offset=%lu, bytes [%lu-%lu], chk=%#x)\n",
+ __func__, (unsigned long)ret, (void *)c,
+ (unsigned long)a->offset, (unsigned long)start, (unsigned long)i - 1,
+ (unsigned)checksum);
+
+ a->offset += ret;
+ return ret;
+}
+
+static size_t getrem(const struct caio *const a)
+{
+ const struct fs_fd *const fd = &a->fd;
+ const off_t n = fd->size - fd->offset;
+ const size_t sz = sizeof a->caches->buf / sizeof *a->caches->buf;
+
+ return n < sz ? n : sz;
+}
+
+static struct caio_cache *rotate(struct caio *const a)
+{
+ const struct fs_fd *const fd = &a->fd;
+ long long maxdiff = LLONG_MAX;
+ struct caio_cache *ret = a->caches;
+
+ for (struct caio_cache *c = a->caches; c; c = c->next)
+ {
+ if (!c->available)
+ return c;
+
+ const long long diff = (long long)c->offset - (long long)fd->offset,
+ adiff = llabs(diff);
+
+ if (adiff < maxdiff)
+ {
+ maxdiff = adiff;
+ ret = c;
+ }
+ }
+
+ return ret;
+}
+
+static int setup_cache(struct caio *const a, const struct aio_done *const d)
+{
+ const size_t rem = getrem(a);
+
+ if (!rem)
+ return 0;
+
+ struct aio *aio = NULL;
+ struct caio_cache *const c = rotate(a);
+ const struct fs_read r =
+ {
+ .fd = &a->fd,
+ .buf = c->buf,
+ .n = rem
+ };
+
+ const struct aio_done dd =
+ {
+ .f = done,
+ .args = a
+ };
+
+ const off_t offset = (a->offset / sizeof c->buf) * sizeof c->buf;
+
+ a->fd.offset = offset;
+
+ if (!(aio = aio_read(&r, &dd)) || loop_add_aio(aio))
+ goto failure;
+ else if (d)
+ a->done = *d;
+ else
+ a->done = (const struct aio_done){0};
+
+ a->aio = aio;
+ c->offset = offset;
+ c->available = rem;
+ Printf("%s: setting up cache %p with offset %lu, fd->offset=%lu and %lu bytes\n",
+ __func__, (void *)c, (unsigned long)c->offset, (unsigned long)a->fd.offset,
+ (unsigned long)c->available);
+ return 0;
+
+failure:
+ aio_free(aio);
+ return -1;
+}
+
+int caio_read(struct caio *const a, void *const buf, const size_t n,
+ const struct aio_done *const d)
+{
+ if (a->offset >= a->fd.size)
+ return 0;
+
+ struct caio_cache *const c = caio_cache(a);
+
+ if (c)
+ {
+ const size_t cr = read_cache(a, c, buf, n);
+
+ if (cr)
+ return cr;
+ }
+
+ return setup_cache(a, d);
+}
diff --git a/src/caio/src/readnodebug.c b/src/caio/src/readnodebug.c
new file mode 100644
index 0000000..ed8187e
--- /dev/null
+++ b/src/caio/src/readnodebug.c
@@ -0,0 +1,152 @@
+/*
+ * wnix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <caio.h>
+#include <caio/routines.h>
+#include <caio/types.h>
+#include <aio.h>
+#include <fs/fs.h>
+#include <loop.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int done(const enum state s, void *const args)
+{
+ struct caio *const a = args;
+ const struct aio_done *const d = &a->done;
+
+ if (loop_rm_aio(a->aio))
+ return -1;
+
+ aio_free(a->aio);
+ a->aio = NULL;
+ return d->f ? d->f(s, d->args) : 0;
+}
+
+static size_t read_cache(struct caio *const a, struct caio_cache *const c,
+ void *const buf, size_t n)
+{
+ char *p = buf;
+ size_t i = a->offset % sizeof c->buf;
+
+ while (i < c->available && n)
+ {
+ *p++ = c->buf[i++];
+ n--;
+ }
+
+ const size_t ret = p - (const char *)buf;
+
+ a->offset += ret;
+ return ret;
+}
+
+static size_t getrem(const struct caio *const a)
+{
+ const struct fs_fd *const fd = &a->fd;
+ const off_t n = fd->size - fd->offset;
+ const size_t sz = sizeof a->caches->buf / sizeof *a->caches->buf;
+
+ return n < sz ? n : sz;
+}
+
+static struct caio_cache *rotate(struct caio *const a)
+{
+ const struct fs_fd *const fd = &a->fd;
+ long long maxdiff = LLONG_MAX;
+ struct caio_cache *ret = a->caches;
+
+ for (struct caio_cache *c = a->caches; c; c = c->next)
+ {
+ const long long diff = c->available ?
+ (long long)c->offset - (long long)fd->offset : 0,
+ adiff = llabs(diff);
+
+ if (adiff < maxdiff)
+ {
+ maxdiff = adiff;
+ ret = c;
+ }
+ }
+
+ return ret;
+}
+
+static int setup_cache(struct caio *const a, const struct aio_done *const d)
+{
+ const size_t rem = getrem(a);
+
+ if (!rem)
+ return 0;
+
+ struct aio *aio = NULL;
+ struct caio_cache *const c = rotate(a);
+ const struct fs_read r =
+ {
+ .fd = &a->fd,
+ .buf = c->buf,
+ .n = rem
+ };
+
+ const struct aio_done dd =
+ {
+ .f = done,
+ .args = a
+ };
+
+ const off_t offset = (a->offset / sizeof c->buf) * sizeof c->buf;
+
+ a->fd.offset = offset;
+
+ if (!(aio = aio_read(&r, &dd)) || loop_add_aio(aio))
+ goto failure;
+ else if (d)
+ a->done = *d;
+ else
+ a->done = (const struct aio_done){0};
+
+ a->aio = aio;
+ c->offset = offset;
+ c->available = rem;
+ return 0;
+
+failure:
+ aio_free(aio);
+ return -1;
+}
+
+int caio_read(struct caio *const a, void *const buf, const size_t n,
+ const struct aio_done *const d)
+{
+ if (a->offset >= a->fd.size)
+ return 0;
+
+ struct caio_cache *const c = caio_cache(a);
+
+ if (c)
+ {
+ const size_t cr = read_cache(a, c, buf, n);
+
+ if (cr)
+ return cr;
+ }
+
+ return setup_cache(a, d);
+}
diff --git a/src/caio/src/seek.c b/src/caio/src/seek.c
new file mode 100644
index 0000000..1c0848d
--- /dev/null
+++ b/src/caio/src/seek.c
@@ -0,0 +1,35 @@
+/*
+ * wnix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <caio.h>
+#include <caio/routines.h>
+#include <caio/types.h>
+#include <sys/types.h>
+
+int caio_seek(struct caio *const a, const off_t offset)
+{
+ struct fs_fd *const fd = &a->fd;
+ const off_t page = offset / sizeof a->caches->buf;
+
+ a->offset = offset;
+
+ if (!caio_cache(a))
+ fd->offset = page * sizeof a->caches->buf;
+
+ return 0;
+}
diff --git a/src/caio/src/set_caches.c b/src/caio/src/set_caches.c
new file mode 100644
index 0000000..dfdd562
--- /dev/null
+++ b/src/caio/src/set_caches.c
@@ -0,0 +1,78 @@
+/*
+ * wnix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <caio.h>
+#include <caio/types.h>
+#include <errno.h>
+#include <stdlib.h>
+
+int caio_set_caches(struct caio *const a, const size_t n)
+{
+ struct caio_cache *c, *prev = NULL;
+ size_t i;
+
+ if (!n)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ for (i = 0, c = a->caches; i < n; i++)
+ {
+ if (!c)
+ {
+ struct caio_cache *const nc = malloc(sizeof *nc);
+
+ if (!nc)
+ return -1;
+
+ *nc = (const struct caio_cache){0};
+
+ if (!a->caches)
+ a->caches = nc;
+ else if (prev)
+ {
+ prev->next = nc;
+ nc->prev = prev;
+ }
+
+ prev = nc;
+ }
+ else
+ {
+ prev = c;
+ c = c->next;
+ }
+ }
+
+ for (i = 0, c = a->caches; c; i++)
+ {
+ struct caio_cache *const next = c->next;
+
+ if (i >= n)
+ {
+ c->prev = c->next;
+ c->next = c->prev;
+ free(c);
+ }
+
+ c = next;
+ }
+
+ return 0;
+}
diff --git a/src/caio/src/tell.c b/src/caio/src/tell.c
new file mode 100644
index 0000000..7bfb63a
--- /dev/null
+++ b/src/caio/src/tell.c
@@ -0,0 +1,26 @@
+/*
+ * wnix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <caio.h>
+#include <caio/types.h>
+
+int caio_tell(const struct caio *const a, off_t *const offset)
+{
+ *offset = a->offset;
+ return 0;
+}
diff --git a/src/caio/src/write.c b/src/caio/src/write.c
new file mode 100644
index 0000000..55ac558
--- /dev/null
+++ b/src/caio/src/write.c
@@ -0,0 +1,29 @@
+/*
+ * wnix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <caio.h>
+#include <caio/types.h>
+#include <aio.h>
+#include <fs/fs.h>
+
+int caio_write(struct caio *const caio, const void *const buf, const size_t n,
+ const struct aio_done *d)
+{
+ /* TODO */
+ return -1;
+}