path_posix.odin 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. //+private
  2. //+build darwin, netbsd, freebsd, openbsd
  3. package os2
  4. import "base:runtime"
  5. import "core:path/filepath"
  6. import "core:sys/posix"
  7. _Path_Separator :: '/'
  8. _Path_Separator_String :: "/"
  9. _Path_List_Separator :: ':'
  10. _is_path_separator :: proc(c: byte) -> bool {
  11. return c == _Path_Separator
  12. }
  13. _mkdir :: proc(name: string, perm: int) -> Error {
  14. TEMP_ALLOCATOR_GUARD()
  15. cname := temp_cstring(name)
  16. if posix.mkdir(cname, transmute(posix.mode_t)posix._mode_t(perm)) != .OK {
  17. return _get_platform_error()
  18. }
  19. return nil
  20. }
  21. _mkdir_all :: proc(path: string, perm: int) -> Error {
  22. if path == "" {
  23. return .Invalid_Path
  24. }
  25. TEMP_ALLOCATOR_GUARD()
  26. if exists(path) {
  27. return .Exist
  28. }
  29. clean_path := filepath.clean(path, temp_allocator())
  30. return internal_mkdir_all(clean_path, perm)
  31. internal_mkdir_all :: proc(path: string, perm: int) -> Error {
  32. a, _ := filepath.split(path)
  33. if a != path {
  34. if len(a) > 1 && a[len(a)-1] == '/' {
  35. a = a[:len(a)-1]
  36. }
  37. internal_mkdir_all(a, perm) or_return
  38. }
  39. err := _mkdir(path, perm)
  40. if err == .Exist { err = nil }
  41. return err
  42. }
  43. }
  44. _remove_all :: proc(path: string) -> Error {
  45. TEMP_ALLOCATOR_GUARD()
  46. cpath := temp_cstring(path)
  47. dir := posix.opendir(cpath)
  48. if dir == nil {
  49. return _get_platform_error()
  50. }
  51. defer posix.closedir(dir)
  52. for {
  53. posix.set_errno(.NONE)
  54. entry := posix.readdir(dir)
  55. if entry == nil {
  56. if errno := posix.errno(); errno != .NONE {
  57. return _get_platform_error()
  58. } else {
  59. break
  60. }
  61. }
  62. cname := cstring(raw_data(entry.d_name[:]))
  63. if cname == "." || cname == ".." {
  64. continue
  65. }
  66. fullpath, _ := concatenate({path, "/", string(cname), "\x00"}, temp_allocator())
  67. if entry.d_type == .DIR {
  68. _remove_all(fullpath[:len(fullpath)-1])
  69. } else {
  70. if posix.unlink(cstring(raw_data(fullpath))) != .OK {
  71. return _get_platform_error()
  72. }
  73. }
  74. }
  75. if posix.rmdir(cpath) != .OK {
  76. return _get_platform_error()
  77. }
  78. return nil
  79. }
  80. _get_working_directory :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) {
  81. TEMP_ALLOCATOR_GUARD()
  82. buf: [dynamic]byte
  83. buf.allocator = temp_allocator()
  84. size := uint(posix.PATH_MAX)
  85. cwd: cstring
  86. for ; cwd == nil; size *= 2 {
  87. resize(&buf, size)
  88. cwd = posix.getcwd(raw_data(buf), len(buf))
  89. if cwd == nil && posix.errno() != .ERANGE {
  90. err = _get_platform_error()
  91. return
  92. }
  93. }
  94. return clone_string(string(cwd), allocator)
  95. }
  96. _set_working_directory :: proc(dir: string) -> (err: Error) {
  97. TEMP_ALLOCATOR_GUARD()
  98. cdir := temp_cstring(dir)
  99. if posix.chdir(cdir) != .OK {
  100. err = _get_platform_error()
  101. }
  102. return
  103. }