import "./core.zc" import "./result.zc" import "./string.zc" import "./vec.zc" raw { #include #include #include // 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 { var h = fopen(path, mode); if (h == NULL) { return Result::Err("Failed to open file"); } return Result::Ok(File { handle: h }); } fn close(self) { if (self.handle) { fclose(self.handle); self.handle = NULL; } } fn read_to_string(self) -> Result { if (self.handle == NULL) return Result::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::Err("Out of memory"); var read = fread(buffer, 1, size, self.handle); buffer[read] = 0; var s = String::new(buffer); free(buffer); return Result::Ok(s); } fn read_all(path: char*) -> Result { var res = File::open(path, "rb"); if (res.is_err()) return Result::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 { if (self.handle == NULL) return Result::Err("File not open"); var len = strlen(content); var written = fwrite(content, 1, len, self.handle); if (written != len) return Result::Err("Write incomplete"); return Result::Ok(true); } fn exists(path: char*) -> bool { return access(path, F_OK) == 0; } fn metadata(path: char*) -> Result { 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::Err("Failed to get metadata"); } return Result::Ok(Metadata { size: (U64)size, is_dir: is_d != 0, is_file: is_f != 0 }); } fn create_dir(path: char*) -> Result { if (_z_fs_mkdir(path) != 0) return Result::Err("Failed to create directory"); return Result::Ok(true); } fn remove_file(path: char*) -> Result { if (unlink(path) != 0) return Result::Err("Failed to remove file"); return Result::Ok(true); } fn remove_dir(path: char*) -> Result { if (rmdir(path) != 0) return Result::Err("Failed to remove directory"); return Result::Ok(true); } fn read_dir(path: char*) -> Result< Vec > { var dir = opendir(path); if (dir == NULL) return Result< Vec >::Err("Failed to open directory"); var entries = Vec::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 >::Ok(entries); } }