dir_windows.odin 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. package os
  2. import win32 "core:sys/windows"
  3. import "core:strings"
  4. import "core:runtime"
  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[:]) or_else ""})
  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. windows_set_file_info_times(&fi, d)
  38. fi.is_dir = fi.mode & File_Mode_Dir != 0
  39. return
  40. }
  41. if fd == 0 {
  42. return nil, ERROR_INVALID_HANDLE
  43. }
  44. context.allocator = allocator
  45. h := win32.HANDLE(fd)
  46. dir_fi, _ := file_info_from_get_file_information_by_handle("", h)
  47. if !dir_fi.is_dir {
  48. return nil, ERROR_FILE_IS_NOT_DIR
  49. }
  50. n := n
  51. size := n
  52. if n <= 0 {
  53. n = -1
  54. size = 100
  55. }
  56. runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator)
  57. wpath: []u16
  58. wpath, err = cleanpath_from_handle_u16(fd, context.temp_allocator)
  59. if len(wpath) == 0 || err != ERROR_NONE {
  60. return
  61. }
  62. dfi := make([dynamic]File_Info, 0, size)
  63. wpath_search := make([]u16, len(wpath)+3, context.temp_allocator)
  64. copy(wpath_search, wpath)
  65. wpath_search[len(wpath)+0] = '\\'
  66. wpath_search[len(wpath)+1] = '*'
  67. wpath_search[len(wpath)+2] = 0
  68. path := cleanpath_from_buf(wpath)
  69. defer delete(path)
  70. find_data := &win32.WIN32_FIND_DATAW{}
  71. find_handle := win32.FindFirstFileW(raw_data(wpath_search), find_data)
  72. defer win32.FindClose(find_handle)
  73. for n != 0 && find_handle != nil {
  74. fi: File_Info
  75. fi = find_data_to_file_info(path, find_data)
  76. if fi.name != "" {
  77. append(&dfi, fi)
  78. n -= 1
  79. }
  80. if !win32.FindNextFileW(find_handle, find_data) {
  81. e := Errno(win32.GetLastError())
  82. if e == ERROR_NO_MORE_FILES {
  83. break
  84. }
  85. return dfi[:], e
  86. }
  87. }
  88. return dfi[:], ERROR_NONE
  89. }