Coverage Report

Created: 2020-02-15 09:57

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