path_wasi.odin 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. #+private
  2. package os2
  3. import "base:runtime"
  4. import "core:sync"
  5. import "core:sys/wasm/wasi"
  6. _Path_Separator :: '/'
  7. _Path_Separator_String :: "/"
  8. _Path_List_Separator :: ':'
  9. _is_path_separator :: proc(c: byte) -> bool {
  10. return c == _Path_Separator
  11. }
  12. _mkdir :: proc(name: string, perm: int) -> Error {
  13. dir_fd, relative, ok := match_preopen(name)
  14. if !ok {
  15. return .Invalid_Path
  16. }
  17. return _get_platform_error(wasi.path_create_directory(dir_fd, relative))
  18. }
  19. _mkdir_all :: proc(path: string, perm: int) -> Error {
  20. if path == "" {
  21. return .Invalid_Path
  22. }
  23. temp_allocator := TEMP_ALLOCATOR_GUARD({})
  24. if exists(path) {
  25. return .Exist
  26. }
  27. clean_path := clean_path(path, temp_allocator)
  28. return internal_mkdir_all(clean_path)
  29. internal_mkdir_all :: proc(path: string) -> Error {
  30. dir, file := split_path(path)
  31. if file != path && dir != "/" {
  32. if len(dir) > 1 && dir[len(dir) - 1] == '/' {
  33. dir = dir[:len(dir) - 1]
  34. }
  35. internal_mkdir_all(dir) or_return
  36. }
  37. err := _mkdir(path, 0)
  38. if err == .Exist { err = nil }
  39. return err
  40. }
  41. }
  42. _remove_all :: proc(path: string) -> (err: Error) {
  43. // PERF: this works, but wastes a bunch of memory using the read_directory_iterator API
  44. // and using open instead of wasi fds directly.
  45. {
  46. dir := open(path) or_return
  47. defer close(dir)
  48. iter := read_directory_iterator_create(dir)
  49. defer read_directory_iterator_destroy(&iter)
  50. for fi in read_directory_iterator(&iter) {
  51. _ = read_directory_iterator_error(&iter) or_break
  52. if fi.type == .Directory {
  53. _remove_all(fi.fullpath) or_return
  54. } else {
  55. remove(fi.fullpath) or_return
  56. }
  57. }
  58. _ = read_directory_iterator_error(&iter) or_return
  59. }
  60. return remove(path)
  61. }
  62. g_wd: string
  63. g_wd_mutex: sync.Mutex
  64. _get_working_directory :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) {
  65. sync.guard(&g_wd_mutex)
  66. return clone_string(g_wd if g_wd != "" else "/", allocator)
  67. }
  68. _set_working_directory :: proc(dir: string) -> (err: Error) {
  69. sync.guard(&g_wd_mutex)
  70. if dir == g_wd {
  71. return
  72. }
  73. if g_wd != "" {
  74. delete(g_wd, file_allocator())
  75. }
  76. g_wd = clone_string(dir, file_allocator()) or_return
  77. return
  78. }
  79. _get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err: Error) {
  80. if len(args) <= 0 {
  81. return clone_string("/", allocator)
  82. }
  83. arg := args[0]
  84. if len(arg) > 0 && (arg[0] == '.' || arg[0] == '/') {
  85. return clone_string(arg, allocator)
  86. }
  87. return concatenate({"/", arg}, allocator)
  88. }