pr93316-cache-direntry.patch 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. diff --git a/include/__filesystem/directory_entry.h b/include/__filesystem/directory_entry.h
  2. index bb7a061..a839bcf 100644
  3. --- a/include/__filesystem/directory_entry.h
  4. +++ b/include/__filesystem/directory_entry.h
  5. @@ -271,6 +271,8 @@ private:
  6. _Empty,
  7. _IterSymlink,
  8. _IterNonSymlink,
  9. + _IterCachedSymlink,
  10. + _IterCachedNonSymlink,
  11. _RefreshSymlink,
  12. _RefreshSymlinkUnresolved,
  13. _RefreshNonSymlink
  14. @@ -315,6 +317,30 @@ private:
  15. return __data;
  16. }
  17. + _LIBCPP_INLINE_VISIBILITY
  18. + static __cached_data __create_iter_cached_result(file_type __ft, uintmax_t __size,
  19. + perms __perm, file_time_type __write_time) {
  20. + __cached_data __data;
  21. + __data.__type_ = __ft;
  22. + __data.__size_ = __size;
  23. + __data.__write_time_ = __write_time;
  24. + if (__ft == file_type::symlink)
  25. + __data.__sym_perms_ = __perm;
  26. + else
  27. + __data.__non_sym_perms_ = __perm;
  28. + __data.__cache_type_ = [&]() {
  29. + switch (__ft) {
  30. + case file_type::none:
  31. + return _Empty;
  32. + case file_type::symlink:
  33. + return _IterCachedSymlink;
  34. + default:
  35. + return _IterCachedNonSymlink;
  36. + }
  37. + }();
  38. + return __data;
  39. + }
  40. +
  41. _LIBCPP_INLINE_VISIBILITY
  42. void __assign_iter_entry(_Path&& __p, __cached_data __dt) {
  43. __p_ = _VSTD::move(__p);
  44. @@ -359,12 +385,14 @@ private:
  45. case _Empty:
  46. return __symlink_status(__p_, __ec).type();
  47. case _IterSymlink:
  48. + case _IterCachedSymlink:
  49. case _RefreshSymlink:
  50. case _RefreshSymlinkUnresolved:
  51. if (__ec)
  52. __ec->clear();
  53. return file_type::symlink;
  54. case _IterNonSymlink:
  55. + case _IterCachedNonSymlink:
  56. case _RefreshNonSymlink:
  57. file_status __st(__data_.__type_);
  58. if (__ec && !_VSTD_FS::exists(__st))
  59. @@ -381,9 +409,11 @@ private:
  60. switch (__data_.__cache_type_) {
  61. case _Empty:
  62. case _IterSymlink:
  63. + case _IterCachedSymlink:
  64. case _RefreshSymlinkUnresolved:
  65. return __status(__p_, __ec).type();
  66. case _IterNonSymlink:
  67. + case _IterCachedNonSymlink:
  68. case _RefreshNonSymlink:
  69. case _RefreshSymlink: {
  70. file_status __st(__data_.__type_);
  71. @@ -403,8 +433,10 @@ private:
  72. case _Empty:
  73. case _IterNonSymlink:
  74. case _IterSymlink:
  75. + case _IterCachedSymlink:
  76. case _RefreshSymlinkUnresolved:
  77. return __status(__p_, __ec);
  78. + case _IterCachedNonSymlink:
  79. case _RefreshNonSymlink:
  80. case _RefreshSymlink:
  81. return file_status(__get_ft(__ec), __data_.__non_sym_perms_);
  82. @@ -419,8 +451,10 @@ private:
  83. case _IterNonSymlink:
  84. case _IterSymlink:
  85. return __symlink_status(__p_, __ec);
  86. + case _IterCachedNonSymlink:
  87. case _RefreshNonSymlink:
  88. return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_);
  89. + case _IterCachedSymlink:
  90. case _RefreshSymlink:
  91. case _RefreshSymlinkUnresolved:
  92. return file_status(__get_sym_ft(__ec), __data_.__sym_perms_);
  93. @@ -434,8 +468,10 @@ private:
  94. case _Empty:
  95. case _IterNonSymlink:
  96. case _IterSymlink:
  97. + case _IterCachedSymlink:
  98. case _RefreshSymlinkUnresolved:
  99. return _VSTD_FS::__file_size(__p_, __ec);
  100. + case _IterCachedNonSymlink:
  101. case _RefreshSymlink:
  102. case _RefreshNonSymlink: {
  103. error_code __m_ec;
  104. @@ -459,6 +495,8 @@ private:
  105. case _Empty:
  106. case _IterNonSymlink:
  107. case _IterSymlink:
  108. + case _IterCachedNonSymlink:
  109. + case _IterCachedSymlink:
  110. case _RefreshSymlinkUnresolved:
  111. return _VSTD_FS::__hard_link_count(__p_, __ec);
  112. case _RefreshSymlink:
  113. @@ -480,6 +518,8 @@ private:
  114. case _IterSymlink:
  115. case _RefreshSymlinkUnresolved:
  116. return _VSTD_FS::__last_write_time(__p_, __ec);
  117. + case _IterCachedNonSymlink:
  118. + case _IterCachedSymlink:
  119. case _RefreshSymlink:
  120. case _RefreshNonSymlink: {
  121. error_code __m_ec;
  122. diff --git a/src/filesystem/directory_iterator.cpp b/src/filesystem/directory_iterator.cpp
  123. index 151fb2f..cf9d631 100644
  124. --- a/src/filesystem/directory_iterator.cpp
  125. +++ b/src/filesystem/directory_iterator.cpp
  126. @@ -80,14 +80,12 @@ public:
  127. bool assign() {
  128. if (!wcscmp(__data_.cFileName, L".") || !wcscmp(__data_.cFileName, L".."))
  129. return false;
  130. - // FIXME: Cache more of this
  131. - //directory_entry::__cached_data cdata;
  132. - //cdata.__type_ = get_file_type(__data_);
  133. - //cdata.__size_ = get_file_size(__data_);
  134. - //cdata.__write_time_ = get_write_time(__data_);
  135. __entry_.__assign_iter_entry(
  136. __root_ / __data_.cFileName,
  137. - directory_entry::__create_iter_result(detail::get_file_type(__data_)));
  138. + directory_entry::__create_iter_cached_result(detail::get_file_type(__data_),
  139. + detail::get_file_size(__data_),
  140. + detail::get_file_perm(__data_),
  141. + detail::get_write_time(__data_)));
  142. return true;
  143. }
  144. diff --git a/src/filesystem/file_descriptor.h b/src/filesystem/file_descriptor.h
  145. index d3a668f..7bc0a4d 100644
  146. --- a/src/filesystem/file_descriptor.h
  147. +++ b/src/filesystem/file_descriptor.h
  148. @@ -99,11 +99,18 @@ inline uintmax_t get_file_size(const WIN32_FIND_DATAW& data) {
  149. return (static_cast<uint64_t>(data.nFileSizeHigh) << 32) + data.nFileSizeLow;
  150. }
  151. inline file_time_type get_write_time(const WIN32_FIND_DATAW& data) {
  152. - ULARGE_INTEGER tmp;
  153. + using detail::fs_time;
  154. const FILETIME& time = data.ftLastWriteTime;
  155. - tmp.u.LowPart = time.dwLowDateTime;
  156. - tmp.u.HighPart = time.dwHighDateTime;
  157. - return file_time_type(file_time_type::duration(tmp.QuadPart));
  158. + auto ts = filetime_to_timespec(time);
  159. + if (!fs_time::is_representable(ts))
  160. + return file_time_type::min();
  161. + return fs_time::convert_from_timespec(ts);
  162. +}
  163. +inline perms get_file_perm(const WIN32_FIND_DATAW& data) {
  164. + unsigned st_mode = 0555; // Read-only
  165. + if (!(data.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
  166. + st_mode |= 0222; // Write
  167. + return static_cast<perms>(st_mode) & perms::mask;
  168. }
  169. #endif // !_LIBCPP_WIN32API