summaryrefslogtreecommitdiff
path: root/std/fs.zc
diff options
context:
space:
mode:
authorZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-11 17:47:30 +0000
committerZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-11 17:47:30 +0000
commitba5ee94871e670fbe1ea091dd5731e593df0b29f (patch)
tree3b706a9ab11effa4acb094482f3d657c986ef501 /std/fs.zc
parentaba9191ab3ef0699b0f9507ee3d03161f9ee7771 (diff)
Some std for you
Diffstat (limited to 'std/fs.zc')
-rw-r--r--std/fs.zc162
1 files changed, 162 insertions, 0 deletions
diff --git a/std/fs.zc b/std/fs.zc
new file mode 100644
index 0000000..4223054
--- /dev/null
+++ b/std/fs.zc
@@ -0,0 +1,162 @@
+
+import "./core.zc"
+import "./result.zc"
+import "./string.zc"
+import "./vec.zc"
+
+raw {
+ #include <dirent.h>
+ #include <sys/stat.h>
+ #include <unistd.h>
+
+ // Helper to get file size for stat
+ int _z_fs_get_metadata(char* path, uint64_t* size, int* is_dir, int* is_file) {
+ struct stat st;
+ if (stat(path, &st) != 0) return -1;
+ *size = st.st_size;
+ *is_dir = S_ISDIR(st.st_mode);
+ *is_file = S_ISREG(st.st_mode);
+ return 0;
+ }
+
+ int _z_fs_read_entry(void* dir, char* out_name, int* is_dir) {
+ struct dirent* ent = readdir((DIR*)dir);
+ if (!ent) return 0;
+ strcpy(out_name, ent->d_name);
+ *is_dir = (ent->d_type == DT_DIR);
+ return 1;
+ }
+
+ int _z_fs_mkdir(char* path) {
+ #ifdef _WIN32
+ return mkdir(path);
+ #else
+ return mkdir(path, 0777);
+ #endif
+ }
+}
+
+extern fn _z_fs_mkdir(path: char*) -> int;
+extern fn _z_fs_get_metadata(path: char*, size: U64*, is_dir: int*, is_file: int*) -> int;
+extern fn _z_fs_read_entry(dir: void*, out_name: char*, is_dir: int*) -> int;
+
+struct File {
+ handle: void*; // FILE*
+}
+
+struct Metadata {
+ size: U64;
+ is_dir: bool;
+ is_file: bool;
+}
+
+@derive(Eq)
+struct DirEntry {
+ name: String;
+ is_dir: bool;
+}
+
+impl File {
+ fn open(path: char*, mode: char*) -> Result<File> {
+ var h = fopen(path, mode);
+ if (h == NULL) {
+ return Result<File>::Err("Failed to open file");
+ }
+ return Result<File>::Ok(File { handle: h });
+ }
+
+ fn close(self) {
+ if (self.handle) {
+ fclose(self.handle);
+ self.handle = NULL;
+ }
+ }
+
+ fn read_to_string(self) -> Result<String> {
+ if (self.handle == NULL) return Result<String>::Err("File not open");
+
+ fseek(self.handle, 0, SEEK_END);
+ var size = ftell(self.handle);
+ fseek(self.handle, 0, SEEK_SET);
+
+ var buffer: char* = malloc((usize)size + 1);
+ if (buffer == NULL) return Result<String>::Err("Out of memory");
+
+ var read = fread(buffer, 1, size, self.handle);
+ buffer[read] = 0;
+
+ var s = String::new(buffer);
+ free(buffer);
+ return Result<String>::Ok(s);
+ }
+
+ fn read_all(path: char*) -> Result<String> {
+ var res = File::open(path, "rb");
+ if (res.is_err()) return Result<String>::Err(res.err);
+
+ var f: File = res.unwrap();
+ var s_res = f.read_to_string();
+ f.close();
+ return s_res;
+ }
+
+ fn write_string(self, content: char*) -> Result<bool> {
+ if (self.handle == NULL) return Result<bool>::Err("File not open");
+ var len = strlen(content);
+ var written = fwrite(content, 1, len, self.handle);
+ if (written != len) return Result<bool>::Err("Write incomplete");
+ return Result<bool>::Ok(true);
+ }
+
+ fn exists(path: char*) -> bool {
+ return access(path, F_OK) == 0;
+ }
+
+ fn metadata(path: char*) -> Result<Metadata> {
+ var size: uint64_t;
+ var is_d: int;
+ var is_f: int;
+ if (_z_fs_get_metadata(path, &size, &is_d, &is_f) != 0) {
+ return Result<Metadata>::Err("Failed to get metadata");
+ }
+ return Result<Metadata>::Ok(Metadata { size: (U64)size, is_dir: is_d != 0, is_file: is_f != 0 });
+ }
+
+ fn create_dir(path: char*) -> Result<bool> {
+ if (_z_fs_mkdir(path) != 0) return Result<bool>::Err("Failed to create directory");
+ return Result<bool>::Ok(true);
+ }
+
+ fn remove_file(path: char*) -> Result<bool> {
+ if (unlink(path) != 0) return Result<bool>::Err("Failed to remove file");
+ return Result<bool>::Ok(true);
+ }
+
+ fn remove_dir(path: char*) -> Result<bool> {
+ if (rmdir(path) != 0) return Result<bool>::Err("Failed to remove directory");
+ return Result<bool>::Ok(true);
+ }
+
+ fn read_dir(path: char*) -> Result< Vec<DirEntry> > {
+ var dir = opendir(path);
+ if (dir == NULL) return Result< Vec<DirEntry> >::Err("Failed to open directory");
+
+ var entries = Vec<DirEntry>::new();
+ var name_buf = malloc(256);
+ var is_d: int = 0;
+
+ while (_z_fs_read_entry(dir, name_buf, &is_d)) {
+ // Skip . and ..
+ if (strcmp(name_buf, ".") == 0 || strcmp(name_buf, "..") == 0) continue;
+
+ entries.push(DirEntry {
+ name: String::new(name_buf),
+ is_dir: is_d != 0
+ });
+ }
+
+ free(name_buf);
+ closedir(dir);
+ return Result< Vec<DirEntry> >::Ok(entries);
+ }
+}