stat_posix.odin 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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. import "core:time"
  8. internal_stat :: proc(stat: posix.stat_t, fullpath: string) -> (fi: File_Info) {
  9. fi.fullpath = fullpath
  10. fi.name = filepath.base(fi.fullpath)
  11. fi.inode = u128(stat.st_ino)
  12. fi.size = i64(stat.st_size)
  13. fi.mode = int(transmute(posix._mode_t)(stat.st_mode - posix.S_IFMT))
  14. fi.type = .Undetermined
  15. switch {
  16. case posix.S_ISBLK(stat.st_mode):
  17. fi.type = .Block_Device
  18. case posix.S_ISCHR(stat.st_mode):
  19. fi.type = .Character_Device
  20. case posix.S_ISDIR(stat.st_mode):
  21. fi.type = .Directory
  22. case posix.S_ISFIFO(stat.st_mode):
  23. fi.type = .Named_Pipe
  24. case posix.S_ISLNK(stat.st_mode):
  25. fi.type = .Symlink
  26. case posix.S_ISREG(stat.st_mode):
  27. fi.type = .Regular
  28. case posix.S_ISSOCK(stat.st_mode):
  29. fi.type = .Socket
  30. }
  31. fi.creation_time = timespec_time(stat.st_birthtimespec)
  32. fi.modification_time = timespec_time(stat.st_mtim)
  33. fi.access_time = timespec_time(stat.st_atim)
  34. timespec_time :: proc(t: posix.timespec) -> time.Time {
  35. return time.Time{_nsec = i64(t.tv_sec) * 1e9 + i64(t.tv_nsec)}
  36. }
  37. return
  38. }
  39. _fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (fi: File_Info, err: Error) {
  40. if f == nil || f.impl == nil {
  41. err = .Invalid_File
  42. return
  43. }
  44. impl := (^File_Impl)(f.impl)
  45. stat: posix.stat_t
  46. if posix.fstat(impl.fd, &stat) != .OK {
  47. err = _get_platform_error()
  48. return
  49. }
  50. fullpath := clone_string(impl.name, allocator) or_return
  51. return internal_stat(stat, fullpath), nil
  52. }
  53. _stat :: proc(name: string, allocator: runtime.Allocator) -> (fi: File_Info, err: Error) {
  54. if name == "" {
  55. err = .Invalid_Path
  56. return
  57. }
  58. TEMP_ALLOCATOR_GUARD()
  59. cname := temp_cstring(name) or_return
  60. fd := posix.open(cname, {})
  61. if fd == -1 {
  62. err = _get_platform_error()
  63. return
  64. }
  65. defer posix.close(fd)
  66. fullpath := _posix_absolute_path(fd, name, allocator) or_return
  67. stat: posix.stat_t
  68. if posix.stat(fullpath, &stat) != .OK {
  69. err = _get_platform_error()
  70. return
  71. }
  72. return internal_stat(stat, string(fullpath)), nil
  73. }
  74. _lstat :: proc(name: string, allocator: runtime.Allocator) -> (fi: File_Info, err: Error) {
  75. if name == "" {
  76. err = .Invalid_Path
  77. return
  78. }
  79. TEMP_ALLOCATOR_GUARD()
  80. // NOTE: can't use realpath or open (+ fcntl F_GETPATH) here because it tries to resolve symlinks.
  81. // NOTE: This might not be correct when given "/symlink/foo.txt",
  82. // you would want that to resolve "/symlink", but not resolve "foo.txt".
  83. fullpath := filepath.clean(name, temp_allocator())
  84. assert(len(fullpath) > 0)
  85. switch {
  86. case fullpath[0] == '/':
  87. // nothing.
  88. case fullpath == ".":
  89. fullpath = getwd(temp_allocator()) or_return
  90. case len(fullpath) > 1 && fullpath[0] == '.' && fullpath[1] == '/':
  91. fullpath = fullpath[2:]
  92. fallthrough
  93. case:
  94. fullpath = concatenate({
  95. getwd(temp_allocator()) or_return,
  96. "/",
  97. fullpath,
  98. }, temp_allocator()) or_return
  99. }
  100. stat: posix.stat_t
  101. if posix.lstat(temp_cstring(fullpath), &stat) != .OK {
  102. err = _get_platform_error()
  103. return
  104. }
  105. fullpath = clone_string(fullpath, allocator) or_return
  106. return internal_stat(stat, fullpath), nil
  107. }
  108. _same_file :: proc(fi1, fi2: File_Info) -> bool {
  109. return fi1.fullpath == fi2.fullpath
  110. }