dir_windows.odin 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package os
  2. import win32 "core:sys/windows"
  3. import "core:strings"
  4. import "core:time"
  5. read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Errno) {
  6. find_data_to_file_info :: proc(base_path: string, d: ^win32.WIN32_FIND_DATAW) -> (fi: File_Info) {
  7. // Ignore "." and ".."
  8. if d.cFileName[0] == '.' && d.cFileName[1] == 0 {
  9. return
  10. }
  11. if d.cFileName[0] == '.' && d.cFileName[1] == '.' && d.cFileName[2] == 0 {
  12. return
  13. }
  14. path := strings.concatenate({base_path, `\`, win32.utf16_to_utf8(d.cFileName[:])})
  15. fi.fullpath = path
  16. fi.name = basename(path)
  17. fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow)
  18. if d.dwFileAttributes & win32.FILE_ATTRIBUTE_READONLY != 0 {
  19. fi.mode |= 0o444
  20. } else {
  21. fi.mode |= 0o666
  22. }
  23. is_sym := false
  24. if d.dwFileAttributes & win32.FILE_ATTRIBUTE_REPARSE_Point == 0 {
  25. is_sym = false
  26. } else {
  27. is_sym = d.dwReserved0 == win32.IO_REPARSE_TAG_SYMLINK || d.dwReserved0 == win32.IO_REPARSE_TAG_MOUNT_POINT
  28. }
  29. if is_sym {
  30. fi.mode |= File_Mode_Sym_Link
  31. } else {
  32. if d.dwFileAttributes & win32.FILE_ATTRIBUTE_DIRECTORY != 0 {
  33. fi.mode |= 0o111 | File_Mode_Dir
  34. }
  35. // fi.mode |= file_type_mode(h);
  36. }
  37. fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime))
  38. fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime))
  39. fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime))
  40. fi.is_dir = fi.mode & File_Mode_Dir != 0
  41. return
  42. }
  43. if fd == 0 {
  44. return nil, ERROR_INVALID_HANDLE
  45. }
  46. context.allocator = allocator
  47. h := win32.HANDLE(fd)
  48. dir_fi, _ := file_info_from_get_file_information_by_handle("", h)
  49. if !dir_fi.is_dir {
  50. return nil, ERROR_FILE_IS_NOT_DIR
  51. }
  52. n := n
  53. size := n
  54. if n <= 0 {
  55. n = -1
  56. size = 100
  57. }
  58. dfi := make([dynamic]File_Info, 0, size)
  59. wpath: []u16
  60. wpath, err = cleanpath_from_handle_u16(fd)
  61. if len(wpath) == 0 || err != ERROR_NONE {
  62. return
  63. }
  64. wpath_search := make([]u16, len(wpath)+3, context.temp_allocator)
  65. copy(wpath_search, wpath)
  66. wpath_search[len(wpath)+0] = '\\'
  67. wpath_search[len(wpath)+1] = '*'
  68. wpath_search[len(wpath)+2] = 0
  69. path := cleanpath_from_buf(wpath)
  70. defer delete(path)
  71. find_data := &win32.WIN32_FIND_DATAW{}
  72. find_handle := win32.FindFirstFileW(raw_data(wpath_search), find_data)
  73. defer win32.FindClose(find_handle)
  74. for n != 0 && find_handle != nil {
  75. fi: File_Info
  76. fi = find_data_to_file_info(path, find_data)
  77. if fi.name != "" {
  78. append(&dfi, fi)
  79. n -= 1
  80. }
  81. if !win32.FindNextFileW(find_handle, find_data) {
  82. e := Errno(win32.GetLastError())
  83. if e == ERROR_NO_MORE_FILES {
  84. break
  85. }
  86. return dfi[:], e
  87. }
  88. }
  89. return dfi[:], ERROR_NONE
  90. }