Coverage Report

Created: 2022-07-16 07:03

/Users/buildslave/jenkins/workspace/coverage/llvm-project/libcxx/src/filesystem/filesystem_common.h
Line
Count
Source (jump to first uncovered line)
1
//===----------------------------------------------------------------------===////
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===////
8
9
#ifndef FILESYSTEM_COMMON_H
10
#define FILESYSTEM_COMMON_H
11
12
#include <__assert>
13
#include <__config>
14
#include <array>
15
#include <chrono>
16
#include <climits>
17
#include <cstdarg>
18
#include <ctime>
19
#include <filesystem>
20
#include <ratio>
21
#include <system_error>
22
#include <utility>
23
24
#if defined(_LIBCPP_WIN32API)
25
# define WIN32_LEAN_AND_MEAN
26
# define NOMINMAX
27
# include <windows.h>
28
#else
29
# include <dirent.h>   // for DIR & friends
30
# include <fcntl.h>    /* values for fchmodat */
31
# include <sys/stat.h>
32
# include <sys/statvfs.h>
33
# include <sys/time.h> // for ::utimes as used in __last_write_time
34
# include <unistd.h>
35
#endif // defined(_LIBCPP_WIN32API)
36
37
#include "../include/apple_availability.h"
38
39
#if !defined(__APPLE__)
40
// We can use the presence of UTIME_OMIT to detect platforms that provide
41
// utimensat.
42
#if defined(UTIME_OMIT)
43
#define _LIBCPP_USE_UTIMENSAT
44
#endif
45
#endif
46
47
_LIBCPP_DIAGNOSTIC_PUSH
48
_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wunused-function")
49
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wunused-function")
50
51
#if defined(_LIBCPP_WIN32API)
52
#  define PATHSTR(x) (L##x)
53
#  define PATH_CSTR_FMT "\"%ls\""
54
#else
55
0
#  define PATHSTR(x) (x)
56
0
#  define PATH_CSTR_FMT "\"%s\""
57
#endif
58
59
_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
60
61
namespace detail {
62
63
#if defined(_LIBCPP_WIN32API)
64
// Non anonymous, to allow access from two translation units.
65
errc __win_err_to_errc(int err);
66
#endif
67
68
namespace {
69
70
static _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 0) string
71
0
format_string_impl(const char* msg, va_list ap) {
72
0
  array<char, 256> buf;
73
74
0
  va_list apcopy;
75
0
  va_copy(apcopy, ap);
76
0
  int ret = ::vsnprintf(buf.data(), buf.size(), msg, apcopy);
77
0
  va_end(apcopy);
78
79
0
  string result;
80
0
  if (static_cast<size_t>(ret) < buf.size()) {
81
0
    result.assign(buf.data(), static_cast<size_t>(ret));
82
0
  } else {
83
    // we did not provide a long enough buffer on our first attempt. The
84
    // return value is the number of bytes (excluding the null byte) that are
85
    // needed for formatting.
86
0
    size_t size_with_null = static_cast<size_t>(ret) + 1;
87
0
    result.__resize_default_init(size_with_null - 1);
88
0
    ret = ::vsnprintf(&result[0], size_with_null, msg, ap);
89
0
    _LIBCPP_ASSERT(static_cast<size_t>(ret) == (size_with_null - 1), "TODO");
90
0
  }
91
0
  return result;
92
0
}
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::format_string_impl(char const*, __va_list_tag*)
Unexecuted instantiation: directory_iterator.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::format_string_impl(char const*, __va_list_tag*)
93
94
static _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 2) string
95
0
format_string(const char* msg, ...) {
96
0
  string ret;
97
0
  va_list ap;
98
0
  va_start(ap, msg);
99
0
#ifndef _LIBCPP_NO_EXCEPTIONS
100
0
  try {
101
0
#endif // _LIBCPP_NO_EXCEPTIONS
102
0
    ret = format_string_impl(msg, ap);
103
0
#ifndef _LIBCPP_NO_EXCEPTIONS
104
0
  } catch (...) {
105
0
    va_end(ap);
106
0
    throw;
107
0
  }
108
0
#endif // _LIBCPP_NO_EXCEPTIONS
109
0
  va_end(ap);
110
0
  return ret;
111
0
}
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::format_string(char const*, ...)
Unexecuted instantiation: directory_iterator.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::format_string(char const*, ...)
112
113
0
error_code capture_errno() {
114
0
  _LIBCPP_ASSERT(errno != 0, "Expected errno to be non-zero");
115
0
  return error_code(errno, generic_category());
116
0
}
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::capture_errno()
Unexecuted instantiation: directory_iterator.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::capture_errno()
117
118
#if defined(_LIBCPP_WIN32API)
119
error_code make_windows_error(int err) {
120
  return make_error_code(__win_err_to_errc(err));
121
}
122
#endif
123
124
template <class T>
125
T error_value();
126
template <>
127
0
_LIBCPP_CONSTEXPR_AFTER_CXX11 void error_value<void>() {}
Unexecuted instantiation: operations.cpp:void std::__1::__fs::filesystem::detail::(anonymous namespace)::error_value<void>()
Unexecuted instantiation: directory_iterator.cpp:void std::__1::__fs::filesystem::detail::(anonymous namespace)::error_value<void>()
128
template <>
129
0
bool error_value<bool>() {
130
0
  return false;
131
0
}
Unexecuted instantiation: operations.cpp:bool std::__1::__fs::filesystem::detail::(anonymous namespace)::error_value<bool>()
Unexecuted instantiation: directory_iterator.cpp:bool std::__1::__fs::filesystem::detail::(anonymous namespace)::error_value<bool>()
132
#if __SIZEOF_SIZE_T__ != __SIZEOF_LONG_LONG__
133
template <>
134
size_t error_value<size_t>() {
135
  return size_t(-1);
136
}
137
#endif
138
template <>
139
0
uintmax_t error_value<uintmax_t>() {
140
0
  return uintmax_t(-1);
141
0
}
Unexecuted instantiation: operations.cpp:unsigned long std::__1::__fs::filesystem::detail::(anonymous namespace)::error_value<unsigned long>()
Unexecuted instantiation: directory_iterator.cpp:unsigned long std::__1::__fs::filesystem::detail::(anonymous namespace)::error_value<unsigned long>()
142
template <>
143
0
_LIBCPP_CONSTEXPR_AFTER_CXX11 file_time_type error_value<file_time_type>() {
144
0
  return file_time_type::min();
145
0
}
Unexecuted instantiation: operations.cpp:std::__1::chrono::time_point<std::__1::__fs::filesystem::_FilesystemClock, std::__1::chrono::duration<__int128, std::__1::ratio<1l, 1000000000l> > > std::__1::__fs::filesystem::detail::(anonymous namespace)::error_value<std::__1::chrono::time_point<std::__1::__fs::filesystem::_FilesystemClock, std::__1::chrono::duration<__int128, std::__1::ratio<1l, 1000000000l> > > >()
Unexecuted instantiation: directory_iterator.cpp:std::__1::chrono::time_point<std::__1::__fs::filesystem::_FilesystemClock, std::__1::chrono::duration<__int128, std::__1::ratio<1l, 1000000000l> > > std::__1::__fs::filesystem::detail::(anonymous namespace)::error_value<std::__1::chrono::time_point<std::__1::__fs::filesystem::_FilesystemClock, std::__1::chrono::duration<__int128, std::__1::ratio<1l, 1000000000l> > > >()
146
template <>
147
0
path error_value<path>() {
148
0
  return {};
149
0
}
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::path std::__1::__fs::filesystem::detail::(anonymous namespace)::error_value<std::__1::__fs::filesystem::path>()
Unexecuted instantiation: directory_iterator.cpp:std::__1::__fs::filesystem::path std::__1::__fs::filesystem::detail::(anonymous namespace)::error_value<std::__1::__fs::filesystem::path>()
150
151
template <class T>
152
struct ErrorHandler {
153
  const char* func_name_;
154
  error_code* ec_ = nullptr;
155
  const path* p1_ = nullptr;
156
  const path* p2_ = nullptr;
157
158
  ErrorHandler(const char* fname, error_code* ec, const path* p1 = nullptr,
159
               const path* p2 = nullptr)
160
0
      : func_name_(fname), ec_(ec), p1_(p1), p2_(p2) {
161
0
    if (ec_)
162
0
      ec_->clear();
163
0
  }
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<void>::ErrorHandler(char const*, std::__1::error_code*, std::__1::__fs::filesystem::path const*, std::__1::__fs::filesystem::path const*)
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<std::__1::__fs::filesystem::path>::ErrorHandler(char const*, std::__1::error_code*, std::__1::__fs::filesystem::path const*, std::__1::__fs::filesystem::path const*)
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<bool>::ErrorHandler(char const*, std::__1::error_code*, std::__1::__fs::filesystem::path const*, std::__1::__fs::filesystem::path const*)
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<unsigned long>::ErrorHandler(char const*, std::__1::error_code*, std::__1::__fs::filesystem::path const*, std::__1::__fs::filesystem::path const*)
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<std::__1::chrono::time_point<std::__1::__fs::filesystem::_FilesystemClock, std::__1::chrono::duration<__int128, std::__1::ratio<1l, 1000000000l> > > >::ErrorHandler(char const*, std::__1::error_code*, std::__1::__fs::filesystem::path const*, std::__1::__fs::filesystem::path const*)
Unexecuted instantiation: directory_iterator.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<void>::ErrorHandler(char const*, std::__1::error_code*, std::__1::__fs::filesystem::path const*, std::__1::__fs::filesystem::path const*)
164
165
0
  T report(const error_code& ec) const {
166
0
    if (ec_) {
167
0
      *ec_ = ec;
168
0
      return error_value<T>();
169
0
    }
170
0
    string what = string("in ") + func_name_;
171
0
    switch (bool(p1_) + bool(p2_)) {
172
0
    case 0:
173
0
      __throw_filesystem_error(what, ec);
174
0
    case 1:
175
0
      __throw_filesystem_error(what, *p1_, ec);
176
0
    case 2:
177
0
      __throw_filesystem_error(what, *p1_, *p2_, ec);
178
0
    }
179
0
    __libcpp_unreachable();
180
0
  }
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<std::__1::__fs::filesystem::path>::report(std::__1::error_code const&) const
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<void>::report(std::__1::error_code const&) const
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<bool>::report(std::__1::error_code const&) const
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<unsigned long>::report(std::__1::error_code const&) const
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<std::__1::chrono::time_point<std::__1::__fs::filesystem::_FilesystemClock, std::__1::chrono::duration<__int128, std::__1::ratio<1l, 1000000000l> > > >::report(std::__1::error_code const&) const
Unexecuted instantiation: directory_iterator.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<void>::report(std::__1::error_code const&) const
181
182
  _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 0)
183
0
  void report_impl(const error_code& ec, const char* msg, va_list ap) const {
184
0
    if (ec_) {
185
0
      *ec_ = ec;
186
0
      return;
187
0
    }
188
0
    string what =
189
0
        string("in ") + func_name_ + ": " + format_string_impl(msg, ap);
190
0
    switch (bool(p1_) + bool(p2_)) {
191
0
    case 0:
192
0
      __throw_filesystem_error(what, ec);
193
0
    case 1:
194
0
      __throw_filesystem_error(what, *p1_, ec);
195
0
    case 2:
196
0
      __throw_filesystem_error(what, *p1_, *p2_, ec);
197
0
    }
198
0
    __libcpp_unreachable();
199
0
  }
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<void>::report_impl(std::__1::error_code const&, char const*, __va_list_tag*) const
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<bool>::report_impl(std::__1::error_code const&, char const*, __va_list_tag*) const
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<std::__1::__fs::filesystem::path>::report_impl(std::__1::error_code const&, char const*, __va_list_tag*) const
Unexecuted instantiation: directory_iterator.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<void>::report_impl(std::__1::error_code const&, char const*, __va_list_tag*) const
200
201
  _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 4)
202
0
  T report(const error_code& ec, const char* msg, ...) const {
203
0
    va_list ap;
204
0
    va_start(ap, msg);
205
0
#ifndef _LIBCPP_NO_EXCEPTIONS
206
0
    try {
207
0
#endif // _LIBCPP_NO_EXCEPTIONS
208
0
      report_impl(ec, msg, ap);
209
0
#ifndef _LIBCPP_NO_EXCEPTIONS
210
0
    } catch (...) {
211
0
      va_end(ap);
212
0
      throw;
213
0
    }
214
0
#endif // _LIBCPP_NO_EXCEPTIONS
215
0
    va_end(ap);
216
0
    return error_value<T>();
217
0
  }
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<void>::report(std::__1::error_code const&, char const*, ...) const
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<std::__1::__fs::filesystem::path>::report(std::__1::error_code const&, char const*, ...) const
Unexecuted instantiation: directory_iterator.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<void>::report(std::__1::error_code const&, char const*, ...) const
218
219
0
  T report(errc const& err) const {
220
0
    return report(make_error_code(err));
221
0
  }
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<std::__1::chrono::time_point<std::__1::__fs::filesystem::_FilesystemClock, std::__1::chrono::duration<__int128, std::__1::ratio<1l, 1000000000l> > > >::report(std::__1::errc const&) const
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<void>::report(std::__1::errc const&) const
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<bool>::report(std::__1::errc const&) const
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<std::__1::__fs::filesystem::path>::report(std::__1::errc const&) const
222
223
  _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 4)
224
0
  T report(errc const& err, const char* msg, ...) const {
225
0
    va_list ap;
226
0
    va_start(ap, msg);
227
0
#ifndef _LIBCPP_NO_EXCEPTIONS
228
0
    try {
229
0
#endif // _LIBCPP_NO_EXCEPTIONS
230
0
      report_impl(make_error_code(err), msg, ap);
231
0
#ifndef _LIBCPP_NO_EXCEPTIONS
232
0
    } catch (...) {
233
0
      va_end(ap);
234
0
      throw;
235
0
    }
236
0
#endif // _LIBCPP_NO_EXCEPTIONS
237
0
    va_end(ap);
238
0
    return error_value<T>();
239
0
  }
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<bool>::report(std::__1::errc const&, char const*, ...) const
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<std::__1::__fs::filesystem::path>::report(std::__1::errc const&, char const*, ...) const
240
241
private:
242
  ErrorHandler(ErrorHandler const&) = delete;
243
  ErrorHandler& operator=(ErrorHandler const&) = delete;
244
};
245
246
using chrono::duration;
247
using chrono::duration_cast;
248
249
#if defined(_LIBCPP_WIN32API)
250
// Various C runtime versions (UCRT, or the legacy msvcrt.dll used by
251
// some mingw toolchains) provide different stat function implementations,
252
// with a number of limitations with respect to what we want from the
253
// stat function. Instead provide our own (in the anonymous detail namespace
254
// in posix_compat.h) which does exactly what we want, along with our own
255
// stat structure and flag macros.
256
257
struct TimeSpec {
258
  int64_t tv_sec;
259
  int64_t tv_nsec;
260
};
261
struct StatT {
262
  unsigned st_mode;
263
  TimeSpec st_atim;
264
  TimeSpec st_mtim;
265
  uint64_t st_dev; // FILE_ID_INFO::VolumeSerialNumber
266
  struct FileIdStruct {
267
    unsigned char id[16]; // FILE_ID_INFO::FileId
268
    bool operator==(const FileIdStruct &other) const {
269
      for (int i = 0; i < 16; i++)
270
        if (id[i] != other.id[i])
271
          return false;
272
      return true;
273
    }
274
  } st_ino;
275
  uint32_t st_nlink;
276
  uintmax_t st_size;
277
};
278
279
#else
280
using TimeSpec = struct timespec;
281
using TimeVal = struct timeval;
282
using StatT = struct stat;
283
#endif
284
285
template <class FileTimeT, class TimeT,
286
          bool IsFloat = is_floating_point<typename FileTimeT::rep>::value>
287
struct time_util_base {
288
  using rep = typename FileTimeT::rep;
289
  using fs_duration = typename FileTimeT::duration;
290
  using fs_seconds = duration<rep>;
291
  using fs_nanoseconds = duration<rep, nano>;
292
  using fs_microseconds = duration<rep, micro>;
293
294
  static constexpr rep max_seconds =
295
      duration_cast<fs_seconds>(FileTimeT::duration::max()).count();
296
297
  static constexpr rep max_nsec =
298
      duration_cast<fs_nanoseconds>(FileTimeT::duration::max() -
299
                                    fs_seconds(max_seconds))
300
          .count();
301
302
  static constexpr rep min_seconds =
303
      duration_cast<fs_seconds>(FileTimeT::duration::min()).count();
304
305
  static constexpr rep min_nsec_timespec =
306
      duration_cast<fs_nanoseconds>(
307
          (FileTimeT::duration::min() - fs_seconds(min_seconds)) +
308
          fs_seconds(1))
309
          .count();
310
311
private:
312
0
  static _LIBCPP_CONSTEXPR_AFTER_CXX11 fs_duration get_min_nsecs() {
313
0
    return duration_cast<fs_duration>(
314
0
        fs_nanoseconds(min_nsec_timespec) -
315
0
        duration_cast<fs_nanoseconds>(fs_seconds(1)));
316
0
  }
317
  // Static assert that these values properly round trip.
318
  static_assert(fs_seconds(min_seconds) + get_min_nsecs() ==
319
                    FileTimeT::duration::min(),
320
                "value doesn't roundtrip");
321
322
0
  static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool check_range() {
323
0
    // This kinda sucks, but it's what happens when we don't have __int128_t.
324
0
    if (sizeof(TimeT) == sizeof(rep)) {
325
0
      typedef duration<long long, ratio<3600 * 24 * 365> > Years;
326
0
      return duration_cast<Years>(fs_seconds(max_seconds)) > Years(250) &&
327
0
             duration_cast<Years>(fs_seconds(min_seconds)) < Years(-250);
328
0
    }
329
0
    return max_seconds >= numeric_limits<TimeT>::max() &&
330
0
           min_seconds <= numeric_limits<TimeT>::min();
331
0
  }
332
  static_assert(check_range(), "the representable range is unacceptable small");
333
};
334
335
template <class FileTimeT, class TimeT>
336
struct time_util_base<FileTimeT, TimeT, true> {
337
  using rep = typename FileTimeT::rep;
338
  using fs_duration = typename FileTimeT::duration;
339
  using fs_seconds = duration<rep>;
340
  using fs_nanoseconds = duration<rep, nano>;
341
  using fs_microseconds = duration<rep, micro>;
342
343
  static const rep max_seconds;
344
  static const rep max_nsec;
345
  static const rep min_seconds;
346
  static const rep min_nsec_timespec;
347
};
348
349
template <class FileTimeT, class TimeT>
350
const typename FileTimeT::rep
351
    time_util_base<FileTimeT, TimeT, true>::max_seconds =
352
        duration_cast<fs_seconds>(FileTimeT::duration::max()).count();
353
354
template <class FileTimeT, class TimeT>
355
const typename FileTimeT::rep time_util_base<FileTimeT, TimeT, true>::max_nsec =
356
    duration_cast<fs_nanoseconds>(FileTimeT::duration::max() -
357
                                  fs_seconds(max_seconds))
358
        .count();
359
360
template <class FileTimeT, class TimeT>
361
const typename FileTimeT::rep
362
    time_util_base<FileTimeT, TimeT, true>::min_seconds =
363
        duration_cast<fs_seconds>(FileTimeT::duration::min()).count();
364
365
template <class FileTimeT, class TimeT>
366
const typename FileTimeT::rep
367
    time_util_base<FileTimeT, TimeT, true>::min_nsec_timespec =
368
        duration_cast<fs_nanoseconds>((FileTimeT::duration::min() -
369
                                       fs_seconds(min_seconds)) +
370
                                      fs_seconds(1))
371
            .count();
372
373
template <class FileTimeT, class TimeT, class TimeSpecT>
374
struct time_util : time_util_base<FileTimeT, TimeT> {
375
  using Base = time_util_base<FileTimeT, TimeT>;
376
  using Base::max_nsec;
377
  using Base::max_seconds;
378
  using Base::min_nsec_timespec;
379
  using Base::min_seconds;
380
381
  using typename Base::fs_duration;
382
  using typename Base::fs_microseconds;
383
  using typename Base::fs_nanoseconds;
384
  using typename Base::fs_seconds;
385
386
public:
387
  template <class CType, class ChronoType>
388
  static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool checked_set(CType* out,
389
0
                                                        ChronoType time) {
390
0
    using Lim = numeric_limits<CType>;
391
0
    if (time > Lim::max() || time < Lim::min())
392
0
      return false;
393
0
    *out = static_cast<CType>(time);
394
0
    return true;
395
0
  }
396
397
0
  static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(TimeSpecT tm) {
398
0
    if (tm.tv_sec >= 0) {
399
0
      return tm.tv_sec < max_seconds ||
400
0
             (tm.tv_sec == max_seconds && tm.tv_nsec <= max_nsec);
401
0
    } else if (tm.tv_sec == (min_seconds - 1)) {
402
0
      return tm.tv_nsec >= min_nsec_timespec;
403
0
    } else {
404
0
      return tm.tv_sec >= min_seconds;
405
0
    }
406
0
  }
407
408
0
  static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(FileTimeT tm) {
409
0
    auto secs = duration_cast<fs_seconds>(tm.time_since_epoch());
410
0
    auto nsecs = duration_cast<fs_nanoseconds>(tm.time_since_epoch() - secs);
411
0
    if (nsecs.count() < 0) {
412
0
      secs = secs + fs_seconds(1);
413
0
      nsecs = nsecs + fs_seconds(1);
414
0
    }
415
0
    using TLim = numeric_limits<TimeT>;
416
0
    if (secs.count() >= 0)
417
0
      return secs.count() <= TLim::max();
418
0
    return secs.count() >= TLim::min();
419
0
  }
420
421
  static _LIBCPP_CONSTEXPR_AFTER_CXX11 FileTimeT
422
0
  convert_from_timespec(TimeSpecT tm) {
423
0
    if (tm.tv_sec >= 0 || tm.tv_nsec == 0) {
424
0
      return FileTimeT(fs_seconds(tm.tv_sec) +
425
0
                       duration_cast<fs_duration>(fs_nanoseconds(tm.tv_nsec)));
426
0
    } else { // tm.tv_sec < 0
427
0
      auto adj_subsec = duration_cast<fs_duration>(fs_seconds(1) -
428
0
                                                   fs_nanoseconds(tm.tv_nsec));
429
0
      auto Dur = fs_seconds(tm.tv_sec + 1) - adj_subsec;
430
0
      return FileTimeT(Dur);
431
0
    }
432
0
  }
433
434
  template <class SubSecT>
435
  static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool
436
0
  set_times_checked(TimeT* sec_out, SubSecT* subsec_out, FileTimeT tp) {
437
0
    auto dur = tp.time_since_epoch();
438
0
    auto sec_dur = duration_cast<fs_seconds>(dur);
439
0
    auto subsec_dur = duration_cast<fs_nanoseconds>(dur - sec_dur);
440
    // The tv_nsec and tv_usec fields must not be negative so adjust accordingly
441
0
    if (subsec_dur.count() < 0) {
442
0
      if (sec_dur.count() > min_seconds) {
443
0
        sec_dur = sec_dur - fs_seconds(1);
444
0
        subsec_dur = subsec_dur + fs_seconds(1);
445
0
      } else {
446
0
        subsec_dur = fs_nanoseconds::zero();
447
0
      }
448
0
    }
449
0
    return checked_set(sec_out, sec_dur.count()) &&
450
0
           checked_set(subsec_out, subsec_dur.count());
451
0
  }
452
  static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool convert_to_timespec(TimeSpecT& dest,
453
0
                                                                FileTimeT tp) {
454
0
    if (!is_representable(tp))
455
0
      return false;
456
0
    return set_times_checked(&dest.tv_sec, &dest.tv_nsec, tp);
457
0
  }
458
};
459
460
#if defined(_LIBCPP_WIN32API)
461
using fs_time = time_util<file_time_type, int64_t, TimeSpec>;
462
#else
463
using fs_time = time_util<file_time_type, time_t, TimeSpec>;
464
#endif
465
466
#if defined(__APPLE__)
467
0
inline TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; }
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::extract_mtime(stat const&)
Unexecuted instantiation: directory_iterator.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::extract_mtime(stat const&)
468
0
inline TimeSpec extract_atime(StatT const& st) { return st.st_atimespec; }
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::extract_atime(stat const&)
Unexecuted instantiation: directory_iterator.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::extract_atime(stat const&)
469
#elif defined(__MVS__)
470
inline TimeSpec extract_mtime(StatT const& st) {
471
  TimeSpec TS = {st.st_mtime, 0};
472
  return TS;
473
}
474
inline TimeSpec extract_atime(StatT const& st) {
475
  TimeSpec TS = {st.st_atime, 0};
476
  return TS;
477
}
478
#elif defined(_AIX)
479
inline TimeSpec extract_mtime(StatT const& st) {
480
  TimeSpec TS = {st.st_mtime, st.st_mtime_n};
481
  return TS;
482
}
483
inline TimeSpec extract_atime(StatT const& st) {
484
  TimeSpec TS = {st.st_atime, st.st_atime_n};
485
  return TS;
486
}
487
#else
488
inline TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; }
489
inline TimeSpec extract_atime(StatT const& st) { return st.st_atim; }
490
#endif
491
492
#if !defined(_LIBCPP_WIN32API)
493
0
inline TimeVal make_timeval(TimeSpec const& ts) {
494
0
  using namespace chrono;
495
0
  auto Convert = [](long nsec) {
496
0
    using int_type = decltype(std::declval<TimeVal>().tv_usec);
497
0
    auto dur = duration_cast<microseconds>(nanoseconds(nsec)).count();
498
0
    return static_cast<int_type>(dur);
499
0
  };
500
0
  TimeVal TV = {};
501
0
  TV.tv_sec = ts.tv_sec;
502
0
  TV.tv_usec = Convert(ts.tv_nsec);
503
0
  return TV;
504
0
}
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::make_timeval(timespec const&)
Unexecuted instantiation: directory_iterator.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::make_timeval(timespec const&)
505
506
inline bool posix_utimes(const path& p, std::array<TimeSpec, 2> const& TS,
507
0
                  error_code& ec) {
508
0
  TimeVal ConvertedTS[2] = {make_timeval(TS[0]), make_timeval(TS[1])};
509
0
  if (::utimes(p.c_str(), ConvertedTS) == -1) {
510
0
    ec = capture_errno();
511
0
    return true;
512
0
  }
513
0
  return false;
514
0
}
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::posix_utimes(std::__1::__fs::filesystem::path const&, std::__1::array<timespec, 2ul> const&, std::__1::error_code&)
Unexecuted instantiation: directory_iterator.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::posix_utimes(std::__1::__fs::filesystem::path const&, std::__1::array<timespec, 2ul> const&, std::__1::error_code&)
515
516
#if defined(_LIBCPP_USE_UTIMENSAT)
517
bool posix_utimensat(const path& p, std::array<TimeSpec, 2> const& TS,
518
0
                     error_code& ec) {
519
0
  if (::utimensat(AT_FDCWD, p.c_str(), TS.data(), 0) == -1) {
520
0
    ec = capture_errno();
521
0
    return true;
522
0
  }
523
0
  return false;
524
0
}
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::posix_utimensat(std::__1::__fs::filesystem::path const&, std::__1::array<timespec, 2ul> const&, std::__1::error_code&)
Unexecuted instantiation: directory_iterator.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::posix_utimensat(std::__1::__fs::filesystem::path const&, std::__1::array<timespec, 2ul> const&, std::__1::error_code&)
525
#endif
526
527
bool set_file_times(const path& p, std::array<TimeSpec, 2> const& TS,
528
0
                    error_code& ec) {
529
#if !defined(_LIBCPP_USE_UTIMENSAT)
530
  return posix_utimes(p, TS, ec);
531
#else
532
0
  return posix_utimensat(p, TS, ec);
533
0
#endif
534
0
}
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::set_file_times(std::__1::__fs::filesystem::path const&, std::__1::array<timespec, 2ul> const&, std::__1::error_code&)
Unexecuted instantiation: directory_iterator.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::set_file_times(std::__1::__fs::filesystem::path const&, std::__1::array<timespec, 2ul> const&, std::__1::error_code&)
535
536
#if defined(DT_BLK)
537
template <class DirEntT, class = decltype(DirEntT::d_type)>
538
0
static file_type get_file_type(DirEntT* ent, int) {
539
0
  switch (ent->d_type) {
540
0
  case DT_BLK:
541
0
    return file_type::block;
542
0
  case DT_CHR:
543
0
    return file_type::character;
544
0
  case DT_DIR:
545
0
    return file_type::directory;
546
0
  case DT_FIFO:
547
0
    return file_type::fifo;
548
0
  case DT_LNK:
549
0
    return file_type::symlink;
550
0
  case DT_REG:
551
0
    return file_type::regular;
552
0
  case DT_SOCK:
553
0
    return file_type::socket;
554
  // Unlike in lstat, hitting "unknown" here simply means that the underlying
555
  // filesystem doesn't support d_type. Report is as 'none' so we correctly
556
  // set the cache to empty.
557
0
  case DT_UNKNOWN:
558
0
    break;
559
0
  }
560
0
  return file_type::none;
561
0
}
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::file_type std::__1::__fs::filesystem::detail::(anonymous namespace)::get_file_type<dirent, unsigned char>(dirent*, int)
Unexecuted instantiation: directory_iterator.cpp:std::__1::__fs::filesystem::file_type std::__1::__fs::filesystem::detail::(anonymous namespace)::get_file_type<dirent, unsigned char>(dirent*, int)
562
#endif // defined(DT_BLK)
563
564
template <class DirEntT>
565
static file_type get_file_type(DirEntT*, long) {
566
  return file_type::none;
567
}
568
569
static pair<string_view, file_type> posix_readdir(DIR* dir_stream,
570
0
                                                  error_code& ec) {
571
0
  struct dirent* dir_entry_ptr = nullptr;
572
0
  errno = 0; // zero errno in order to detect errors
573
0
  ec.clear();
574
0
  if ((dir_entry_ptr = ::readdir(dir_stream)) == nullptr) {
575
0
    if (errno)
576
0
      ec = capture_errno();
577
0
    return {};
578
0
  } else {
579
0
    return {dir_entry_ptr->d_name, get_file_type(dir_entry_ptr, 0)};
580
0
  }
581
0
}
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::posix_readdir(DIR*, std::__1::error_code&)
Unexecuted instantiation: directory_iterator.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::posix_readdir(DIR*, std::__1::error_code&)
582
583
#else // _LIBCPP_WIN32API
584
585
static file_type get_file_type(const WIN32_FIND_DATAW& data) {
586
  if (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT &&
587
      data.dwReserved0 == IO_REPARSE_TAG_SYMLINK)
588
    return file_type::symlink;
589
  if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
590
    return file_type::directory;
591
  return file_type::regular;
592
}
593
static uintmax_t get_file_size(const WIN32_FIND_DATAW& data) {
594
  return (static_cast<uint64_t>(data.nFileSizeHigh) << 32) + data.nFileSizeLow;
595
}
596
static file_time_type get_write_time(const WIN32_FIND_DATAW& data) {
597
  ULARGE_INTEGER tmp;
598
  const FILETIME& time = data.ftLastWriteTime;
599
  tmp.u.LowPart = time.dwLowDateTime;
600
  tmp.u.HighPart = time.dwHighDateTime;
601
  return file_time_type(file_time_type::duration(tmp.QuadPart));
602
}
603
604
#endif // !_LIBCPP_WIN32API
605
606
} // namespace
607
} // end namespace detail
608
609
_LIBCPP_END_NAMESPACE_FILESYSTEM
610
611
_LIBCPP_DIAGNOSTIC_POP
612
613
#endif // FILESYSTEM_COMMON_H