Coverage Report

Created: 2021-01-23 06:44

/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 "__config"
13
#include "filesystem"
14
#include "array"
15
#include "chrono"
16
#include "climits"
17
#include "cstdlib"
18
#include "ctime"
19
20
#if !defined(_LIBCPP_WIN32API)
21
# include <unistd.h>
22
# include <sys/stat.h>
23
# include <sys/statvfs.h>
24
# include <sys/time.h> // for ::utimes as used in __last_write_time
25
# include <fcntl.h>    /* values for fchmodat */
26
#endif
27
28
#include "../include/apple_availability.h"
29
30
#if !defined(__APPLE__)
31
// We can use the presence of UTIME_OMIT to detect platforms that provide
32
// utimensat.
33
#if defined(UTIME_OMIT)
34
#define _LIBCPP_USE_UTIMENSAT
35
#endif
36
#endif
37
38
#if defined(__GNUC__)
39
#pragma GCC diagnostic push
40
#pragma GCC diagnostic ignored "-Wunused-function"
41
#endif
42
43
#if defined(_LIBCPP_WIN32API)
44
#define PS(x) (L##x)
45
#else
46
0
#define PS(x) (x)
47
#endif
48
49
_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
50
51
namespace detail {
52
53
#if defined(_LIBCPP_WIN32API)
54
// Non anonymous, to allow access from two translation units.
55
errc __win_err_to_errc(int err);
56
#endif
57
58
namespace {
59
60
0
static string format_string_imp(const char* msg, ...) {
61
  // we might need a second shot at this, so pre-emptivly make a copy
62
0
  struct GuardVAList {
63
0
    va_list& target;
64
0
    bool active = true;
65
0
    GuardVAList(va_list& tgt) : target(tgt), active(true) {}
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::format_string_imp(char const*, ...)::GuardVAList::GuardVAList(__va_list_tag (&) [1])
Unexecuted instantiation: directory_iterator.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::format_string_imp(char const*, ...)::GuardVAList::GuardVAList(__va_list_tag (&) [1])
66
0
    void clear() {
67
0
      if (active)
68
0
        va_end(target);
69
0
      active = false;
70
0
    }
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::format_string_imp(char const*, ...)::GuardVAList::clear()
Unexecuted instantiation: directory_iterator.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::format_string_imp(char const*, ...)::GuardVAList::clear()
71
0
    ~GuardVAList() {
72
0
      if (active)
73
0
        va_end(target);
74
0
    }
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::format_string_imp(char const*, ...)::GuardVAList::~GuardVAList()
Unexecuted instantiation: directory_iterator.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::format_string_imp(char const*, ...)::GuardVAList::~GuardVAList()
75
0
  };
76
0
  va_list args;
77
0
  va_start(args, msg);
78
0
  GuardVAList args_guard(args);
79
80
0
  va_list args_cp;
81
0
  va_copy(args_cp, args);
82
0
  GuardVAList args_copy_guard(args_cp);
83
84
0
  std::string result;
85
86
0
  array<char, 256> local_buff;
87
0
  size_t size_with_null = local_buff.size();
88
0
  auto ret = ::vsnprintf(local_buff.data(), size_with_null, msg, args_cp);
89
90
0
  args_copy_guard.clear();
91
92
  // handle empty expansion
93
0
  if (ret == 0)
94
0
    return result;
95
0
  if (static_cast<size_t>(ret) < size_with_null) {
96
0
    result.assign(local_buff.data(), static_cast<size_t>(ret));
97
0
    return result;
98
0
  }
99
100
  // we did not provide a long enough buffer on our first attempt. The
101
  // return value is the number of bytes (excluding the null byte) that are
102
  // needed for formatting.
103
0
  size_with_null = static_cast<size_t>(ret) + 1;
104
0
  result.__resize_default_init(size_with_null - 1);
105
0
  ret = ::vsnprintf(&result[0], size_with_null, msg, args);
106
0
  _LIBCPP_ASSERT(static_cast<size_t>(ret) == (size_with_null - 1), "TODO");
107
108
0
  return result;
109
0
}
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::format_string_imp(char const*, ...)
Unexecuted instantiation: directory_iterator.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::format_string_imp(char const*, ...)
110
111
0
const path::value_type* unwrap(path::string_type const& s) { return s.c_str(); }
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::unwrap(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: directory_iterator.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::unwrap(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
112
0
const path::value_type* unwrap(path const& p) { return p.native().c_str(); }
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::unwrap(std::__1::__fs::filesystem::path const&)
Unexecuted instantiation: directory_iterator.cpp:std::__1::__fs::filesystem::detail::(anonymous namespace)::unwrap(std::__1::__fs::filesystem::path const&)
113
template <class Arg>
114
0
Arg const& unwrap(Arg const& a) {
115
0
  static_assert(!is_class<Arg>::value, "cannot pass class here");
116
0
  return a;
117
0
}
118
119
template <class... Args>
120
0
string format_string(const char* fmt, Args const&... args) {
121
0
  return format_string_imp(fmt, unwrap(args)...);
122
0
}
Unexecuted instantiation: operations.cpp:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > std::__1::__fs::filesystem::detail::(anonymous namespace)::format_string<char const*>(char const*, char const* const&)
Unexecuted instantiation: operations.cpp:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > std::__1::__fs::filesystem::detail::(anonymous namespace)::format_string<char const*, char const*>(char const*, char const* const&, char const* const&)
Unexecuted instantiation: operations.cpp:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > std::__1::__fs::filesystem::detail::(anonymous namespace)::format_string<char const*, char const*, char const*>(char const*, char const* const&, char const* const&, char const* const&)
Unexecuted instantiation: operations.cpp:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > std::__1::__fs::filesystem::detail::(anonymous namespace)::format_string<>(char const*)
Unexecuted instantiation: operations.cpp:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > std::__1::__fs::filesystem::detail::(anonymous namespace)::format_string<std::__1::__fs::filesystem::path>(char const*, std::__1::__fs::filesystem::path const&)
Unexecuted instantiation: directory_iterator.cpp:std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > std::__1::__fs::filesystem::detail::(anonymous namespace)::format_string<std::__1::__fs::filesystem::path>(char const*, std::__1::__fs::filesystem::path const&)
123
124
0
error_code capture_errno() {
125
0
  _LIBCPP_ASSERT(errno, "Expected errno to be non-zero");
126
0
  return error_code(errno, generic_category());
127
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()
128
129
#if defined(_LIBCPP_WIN32API)
130
error_code make_windows_error(int err) {
131
  return make_error_code(__win_err_to_errc(err));
132
}
133
#endif
134
135
template <class T>
136
T error_value();
137
template <>
138
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>()
139
template <>
140
0
bool error_value<bool>() {
141
0
  return false;
142
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>()
143
#if __SIZEOF_SIZE_T__ != __SIZEOF_LONG_LONG__
144
template <>
145
size_t error_value<size_t>() {
146
  return size_t(-1);
147
}
148
#endif
149
template <>
150
0
uintmax_t error_value<uintmax_t>() {
151
0
  return uintmax_t(-1);
152
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>()
153
template <>
154
0
_LIBCPP_CONSTEXPR_AFTER_CXX11 file_time_type error_value<file_time_type>() {
155
0
  return file_time_type::min();
156
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> > > >()
157
template <>
158
0
path error_value<path>() {
159
0
  return {};
160
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>()
161
162
template <class T>
163
struct ErrorHandler {
164
  const char* func_name_;
165
  error_code* ec_ = nullptr;
166
  const path* p1_ = nullptr;
167
  const path* p2_ = nullptr;
168
169
  ErrorHandler(const char* fname, error_code* ec, const path* p1 = nullptr,
170
               const path* p2 = nullptr)
171
0
      : func_name_(fname), ec_(ec), p1_(p1), p2_(p2) {
172
0
    if (ec_)
173
0
      ec_->clear();
174
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*)
175
176
0
  T report(const error_code& ec) const {
177
0
    if (ec_) {
178
0
      *ec_ = ec;
179
0
      return error_value<T>();
180
0
    }
181
0
    string what = string("in ") + func_name_;
182
0
    switch (bool(p1_) + bool(p2_)) {
183
0
    case 0:
184
0
      __throw_filesystem_error(what, ec);
185
0
    case 1:
186
0
      __throw_filesystem_error(what, *p1_, ec);
187
0
    case 2:
188
0
      __throw_filesystem_error(what, *p1_, *p2_, ec);
189
0
    }
190
0
    _LIBCPP_UNREACHABLE();
191
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
192
193
  template <class... Args>
194
0
  T report(const error_code& ec, const char* msg, Args const&... args) const {
195
0
    if (ec_) {
196
0
      *ec_ = ec;
197
0
      return error_value<T>();
198
0
    }
199
0
    string what =
200
0
        string("in ") + func_name_ + ": " + format_string(msg, args...);
201
0
    switch (bool(p1_) + bool(p2_)) {
202
0
    case 0:
203
0
      __throw_filesystem_error(what, ec);
204
0
    case 1:
205
0
      __throw_filesystem_error(what, *p1_, ec);
206
0
    case 2:
207
0
      __throw_filesystem_error(what, *p1_, *p2_, ec);
208
0
    }
209
0
    _LIBCPP_UNREACHABLE();
210
0
  }
Unexecuted instantiation: operations.cpp:void std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<void>::report<>(std::__1::error_code const&, char const*) const
Unexecuted instantiation: operations.cpp:bool std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<bool>::report<>(std::__1::error_code const&, char const*) const
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::path std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<std::__1::__fs::filesystem::path>::report<>(std::__1::error_code const&, char const*) const
Unexecuted instantiation: operations.cpp:std::__1::__fs::filesystem::path std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<std::__1::__fs::filesystem::path>::report<std::__1::__fs::filesystem::path>(std::__1::error_code const&, char const*, std::__1::__fs::filesystem::path const&) const
Unexecuted instantiation: directory_iterator.cpp:void std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<void>::report<std::__1::__fs::filesystem::path>(std::__1::error_code const&, char const*, std::__1::__fs::filesystem::path const&) const
211
212
0
  T report(errc const& err) const { return report(make_error_code(err)); }
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
213
214
  template <class... Args>
215
0
  T report(errc const& err, const char* msg, Args const&... args) const {
216
0
    return report(make_error_code(err), msg, args...);
217
0
  }
Unexecuted instantiation: operations.cpp:bool 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::path std::__1::__fs::filesystem::detail::(anonymous namespace)::ErrorHandler<std::__1::__fs::filesystem::path>::report<std::__1::__fs::filesystem::path>(std::__1::errc const&, char const*, std::__1::__fs::filesystem::path const&) const
218
219
private:
220
  ErrorHandler(ErrorHandler const&) = delete;
221
  ErrorHandler& operator=(ErrorHandler const&) = delete;
222
};
223
224
using chrono::duration;
225
using chrono::duration_cast;
226
227
using TimeSpec = struct timespec;
228
using TimeVal = struct timeval;
229
using StatT = struct stat;
230
231
template <class FileTimeT, class TimeT,
232
          bool IsFloat = is_floating_point<typename FileTimeT::rep>::value>
233
struct time_util_base {
234
  using rep = typename FileTimeT::rep;
235
  using fs_duration = typename FileTimeT::duration;
236
  using fs_seconds = duration<rep>;
237
  using fs_nanoseconds = duration<rep, nano>;
238
  using fs_microseconds = duration<rep, micro>;
239
240
  static constexpr rep max_seconds =
241
      duration_cast<fs_seconds>(FileTimeT::duration::max()).count();
242
243
  static constexpr rep max_nsec =
244
      duration_cast<fs_nanoseconds>(FileTimeT::duration::max() -
245
                                    fs_seconds(max_seconds))
246
          .count();
247
248
  static constexpr rep min_seconds =
249
      duration_cast<fs_seconds>(FileTimeT::duration::min()).count();
250
251
  static constexpr rep min_nsec_timespec =
252
      duration_cast<fs_nanoseconds>(
253
          (FileTimeT::duration::min() - fs_seconds(min_seconds)) +
254
          fs_seconds(1))
255
          .count();
256
257
private:
258
#if _LIBCPP_STD_VER > 11 && !defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR)
259
0
  static constexpr fs_duration get_min_nsecs() {
260
0
    return duration_cast<fs_duration>(
261
0
        fs_nanoseconds(min_nsec_timespec) -
262
0
        duration_cast<fs_nanoseconds>(fs_seconds(1)));
263
0
  }
264
  // Static assert that these values properly round trip.
265
  static_assert(fs_seconds(min_seconds) + get_min_nsecs() ==
266
                    FileTimeT::duration::min(),
267
                "value doesn't roundtrip");
268
269
0
  static constexpr bool check_range() {
270
0
    // This kinda sucks, but it's what happens when we don't have __int128_t.
271
0
    if (sizeof(TimeT) == sizeof(rep)) {
272
0
      typedef duration<long long, ratio<3600 * 24 * 365> > Years;
273
0
      return duration_cast<Years>(fs_seconds(max_seconds)) > Years(250) &&
274
0
             duration_cast<Years>(fs_seconds(min_seconds)) < Years(-250);
275
0
    }
276
0
    return max_seconds >= numeric_limits<TimeT>::max() &&
277
0
           min_seconds <= numeric_limits<TimeT>::min();
278
0
  }
279
  static_assert(check_range(), "the representable range is unacceptable small");
280
#endif
281
};
282
283
template <class FileTimeT, class TimeT>
284
struct time_util_base<FileTimeT, TimeT, true> {
285
  using rep = typename FileTimeT::rep;
286
  using fs_duration = typename FileTimeT::duration;
287
  using fs_seconds = duration<rep>;
288
  using fs_nanoseconds = duration<rep, nano>;
289
  using fs_microseconds = duration<rep, micro>;
290
291
  static const rep max_seconds;
292
  static const rep max_nsec;
293
  static const rep min_seconds;
294
  static const rep min_nsec_timespec;
295
};
296
297
template <class FileTimeT, class TimeT>
298
const typename FileTimeT::rep
299
    time_util_base<FileTimeT, TimeT, true>::max_seconds =
300
        duration_cast<fs_seconds>(FileTimeT::duration::max()).count();
301
302
template <class FileTimeT, class TimeT>
303
const typename FileTimeT::rep time_util_base<FileTimeT, TimeT, true>::max_nsec =
304
    duration_cast<fs_nanoseconds>(FileTimeT::duration::max() -
305
                                  fs_seconds(max_seconds))
306
        .count();
307
308
template <class FileTimeT, class TimeT>
309
const typename FileTimeT::rep
310
    time_util_base<FileTimeT, TimeT, true>::min_seconds =
311
        duration_cast<fs_seconds>(FileTimeT::duration::min()).count();
312
313
template <class FileTimeT, class TimeT>
314
const typename FileTimeT::rep
315
    time_util_base<FileTimeT, TimeT, true>::min_nsec_timespec =
316
        duration_cast<fs_nanoseconds>((FileTimeT::duration::min() -
317
                                       fs_seconds(min_seconds)) +
318
                                      fs_seconds(1))
319
            .count();
320
321
template <class FileTimeT, class TimeT, class TimeSpecT>
322
struct time_util : time_util_base<FileTimeT, TimeT> {
323
  using Base = time_util_base<FileTimeT, TimeT>;
324
  using Base::max_nsec;
325
  using Base::max_seconds;
326
  using Base::min_nsec_timespec;
327
  using Base::min_seconds;
328
329
  using typename Base::fs_duration;
330
  using typename Base::fs_microseconds;
331
  using typename Base::fs_nanoseconds;
332
  using typename Base::fs_seconds;
333
334
public:
335
  template <class CType, class ChronoType>
336
  static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool checked_set(CType* out,
337
0
                                                        ChronoType time) {
338
0
    using Lim = numeric_limits<CType>;
339
0
    if (time > Lim::max() || time < Lim::min())
340
0
      return false;
341
0
    *out = static_cast<CType>(time);
342
0
    return true;
343
0
  }
344
345
0
  static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(TimeSpecT tm) {
346
0
    if (tm.tv_sec >= 0) {
347
0
      return tm.tv_sec < max_seconds ||
348
0
             (tm.tv_sec == max_seconds && tm.tv_nsec <= max_nsec);
349
0
    } else if (tm.tv_sec == (min_seconds - 1)) {
350
0
      return tm.tv_nsec >= min_nsec_timespec;
351
0
    } else {
352
0
      return tm.tv_sec >= min_seconds;
353
0
    }
354
0
  }
355
356
0
  static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(FileTimeT tm) {
357
0
    auto secs = duration_cast<fs_seconds>(tm.time_since_epoch());
358
0
    auto nsecs = duration_cast<fs_nanoseconds>(tm.time_since_epoch() - secs);
359
0
    if (nsecs.count() < 0) {
360
0
      secs = secs + fs_seconds(1);
361
0
      nsecs = nsecs + fs_seconds(1);
362
0
    }
363
0
    using TLim = numeric_limits<TimeT>;
364
0
    if (secs.count() >= 0)
365
0
      return secs.count() <= TLim::max();
366
0
    return secs.count() >= TLim::min();
367
0
  }
368
369
  static _LIBCPP_CONSTEXPR_AFTER_CXX11 FileTimeT
370
0
  convert_from_timespec(TimeSpecT tm) {
371
0
    if (tm.tv_sec >= 0 || tm.tv_nsec == 0) {
372
0
      return FileTimeT(fs_seconds(tm.tv_sec) +
373
0
                       duration_cast<fs_duration>(fs_nanoseconds(tm.tv_nsec)));
374
0
    } else { // tm.tv_sec < 0
375
0
      auto adj_subsec = duration_cast<fs_duration>(fs_seconds(1) -
376
0
                                                   fs_nanoseconds(tm.tv_nsec));
377
0
      auto Dur = fs_seconds(tm.tv_sec + 1) - adj_subsec;
378
0
      return FileTimeT(Dur);
379
0
    }
380
0
  }
381
382
  template <class SubSecT>
383
  static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool
384
0
  set_times_checked(TimeT* sec_out, SubSecT* subsec_out, FileTimeT tp) {
385
0
    auto dur = tp.time_since_epoch();
386
0
    auto sec_dur = duration_cast<fs_seconds>(dur);
387
0
    auto subsec_dur = duration_cast<fs_nanoseconds>(dur - sec_dur);
388
    // The tv_nsec and tv_usec fields must not be negative so adjust accordingly
389
0
    if (subsec_dur.count() < 0) {
390
0
      if (sec_dur.count() > min_seconds) {
391
0
        sec_dur = sec_dur - fs_seconds(1);
392
0
        subsec_dur = subsec_dur + fs_seconds(1);
393
0
      } else {
394
0
        subsec_dur = fs_nanoseconds::zero();
395
0
      }
396
0
    }
397
0
    return checked_set(sec_out, sec_dur.count()) &&
398
0
           checked_set(subsec_out, subsec_dur.count());
399
0
  }
400
  static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool convert_to_timespec(TimeSpecT& dest,
401
0
                                                                FileTimeT tp) {
402
0
    if (!is_representable(tp))
403
0
      return false;
404
0
    return set_times_checked(&dest.tv_sec, &dest.tv_nsec, tp);
405
0
  }
406
};
407
408
using fs_time = time_util<file_time_type, time_t, TimeSpec>;
409
410
#if defined(__APPLE__)
411
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&)
412
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&)
413
#elif defined(__MVS__)
414
inline TimeSpec extract_mtime(StatT const& st) {
415
  TimeSpec TS = {st.st_mtime, 0};
416
  return TS;
417
}
418
inline TimeSpec extract_atime(StatT const& st) {
419
  TimeSpec TS = {st.st_atime, 0};
420
  return TS;
421
}
422
#else
423
inline TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; }
424
inline TimeSpec extract_atime(StatT const& st) { return st.st_atim; }
425
#endif
426
427
0
inline TimeVal make_timeval(TimeSpec const& ts) {
428
0
  using namespace chrono;
429
0
  auto Convert = [](long nsec) {
430
0
    using int_type = decltype(std::declval<TimeVal>().tv_usec);
431
0
    auto dur = duration_cast<microseconds>(nanoseconds(nsec)).count();
432
0
    return static_cast<int_type>(dur);
433
0
  };
434
0
  TimeVal TV = {};
435
0
  TV.tv_sec = ts.tv_sec;
436
0
  TV.tv_usec = Convert(ts.tv_nsec);
437
0
  return TV;
438
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&)
439
440
inline bool posix_utimes(const path& p, std::array<TimeSpec, 2> const& TS,
441
0
                  error_code& ec) {
442
0
  TimeVal ConvertedTS[2] = {make_timeval(TS[0]), make_timeval(TS[1])};
443
0
  if (::utimes(p.c_str(), ConvertedTS) == -1) {
444
0
    ec = capture_errno();
445
0
    return true;
446
0
  }
447
0
  return false;
448
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&)
449
450
#if defined(_LIBCPP_USE_UTIMENSAT)
451
bool posix_utimensat(const path& p, std::array<TimeSpec, 2> const& TS,
452
0
                     error_code& ec) {
453
0
  if (::utimensat(AT_FDCWD, p.c_str(), TS.data(), 0) == -1) {
454
0
    ec = capture_errno();
455
0
    return true;
456
0
  }
457
0
  return false;
458
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&)
459
#endif
460
461
bool set_file_times(const path& p, std::array<TimeSpec, 2> const& TS,
462
0
                    error_code& ec) {
463
#if !defined(_LIBCPP_USE_UTIMENSAT)
464
  return posix_utimes(p, TS, ec);
465
#else
466
0
  return posix_utimensat(p, TS, ec);
467
0
#endif
468
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&)
469
470
} // namespace
471
} // end namespace detail
472
473
_LIBCPP_END_NAMESPACE_FILESYSTEM
474
475
#endif // FILESYSTEM_COMMON_H