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