Skip to content

Commit 1fea8e1

Browse files
committed
[libcxx] Cache file attributes during directory iteration.
1 parent 6481dc5 commit 1fea8e1

File tree

3 files changed

+55
-10
lines changed

3 files changed

+55
-10
lines changed

libcxx/include/__filesystem/directory_entry.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,8 @@ class directory_entry {
199199
_Empty,
200200
_IterSymlink,
201201
_IterNonSymlink,
202+
_IterCachedSymlink,
203+
_IterCachedNonSymlink,
202204
_RefreshSymlink,
203205
_RefreshSymlinkUnresolved,
204206
_RefreshNonSymlink
@@ -240,6 +242,28 @@ class directory_entry {
240242
return __data;
241243
}
242244

245+
_LIBCPP_HIDE_FROM_ABI static __cached_data __create_iter_cached_result(file_type __ft, uintmax_t __size, perms __perm, file_time_type __write_time) {
246+
__cached_data __data;
247+
__data.__type_ = __ft;
248+
__data.__size_ = __size;
249+
__data.__write_time_ = __write_time;
250+
if (__ft == file_type::symlink)
251+
__data.__sym_perms_ = __perm;
252+
else
253+
__data.__non_sym_perms_ = __perm;
254+
__data.__cache_type_ = [&]() {
255+
switch (__ft) {
256+
case file_type::none:
257+
return _Empty;
258+
case file_type::symlink:
259+
return _IterCachedSymlink;
260+
default:
261+
return _IterCachedNonSymlink;
262+
}
263+
}();
264+
return __data;
265+
}
266+
243267
_LIBCPP_HIDE_FROM_ABI void __assign_iter_entry(_Path&& __p, __cached_data __dt) {
244268
__p_ = std::move(__p);
245269
__data_ = __dt;
@@ -281,12 +305,14 @@ class directory_entry {
281305
case _Empty:
282306
return __symlink_status(__p_, __ec).type();
283307
case _IterSymlink:
308+
case _IterCachedSymlink:
284309
case _RefreshSymlink:
285310
case _RefreshSymlinkUnresolved:
286311
if (__ec)
287312
__ec->clear();
288313
return file_type::symlink;
289314
case _IterNonSymlink:
315+
case _IterCachedNonSymlink:
290316
case _RefreshNonSymlink:
291317
file_status __st(__data_.__type_);
292318
if (__ec && !filesystem::exists(__st))
@@ -302,9 +328,11 @@ class directory_entry {
302328
switch (__data_.__cache_type_) {
303329
case _Empty:
304330
case _IterSymlink:
331+
case _IterCachedSymlink:
305332
case _RefreshSymlinkUnresolved:
306333
return __status(__p_, __ec).type();
307334
case _IterNonSymlink:
335+
case _IterCachedNonSymlink:
308336
case _RefreshNonSymlink:
309337
case _RefreshSymlink: {
310338
file_status __st(__data_.__type_);
@@ -323,8 +351,10 @@ class directory_entry {
323351
case _Empty:
324352
case _IterNonSymlink:
325353
case _IterSymlink:
354+
case _IterCachedSymlink:
326355
case _RefreshSymlinkUnresolved:
327356
return __status(__p_, __ec);
357+
case _IterCachedNonSymlink:
328358
case _RefreshNonSymlink:
329359
case _RefreshSymlink:
330360
return file_status(__get_ft(__ec), __data_.__non_sym_perms_);
@@ -338,8 +368,10 @@ class directory_entry {
338368
case _IterNonSymlink:
339369
case _IterSymlink:
340370
return __symlink_status(__p_, __ec);
371+
case _IterCachedNonSymlink:
341372
case _RefreshNonSymlink:
342373
return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_);
374+
case _IterCachedSymlink:
343375
case _RefreshSymlink:
344376
case _RefreshSymlinkUnresolved:
345377
return file_status(__get_sym_ft(__ec), __data_.__sym_perms_);
@@ -352,8 +384,10 @@ class directory_entry {
352384
case _Empty:
353385
case _IterNonSymlink:
354386
case _IterSymlink:
387+
case _IterCachedSymlink:
355388
case _RefreshSymlinkUnresolved:
356389
return filesystem::__file_size(__p_, __ec);
390+
case _IterCachedNonSymlink:
357391
case _RefreshSymlink:
358392
case _RefreshNonSymlink: {
359393
error_code __m_ec;
@@ -374,6 +408,8 @@ class directory_entry {
374408
case _Empty:
375409
case _IterNonSymlink:
376410
case _IterSymlink:
411+
case _IterCachedNonSymlink:
412+
case _IterCachedSymlink:
377413
case _RefreshSymlinkUnresolved:
378414
return filesystem::__hard_link_count(__p_, __ec);
379415
case _RefreshSymlink:
@@ -394,6 +430,8 @@ class directory_entry {
394430
case _IterSymlink:
395431
case _RefreshSymlinkUnresolved:
396432
return filesystem::__last_write_time(__p_, __ec);
433+
case _IterCachedNonSymlink:
434+
case _IterCachedSymlink:
397435
case _RefreshSymlink:
398436
case _RefreshNonSymlink: {
399437
error_code __m_ec;

libcxx/src/filesystem/directory_iterator.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,13 @@ class __dir_stream {
7777
bool assign() {
7878
if (!wcscmp(__data_.cFileName, L".") || !wcscmp(__data_.cFileName, L".."))
7979
return false;
80-
// FIXME: Cache more of this
81-
// directory_entry::__cached_data cdata;
82-
// cdata.__type_ = get_file_type(__data_);
83-
// cdata.__size_ = get_file_size(__data_);
84-
// cdata.__write_time_ = get_write_time(__data_);
8580
__entry_.__assign_iter_entry(
86-
__root_ / __data_.cFileName, directory_entry::__create_iter_result(detail::get_file_type(__data_)));
81+
__root_ / __data_.cFileName,
82+
directory_entry::__create_iter_cached_result(
83+
detail::get_file_type(__data_),
84+
detail::get_file_size(__data_),
85+
detail::get_file_perm(__data_),
86+
detail::get_write_time(__data_)));
8787
return true;
8888
}
8989

libcxx/src/filesystem/file_descriptor.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,18 @@ inline uintmax_t get_file_size(const WIN32_FIND_DATAW& data) {
9797
return (static_cast<uint64_t>(data.nFileSizeHigh) << 32) + data.nFileSizeLow;
9898
}
9999
inline file_time_type get_write_time(const WIN32_FIND_DATAW& data) {
100-
ULARGE_INTEGER tmp;
100+
using detail::fs_time;
101101
const FILETIME& time = data.ftLastWriteTime;
102-
tmp.u.LowPart = time.dwLowDateTime;
103-
tmp.u.HighPart = time.dwHighDateTime;
104-
return file_time_type(file_time_type::duration(tmp.QuadPart));
102+
auto ts = filetime_to_timespec(time);
103+
if (!fs_time::is_representable(ts))
104+
return file_time_type::min();
105+
return fs_time::convert_from_timespec(ts);
106+
}
107+
inline perms get_file_perm(const WIN32_FIND_DATAW& data) {
108+
unsigned st_mode = 0555; // Read-only
109+
if (!(data.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
110+
st_mode |= 0222; // Write
111+
return static_cast<perms>(st_mode) & perms::mask;
105112
}
106113

107114
#endif // !_LIBCPP_WIN32API

0 commit comments

Comments
 (0)