stat_unix.odin 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. //+build linux, darwin, freebsd, openbsd, netbsd, 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, require_results)
  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, require_results)
  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. @(require_results)
  85. lstat :: proc(name: string, allocator := context.allocator) -> (fi: File_Info, err: Error) {
  86. context.allocator = allocator
  87. s := _lstat(name) or_return
  88. _fill_file_info_from_stat(&fi, s)
  89. fi.fullpath = absolute_path_from_relative(name) or_return
  90. fi.name = path_base(fi.fullpath)
  91. return
  92. }
  93. @(require_results)
  94. stat :: proc(name: string, allocator := context.allocator) -> (fi: File_Info, err: Error) {
  95. context.allocator = allocator
  96. s := _stat(name) or_return
  97. _fill_file_info_from_stat(&fi, s)
  98. fi.fullpath = absolute_path_from_relative(name) or_return
  99. fi.name = path_base(fi.fullpath)
  100. return
  101. }
  102. @(require_results)
  103. fstat :: proc(fd: Handle, allocator := context.allocator) -> (fi: File_Info, err: Error) {
  104. context.allocator = allocator
  105. s := _fstat(fd) or_return
  106. _fill_file_info_from_stat(&fi, s)
  107. fi.fullpath = absolute_path_from_handle(fd) or_return
  108. fi.name = path_base(fi.fullpath)
  109. return
  110. }