Coverage Report

Created: 2022-01-18 06:27

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