dir_windows.odin 2.4 KB

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