From 58c515e90ae4ad6696c2d51e8af6ba4b9f64aff0 Mon Sep 17 00:00:00 2001 From: kamkow1 Date: Mon, 2 Mar 2026 22:47:10 +0100 Subject: [PATCH] Create libioutil, implement a filewriter --- Makefile | 1 + aux/compiledb.sh | 1 + aux/devel.sh | 1 + aux/docs.sh | 1 + aux/format.sh | 1 + ce/Makefile | 1 + ce/ce.c | 29 +++++++++++--- include/map.h | 9 +++++ include/page_size.h | 8 ++++ include/write_file.h | 6 +++ kernel/fs/fatfs.c | 10 ++++- kernel/fs/fatfs.h | 2 +- kernel/fs/tarfs.c | 4 +- kernel/fs/tarfs.h | 2 +- kernel/fs/vfs.c | 4 +- kernel/fs/vfs.h | 4 +- kernel/syscall/syscall.c | 6 ++- liballoc/liballoc.c | 2 + libioutil/.gitignore | 4 ++ libioutil/Makefile | 8 ++++ libioutil/filewriter.c | 83 ++++++++++++++++++++++++++++++++++++++++ libioutil/filewriter.h | 36 +++++++++++++++++ libioutil/src.mk | 3 ++ libprocess/process.c | 2 + libprocess/process.h | 1 + libsystem/system.c | 4 +- libsystem/system.h | 11 +----- make/libioutil.mk | 16 ++++++++ 28 files changed, 231 insertions(+), 29 deletions(-) create mode 100644 include/map.h create mode 100644 include/page_size.h create mode 100644 include/write_file.h create mode 100644 libioutil/.gitignore create mode 100644 libioutil/Makefile create mode 100644 libioutil/filewriter.c create mode 100644 libioutil/filewriter.h create mode 100644 libioutil/src.mk create mode 100644 make/libioutil.mk diff --git a/Makefile b/Makefile index 0872457..8875fe7 100644 --- a/Makefile +++ b/Makefile @@ -11,3 +11,4 @@ include make/libstring.mk include make/libkb.mk include make/libaux.mk include make/libarena.mk +include make/libioutil.mk diff --git a/aux/compiledb.sh b/aux/compiledb.sh index 903a820..8c28bb2 100755 --- a/aux/compiledb.sh +++ b/aux/compiledb.sh @@ -11,3 +11,4 @@ make -B all_compiledb_libstring make -B all_compiledb_libkb make -B all_compiledb_libaux make -B all_compiledb_libarena +make -B all_compiledb_libioutil diff --git a/aux/devel.sh b/aux/devel.sh index 254af40..d6a748e 100755 --- a/aux/devel.sh +++ b/aux/devel.sh @@ -16,6 +16,7 @@ make -B all_libstring make -B all_libkb make -B all_libaux make -B all_libarena +make -B all_libioutil make -B all_apps make -B all_dist ./aux/limine_iso_amd64.sh diff --git a/aux/docs.sh b/aux/docs.sh index cc94b26..2d727f8 100755 --- a/aux/docs.sh +++ b/aux/docs.sh @@ -12,5 +12,6 @@ make -B docs_libterminal make -B docs_libkb make -B docs_libaux make -B docs_libarena +make -B docs_libioutil mkdocs build diff --git a/aux/format.sh b/aux/format.sh index 6c4bf1e..8253fab 100755 --- a/aux/format.sh +++ b/aux/format.sh @@ -11,4 +11,5 @@ make -B format_libstring make -B format_libkb make -B format_libaux make -B format_libarena +make -B format_libioutil make -B format_apps diff --git a/ce/Makefile b/ce/Makefile index f8abfbd..c9f6740 100644 --- a/ce/Makefile +++ b/ce/Makefile @@ -4,6 +4,7 @@ $(eval $(call add_lib,libstring)) $(eval $(call add_lib,libprocess)) $(eval $(call add_lib,libaux)) $(eval $(call add_lib,libarena)) +$(eval $(call add_lib,libioutil)) $(eval $(call add_include,libterminal)) cflags += -DPRINTF_INCLUDE_CONFIG_H=1 diff --git a/ce/ce.c b/ce/ce.c index 99c8cd3..fbf2cbd 100644 --- a/ce/ce.c +++ b/ce/ce.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -546,15 +547,33 @@ static void execute_redir (struct ast_redir* redir, struct context* context) { return; } - if ((ret = volume_open (volume)) < 0) { - cprintf (context, "ERROR could not open volume '%s': %s\n", volume, str_status[-ret]); + struct filewriter fw; + if ((ret = filewriter_init (&fw, volume, path, FW_CREATE_FILE | FW_APPEND)) < 0) { + cprintf (context, "ERROR could not initialize filewriter for '%s:%s'\n", volume, path); return; } - create_file (path); - write_file (path, 0, (uint8_t*)context->strbuf.items, context->strbuf.count - 1); + size_t chunk_size = 1024; + size_t chunks = (context->strbuf.count - 1) / chunk_size; + size_t rem = (context->strbuf.count - 1) % chunk_size; - volume_close (); + for (size_t chunk = 0; chunk < chunks; chunk++) { + if ((ret = filewriter_write (&fw, (uint8_t*)&context->strbuf.items[chunk * chunk_size], + chunk_size)) < 0) { + filewriter_fini (&fw); + cprintf (context, "ERROR filewriter failed to write to '%s:%s'\n", volume, path); + return; + } + } + + if ((ret = filewriter_write (&fw, (uint8_t*)&context->strbuf.items[chunks * chunk_size], rem)) < + 0) { + filewriter_fini (&fw); + cprintf (context, "ERROR filewriter failed to write to '%s:%s'\n", volume, path); + return; + } + + filewriter_fini (&fw); } static void execute (struct ast_node* root, struct context* context) { diff --git a/include/map.h b/include/map.h new file mode 100644 index 0000000..1fe2835 --- /dev/null +++ b/include/map.h @@ -0,0 +1,9 @@ +#ifndef _MAP_H +#define _MAP_H + +#define MAP_PRESENT (1 << 0) +#define MAP_RW (1 << 1) +#define MAP_USER (1 << 2) +#define MAP_FLAGS (MAP_PRESENT | MAP_USER) + +#endif // _MAP_H diff --git a/include/page_size.h b/include/page_size.h new file mode 100644 index 0000000..74eba59 --- /dev/null +++ b/include/page_size.h @@ -0,0 +1,8 @@ +#ifndef _PAGE_SIZE_H +#define _PAGE_SIZE_H + +#if defined(__x86_64__) +#define PAGE_SIZE 4096 +#endif + +#endif // _PAGE_SIZE_H diff --git a/include/write_file.h b/include/write_file.h new file mode 100644 index 0000000..9c0b06b --- /dev/null +++ b/include/write_file.h @@ -0,0 +1,6 @@ +#ifndef _WRITE_FILE_H +#define _WRITE_FILE_H + +#define WF_APPEND (1 << 0) + +#endif // _WRITE_FILE_H diff --git a/kernel/fs/fatfs.c b/kernel/fs/fatfs.c index d5e7394..32c53f7 100644 --- a/kernel/fs/fatfs.c +++ b/kernel/fs/fatfs.c @@ -14,6 +14,7 @@ #include #include #include +#include static int fat1_diskio_read (struct fatfs_ctx* ctx, uint32_t sector, uint8_t* buffer, uint32_t sector_count) { @@ -196,13 +197,18 @@ int fatfs_read_file (struct vfs_volume* volume, const char* path, uint8_t* buffe } int fatfs_write_file (struct vfs_volume* volume, const char* path, uint8_t* buffer, size_t off, - size_t size) { + size_t size, uint32_t flags) { struct fatfs_ctx* fatfs_ctx = volume->udata; if (fl_is_dir (fatfs_ctx, path)) return -ST_NOT_FOUND; - FL_FILE* file = fl_fopen (fatfs_ctx, path, "wb+"); + FL_FILE* file; + + if ((flags & WF_APPEND)) + file = fl_fopen (fatfs_ctx, path, "wb+"); + else + file = fl_fopen (fatfs_ctx, path, "wb"); if (file == NULL) return -ST_NOT_FOUND; diff --git a/kernel/fs/fatfs.h b/kernel/fs/fatfs.h index 803c4bc..55259b6 100644 --- a/kernel/fs/fatfs.h +++ b/kernel/fs/fatfs.h @@ -22,7 +22,7 @@ int fatfs_read_file (struct vfs_volume* volume, const char* path, uint8_t* buffe size_t size); int fatfs_write_file (struct vfs_volume* volume, const char* path, uint8_t* buffer, size_t off, - size_t size); + size_t size, uint32_t flags); int fatfs_read_dir_entry (struct vfs_volume* volume, const char* path, struct dir_entry* entry, size_t entry_num); diff --git a/kernel/fs/tarfs.c b/kernel/fs/tarfs.c index cb850ff..11dd794 100644 --- a/kernel/fs/tarfs.c +++ b/kernel/fs/tarfs.c @@ -199,8 +199,8 @@ int tarfs_read_dir_entry (struct vfs_volume* volume, const char* path, struct di } int tarfs_write_file (struct vfs_volume* volume, const char* path, uint8_t* buffer, size_t off, - size_t size) { - (void)volume, (void)path, (void)buffer, (void)off, (void)size; + size_t size, uint32_t flags) { + (void)volume, (void)path, (void)buffer, (void)off, (void)size, (void)flags; return ST_OK; } diff --git a/kernel/fs/tarfs.h b/kernel/fs/tarfs.h index 4e0c488..2c76042 100644 --- a/kernel/fs/tarfs.h +++ b/kernel/fs/tarfs.h @@ -44,7 +44,7 @@ int tarfs_read_file (struct vfs_volume* volume, const char* path, uint8_t* buffe size_t size); int tarfs_write_file (struct vfs_volume* volume, const char* path, uint8_t* buffer, size_t off, - size_t size); + size_t size, uint32_t flags); int tarfs_read_dir_entry (struct vfs_volume* volume, const char* path, struct dir_entry* entry, size_t entry_num); diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c index 08fe822..7b144d1 100644 --- a/kernel/fs/vfs.c +++ b/kernel/fs/vfs.c @@ -206,7 +206,7 @@ int vfs_read_file (struct proc* proc, const char* volume_name, const char* path, } int vfs_write_file (struct proc* proc, const char* volume_name, const char* path, uint8_t* buffer, - size_t off, size_t size) { + size_t off, size_t size, uint32_t flags) { struct vfs_volume* volume = vfs_find_volume (volume_name); if (volume == NULL) @@ -221,7 +221,7 @@ int vfs_write_file (struct proc* proc, const char* volume_name, const char* path spin_unlock (&volume->lock); - return volume->driver_ops.write_file (volume, path, buffer, off, size); + return volume->driver_ops.write_file (volume, path, buffer, off, size, flags); } int vfs_create_file (struct proc* proc, const char* volume_name, const char* path) { diff --git a/kernel/fs/vfs.h b/kernel/fs/vfs.h index 092437b..b251f02 100644 --- a/kernel/fs/vfs.h +++ b/kernel/fs/vfs.h @@ -42,7 +42,7 @@ struct vfs_volume { size_t size); int (*write_file) (struct vfs_volume* volume, const char* path, uint8_t* buffer, size_t off, - size_t size); + size_t size, uint32_t flags); int (*read_dir_entry) (struct vfs_volume* volume, const char* path, struct dir_entry* entry, size_t entry_num); @@ -70,7 +70,7 @@ int vfs_read_file (struct proc* proc, const char* volume, const char* path, uint size_t off, size_t size); int vfs_write_file (struct proc* proc, const char* volume, const char* path, uint8_t* buffer, - size_t off, size_t size); + size_t off, size_t size, uint32_t flags); int vfs_describe (struct proc* proc, const char* volume, const char* path, struct desc* desc); diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index ff450c3..1ad73ce 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -21,6 +21,7 @@ #include #include #include +#include #define DEFINE_SYSCALL(name) \ uintptr_t name (struct proc* UNUSED proc, void* UNUSED regs, struct reschedule_ctx* UNUSED rctx, \ @@ -503,12 +504,13 @@ DEFINE_SYSCALL (sys_create_file) { return SYSRESULT (ret); } -/* int write_file (char* path, size_t off, uint8_t* buffer, size_t size) */ +/* int write_file (char* path, size_t off, uint8_t* buffer, size_t size, uint32_t flags) */ DEFINE_SYSCALL (sys_write_file) { uintptr_t uvaddr_path = a1; size_t off = (size_t)a2; uintptr_t uvaddr_buffer = a3; size_t size = (size_t)a4; + uint32_t flags = (uint32_t)a5; struct limine_hhdm_response* hhdm = limine_hhdm_request.response; @@ -529,7 +531,7 @@ DEFINE_SYSCALL (sys_write_file) { return SYSRESULT (-ST_BAD_ADDRESS_SPACE); spin_lock (&proc->lock); - int ret = vfs_write_file (proc, proc->cwv, path, buffer, off, size); + int ret = vfs_write_file (proc, proc->cwv, path, buffer, off, size, flags); spin_unlock (&proc->lock); return SYSRESULT (ret); diff --git a/liballoc/liballoc.c b/liballoc/liballoc.c index c9b477b..56684d9 100644 --- a/liballoc/liballoc.c +++ b/liballoc/liballoc.c @@ -2,6 +2,8 @@ #pragma clang optimize off #include +#include +#include #include int liballoc_mutex; diff --git a/libioutil/.gitignore b/libioutil/.gitignore new file mode 100644 index 0000000..de276e3 --- /dev/null +++ b/libioutil/.gitignore @@ -0,0 +1,4 @@ +*.o +*.json +docs/ +.cache/ diff --git a/libioutil/Makefile b/libioutil/Makefile new file mode 100644 index 0000000..0ee0dcc --- /dev/null +++ b/libioutil/Makefile @@ -0,0 +1,8 @@ +include ../make/ufuncs.mk + +$(eval $(call add_include,libsystem)) +$(eval $(call add_include,libstring)) + +libname := libioutil + +include ../make/lib.mk diff --git a/libioutil/filewriter.c b/libioutil/filewriter.c new file mode 100644 index 0000000..b9ae0b7 --- /dev/null +++ b/libioutil/filewriter.c @@ -0,0 +1,83 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int filewriter_init (struct filewriter* fw, const char* volume, const char* path, uint32_t flags) { + memset (fw, 0, sizeof (*fw)); + strncpy (fw->volume, volume, VOLUME_MAX); + strncpy (fw->path, path, PATH_MAX); + fw->flags = flags; + + int ret; + struct desc desc; + + if ((ret = volume_open (fw->volume)) < 0) + return -FW_VOLUME_OPEN_ERROR; + + if ((fw->flags & FW_CREATE_FILE)) { + if ((ret = create_file (fw->path)) < 0) { + volume_close (); + return -FW_CREATE_FILE_ERROR; + } + } + + if ((ret = describe (fw->path, &desc)) < 0) { + volume_close (); + return -FW_DESC_ERROR; + } + + if (desc.type != FS_FILE) + return -FW_NOT_FILE; + + fw->file_size = desc.size; + fw->flags |= FW_OPEN; + + if ((fw->flags & FW_APPEND)) + fw->write_cursor = desc.size; + + return FW_OK; +} + +int filewriter_fini (struct filewriter* fw) { + if ((fw->flags & FW_OPEN)) { + volume_close (); + fw->flags &= ~FW_OPEN; + } + + return FW_OK; +} + +int filewriter_write (struct filewriter* fw, uint8_t* buffer, size_t buffer_size) { + if (!(fw->flags & FW_OPEN)) + return -FW_VOLUME_NOT_OPENED; + + struct desc desc; + int ret; + + if ((fw->flags & FW_APPEND)) { + if ((ret = describe (fw->path, &desc)) < 0) + return -FW_DESC_ERROR; + + fw->file_size = desc.size; + fw->write_cursor = fw->file_size; + } + + if (buffer_size > 0) { + if (!(fw->flags & FW_APPEND) && !(fw->write_cursor + buffer_size <= fw->file_size)) + return -FW_CURSOR_OOB; + + uint32_t flags = (fw->flags & FW_APPEND) ? WF_APPEND : 0; + if ((ret = write_file (fw->path, fw->write_cursor, buffer, buffer_size, flags)) < 0) + return -FW_WRITE_ERROR; + + fw->write_cursor += buffer_size; + } + + return FW_OK; +} diff --git a/libioutil/filewriter.h b/libioutil/filewriter.h new file mode 100644 index 0000000..8ae9fa3 --- /dev/null +++ b/libioutil/filewriter.h @@ -0,0 +1,36 @@ +#ifndef _LIBIOUTIL_FILEWRITER_H +#define _LIBIOUTIL_FILEWRITER_H + +#include +#include +#include +#include + +#define FW_OK 0 +#define FW_VOLUME_OPEN_ERROR 1 +#define FW_DESC_ERROR 2 +#define FW_NOT_FILE 3 +#define FW_VOLUME_NOT_OPENED 4 +#define FW_WRITE_ERROR 5 +#define FW_CURSOR_OOB 6 +#define FW_CREATE_FILE_ERROR 7 + +#define FW_CREATE_FILE (1 << 0) +#define FW_APPEND (1 << 1) +#define FW_OPEN (1 << 31) + +struct filewriter { + char volume[VOLUME_MAX]; + char path[PATH_MAX]; + size_t write_cursor; + size_t file_size; + uint32_t flags; +}; + +int filewriter_init (struct filewriter* fw, const char* volume, const char* path, uint32_t flags); + +int filewriter_fini (struct filewriter* fw); + +int filewriter_write (struct filewriter* fw, uint8_t* buffer, size_t buffer_size); + +#endif // _LIBIOUTIL_FILEWRITER_H diff --git a/libioutil/src.mk b/libioutil/src.mk new file mode 100644 index 0000000..f4eb992 --- /dev/null +++ b/libioutil/src.mk @@ -0,0 +1,3 @@ +c += filewriter.c + +o += filewriter.o diff --git a/libprocess/process.c b/libprocess/process.c index c3eed57..0f08790 100644 --- a/libprocess/process.c +++ b/libprocess/process.c @@ -1,4 +1,6 @@ #include +#include +#include #include #include #include diff --git a/libprocess/process.h b/libprocess/process.h index be0d938..3d0c976 100644 --- a/libprocess/process.h +++ b/libprocess/process.h @@ -1,6 +1,7 @@ #ifndef _LIBPROCESS_PROCESS_PROCESS_H #define _LIBPROCESS_PROCESS_PROCESS_H +#include #include /* Size of process' stack */ diff --git a/libsystem/system.c b/libsystem/system.c index 2aa55c9..4c816a6 100644 --- a/libsystem/system.c +++ b/libsystem/system.c @@ -71,8 +71,8 @@ int read_dir_entry (const char* path, struct dir_entry* entry, size_t entry_num) int create_file (const char* path) { return (int)do_syscall (SYS_CREATE_FILE, path); } -int write_file (const char* path, size_t off, uint8_t* buffer, size_t size) { - return (int)do_syscall (SYS_WRITE_FILE, path, off, buffer, size); +int write_file (const char* path, size_t off, uint8_t* buffer, size_t size, uint32_t flags) { + return (int)do_syscall (SYS_WRITE_FILE, path, off, buffer, size, flags); } int wait_for_pid (int pid) { return (int)do_syscall (SYS_WAIT_FOR_PID, pid); } diff --git a/libsystem/system.h b/libsystem/system.h index 907dfc9..4529d14 100644 --- a/libsystem/system.h +++ b/libsystem/system.h @@ -6,15 +6,6 @@ #include #include -#if defined(__x86_64__) -#define PAGE_SIZE 4096 -#endif - -#define MAP_PRESENT (1 << 0) -#define MAP_RW (1 << 1) -#define MAP_USER (1 << 2) -#define MAP_FLAGS (MAP_PRESENT | MAP_USER) - /* Quit the current running process */ int quit (void); @@ -85,7 +76,7 @@ int read_dir_entry (const char* path, struct dir_entry* entry, size_t entry_num) int create_file (const char* path); /* write to a file */ -int write_file (const char* path, size_t off, uint8_t* buffer, size_t size); +int write_file (const char* path, size_t off, uint8_t* buffer, size_t size, uint32_t flags); /* wait for process */ int wait_for_pid (int pid); diff --git a/make/libioutil.mk b/make/libioutil.mk new file mode 100644 index 0000000..1db6cec --- /dev/null +++ b/make/libioutil.mk @@ -0,0 +1,16 @@ +all_libioutil: + make -C libioutil platform=$(platform) all + +all_compiledb_libioutil: + bear --output libioutil/compile_commands.json -- make -C libioutil platform=$(platform) all + +clean_libioutil: + make -C libioutil platform=$(platform) clean + +format_libioutil: + make -C libioutil platform=$(platform) format + +docs_libioutil: + make -C libioutil platform=$(platform) docs + +.PHONY: all_libioutil clean_libioutil format_libioutil docs_libioutil all_compiledb_libioutil