Coverage Report

Created: 2021-09-21 08:58

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