dir_windows.odin 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. package os
  2. import win32 "core:sys/windows"
  3. import "core:strings"
  4. import "base:runtime"
  5. @(require_results)
  6. read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Error) {
  7. @(require_results)
  8. find_data_to_file_info :: proc(base_path: string, d: ^win32.WIN32_FIND_DATAW) -> (fi: File_Info) {
  9. // Ignore "." and ".."
  10. if d.cFileName[0] == '.' && d.cFileName[1] == 0 {
  11. return
  12. }
  13. if d.cFileName[0] == '.' && d.cFileName[1] == '.' && d.cFileName[2] == 0 {
  14. return
  15. }
  16. path := strings.concatenate({base_path, `\`, win32.utf16_to_utf8(d.cFileName[:]) or_else ""})
  17. fi.fullpath = path
  18. fi.name = basename(path)
  19. fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow)
  20. if d.dwFileAttributes & win32.FILE_ATTRIBUTE_READONLY != 0 {
  21. fi.mode |= 0o444
  22. } else {
  23. fi.mode |= 0o666
  24. }
  25. is_sym := false
  26. if d.dwFileAttributes & win32.FILE_ATTRIBUTE_REPARSE_Point == 0 {
  27. is_sym = false
  28. } else {
  29. is_sym = d.dwReserved0 == win32.IO_REPARSE_TAG_SYMLINK || d.dwReserved0 == win32.IO_REPARSE_TAG_MOUNT_POINT
  30. }
  31. if is_sym {
  32. fi.mode |= File_Mode_Sym_Link
  33. } else {
  34. if d.dwFileAttributes & win32.FILE_ATTRIBUTE_DIRECTORY != 0 {
  35. fi.mode |= 0o111 | File_Mode_Dir
  36. }
  37. // fi.mode |= file_type_mode(h);
  38. }
  39. windows_set_file_info_times(&fi, d)
  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, .Not_Dir
  51. }
  52. n := n
  53. size := n
  54. if n <= 0 {
  55. n = -1
  56. size = 100
  57. }
  58. runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator)
  59. wpath := cleanpath_from_handle_u16(fd, context.temp_allocator) or_return
  60. if len(wpath) == 0 {
  61. return
  62. }
  63. dfi := make([dynamic]File_Info, 0, size) or_return
  64. wpath_search := make([]u16, len(wpath)+3, context.temp_allocator) or_return
  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. if find_handle == win32.INVALID_HANDLE_VALUE {
  74. err = get_last_error()
  75. return dfi[:], err
  76. }
  77. defer win32.FindClose(find_handle)
  78. for n != 0 {
  79. fi: File_Info
  80. fi = find_data_to_file_info(path, find_data)
  81. if fi.name != "" {
  82. append(&dfi, fi)
  83. n -= 1
  84. }
  85. if !win32.FindNextFileW(find_handle, find_data) {
  86. e := get_last_error()
  87. if e == ERROR_NO_MORE_FILES {
  88. break
  89. }
  90. return dfi[:], e
  91. }
  92. }
  93. return dfi[:], nil
  94. }