123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- #+private
- package os2
- import "base:runtime"
- import "core:sync"
- import "core:sys/wasm/wasi"
- _Path_Separator :: '/'
- _Path_Separator_String :: "/"
- _Path_List_Separator :: ':'
- _is_path_separator :: proc(c: byte) -> bool {
- return c == _Path_Separator
- }
- _mkdir :: proc(name: string, perm: int) -> Error {
- dir_fd, relative, ok := match_preopen(name)
- if !ok {
- return .Invalid_Path
- }
- return _get_platform_error(wasi.path_create_directory(dir_fd, relative))
- }
- _mkdir_all :: proc(path: string, perm: int) -> Error {
- if path == "" {
- return .Invalid_Path
- }
- temp_allocator := TEMP_ALLOCATOR_GUARD({})
- if exists(path) {
- return .Exist
- }
- clean_path := clean_path(path, temp_allocator)
- return internal_mkdir_all(clean_path)
- internal_mkdir_all :: proc(path: string) -> Error {
- dir, file := split_path(path)
- if file != path && dir != "/" {
- if len(dir) > 1 && dir[len(dir) - 1] == '/' {
- dir = dir[:len(dir) - 1]
- }
- internal_mkdir_all(dir) or_return
- }
- err := _mkdir(path, 0)
- if err == .Exist { err = nil }
- return err
- }
- }
- _remove_all :: proc(path: string) -> (err: Error) {
- // PERF: this works, but wastes a bunch of memory using the read_directory_iterator API
- // and using open instead of wasi fds directly.
- {
- dir := open(path) or_return
- defer close(dir)
- iter := read_directory_iterator_create(dir)
- defer read_directory_iterator_destroy(&iter)
- for fi in read_directory_iterator(&iter) {
- _ = read_directory_iterator_error(&iter) or_break
- if fi.type == .Directory {
- _remove_all(fi.fullpath) or_return
- } else {
- remove(fi.fullpath) or_return
- }
- }
- _ = read_directory_iterator_error(&iter) or_return
- }
- return remove(path)
- }
- g_wd: string
- g_wd_mutex: sync.Mutex
- _get_working_directory :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) {
- sync.guard(&g_wd_mutex)
- return clone_string(g_wd if g_wd != "" else "/", allocator)
- }
- _set_working_directory :: proc(dir: string) -> (err: Error) {
- sync.guard(&g_wd_mutex)
- if dir == g_wd {
- return
- }
- if g_wd != "" {
- delete(g_wd, file_allocator())
- }
- g_wd = clone_string(dir, file_allocator()) or_return
- return
- }
- _get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err: Error) {
- if len(args) <= 0 {
- return clone_string("/", allocator)
- }
- arg := args[0]
- if len(arg) > 0 && (arg[0] == '.' || arg[0] == '/') {
- return clone_string(arg, allocator)
- }
- return concatenate({"/", arg}, allocator)
- }
|