Skip to content

Commit 08ca1dc

Browse files
committed
[libcxx] Cache file attributes during directory
iteration.
1 parent ab7e6b6 commit 08ca1dc

File tree

3 files changed

+55
-11
lines changed

3 files changed

+55
-11
lines changed

libcxx/include/__filesystem/directory_entry.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ class directory_entry {
200200
_Empty,
201201
_IterSymlink,
202202
_IterNonSymlink,
203+
_IterCachedSymlink,
204+
_IterCachedNonSymlink,
203205
_RefreshSymlink,
204206
_RefreshSymlinkUnresolved,
205207
_RefreshNonSymlink
@@ -241,6 +243,28 @@ class directory_entry {
241243
return __data;
242244
}
243245

246+
_LIBCPP_HIDE_FROM_ABI static __cached_data __create_iter_cached_result(file_type __ft, uintmax_t __size, perms __perm, file_time_type __write_time) {
247+
__cached_data __data;
248+
__data.__type_ = __ft;
249+
__data.__size_ = __size;
250+
__data.__write_time_ = __write_time;
251+
if (__ft == file_type::symlink)
252+
__data.__sym_perms_ = __perm;
253+
else
254+
__data.__non_sym_perms_ = __perm;
255+
__data.__cache_type_ = [&]() {
256+
switch (__ft) {
257+
case file_type::none:
258+
return _Empty;
259+
case file_type::symlink:
260+
return _IterCachedSymlink;
261+
default:
262+
return _IterCachedNonSymlink;
263+
}
264+
}();
265+
return __data;
266+
}
267+
244268
_LIBCPP_HIDE_FROM_ABI void __assign_iter_entry(_Path&& __p, __cached_data __dt) {
245269
__p_ = std::move(__p);
246270
__data_ = __dt;
@@ -282,12 +306,14 @@ class directory_entry {
282306
case _Empty:
283307
return __symlink_status(__p_, __ec).type();
284308
case _IterSymlink:
309+
case _IterCachedSymlink:
285310
case _RefreshSymlink:
286311
case _RefreshSymlinkUnresolved:
287312
if (__ec)
288313
__ec->clear();
289314
return file_type::symlink;
290315
case _IterNonSymlink:
316+
case _IterCachedNonSymlink:
291317
case _RefreshNonSymlink:
292318
file_status __st(__data_.__type_);
293319
if (__ec && !filesystem::exists(__st))
@@ -303,9 +329,11 @@ class directory_entry {
303329
switch (__data_.__cache_type_) {
304330
case _Empty:
305331
case _IterSymlink:
332+
case _IterCachedSymlink:
306333
case _RefreshSymlinkUnresolved:
307334
return __status(__p_, __ec).type();
308335
case _IterNonSymlink:
336+
case _IterCachedNonSymlink:
309337
case _RefreshNonSymlink:
310338
case _RefreshSymlink: {
311339
file_status __st(__data_.__type_);
@@ -324,8 +352,10 @@ class directory_entry {
324352
case _Empty:
325353
case _IterNonSymlink:
326354
case _IterSymlink:
355+
case _IterCachedSymlink:
327356
case _RefreshSymlinkUnresolved:
328357
return __status(__p_, __ec);
358+
case _IterCachedNonSymlink:
329359
case _RefreshNonSymlink:
330360
case _RefreshSymlink:
331361
return file_status(__get_ft(__ec), __data_.__non_sym_perms_);
@@ -339,8 +369,10 @@ class directory_entry {
339369
case _IterNonSymlink:
340370
case _IterSymlink:
341371
return __symlink_status(__p_, __ec);
372+
case _IterCachedNonSymlink:
342373
case _RefreshNonSymlink:
343374
return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_);
375+
case _IterCachedSymlink:
344376
case _RefreshSymlink:
345377
case _RefreshSymlinkUnresolved:
346378
return file_status(__get_sym_ft(__ec), __data_.__sym_perms_);
@@ -353,8 +385,10 @@ class directory_entry {
353385
case _Empty:
354386
case _IterNonSymlink:
355387
case _IterSymlink:
388+
case _IterCachedSymlink:
356389
case _RefreshSymlinkUnresolved:
357390
return filesystem::__file_size(__p_, __ec);
391+
case _IterCachedNonSymlink:
358392
case _RefreshSymlink:
359393
case _RefreshNonSymlink: {
360394
error_code __m_ec;
@@ -375,6 +409,8 @@ class directory_entry {
375409
case _Empty:
376410
case _IterNonSymlink:
377411
case _IterSymlink:
412+
case _IterCachedNonSymlink:
413+
case _IterCachedSymlink:
378414
case _RefreshSymlinkUnresolved:
379415
return filesystem::__hard_link_count(__p_, __ec);
380416
case _RefreshSymlink:
@@ -395,6 +431,8 @@ class directory_entry {
395431
case _IterSymlink:
396432
case _RefreshSymlinkUnresolved:
397433
return filesystem::__last_write_time(__p_, __ec);
434+
case _IterCachedNonSymlink:
435+
case _IterCachedSymlink:
398436
case _RefreshSymlink:
399437
case _RefreshNonSymlink: {
400438
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 & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,17 @@ 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;
101-
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));
100+
using detail::fs_time;
101+
auto ts = filetime_to_timespec(time);
102+
if (!fs_time::is_representable(ts))
103+
return file_time_type::min();
104+
return fs_time::convert_from_timespec(ts);
105+
}
106+
inline perms get_file_perm(const WIN32_FIND_DATAW& data) {
107+
unsigned st_mode = 0555; // Read-only
108+
if (!(data.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
109+
st_mode |= 0222; // Write
110+
return static_cast<perms>(st_mode) & perms::mask;
105111
}
106112

107113
#endif // !_LIBCPP_WIN32API

0 commit comments

Comments
 (0)