stat_unix.odin 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. //+build linux, darwin, freebsd, openbsd, haiku
  2. package os
  3. import "core:time"
  4. /*
  5. For reference
  6. -------------
  7. Unix_File_Time :: struct {
  8. seconds: i64,
  9. nanoseconds: i64,
  10. }
  11. Stat :: struct {
  12. device_id: u64, // ID of device containing file
  13. serial: u64, // File serial number
  14. nlink: u64, // Number of hard links
  15. mode: u32, // Mode of the file
  16. uid: u32, // User ID of the file's owner
  17. gid: u32, // Group ID of the file's group
  18. _padding: i32, // 32 bits of padding
  19. rdev: u64, // Device ID, if device
  20. size: i64, // Size of the file, in bytes
  21. block_size: i64, // Optimal bllocksize for I/O
  22. blocks: i64, // Number of 512-byte blocks allocated
  23. last_access: Unix_File_Time, // Time of last access
  24. modified: Unix_File_Time, // Time of last modification
  25. status_change: Unix_File_Time, // Time of last status change
  26. _reserve1,
  27. _reserve2,
  28. _reserve3: i64,
  29. };
  30. Time :: struct {
  31. _nsec: i64, // zero is 1970-01-01 00:00:00
  32. }
  33. File_Info :: struct {
  34. fullpath: string,
  35. name: string,
  36. size: i64,
  37. mode: File_Mode,
  38. is_dir: bool,
  39. creation_time: time.Time,
  40. modification_time: time.Time,
  41. access_time: time.Time,
  42. }
  43. */
  44. @private
  45. _make_time_from_unix_file_time :: proc(uft: Unix_File_Time) -> time.Time {
  46. return time.Time{
  47. _nsec = uft.nanoseconds + uft.seconds * 1_000_000_000,
  48. }
  49. }
  50. @private
  51. _fill_file_info_from_stat :: proc(fi: ^File_Info, s: OS_Stat) {
  52. fi.size = s.size
  53. fi.mode = cast(File_Mode)s.mode
  54. fi.is_dir = S_ISDIR(s.mode)
  55. // NOTE(laleksic, 2021-01-21): Not really creation time, but closest we can get (maybe better to leave it 0?)
  56. fi.creation_time = _make_time_from_unix_file_time(s.status_change)
  57. fi.modification_time = _make_time_from_unix_file_time(s.modified)
  58. fi.access_time = _make_time_from_unix_file_time(s.last_access)
  59. }
  60. @private
  61. path_base :: proc(path: string) -> string {
  62. is_separator :: proc(c: byte) -> bool {
  63. return c == '/'
  64. }
  65. if path == "" {
  66. return "."
  67. }
  68. path := path
  69. for len(path) > 0 && is_separator(path[len(path)-1]) {
  70. path = path[:len(path)-1]
  71. }
  72. i := len(path)-1
  73. for i >= 0 && !is_separator(path[i]) {
  74. i -= 1
  75. }
  76. if i >= 0 {
  77. path = path[i+1:]
  78. }
  79. if path == "" {
  80. return "/"
  81. }
  82. return path
  83. }
  84. lstat :: proc(name: string, allocator := context.allocator) -> (fi: File_Info, err: Errno) {
  85. context.allocator = allocator
  86. s: OS_Stat
  87. s, err = _lstat(name)
  88. if err != ERROR_NONE {
  89. return fi, err
  90. }
  91. _fill_file_info_from_stat(&fi, s)
  92. fi.fullpath, err = absolute_path_from_relative(name)
  93. if err != ERROR_NONE {
  94. return
  95. }
  96. fi.name = path_base(fi.fullpath)
  97. return fi, ERROR_NONE
  98. }
  99. stat :: proc(name: string, allocator := context.allocator) -> (fi: File_Info, err: Errno) {
  100. context.allocator = allocator
  101. s: OS_Stat
  102. s, err = _stat(name)
  103. if err != ERROR_NONE {
  104. return fi, err
  105. }
  106. _fill_file_info_from_stat(&fi, s)
  107. fi.fullpath, err = absolute_path_from_relative(name)
  108. if err != ERROR_NONE {
  109. return
  110. }
  111. fi.name = path_base(fi.fullpath)
  112. return fi, ERROR_NONE
  113. }
  114. fstat :: proc(fd: Handle, allocator := context.allocator) -> (fi: File_Info, err: Errno) {
  115. context.allocator = allocator
  116. s: OS_Stat
  117. s, err = _fstat(fd)
  118. if err != ERROR_NONE {
  119. return fi, err
  120. }
  121. _fill_file_info_from_stat(&fi, s)
  122. fi.fullpath, err = absolute_path_from_handle(fd)
  123. if err != ERROR_NONE {
  124. return
  125. }
  126. fi.name = path_base(fi.fullpath)
  127. return fi, ERROR_NONE
  128. }