00-future-2024-09-09-cache-direntry.patch 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. diff --git a/include/__filesystem/directory_entry.h b/include/__filesystem/directory_entry.h
  2. index 016ad94..90e44f5 100644
  3. --- a/include/__filesystem/directory_entry.h
  4. +++ b/include/__filesystem/directory_entry.h
  5. @@ -202,7 +202,9 @@ private:
  6. _IterNonSymlink,
  7. _RefreshSymlink,
  8. _RefreshSymlinkUnresolved,
  9. - _RefreshNonSymlink
  10. + _RefreshNonSymlink,
  11. + _IterCachedSymlink,
  12. + _IterCachedNonSymlink
  13. };
  14. struct __cached_data {
  15. @@ -241,6 +243,29 @@ private:
  16. return __data;
  17. }
  18. + _LIBCPP_HIDE_FROM_ABI static __cached_data
  19. + __create_iter_cached_result(file_type __ft, uintmax_t __size, 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_HIDE_FROM_ABI void __assign_iter_entry(_Path&& __p, __cached_data __dt) {
  42. __p_ = std::move(__p);
  43. __data_ = __dt;
  44. @@ -282,13 +307,15 @@ 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 _IterCachedNonSymlink:
  55. case _IterNonSymlink:
  56. - case _RefreshNonSymlink:
  57. + case _RefreshNonSymlink: {
  58. file_status __st(__data_.__type_);
  59. if (__ec && !filesystem::exists(__st))
  60. *__ec = make_error_code(errc::no_such_file_or_directory);
  61. @@ -296,6 +323,7 @@ private:
  62. __ec->clear();
  63. return __data_.__type_;
  64. }
  65. + }
  66. __libcpp_unreachable();
  67. }
  68. @@ -303,8 +331,10 @@ private:
  69. switch (__data_.__cache_type_) {
  70. case _Empty:
  71. case _IterSymlink:
  72. + case _IterCachedSymlink:
  73. case _RefreshSymlinkUnresolved:
  74. return __status(__p_, __ec).type();
  75. + case _IterCachedNonSymlink:
  76. case _IterNonSymlink:
  77. case _RefreshNonSymlink:
  78. case _RefreshSymlink: {
  79. @@ -324,8 +354,10 @@ private:
  80. case _Empty:
  81. case _IterNonSymlink:
  82. case _IterSymlink:
  83. + case _IterCachedSymlink:
  84. case _RefreshSymlinkUnresolved:
  85. return __status(__p_, __ec);
  86. + case _IterCachedNonSymlink:
  87. case _RefreshNonSymlink:
  88. case _RefreshSymlink:
  89. return file_status(__get_ft(__ec), __data_.__non_sym_perms_);
  90. @@ -339,8 +371,10 @@ private:
  91. case _IterNonSymlink:
  92. case _IterSymlink:
  93. return __symlink_status(__p_, __ec);
  94. + case _IterCachedNonSymlink:
  95. case _RefreshNonSymlink:
  96. return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_);
  97. + case _IterCachedSymlink:
  98. case _RefreshSymlink:
  99. case _RefreshSymlinkUnresolved:
  100. return file_status(__get_sym_ft(__ec), __data_.__sym_perms_);
  101. @@ -353,8 +387,10 @@ private:
  102. case _Empty:
  103. case _IterNonSymlink:
  104. case _IterSymlink:
  105. + case _IterCachedSymlink:
  106. case _RefreshSymlinkUnresolved:
  107. return filesystem::__file_size(__p_, __ec);
  108. + case _IterCachedNonSymlink:
  109. case _RefreshSymlink:
  110. case _RefreshNonSymlink: {
  111. error_code __m_ec;
  112. @@ -375,6 +411,8 @@ private:
  113. case _Empty:
  114. case _IterNonSymlink:
  115. case _IterSymlink:
  116. + case _IterCachedNonSymlink:
  117. + case _IterCachedSymlink:
  118. case _RefreshSymlinkUnresolved:
  119. return filesystem::__hard_link_count(__p_, __ec);
  120. case _RefreshSymlink:
  121. @@ -393,8 +431,10 @@ private:
  122. case _Empty:
  123. case _IterNonSymlink:
  124. case _IterSymlink:
  125. + case _IterCachedSymlink:
  126. case _RefreshSymlinkUnresolved:
  127. return filesystem::__last_write_time(__p_, __ec);
  128. + case _IterCachedNonSymlink:
  129. case _RefreshSymlink:
  130. case _RefreshNonSymlink: {
  131. error_code __m_ec;
  132. diff --git a/src/filesystem/directory_iterator.cpp b/src/filesystem/directory_iterator.cpp
  133. index dceb348..d7ed9a3 100644
  134. --- a/src/filesystem/directory_iterator.cpp
  135. +++ b/src/filesystem/directory_iterator.cpp
  136. @@ -77,13 +77,13 @@ public:
  137. bool assign() {
  138. if (!wcscmp(__data_.cFileName, L".") || !wcscmp(__data_.cFileName, L".."))
  139. return false;
  140. - // FIXME: Cache more of this
  141. - // directory_entry::__cached_data cdata;
  142. - // cdata.__type_ = get_file_type(__data_);
  143. - // cdata.__size_ = get_file_size(__data_);
  144. - // cdata.__write_time_ = get_write_time(__data_);
  145. __entry_.__assign_iter_entry(
  146. - __root_ / __data_.cFileName, directory_entry::__create_iter_result(detail::get_file_type(__data_)));
  147. + __root_ / __data_.cFileName,
  148. + directory_entry::__create_iter_cached_result(
  149. + detail::get_file_type(__data_),
  150. + detail::get_file_size(__data_),
  151. + detail::get_file_perm(__data_),
  152. + detail::get_write_time(__data_)));
  153. return true;
  154. }
  155. diff --git a/src/filesystem/file_descriptor.h b/src/filesystem/file_descriptor.h
  156. index 50178ff..2c9e0d7 100644
  157. --- a/src/filesystem/file_descriptor.h
  158. +++ b/src/filesystem/file_descriptor.h
  159. @@ -97,11 +97,18 @@ inline uintmax_t get_file_size(const WIN32_FIND_DATAW& data) {
  160. return (static_cast<uint64_t>(data.nFileSizeHigh) << 32) + data.nFileSizeLow;
  161. }
  162. inline file_time_type get_write_time(const WIN32_FIND_DATAW& data) {
  163. - ULARGE_INTEGER tmp;
  164. + using detail::fs_time;
  165. const FILETIME& time = data.ftLastWriteTime;
  166. - tmp.u.LowPart = time.dwLowDateTime;
  167. - tmp.u.HighPart = time.dwHighDateTime;
  168. - return file_time_type(file_time_type::duration(tmp.QuadPart));
  169. + auto ts = filetime_to_timespec(time);
  170. + if (!fs_time::is_representable(ts))
  171. + return file_time_type::min();
  172. + return fs_time::convert_from_timespec(ts);
  173. +}
  174. +inline perms get_file_perm(const WIN32_FIND_DATAW& data) {
  175. + unsigned st_mode = 0555; // Read-only
  176. + if (!(data.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
  177. + st_mode |= 0222; // Write
  178. + return static_cast<perms>(st_mode) & perms::mask;
  179. }
  180. #endif // !_LIBCPP_WIN32API