1*58b9f456SAndroid Build Coastguard Worker //===--------------------- filesystem/ops.cpp -----------------------------===//
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 #include "filesystem"
11*58b9f456SAndroid Build Coastguard Worker #include "array"
12*58b9f456SAndroid Build Coastguard Worker #include "iterator"
13*58b9f456SAndroid Build Coastguard Worker #include "fstream"
14*58b9f456SAndroid Build Coastguard Worker #include "random" /* for unique_path */
15*58b9f456SAndroid Build Coastguard Worker #include "string_view"
16*58b9f456SAndroid Build Coastguard Worker #include "type_traits"
17*58b9f456SAndroid Build Coastguard Worker #include "vector"
18*58b9f456SAndroid Build Coastguard Worker #include "cstdlib"
19*58b9f456SAndroid Build Coastguard Worker #include "climits"
20*58b9f456SAndroid Build Coastguard Worker
21*58b9f456SAndroid Build Coastguard Worker #include "filesystem_common.h"
22*58b9f456SAndroid Build Coastguard Worker
23*58b9f456SAndroid Build Coastguard Worker #include <unistd.h>
24*58b9f456SAndroid Build Coastguard Worker #include <sys/stat.h>
25*58b9f456SAndroid Build Coastguard Worker #include <sys/statvfs.h>
26*58b9f456SAndroid Build Coastguard Worker #include <time.h>
27*58b9f456SAndroid Build Coastguard Worker #include <fcntl.h> /* values for fchmodat */
28*58b9f456SAndroid Build Coastguard Worker
29*58b9f456SAndroid Build Coastguard Worker #if defined(__linux__)
30*58b9f456SAndroid Build Coastguard Worker #include <linux/version.h>
31*58b9f456SAndroid Build Coastguard Worker #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
32*58b9f456SAndroid Build Coastguard Worker #include <sys/sendfile.h>
33*58b9f456SAndroid Build Coastguard Worker #define _LIBCPP_USE_SENDFILE
34*58b9f456SAndroid Build Coastguard Worker #endif
35*58b9f456SAndroid Build Coastguard Worker #elif defined(__APPLE__) || __has_include(<copyfile.h>)
36*58b9f456SAndroid Build Coastguard Worker #include <copyfile.h>
37*58b9f456SAndroid Build Coastguard Worker #define _LIBCPP_USE_COPYFILE
38*58b9f456SAndroid Build Coastguard Worker #endif
39*58b9f456SAndroid Build Coastguard Worker
40*58b9f456SAndroid Build Coastguard Worker #if !defined(__APPLE__)
41*58b9f456SAndroid Build Coastguard Worker #define _LIBCPP_USE_CLOCK_GETTIME
42*58b9f456SAndroid Build Coastguard Worker #endif
43*58b9f456SAndroid Build Coastguard Worker
44*58b9f456SAndroid Build Coastguard Worker #if !defined(CLOCK_REALTIME) || !defined(_LIBCPP_USE_CLOCK_GETTIME)
45*58b9f456SAndroid Build Coastguard Worker #include <sys/time.h> // for gettimeofday and timeval
46*58b9f456SAndroid Build Coastguard Worker #endif // !defined(CLOCK_REALTIME)
47*58b9f456SAndroid Build Coastguard Worker
48*58b9f456SAndroid Build Coastguard Worker #if defined(_LIBCPP_COMPILER_GCC)
49*58b9f456SAndroid Build Coastguard Worker #if _GNUC_VER < 500
50*58b9f456SAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
51*58b9f456SAndroid Build Coastguard Worker #endif
52*58b9f456SAndroid Build Coastguard Worker #endif
53*58b9f456SAndroid Build Coastguard Worker
54*58b9f456SAndroid Build Coastguard Worker _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
55*58b9f456SAndroid Build Coastguard Worker
56*58b9f456SAndroid Build Coastguard Worker namespace {
57*58b9f456SAndroid Build Coastguard Worker namespace parser {
58*58b9f456SAndroid Build Coastguard Worker
59*58b9f456SAndroid Build Coastguard Worker using string_view_t = path::__string_view;
60*58b9f456SAndroid Build Coastguard Worker using string_view_pair = pair<string_view_t, string_view_t>;
61*58b9f456SAndroid Build Coastguard Worker using PosPtr = path::value_type const*;
62*58b9f456SAndroid Build Coastguard Worker
63*58b9f456SAndroid Build Coastguard Worker struct PathParser {
64*58b9f456SAndroid Build Coastguard Worker enum ParserState : unsigned char {
65*58b9f456SAndroid Build Coastguard Worker // Zero is a special sentinel value used by default constructed iterators.
66*58b9f456SAndroid Build Coastguard Worker PS_BeforeBegin = path::iterator::_BeforeBegin,
67*58b9f456SAndroid Build Coastguard Worker PS_InRootName = path::iterator::_InRootName,
68*58b9f456SAndroid Build Coastguard Worker PS_InRootDir = path::iterator::_InRootDir,
69*58b9f456SAndroid Build Coastguard Worker PS_InFilenames = path::iterator::_InFilenames,
70*58b9f456SAndroid Build Coastguard Worker PS_InTrailingSep = path::iterator::_InTrailingSep,
71*58b9f456SAndroid Build Coastguard Worker PS_AtEnd = path::iterator::_AtEnd
72*58b9f456SAndroid Build Coastguard Worker };
73*58b9f456SAndroid Build Coastguard Worker
74*58b9f456SAndroid Build Coastguard Worker const string_view_t Path;
75*58b9f456SAndroid Build Coastguard Worker string_view_t RawEntry;
76*58b9f456SAndroid Build Coastguard Worker ParserState State;
77*58b9f456SAndroid Build Coastguard Worker
78*58b9f456SAndroid Build Coastguard Worker private:
PathParser__anon3f21bde00111::parser::PathParser79*58b9f456SAndroid Build Coastguard Worker PathParser(string_view_t P, ParserState State) noexcept : Path(P),
80*58b9f456SAndroid Build Coastguard Worker State(State) {}
81*58b9f456SAndroid Build Coastguard Worker
82*58b9f456SAndroid Build Coastguard Worker public:
PathParser__anon3f21bde00111::parser::PathParser83*58b9f456SAndroid Build Coastguard Worker PathParser(string_view_t P, string_view_t E, unsigned char S)
84*58b9f456SAndroid Build Coastguard Worker : Path(P), RawEntry(E), State(static_cast<ParserState>(S)) {
85*58b9f456SAndroid Build Coastguard Worker // S cannot be '0' or PS_BeforeBegin.
86*58b9f456SAndroid Build Coastguard Worker }
87*58b9f456SAndroid Build Coastguard Worker
CreateBegin__anon3f21bde00111::parser::PathParser88*58b9f456SAndroid Build Coastguard Worker static PathParser CreateBegin(string_view_t P) noexcept {
89*58b9f456SAndroid Build Coastguard Worker PathParser PP(P, PS_BeforeBegin);
90*58b9f456SAndroid Build Coastguard Worker PP.increment();
91*58b9f456SAndroid Build Coastguard Worker return PP;
92*58b9f456SAndroid Build Coastguard Worker }
93*58b9f456SAndroid Build Coastguard Worker
CreateEnd__anon3f21bde00111::parser::PathParser94*58b9f456SAndroid Build Coastguard Worker static PathParser CreateEnd(string_view_t P) noexcept {
95*58b9f456SAndroid Build Coastguard Worker PathParser PP(P, PS_AtEnd);
96*58b9f456SAndroid Build Coastguard Worker return PP;
97*58b9f456SAndroid Build Coastguard Worker }
98*58b9f456SAndroid Build Coastguard Worker
peek__anon3f21bde00111::parser::PathParser99*58b9f456SAndroid Build Coastguard Worker PosPtr peek() const noexcept {
100*58b9f456SAndroid Build Coastguard Worker auto TkEnd = getNextTokenStartPos();
101*58b9f456SAndroid Build Coastguard Worker auto End = getAfterBack();
102*58b9f456SAndroid Build Coastguard Worker return TkEnd == End ? nullptr : TkEnd;
103*58b9f456SAndroid Build Coastguard Worker }
104*58b9f456SAndroid Build Coastguard Worker
increment__anon3f21bde00111::parser::PathParser105*58b9f456SAndroid Build Coastguard Worker void increment() noexcept {
106*58b9f456SAndroid Build Coastguard Worker const PosPtr End = getAfterBack();
107*58b9f456SAndroid Build Coastguard Worker const PosPtr Start = getNextTokenStartPos();
108*58b9f456SAndroid Build Coastguard Worker if (Start == End)
109*58b9f456SAndroid Build Coastguard Worker return makeState(PS_AtEnd);
110*58b9f456SAndroid Build Coastguard Worker
111*58b9f456SAndroid Build Coastguard Worker switch (State) {
112*58b9f456SAndroid Build Coastguard Worker case PS_BeforeBegin: {
113*58b9f456SAndroid Build Coastguard Worker PosPtr TkEnd = consumeSeparator(Start, End);
114*58b9f456SAndroid Build Coastguard Worker if (TkEnd)
115*58b9f456SAndroid Build Coastguard Worker return makeState(PS_InRootDir, Start, TkEnd);
116*58b9f456SAndroid Build Coastguard Worker else
117*58b9f456SAndroid Build Coastguard Worker return makeState(PS_InFilenames, Start, consumeName(Start, End));
118*58b9f456SAndroid Build Coastguard Worker }
119*58b9f456SAndroid Build Coastguard Worker case PS_InRootDir:
120*58b9f456SAndroid Build Coastguard Worker return makeState(PS_InFilenames, Start, consumeName(Start, End));
121*58b9f456SAndroid Build Coastguard Worker
122*58b9f456SAndroid Build Coastguard Worker case PS_InFilenames: {
123*58b9f456SAndroid Build Coastguard Worker PosPtr SepEnd = consumeSeparator(Start, End);
124*58b9f456SAndroid Build Coastguard Worker if (SepEnd != End) {
125*58b9f456SAndroid Build Coastguard Worker PosPtr TkEnd = consumeName(SepEnd, End);
126*58b9f456SAndroid Build Coastguard Worker if (TkEnd)
127*58b9f456SAndroid Build Coastguard Worker return makeState(PS_InFilenames, SepEnd, TkEnd);
128*58b9f456SAndroid Build Coastguard Worker }
129*58b9f456SAndroid Build Coastguard Worker return makeState(PS_InTrailingSep, Start, SepEnd);
130*58b9f456SAndroid Build Coastguard Worker }
131*58b9f456SAndroid Build Coastguard Worker
132*58b9f456SAndroid Build Coastguard Worker case PS_InTrailingSep:
133*58b9f456SAndroid Build Coastguard Worker return makeState(PS_AtEnd);
134*58b9f456SAndroid Build Coastguard Worker
135*58b9f456SAndroid Build Coastguard Worker case PS_InRootName:
136*58b9f456SAndroid Build Coastguard Worker case PS_AtEnd:
137*58b9f456SAndroid Build Coastguard Worker _LIBCPP_UNREACHABLE();
138*58b9f456SAndroid Build Coastguard Worker }
139*58b9f456SAndroid Build Coastguard Worker }
140*58b9f456SAndroid Build Coastguard Worker
decrement__anon3f21bde00111::parser::PathParser141*58b9f456SAndroid Build Coastguard Worker void decrement() noexcept {
142*58b9f456SAndroid Build Coastguard Worker const PosPtr REnd = getBeforeFront();
143*58b9f456SAndroid Build Coastguard Worker const PosPtr RStart = getCurrentTokenStartPos() - 1;
144*58b9f456SAndroid Build Coastguard Worker if (RStart == REnd) // we're decrementing the begin
145*58b9f456SAndroid Build Coastguard Worker return makeState(PS_BeforeBegin);
146*58b9f456SAndroid Build Coastguard Worker
147*58b9f456SAndroid Build Coastguard Worker switch (State) {
148*58b9f456SAndroid Build Coastguard Worker case PS_AtEnd: {
149*58b9f456SAndroid Build Coastguard Worker // Try to consume a trailing separator or root directory first.
150*58b9f456SAndroid Build Coastguard Worker if (PosPtr SepEnd = consumeSeparator(RStart, REnd)) {
151*58b9f456SAndroid Build Coastguard Worker if (SepEnd == REnd)
152*58b9f456SAndroid Build Coastguard Worker return makeState(PS_InRootDir, Path.data(), RStart + 1);
153*58b9f456SAndroid Build Coastguard Worker return makeState(PS_InTrailingSep, SepEnd + 1, RStart + 1);
154*58b9f456SAndroid Build Coastguard Worker } else {
155*58b9f456SAndroid Build Coastguard Worker PosPtr TkStart = consumeName(RStart, REnd);
156*58b9f456SAndroid Build Coastguard Worker return makeState(PS_InFilenames, TkStart + 1, RStart + 1);
157*58b9f456SAndroid Build Coastguard Worker }
158*58b9f456SAndroid Build Coastguard Worker }
159*58b9f456SAndroid Build Coastguard Worker case PS_InTrailingSep:
160*58b9f456SAndroid Build Coastguard Worker return makeState(PS_InFilenames, consumeName(RStart, REnd) + 1,
161*58b9f456SAndroid Build Coastguard Worker RStart + 1);
162*58b9f456SAndroid Build Coastguard Worker case PS_InFilenames: {
163*58b9f456SAndroid Build Coastguard Worker PosPtr SepEnd = consumeSeparator(RStart, REnd);
164*58b9f456SAndroid Build Coastguard Worker if (SepEnd == REnd)
165*58b9f456SAndroid Build Coastguard Worker return makeState(PS_InRootDir, Path.data(), RStart + 1);
166*58b9f456SAndroid Build Coastguard Worker PosPtr TkEnd = consumeName(SepEnd, REnd);
167*58b9f456SAndroid Build Coastguard Worker return makeState(PS_InFilenames, TkEnd + 1, SepEnd + 1);
168*58b9f456SAndroid Build Coastguard Worker }
169*58b9f456SAndroid Build Coastguard Worker case PS_InRootDir:
170*58b9f456SAndroid Build Coastguard Worker // return makeState(PS_InRootName, Path.data(), RStart + 1);
171*58b9f456SAndroid Build Coastguard Worker case PS_InRootName:
172*58b9f456SAndroid Build Coastguard Worker case PS_BeforeBegin:
173*58b9f456SAndroid Build Coastguard Worker _LIBCPP_UNREACHABLE();
174*58b9f456SAndroid Build Coastguard Worker }
175*58b9f456SAndroid Build Coastguard Worker }
176*58b9f456SAndroid Build Coastguard Worker
177*58b9f456SAndroid Build Coastguard Worker /// \brief Return a view with the "preferred representation" of the current
178*58b9f456SAndroid Build Coastguard Worker /// element. For example trailing separators are represented as a '.'
operator *__anon3f21bde00111::parser::PathParser179*58b9f456SAndroid Build Coastguard Worker string_view_t operator*() const noexcept {
180*58b9f456SAndroid Build Coastguard Worker switch (State) {
181*58b9f456SAndroid Build Coastguard Worker case PS_BeforeBegin:
182*58b9f456SAndroid Build Coastguard Worker case PS_AtEnd:
183*58b9f456SAndroid Build Coastguard Worker return "";
184*58b9f456SAndroid Build Coastguard Worker case PS_InRootDir:
185*58b9f456SAndroid Build Coastguard Worker return "/";
186*58b9f456SAndroid Build Coastguard Worker case PS_InTrailingSep:
187*58b9f456SAndroid Build Coastguard Worker return "";
188*58b9f456SAndroid Build Coastguard Worker case PS_InRootName:
189*58b9f456SAndroid Build Coastguard Worker case PS_InFilenames:
190*58b9f456SAndroid Build Coastguard Worker return RawEntry;
191*58b9f456SAndroid Build Coastguard Worker }
192*58b9f456SAndroid Build Coastguard Worker _LIBCPP_UNREACHABLE();
193*58b9f456SAndroid Build Coastguard Worker }
194*58b9f456SAndroid Build Coastguard Worker
operator bool__anon3f21bde00111::parser::PathParser195*58b9f456SAndroid Build Coastguard Worker explicit operator bool() const noexcept {
196*58b9f456SAndroid Build Coastguard Worker return State != PS_BeforeBegin && State != PS_AtEnd;
197*58b9f456SAndroid Build Coastguard Worker }
198*58b9f456SAndroid Build Coastguard Worker
operator ++__anon3f21bde00111::parser::PathParser199*58b9f456SAndroid Build Coastguard Worker PathParser& operator++() noexcept {
200*58b9f456SAndroid Build Coastguard Worker increment();
201*58b9f456SAndroid Build Coastguard Worker return *this;
202*58b9f456SAndroid Build Coastguard Worker }
203*58b9f456SAndroid Build Coastguard Worker
operator --__anon3f21bde00111::parser::PathParser204*58b9f456SAndroid Build Coastguard Worker PathParser& operator--() noexcept {
205*58b9f456SAndroid Build Coastguard Worker decrement();
206*58b9f456SAndroid Build Coastguard Worker return *this;
207*58b9f456SAndroid Build Coastguard Worker }
208*58b9f456SAndroid Build Coastguard Worker
atEnd__anon3f21bde00111::parser::PathParser209*58b9f456SAndroid Build Coastguard Worker bool atEnd() const noexcept {
210*58b9f456SAndroid Build Coastguard Worker return State == PS_AtEnd;
211*58b9f456SAndroid Build Coastguard Worker }
212*58b9f456SAndroid Build Coastguard Worker
inRootDir__anon3f21bde00111::parser::PathParser213*58b9f456SAndroid Build Coastguard Worker bool inRootDir() const noexcept {
214*58b9f456SAndroid Build Coastguard Worker return State == PS_InRootDir;
215*58b9f456SAndroid Build Coastguard Worker }
216*58b9f456SAndroid Build Coastguard Worker
inRootName__anon3f21bde00111::parser::PathParser217*58b9f456SAndroid Build Coastguard Worker bool inRootName() const noexcept {
218*58b9f456SAndroid Build Coastguard Worker return State == PS_InRootName;
219*58b9f456SAndroid Build Coastguard Worker }
220*58b9f456SAndroid Build Coastguard Worker
inRootPath__anon3f21bde00111::parser::PathParser221*58b9f456SAndroid Build Coastguard Worker bool inRootPath() const noexcept {
222*58b9f456SAndroid Build Coastguard Worker return inRootName() || inRootDir();
223*58b9f456SAndroid Build Coastguard Worker }
224*58b9f456SAndroid Build Coastguard Worker
225*58b9f456SAndroid Build Coastguard Worker private:
makeState__anon3f21bde00111::parser::PathParser226*58b9f456SAndroid Build Coastguard Worker void makeState(ParserState NewState, PosPtr Start, PosPtr End) noexcept {
227*58b9f456SAndroid Build Coastguard Worker State = NewState;
228*58b9f456SAndroid Build Coastguard Worker RawEntry = string_view_t(Start, End - Start);
229*58b9f456SAndroid Build Coastguard Worker }
makeState__anon3f21bde00111::parser::PathParser230*58b9f456SAndroid Build Coastguard Worker void makeState(ParserState NewState) noexcept {
231*58b9f456SAndroid Build Coastguard Worker State = NewState;
232*58b9f456SAndroid Build Coastguard Worker RawEntry = {};
233*58b9f456SAndroid Build Coastguard Worker }
234*58b9f456SAndroid Build Coastguard Worker
getAfterBack__anon3f21bde00111::parser::PathParser235*58b9f456SAndroid Build Coastguard Worker PosPtr getAfterBack() const noexcept { return Path.data() + Path.size(); }
236*58b9f456SAndroid Build Coastguard Worker
getBeforeFront__anon3f21bde00111::parser::PathParser237*58b9f456SAndroid Build Coastguard Worker PosPtr getBeforeFront() const noexcept { return Path.data() - 1; }
238*58b9f456SAndroid Build Coastguard Worker
239*58b9f456SAndroid Build Coastguard Worker /// \brief Return a pointer to the first character after the currently
240*58b9f456SAndroid Build Coastguard Worker /// lexed element.
getNextTokenStartPos__anon3f21bde00111::parser::PathParser241*58b9f456SAndroid Build Coastguard Worker PosPtr getNextTokenStartPos() const noexcept {
242*58b9f456SAndroid Build Coastguard Worker switch (State) {
243*58b9f456SAndroid Build Coastguard Worker case PS_BeforeBegin:
244*58b9f456SAndroid Build Coastguard Worker return Path.data();
245*58b9f456SAndroid Build Coastguard Worker case PS_InRootName:
246*58b9f456SAndroid Build Coastguard Worker case PS_InRootDir:
247*58b9f456SAndroid Build Coastguard Worker case PS_InFilenames:
248*58b9f456SAndroid Build Coastguard Worker return &RawEntry.back() + 1;
249*58b9f456SAndroid Build Coastguard Worker case PS_InTrailingSep:
250*58b9f456SAndroid Build Coastguard Worker case PS_AtEnd:
251*58b9f456SAndroid Build Coastguard Worker return getAfterBack();
252*58b9f456SAndroid Build Coastguard Worker }
253*58b9f456SAndroid Build Coastguard Worker _LIBCPP_UNREACHABLE();
254*58b9f456SAndroid Build Coastguard Worker }
255*58b9f456SAndroid Build Coastguard Worker
256*58b9f456SAndroid Build Coastguard Worker /// \brief Return a pointer to the first character in the currently lexed
257*58b9f456SAndroid Build Coastguard Worker /// element.
getCurrentTokenStartPos__anon3f21bde00111::parser::PathParser258*58b9f456SAndroid Build Coastguard Worker PosPtr getCurrentTokenStartPos() const noexcept {
259*58b9f456SAndroid Build Coastguard Worker switch (State) {
260*58b9f456SAndroid Build Coastguard Worker case PS_BeforeBegin:
261*58b9f456SAndroid Build Coastguard Worker case PS_InRootName:
262*58b9f456SAndroid Build Coastguard Worker return &Path.front();
263*58b9f456SAndroid Build Coastguard Worker case PS_InRootDir:
264*58b9f456SAndroid Build Coastguard Worker case PS_InFilenames:
265*58b9f456SAndroid Build Coastguard Worker case PS_InTrailingSep:
266*58b9f456SAndroid Build Coastguard Worker return &RawEntry.front();
267*58b9f456SAndroid Build Coastguard Worker case PS_AtEnd:
268*58b9f456SAndroid Build Coastguard Worker return &Path.back() + 1;
269*58b9f456SAndroid Build Coastguard Worker }
270*58b9f456SAndroid Build Coastguard Worker _LIBCPP_UNREACHABLE();
271*58b9f456SAndroid Build Coastguard Worker }
272*58b9f456SAndroid Build Coastguard Worker
consumeSeparator__anon3f21bde00111::parser::PathParser273*58b9f456SAndroid Build Coastguard Worker PosPtr consumeSeparator(PosPtr P, PosPtr End) const noexcept {
274*58b9f456SAndroid Build Coastguard Worker if (P == End || *P != '/')
275*58b9f456SAndroid Build Coastguard Worker return nullptr;
276*58b9f456SAndroid Build Coastguard Worker const int Inc = P < End ? 1 : -1;
277*58b9f456SAndroid Build Coastguard Worker P += Inc;
278*58b9f456SAndroid Build Coastguard Worker while (P != End && *P == '/')
279*58b9f456SAndroid Build Coastguard Worker P += Inc;
280*58b9f456SAndroid Build Coastguard Worker return P;
281*58b9f456SAndroid Build Coastguard Worker }
282*58b9f456SAndroid Build Coastguard Worker
consumeName__anon3f21bde00111::parser::PathParser283*58b9f456SAndroid Build Coastguard Worker PosPtr consumeName(PosPtr P, PosPtr End) const noexcept {
284*58b9f456SAndroid Build Coastguard Worker if (P == End || *P == '/')
285*58b9f456SAndroid Build Coastguard Worker return nullptr;
286*58b9f456SAndroid Build Coastguard Worker const int Inc = P < End ? 1 : -1;
287*58b9f456SAndroid Build Coastguard Worker P += Inc;
288*58b9f456SAndroid Build Coastguard Worker while (P != End && *P != '/')
289*58b9f456SAndroid Build Coastguard Worker P += Inc;
290*58b9f456SAndroid Build Coastguard Worker return P;
291*58b9f456SAndroid Build Coastguard Worker }
292*58b9f456SAndroid Build Coastguard Worker };
293*58b9f456SAndroid Build Coastguard Worker
separate_filename(string_view_t const & s)294*58b9f456SAndroid Build Coastguard Worker string_view_pair separate_filename(string_view_t const& s) {
295*58b9f456SAndroid Build Coastguard Worker if (s == "." || s == ".." || s.empty())
296*58b9f456SAndroid Build Coastguard Worker return string_view_pair{s, ""};
297*58b9f456SAndroid Build Coastguard Worker auto pos = s.find_last_of('.');
298*58b9f456SAndroid Build Coastguard Worker if (pos == string_view_t::npos || pos == 0)
299*58b9f456SAndroid Build Coastguard Worker return string_view_pair{s, string_view_t{}};
300*58b9f456SAndroid Build Coastguard Worker return string_view_pair{s.substr(0, pos), s.substr(pos)};
301*58b9f456SAndroid Build Coastguard Worker }
302*58b9f456SAndroid Build Coastguard Worker
createView(PosPtr S,PosPtr E)303*58b9f456SAndroid Build Coastguard Worker string_view_t createView(PosPtr S, PosPtr E) noexcept {
304*58b9f456SAndroid Build Coastguard Worker return {S, static_cast<size_t>(E - S) + 1};
305*58b9f456SAndroid Build Coastguard Worker }
306*58b9f456SAndroid Build Coastguard Worker
307*58b9f456SAndroid Build Coastguard Worker } // namespace parser
308*58b9f456SAndroid Build Coastguard Worker } // namespace
309*58b9f456SAndroid Build Coastguard Worker
310*58b9f456SAndroid Build Coastguard Worker // POSIX HELPERS
311*58b9f456SAndroid Build Coastguard Worker
312*58b9f456SAndroid Build Coastguard Worker namespace detail {
313*58b9f456SAndroid Build Coastguard Worker namespace {
314*58b9f456SAndroid Build Coastguard Worker
315*58b9f456SAndroid Build Coastguard Worker using value_type = path::value_type;
316*58b9f456SAndroid Build Coastguard Worker using string_type = path::string_type;
317*58b9f456SAndroid Build Coastguard Worker
318*58b9f456SAndroid Build Coastguard Worker struct FileDescriptor {
319*58b9f456SAndroid Build Coastguard Worker const path& name;
320*58b9f456SAndroid Build Coastguard Worker int fd = -1;
321*58b9f456SAndroid Build Coastguard Worker StatT m_stat;
322*58b9f456SAndroid Build Coastguard Worker file_status m_status;
323*58b9f456SAndroid Build Coastguard Worker
324*58b9f456SAndroid Build Coastguard Worker template <class... Args>
createdetail::__anon3f21bde00211::FileDescriptor325*58b9f456SAndroid Build Coastguard Worker static FileDescriptor create(const path* p, error_code& ec, Args... args) {
326*58b9f456SAndroid Build Coastguard Worker ec.clear();
327*58b9f456SAndroid Build Coastguard Worker int fd;
328*58b9f456SAndroid Build Coastguard Worker if ((fd = ::open(p->c_str(), args...)) == -1) {
329*58b9f456SAndroid Build Coastguard Worker ec = capture_errno();
330*58b9f456SAndroid Build Coastguard Worker return FileDescriptor{p};
331*58b9f456SAndroid Build Coastguard Worker }
332*58b9f456SAndroid Build Coastguard Worker return FileDescriptor(p, fd);
333*58b9f456SAndroid Build Coastguard Worker }
334*58b9f456SAndroid Build Coastguard Worker
335*58b9f456SAndroid Build Coastguard Worker template <class... Args>
create_with_statusdetail::__anon3f21bde00211::FileDescriptor336*58b9f456SAndroid Build Coastguard Worker static FileDescriptor create_with_status(const path* p, error_code& ec,
337*58b9f456SAndroid Build Coastguard Worker Args... args) {
338*58b9f456SAndroid Build Coastguard Worker FileDescriptor fd = create(p, ec, args...);
339*58b9f456SAndroid Build Coastguard Worker if (!ec)
340*58b9f456SAndroid Build Coastguard Worker fd.refresh_status(ec);
341*58b9f456SAndroid Build Coastguard Worker
342*58b9f456SAndroid Build Coastguard Worker return fd;
343*58b9f456SAndroid Build Coastguard Worker }
344*58b9f456SAndroid Build Coastguard Worker
get_statusdetail::__anon3f21bde00211::FileDescriptor345*58b9f456SAndroid Build Coastguard Worker file_status get_status() const { return m_status; }
get_statdetail::__anon3f21bde00211::FileDescriptor346*58b9f456SAndroid Build Coastguard Worker StatT const& get_stat() const { return m_stat; }
347*58b9f456SAndroid Build Coastguard Worker
status_knowndetail::__anon3f21bde00211::FileDescriptor348*58b9f456SAndroid Build Coastguard Worker bool status_known() const { return _VSTD_FS::status_known(m_status); }
349*58b9f456SAndroid Build Coastguard Worker
350*58b9f456SAndroid Build Coastguard Worker file_status refresh_status(error_code& ec);
351*58b9f456SAndroid Build Coastguard Worker
closedetail::__anon3f21bde00211::FileDescriptor352*58b9f456SAndroid Build Coastguard Worker void close() noexcept {
353*58b9f456SAndroid Build Coastguard Worker if (fd != -1)
354*58b9f456SAndroid Build Coastguard Worker ::close(fd);
355*58b9f456SAndroid Build Coastguard Worker fd = -1;
356*58b9f456SAndroid Build Coastguard Worker }
357*58b9f456SAndroid Build Coastguard Worker
FileDescriptordetail::__anon3f21bde00211::FileDescriptor358*58b9f456SAndroid Build Coastguard Worker FileDescriptor(FileDescriptor&& other)
359*58b9f456SAndroid Build Coastguard Worker : name(other.name), fd(other.fd), m_stat(other.m_stat),
360*58b9f456SAndroid Build Coastguard Worker m_status(other.m_status) {
361*58b9f456SAndroid Build Coastguard Worker other.fd = -1;
362*58b9f456SAndroid Build Coastguard Worker other.m_status = file_status{};
363*58b9f456SAndroid Build Coastguard Worker }
364*58b9f456SAndroid Build Coastguard Worker
~FileDescriptordetail::__anon3f21bde00211::FileDescriptor365*58b9f456SAndroid Build Coastguard Worker ~FileDescriptor() { close(); }
366*58b9f456SAndroid Build Coastguard Worker
367*58b9f456SAndroid Build Coastguard Worker FileDescriptor(FileDescriptor const&) = delete;
368*58b9f456SAndroid Build Coastguard Worker FileDescriptor& operator=(FileDescriptor const&) = delete;
369*58b9f456SAndroid Build Coastguard Worker
370*58b9f456SAndroid Build Coastguard Worker private:
FileDescriptordetail::__anon3f21bde00211::FileDescriptor371*58b9f456SAndroid Build Coastguard Worker explicit FileDescriptor(const path* p, int fd = -1) : name(*p), fd(fd) {}
372*58b9f456SAndroid Build Coastguard Worker };
373*58b9f456SAndroid Build Coastguard Worker
posix_get_perms(const StatT & st)374*58b9f456SAndroid Build Coastguard Worker perms posix_get_perms(const StatT& st) noexcept {
375*58b9f456SAndroid Build Coastguard Worker return static_cast<perms>(st.st_mode) & perms::mask;
376*58b9f456SAndroid Build Coastguard Worker }
377*58b9f456SAndroid Build Coastguard Worker
posix_convert_perms(perms prms)378*58b9f456SAndroid Build Coastguard Worker ::mode_t posix_convert_perms(perms prms) {
379*58b9f456SAndroid Build Coastguard Worker return static_cast< ::mode_t>(prms & perms::mask);
380*58b9f456SAndroid Build Coastguard Worker }
381*58b9f456SAndroid Build Coastguard Worker
create_file_status(error_code & m_ec,path const & p,const StatT & path_stat,error_code * ec)382*58b9f456SAndroid Build Coastguard Worker file_status create_file_status(error_code& m_ec, path const& p,
383*58b9f456SAndroid Build Coastguard Worker const StatT& path_stat, error_code* ec) {
384*58b9f456SAndroid Build Coastguard Worker if (ec)
385*58b9f456SAndroid Build Coastguard Worker *ec = m_ec;
386*58b9f456SAndroid Build Coastguard Worker if (m_ec && (m_ec.value() == ENOENT || m_ec.value() == ENOTDIR)) {
387*58b9f456SAndroid Build Coastguard Worker return file_status(file_type::not_found);
388*58b9f456SAndroid Build Coastguard Worker } else if (m_ec) {
389*58b9f456SAndroid Build Coastguard Worker ErrorHandler<void> err("posix_stat", ec, &p);
390*58b9f456SAndroid Build Coastguard Worker err.report(m_ec, "failed to determine attributes for the specified path");
391*58b9f456SAndroid Build Coastguard Worker return file_status(file_type::none);
392*58b9f456SAndroid Build Coastguard Worker }
393*58b9f456SAndroid Build Coastguard Worker // else
394*58b9f456SAndroid Build Coastguard Worker
395*58b9f456SAndroid Build Coastguard Worker file_status fs_tmp;
396*58b9f456SAndroid Build Coastguard Worker auto const mode = path_stat.st_mode;
397*58b9f456SAndroid Build Coastguard Worker if (S_ISLNK(mode))
398*58b9f456SAndroid Build Coastguard Worker fs_tmp.type(file_type::symlink);
399*58b9f456SAndroid Build Coastguard Worker else if (S_ISREG(mode))
400*58b9f456SAndroid Build Coastguard Worker fs_tmp.type(file_type::regular);
401*58b9f456SAndroid Build Coastguard Worker else if (S_ISDIR(mode))
402*58b9f456SAndroid Build Coastguard Worker fs_tmp.type(file_type::directory);
403*58b9f456SAndroid Build Coastguard Worker else if (S_ISBLK(mode))
404*58b9f456SAndroid Build Coastguard Worker fs_tmp.type(file_type::block);
405*58b9f456SAndroid Build Coastguard Worker else if (S_ISCHR(mode))
406*58b9f456SAndroid Build Coastguard Worker fs_tmp.type(file_type::character);
407*58b9f456SAndroid Build Coastguard Worker else if (S_ISFIFO(mode))
408*58b9f456SAndroid Build Coastguard Worker fs_tmp.type(file_type::fifo);
409*58b9f456SAndroid Build Coastguard Worker else if (S_ISSOCK(mode))
410*58b9f456SAndroid Build Coastguard Worker fs_tmp.type(file_type::socket);
411*58b9f456SAndroid Build Coastguard Worker else
412*58b9f456SAndroid Build Coastguard Worker fs_tmp.type(file_type::unknown);
413*58b9f456SAndroid Build Coastguard Worker
414*58b9f456SAndroid Build Coastguard Worker fs_tmp.permissions(detail::posix_get_perms(path_stat));
415*58b9f456SAndroid Build Coastguard Worker return fs_tmp;
416*58b9f456SAndroid Build Coastguard Worker }
417*58b9f456SAndroid Build Coastguard Worker
posix_stat(path const & p,StatT & path_stat,error_code * ec)418*58b9f456SAndroid Build Coastguard Worker file_status posix_stat(path const& p, StatT& path_stat, error_code* ec) {
419*58b9f456SAndroid Build Coastguard Worker error_code m_ec;
420*58b9f456SAndroid Build Coastguard Worker if (::stat(p.c_str(), &path_stat) == -1)
421*58b9f456SAndroid Build Coastguard Worker m_ec = detail::capture_errno();
422*58b9f456SAndroid Build Coastguard Worker return create_file_status(m_ec, p, path_stat, ec);
423*58b9f456SAndroid Build Coastguard Worker }
424*58b9f456SAndroid Build Coastguard Worker
posix_stat(path const & p,error_code * ec)425*58b9f456SAndroid Build Coastguard Worker file_status posix_stat(path const& p, error_code* ec) {
426*58b9f456SAndroid Build Coastguard Worker StatT path_stat;
427*58b9f456SAndroid Build Coastguard Worker return posix_stat(p, path_stat, ec);
428*58b9f456SAndroid Build Coastguard Worker }
429*58b9f456SAndroid Build Coastguard Worker
posix_lstat(path const & p,StatT & path_stat,error_code * ec)430*58b9f456SAndroid Build Coastguard Worker file_status posix_lstat(path const& p, StatT& path_stat, error_code* ec) {
431*58b9f456SAndroid Build Coastguard Worker error_code m_ec;
432*58b9f456SAndroid Build Coastguard Worker if (::lstat(p.c_str(), &path_stat) == -1)
433*58b9f456SAndroid Build Coastguard Worker m_ec = detail::capture_errno();
434*58b9f456SAndroid Build Coastguard Worker return create_file_status(m_ec, p, path_stat, ec);
435*58b9f456SAndroid Build Coastguard Worker }
436*58b9f456SAndroid Build Coastguard Worker
posix_lstat(path const & p,error_code * ec)437*58b9f456SAndroid Build Coastguard Worker file_status posix_lstat(path const& p, error_code* ec) {
438*58b9f456SAndroid Build Coastguard Worker StatT path_stat;
439*58b9f456SAndroid Build Coastguard Worker return posix_lstat(p, path_stat, ec);
440*58b9f456SAndroid Build Coastguard Worker }
441*58b9f456SAndroid Build Coastguard Worker
posix_ftruncate(const FileDescriptor & fd,size_t to_size,error_code & ec)442*58b9f456SAndroid Build Coastguard Worker bool posix_ftruncate(const FileDescriptor& fd, size_t to_size, error_code& ec) {
443*58b9f456SAndroid Build Coastguard Worker if (::ftruncate(fd.fd, to_size) == -1) {
444*58b9f456SAndroid Build Coastguard Worker ec = capture_errno();
445*58b9f456SAndroid Build Coastguard Worker return true;
446*58b9f456SAndroid Build Coastguard Worker }
447*58b9f456SAndroid Build Coastguard Worker ec.clear();
448*58b9f456SAndroid Build Coastguard Worker return false;
449*58b9f456SAndroid Build Coastguard Worker }
450*58b9f456SAndroid Build Coastguard Worker
posix_fchmod(const FileDescriptor & fd,const StatT & st,error_code & ec)451*58b9f456SAndroid Build Coastguard Worker bool posix_fchmod(const FileDescriptor& fd, const StatT& st, error_code& ec) {
452*58b9f456SAndroid Build Coastguard Worker if (::fchmod(fd.fd, st.st_mode) == -1) {
453*58b9f456SAndroid Build Coastguard Worker ec = capture_errno();
454*58b9f456SAndroid Build Coastguard Worker return true;
455*58b9f456SAndroid Build Coastguard Worker }
456*58b9f456SAndroid Build Coastguard Worker ec.clear();
457*58b9f456SAndroid Build Coastguard Worker return false;
458*58b9f456SAndroid Build Coastguard Worker }
459*58b9f456SAndroid Build Coastguard Worker
stat_equivalent(const StatT & st1,const StatT & st2)460*58b9f456SAndroid Build Coastguard Worker bool stat_equivalent(const StatT& st1, const StatT& st2) {
461*58b9f456SAndroid Build Coastguard Worker return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
462*58b9f456SAndroid Build Coastguard Worker }
463*58b9f456SAndroid Build Coastguard Worker
refresh_status(error_code & ec)464*58b9f456SAndroid Build Coastguard Worker file_status FileDescriptor::refresh_status(error_code& ec) {
465*58b9f456SAndroid Build Coastguard Worker // FD must be open and good.
466*58b9f456SAndroid Build Coastguard Worker m_status = file_status{};
467*58b9f456SAndroid Build Coastguard Worker m_stat = {};
468*58b9f456SAndroid Build Coastguard Worker error_code m_ec;
469*58b9f456SAndroid Build Coastguard Worker if (::fstat(fd, &m_stat) == -1)
470*58b9f456SAndroid Build Coastguard Worker m_ec = capture_errno();
471*58b9f456SAndroid Build Coastguard Worker m_status = create_file_status(m_ec, name, m_stat, &ec);
472*58b9f456SAndroid Build Coastguard Worker return m_status;
473*58b9f456SAndroid Build Coastguard Worker }
474*58b9f456SAndroid Build Coastguard Worker } // namespace
475*58b9f456SAndroid Build Coastguard Worker } // end namespace detail
476*58b9f456SAndroid Build Coastguard Worker
477*58b9f456SAndroid Build Coastguard Worker using detail::capture_errno;
478*58b9f456SAndroid Build Coastguard Worker using detail::ErrorHandler;
479*58b9f456SAndroid Build Coastguard Worker using detail::StatT;
480*58b9f456SAndroid Build Coastguard Worker using detail::TimeSpec;
481*58b9f456SAndroid Build Coastguard Worker using parser::createView;
482*58b9f456SAndroid Build Coastguard Worker using parser::PathParser;
483*58b9f456SAndroid Build Coastguard Worker using parser::string_view_t;
484*58b9f456SAndroid Build Coastguard Worker
485*58b9f456SAndroid Build Coastguard Worker const bool _FilesystemClock::is_steady;
486*58b9f456SAndroid Build Coastguard Worker
now()487*58b9f456SAndroid Build Coastguard Worker _FilesystemClock::time_point _FilesystemClock::now() noexcept {
488*58b9f456SAndroid Build Coastguard Worker typedef chrono::duration<rep> __secs;
489*58b9f456SAndroid Build Coastguard Worker #if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
490*58b9f456SAndroid Build Coastguard Worker typedef chrono::duration<rep, nano> __nsecs;
491*58b9f456SAndroid Build Coastguard Worker struct timespec tp;
492*58b9f456SAndroid Build Coastguard Worker if (0 != clock_gettime(CLOCK_REALTIME, &tp))
493*58b9f456SAndroid Build Coastguard Worker __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed");
494*58b9f456SAndroid Build Coastguard Worker return time_point(__secs(tp.tv_sec) +
495*58b9f456SAndroid Build Coastguard Worker chrono::duration_cast<duration>(__nsecs(tp.tv_nsec)));
496*58b9f456SAndroid Build Coastguard Worker #else
497*58b9f456SAndroid Build Coastguard Worker typedef chrono::duration<rep, micro> __microsecs;
498*58b9f456SAndroid Build Coastguard Worker timeval tv;
499*58b9f456SAndroid Build Coastguard Worker gettimeofday(&tv, 0);
500*58b9f456SAndroid Build Coastguard Worker return time_point(__secs(tv.tv_sec) + __microsecs(tv.tv_usec));
501*58b9f456SAndroid Build Coastguard Worker #endif // _LIBCPP_USE_CLOCK_GETTIME && CLOCK_REALTIME
502*58b9f456SAndroid Build Coastguard Worker }
503*58b9f456SAndroid Build Coastguard Worker
~filesystem_error()504*58b9f456SAndroid Build Coastguard Worker filesystem_error::~filesystem_error() {}
505*58b9f456SAndroid Build Coastguard Worker
__create_what(int __num_paths)506*58b9f456SAndroid Build Coastguard Worker void filesystem_error::__create_what(int __num_paths) {
507*58b9f456SAndroid Build Coastguard Worker const char* derived_what = system_error::what();
508*58b9f456SAndroid Build Coastguard Worker __storage_->__what_ = [&]() -> string {
509*58b9f456SAndroid Build Coastguard Worker const char* p1 = path1().native().empty() ? "\"\"" : path1().c_str();
510*58b9f456SAndroid Build Coastguard Worker const char* p2 = path2().native().empty() ? "\"\"" : path2().c_str();
511*58b9f456SAndroid Build Coastguard Worker switch (__num_paths) {
512*58b9f456SAndroid Build Coastguard Worker default:
513*58b9f456SAndroid Build Coastguard Worker return detail::format_string("filesystem error: %s", derived_what);
514*58b9f456SAndroid Build Coastguard Worker case 1:
515*58b9f456SAndroid Build Coastguard Worker return detail::format_string("filesystem error: %s [%s]", derived_what,
516*58b9f456SAndroid Build Coastguard Worker p1);
517*58b9f456SAndroid Build Coastguard Worker case 2:
518*58b9f456SAndroid Build Coastguard Worker return detail::format_string("filesystem error: %s [%s] [%s]",
519*58b9f456SAndroid Build Coastguard Worker derived_what, p1, p2);
520*58b9f456SAndroid Build Coastguard Worker }
521*58b9f456SAndroid Build Coastguard Worker }();
522*58b9f456SAndroid Build Coastguard Worker }
523*58b9f456SAndroid Build Coastguard Worker
__do_absolute(const path & p,path * cwd,error_code * ec)524*58b9f456SAndroid Build Coastguard Worker static path __do_absolute(const path& p, path* cwd, error_code* ec) {
525*58b9f456SAndroid Build Coastguard Worker if (ec)
526*58b9f456SAndroid Build Coastguard Worker ec->clear();
527*58b9f456SAndroid Build Coastguard Worker if (p.is_absolute())
528*58b9f456SAndroid Build Coastguard Worker return p;
529*58b9f456SAndroid Build Coastguard Worker *cwd = __current_path(ec);
530*58b9f456SAndroid Build Coastguard Worker if (ec && *ec)
531*58b9f456SAndroid Build Coastguard Worker return {};
532*58b9f456SAndroid Build Coastguard Worker return (*cwd) / p;
533*58b9f456SAndroid Build Coastguard Worker }
534*58b9f456SAndroid Build Coastguard Worker
__absolute(const path & p,error_code * ec)535*58b9f456SAndroid Build Coastguard Worker path __absolute(const path& p, error_code* ec) {
536*58b9f456SAndroid Build Coastguard Worker path cwd;
537*58b9f456SAndroid Build Coastguard Worker return __do_absolute(p, &cwd, ec);
538*58b9f456SAndroid Build Coastguard Worker }
539*58b9f456SAndroid Build Coastguard Worker
__canonical(path const & orig_p,error_code * ec)540*58b9f456SAndroid Build Coastguard Worker path __canonical(path const& orig_p, error_code* ec) {
541*58b9f456SAndroid Build Coastguard Worker path cwd;
542*58b9f456SAndroid Build Coastguard Worker ErrorHandler<path> err("canonical", ec, &orig_p, &cwd);
543*58b9f456SAndroid Build Coastguard Worker
544*58b9f456SAndroid Build Coastguard Worker path p = __do_absolute(orig_p, &cwd, ec);
545*58b9f456SAndroid Build Coastguard Worker char buff[PATH_MAX + 1];
546*58b9f456SAndroid Build Coastguard Worker char* ret;
547*58b9f456SAndroid Build Coastguard Worker if ((ret = ::realpath(p.c_str(), buff)) == nullptr)
548*58b9f456SAndroid Build Coastguard Worker return err.report(capture_errno());
549*58b9f456SAndroid Build Coastguard Worker return {ret};
550*58b9f456SAndroid Build Coastguard Worker }
551*58b9f456SAndroid Build Coastguard Worker
__copy(const path & from,const path & to,copy_options options,error_code * ec)552*58b9f456SAndroid Build Coastguard Worker void __copy(const path& from, const path& to, copy_options options,
553*58b9f456SAndroid Build Coastguard Worker error_code* ec) {
554*58b9f456SAndroid Build Coastguard Worker ErrorHandler<void> err("copy", ec, &from, &to);
555*58b9f456SAndroid Build Coastguard Worker
556*58b9f456SAndroid Build Coastguard Worker const bool sym_status = bool(
557*58b9f456SAndroid Build Coastguard Worker options & (copy_options::create_symlinks | copy_options::skip_symlinks));
558*58b9f456SAndroid Build Coastguard Worker
559*58b9f456SAndroid Build Coastguard Worker const bool sym_status2 = bool(options & copy_options::copy_symlinks);
560*58b9f456SAndroid Build Coastguard Worker
561*58b9f456SAndroid Build Coastguard Worker error_code m_ec1;
562*58b9f456SAndroid Build Coastguard Worker StatT f_st = {};
563*58b9f456SAndroid Build Coastguard Worker const file_status f = sym_status || sym_status2
564*58b9f456SAndroid Build Coastguard Worker ? detail::posix_lstat(from, f_st, &m_ec1)
565*58b9f456SAndroid Build Coastguard Worker : detail::posix_stat(from, f_st, &m_ec1);
566*58b9f456SAndroid Build Coastguard Worker if (m_ec1)
567*58b9f456SAndroid Build Coastguard Worker return err.report(m_ec1);
568*58b9f456SAndroid Build Coastguard Worker
569*58b9f456SAndroid Build Coastguard Worker StatT t_st = {};
570*58b9f456SAndroid Build Coastguard Worker const file_status t = sym_status ? detail::posix_lstat(to, t_st, &m_ec1)
571*58b9f456SAndroid Build Coastguard Worker : detail::posix_stat(to, t_st, &m_ec1);
572*58b9f456SAndroid Build Coastguard Worker
573*58b9f456SAndroid Build Coastguard Worker if (not status_known(t))
574*58b9f456SAndroid Build Coastguard Worker return err.report(m_ec1);
575*58b9f456SAndroid Build Coastguard Worker
576*58b9f456SAndroid Build Coastguard Worker if (!exists(f) || is_other(f) || is_other(t) ||
577*58b9f456SAndroid Build Coastguard Worker (is_directory(f) && is_regular_file(t)) ||
578*58b9f456SAndroid Build Coastguard Worker detail::stat_equivalent(f_st, t_st)) {
579*58b9f456SAndroid Build Coastguard Worker return err.report(errc::function_not_supported);
580*58b9f456SAndroid Build Coastguard Worker }
581*58b9f456SAndroid Build Coastguard Worker
582*58b9f456SAndroid Build Coastguard Worker if (ec)
583*58b9f456SAndroid Build Coastguard Worker ec->clear();
584*58b9f456SAndroid Build Coastguard Worker
585*58b9f456SAndroid Build Coastguard Worker if (is_symlink(f)) {
586*58b9f456SAndroid Build Coastguard Worker if (bool(copy_options::skip_symlinks & options)) {
587*58b9f456SAndroid Build Coastguard Worker // do nothing
588*58b9f456SAndroid Build Coastguard Worker } else if (not exists(t)) {
589*58b9f456SAndroid Build Coastguard Worker __copy_symlink(from, to, ec);
590*58b9f456SAndroid Build Coastguard Worker } else {
591*58b9f456SAndroid Build Coastguard Worker return err.report(errc::file_exists);
592*58b9f456SAndroid Build Coastguard Worker }
593*58b9f456SAndroid Build Coastguard Worker return;
594*58b9f456SAndroid Build Coastguard Worker } else if (is_regular_file(f)) {
595*58b9f456SAndroid Build Coastguard Worker if (bool(copy_options::directories_only & options)) {
596*58b9f456SAndroid Build Coastguard Worker // do nothing
597*58b9f456SAndroid Build Coastguard Worker } else if (bool(copy_options::create_symlinks & options)) {
598*58b9f456SAndroid Build Coastguard Worker __create_symlink(from, to, ec);
599*58b9f456SAndroid Build Coastguard Worker } else if (bool(copy_options::create_hard_links & options)) {
600*58b9f456SAndroid Build Coastguard Worker __create_hard_link(from, to, ec);
601*58b9f456SAndroid Build Coastguard Worker } else if (is_directory(t)) {
602*58b9f456SAndroid Build Coastguard Worker __copy_file(from, to / from.filename(), options, ec);
603*58b9f456SAndroid Build Coastguard Worker } else {
604*58b9f456SAndroid Build Coastguard Worker __copy_file(from, to, options, ec);
605*58b9f456SAndroid Build Coastguard Worker }
606*58b9f456SAndroid Build Coastguard Worker return;
607*58b9f456SAndroid Build Coastguard Worker } else if (is_directory(f) && bool(copy_options::create_symlinks & options)) {
608*58b9f456SAndroid Build Coastguard Worker return err.report(errc::is_a_directory);
609*58b9f456SAndroid Build Coastguard Worker } else if (is_directory(f) && (bool(copy_options::recursive & options) ||
610*58b9f456SAndroid Build Coastguard Worker copy_options::none == options)) {
611*58b9f456SAndroid Build Coastguard Worker
612*58b9f456SAndroid Build Coastguard Worker if (!exists(t)) {
613*58b9f456SAndroid Build Coastguard Worker // create directory to with attributes from 'from'.
614*58b9f456SAndroid Build Coastguard Worker __create_directory(to, from, ec);
615*58b9f456SAndroid Build Coastguard Worker if (ec && *ec) {
616*58b9f456SAndroid Build Coastguard Worker return;
617*58b9f456SAndroid Build Coastguard Worker }
618*58b9f456SAndroid Build Coastguard Worker }
619*58b9f456SAndroid Build Coastguard Worker directory_iterator it =
620*58b9f456SAndroid Build Coastguard Worker ec ? directory_iterator(from, *ec) : directory_iterator(from);
621*58b9f456SAndroid Build Coastguard Worker if (ec && *ec) {
622*58b9f456SAndroid Build Coastguard Worker return;
623*58b9f456SAndroid Build Coastguard Worker }
624*58b9f456SAndroid Build Coastguard Worker error_code m_ec2;
625*58b9f456SAndroid Build Coastguard Worker for (; it != directory_iterator(); it.increment(m_ec2)) {
626*58b9f456SAndroid Build Coastguard Worker if (m_ec2) {
627*58b9f456SAndroid Build Coastguard Worker return err.report(m_ec2);
628*58b9f456SAndroid Build Coastguard Worker }
629*58b9f456SAndroid Build Coastguard Worker __copy(it->path(), to / it->path().filename(),
630*58b9f456SAndroid Build Coastguard Worker options | copy_options::__in_recursive_copy, ec);
631*58b9f456SAndroid Build Coastguard Worker if (ec && *ec) {
632*58b9f456SAndroid Build Coastguard Worker return;
633*58b9f456SAndroid Build Coastguard Worker }
634*58b9f456SAndroid Build Coastguard Worker }
635*58b9f456SAndroid Build Coastguard Worker }
636*58b9f456SAndroid Build Coastguard Worker }
637*58b9f456SAndroid Build Coastguard Worker
638*58b9f456SAndroid Build Coastguard Worker namespace detail {
639*58b9f456SAndroid Build Coastguard Worker namespace {
640*58b9f456SAndroid Build Coastguard Worker
641*58b9f456SAndroid Build Coastguard Worker #ifdef _LIBCPP_USE_SENDFILE
copy_file_impl_sendfile(FileDescriptor & read_fd,FileDescriptor & write_fd,error_code & ec)642*58b9f456SAndroid Build Coastguard Worker bool copy_file_impl_sendfile(FileDescriptor& read_fd, FileDescriptor& write_fd,
643*58b9f456SAndroid Build Coastguard Worker error_code& ec) {
644*58b9f456SAndroid Build Coastguard Worker
645*58b9f456SAndroid Build Coastguard Worker size_t count = read_fd.get_stat().st_size;
646*58b9f456SAndroid Build Coastguard Worker do {
647*58b9f456SAndroid Build Coastguard Worker ssize_t res;
648*58b9f456SAndroid Build Coastguard Worker if ((res = ::sendfile(write_fd.fd, read_fd.fd, nullptr, count)) == -1) {
649*58b9f456SAndroid Build Coastguard Worker ec = capture_errno();
650*58b9f456SAndroid Build Coastguard Worker return false;
651*58b9f456SAndroid Build Coastguard Worker }
652*58b9f456SAndroid Build Coastguard Worker count -= res;
653*58b9f456SAndroid Build Coastguard Worker } while (count > 0);
654*58b9f456SAndroid Build Coastguard Worker
655*58b9f456SAndroid Build Coastguard Worker ec.clear();
656*58b9f456SAndroid Build Coastguard Worker
657*58b9f456SAndroid Build Coastguard Worker return true;
658*58b9f456SAndroid Build Coastguard Worker }
659*58b9f456SAndroid Build Coastguard Worker #elif defined(_LIBCPP_USE_COPYFILE)
660*58b9f456SAndroid Build Coastguard Worker bool copy_file_impl_copyfile(FileDescriptor& read_fd, FileDescriptor& write_fd,
661*58b9f456SAndroid Build Coastguard Worker error_code& ec) {
662*58b9f456SAndroid Build Coastguard Worker struct CopyFileState {
663*58b9f456SAndroid Build Coastguard Worker copyfile_state_t state;
664*58b9f456SAndroid Build Coastguard Worker CopyFileState() { state = copyfile_state_alloc(); }
665*58b9f456SAndroid Build Coastguard Worker ~CopyFileState() { copyfile_state_free(state); }
666*58b9f456SAndroid Build Coastguard Worker
667*58b9f456SAndroid Build Coastguard Worker private:
668*58b9f456SAndroid Build Coastguard Worker CopyFileState(CopyFileState const&) = delete;
669*58b9f456SAndroid Build Coastguard Worker CopyFileState& operator=(CopyFileState const&) = delete;
670*58b9f456SAndroid Build Coastguard Worker };
671*58b9f456SAndroid Build Coastguard Worker
672*58b9f456SAndroid Build Coastguard Worker CopyFileState cfs;
673*58b9f456SAndroid Build Coastguard Worker if (fcopyfile(read_fd.fd, write_fd.fd, cfs.state, COPYFILE_DATA) < 0) {
674*58b9f456SAndroid Build Coastguard Worker ec = capture_errno();
675*58b9f456SAndroid Build Coastguard Worker return false;
676*58b9f456SAndroid Build Coastguard Worker }
677*58b9f456SAndroid Build Coastguard Worker
678*58b9f456SAndroid Build Coastguard Worker ec.clear();
679*58b9f456SAndroid Build Coastguard Worker return true;
680*58b9f456SAndroid Build Coastguard Worker }
681*58b9f456SAndroid Build Coastguard Worker #endif
682*58b9f456SAndroid Build Coastguard Worker
683*58b9f456SAndroid Build Coastguard Worker // Note: This function isn't guarded by ifdef's even though it may be unused
684*58b9f456SAndroid Build Coastguard Worker // in order to assure it still compiles.
copy_file_impl_default(FileDescriptor & read_fd,FileDescriptor & write_fd,error_code & ec)685*58b9f456SAndroid Build Coastguard Worker __attribute__((unused)) bool copy_file_impl_default(FileDescriptor& read_fd,
686*58b9f456SAndroid Build Coastguard Worker FileDescriptor& write_fd,
687*58b9f456SAndroid Build Coastguard Worker error_code& ec) {
688*58b9f456SAndroid Build Coastguard Worker ifstream in;
689*58b9f456SAndroid Build Coastguard Worker in.__open(read_fd.fd, ios::binary);
690*58b9f456SAndroid Build Coastguard Worker if (!in.is_open()) {
691*58b9f456SAndroid Build Coastguard Worker // This assumes that __open didn't reset the error code.
692*58b9f456SAndroid Build Coastguard Worker ec = capture_errno();
693*58b9f456SAndroid Build Coastguard Worker return false;
694*58b9f456SAndroid Build Coastguard Worker }
695*58b9f456SAndroid Build Coastguard Worker ofstream out;
696*58b9f456SAndroid Build Coastguard Worker out.__open(write_fd.fd, ios::binary);
697*58b9f456SAndroid Build Coastguard Worker if (!out.is_open()) {
698*58b9f456SAndroid Build Coastguard Worker ec = capture_errno();
699*58b9f456SAndroid Build Coastguard Worker return false;
700*58b9f456SAndroid Build Coastguard Worker }
701*58b9f456SAndroid Build Coastguard Worker
702*58b9f456SAndroid Build Coastguard Worker if (in.good() && out.good()) {
703*58b9f456SAndroid Build Coastguard Worker using InIt = istreambuf_iterator<char>;
704*58b9f456SAndroid Build Coastguard Worker using OutIt = ostreambuf_iterator<char>;
705*58b9f456SAndroid Build Coastguard Worker InIt bin(in);
706*58b9f456SAndroid Build Coastguard Worker InIt ein;
707*58b9f456SAndroid Build Coastguard Worker OutIt bout(out);
708*58b9f456SAndroid Build Coastguard Worker copy(bin, ein, bout);
709*58b9f456SAndroid Build Coastguard Worker }
710*58b9f456SAndroid Build Coastguard Worker if (out.fail() || in.fail()) {
711*58b9f456SAndroid Build Coastguard Worker ec = make_error_code(errc::io_error);
712*58b9f456SAndroid Build Coastguard Worker return false;
713*58b9f456SAndroid Build Coastguard Worker }
714*58b9f456SAndroid Build Coastguard Worker
715*58b9f456SAndroid Build Coastguard Worker ec.clear();
716*58b9f456SAndroid Build Coastguard Worker return true;
717*58b9f456SAndroid Build Coastguard Worker }
718*58b9f456SAndroid Build Coastguard Worker
copy_file_impl(FileDescriptor & from,FileDescriptor & to,error_code & ec)719*58b9f456SAndroid Build Coastguard Worker bool copy_file_impl(FileDescriptor& from, FileDescriptor& to, error_code& ec) {
720*58b9f456SAndroid Build Coastguard Worker #if defined(_LIBCPP_USE_SENDFILE)
721*58b9f456SAndroid Build Coastguard Worker return copy_file_impl_sendfile(from, to, ec);
722*58b9f456SAndroid Build Coastguard Worker #elif defined(_LIBCPP_USE_COPYFILE)
723*58b9f456SAndroid Build Coastguard Worker return copy_file_impl_copyfile(from, to, ec);
724*58b9f456SAndroid Build Coastguard Worker #else
725*58b9f456SAndroid Build Coastguard Worker return copy_file_impl_default(from, to, ec);
726*58b9f456SAndroid Build Coastguard Worker #endif
727*58b9f456SAndroid Build Coastguard Worker }
728*58b9f456SAndroid Build Coastguard Worker
729*58b9f456SAndroid Build Coastguard Worker } // namespace
730*58b9f456SAndroid Build Coastguard Worker } // namespace detail
731*58b9f456SAndroid Build Coastguard Worker
__copy_file(const path & from,const path & to,copy_options options,error_code * ec)732*58b9f456SAndroid Build Coastguard Worker bool __copy_file(const path& from, const path& to, copy_options options,
733*58b9f456SAndroid Build Coastguard Worker error_code* ec) {
734*58b9f456SAndroid Build Coastguard Worker using detail::FileDescriptor;
735*58b9f456SAndroid Build Coastguard Worker ErrorHandler<bool> err("copy_file", ec, &to, &from);
736*58b9f456SAndroid Build Coastguard Worker
737*58b9f456SAndroid Build Coastguard Worker error_code m_ec;
738*58b9f456SAndroid Build Coastguard Worker FileDescriptor from_fd =
739*58b9f456SAndroid Build Coastguard Worker FileDescriptor::create_with_status(&from, m_ec, O_RDONLY | O_NONBLOCK);
740*58b9f456SAndroid Build Coastguard Worker if (m_ec)
741*58b9f456SAndroid Build Coastguard Worker return err.report(m_ec);
742*58b9f456SAndroid Build Coastguard Worker
743*58b9f456SAndroid Build Coastguard Worker auto from_st = from_fd.get_status();
744*58b9f456SAndroid Build Coastguard Worker StatT const& from_stat = from_fd.get_stat();
745*58b9f456SAndroid Build Coastguard Worker if (!is_regular_file(from_st)) {
746*58b9f456SAndroid Build Coastguard Worker if (not m_ec)
747*58b9f456SAndroid Build Coastguard Worker m_ec = make_error_code(errc::not_supported);
748*58b9f456SAndroid Build Coastguard Worker return err.report(m_ec);
749*58b9f456SAndroid Build Coastguard Worker }
750*58b9f456SAndroid Build Coastguard Worker
751*58b9f456SAndroid Build Coastguard Worker const bool skip_existing = bool(copy_options::skip_existing & options);
752*58b9f456SAndroid Build Coastguard Worker const bool update_existing = bool(copy_options::update_existing & options);
753*58b9f456SAndroid Build Coastguard Worker const bool overwrite_existing =
754*58b9f456SAndroid Build Coastguard Worker bool(copy_options::overwrite_existing & options);
755*58b9f456SAndroid Build Coastguard Worker
756*58b9f456SAndroid Build Coastguard Worker StatT to_stat_path;
757*58b9f456SAndroid Build Coastguard Worker file_status to_st = detail::posix_stat(to, to_stat_path, &m_ec);
758*58b9f456SAndroid Build Coastguard Worker if (!status_known(to_st))
759*58b9f456SAndroid Build Coastguard Worker return err.report(m_ec);
760*58b9f456SAndroid Build Coastguard Worker
761*58b9f456SAndroid Build Coastguard Worker const bool to_exists = exists(to_st);
762*58b9f456SAndroid Build Coastguard Worker if (to_exists && !is_regular_file(to_st))
763*58b9f456SAndroid Build Coastguard Worker return err.report(errc::not_supported);
764*58b9f456SAndroid Build Coastguard Worker
765*58b9f456SAndroid Build Coastguard Worker if (to_exists && detail::stat_equivalent(from_stat, to_stat_path))
766*58b9f456SAndroid Build Coastguard Worker return err.report(errc::file_exists);
767*58b9f456SAndroid Build Coastguard Worker
768*58b9f456SAndroid Build Coastguard Worker if (to_exists && skip_existing)
769*58b9f456SAndroid Build Coastguard Worker return false;
770*58b9f456SAndroid Build Coastguard Worker
771*58b9f456SAndroid Build Coastguard Worker bool ShouldCopy = [&]() {
772*58b9f456SAndroid Build Coastguard Worker if (to_exists && update_existing) {
773*58b9f456SAndroid Build Coastguard Worker auto from_time = detail::extract_mtime(from_stat);
774*58b9f456SAndroid Build Coastguard Worker auto to_time = detail::extract_mtime(to_stat_path);
775*58b9f456SAndroid Build Coastguard Worker if (from_time.tv_sec < to_time.tv_sec)
776*58b9f456SAndroid Build Coastguard Worker return false;
777*58b9f456SAndroid Build Coastguard Worker if (from_time.tv_sec == to_time.tv_sec &&
778*58b9f456SAndroid Build Coastguard Worker from_time.tv_nsec <= to_time.tv_nsec)
779*58b9f456SAndroid Build Coastguard Worker return false;
780*58b9f456SAndroid Build Coastguard Worker return true;
781*58b9f456SAndroid Build Coastguard Worker }
782*58b9f456SAndroid Build Coastguard Worker if (!to_exists || overwrite_existing)
783*58b9f456SAndroid Build Coastguard Worker return true;
784*58b9f456SAndroid Build Coastguard Worker return err.report(errc::file_exists);
785*58b9f456SAndroid Build Coastguard Worker }();
786*58b9f456SAndroid Build Coastguard Worker if (!ShouldCopy)
787*58b9f456SAndroid Build Coastguard Worker return false;
788*58b9f456SAndroid Build Coastguard Worker
789*58b9f456SAndroid Build Coastguard Worker // Don't truncate right away. We may not be opening the file we originally
790*58b9f456SAndroid Build Coastguard Worker // looked at; we'll check this later.
791*58b9f456SAndroid Build Coastguard Worker int to_open_flags = O_WRONLY;
792*58b9f456SAndroid Build Coastguard Worker if (!to_exists)
793*58b9f456SAndroid Build Coastguard Worker to_open_flags |= O_CREAT;
794*58b9f456SAndroid Build Coastguard Worker FileDescriptor to_fd = FileDescriptor::create_with_status(
795*58b9f456SAndroid Build Coastguard Worker &to, m_ec, to_open_flags, from_stat.st_mode);
796*58b9f456SAndroid Build Coastguard Worker if (m_ec)
797*58b9f456SAndroid Build Coastguard Worker return err.report(m_ec);
798*58b9f456SAndroid Build Coastguard Worker
799*58b9f456SAndroid Build Coastguard Worker if (to_exists) {
800*58b9f456SAndroid Build Coastguard Worker // Check that the file we initially stat'ed is equivalent to the one
801*58b9f456SAndroid Build Coastguard Worker // we opened.
802*58b9f456SAndroid Build Coastguard Worker // FIXME: report this better.
803*58b9f456SAndroid Build Coastguard Worker if (!detail::stat_equivalent(to_stat_path, to_fd.get_stat()))
804*58b9f456SAndroid Build Coastguard Worker return err.report(errc::bad_file_descriptor);
805*58b9f456SAndroid Build Coastguard Worker
806*58b9f456SAndroid Build Coastguard Worker // Set the permissions and truncate the file we opened.
807*58b9f456SAndroid Build Coastguard Worker if (detail::posix_fchmod(to_fd, from_stat, m_ec))
808*58b9f456SAndroid Build Coastguard Worker return err.report(m_ec);
809*58b9f456SAndroid Build Coastguard Worker if (detail::posix_ftruncate(to_fd, 0, m_ec))
810*58b9f456SAndroid Build Coastguard Worker return err.report(m_ec);
811*58b9f456SAndroid Build Coastguard Worker }
812*58b9f456SAndroid Build Coastguard Worker
813*58b9f456SAndroid Build Coastguard Worker if (!copy_file_impl(from_fd, to_fd, m_ec)) {
814*58b9f456SAndroid Build Coastguard Worker // FIXME: Remove the dest file if we failed, and it didn't exist previously.
815*58b9f456SAndroid Build Coastguard Worker return err.report(m_ec);
816*58b9f456SAndroid Build Coastguard Worker }
817*58b9f456SAndroid Build Coastguard Worker
818*58b9f456SAndroid Build Coastguard Worker return true;
819*58b9f456SAndroid Build Coastguard Worker }
820*58b9f456SAndroid Build Coastguard Worker
__copy_symlink(const path & existing_symlink,const path & new_symlink,error_code * ec)821*58b9f456SAndroid Build Coastguard Worker void __copy_symlink(const path& existing_symlink, const path& new_symlink,
822*58b9f456SAndroid Build Coastguard Worker error_code* ec) {
823*58b9f456SAndroid Build Coastguard Worker const path real_path(__read_symlink(existing_symlink, ec));
824*58b9f456SAndroid Build Coastguard Worker if (ec && *ec) {
825*58b9f456SAndroid Build Coastguard Worker return;
826*58b9f456SAndroid Build Coastguard Worker }
827*58b9f456SAndroid Build Coastguard Worker // NOTE: proposal says you should detect if you should call
828*58b9f456SAndroid Build Coastguard Worker // create_symlink or create_directory_symlink. I don't think this
829*58b9f456SAndroid Build Coastguard Worker // is needed with POSIX
830*58b9f456SAndroid Build Coastguard Worker __create_symlink(real_path, new_symlink, ec);
831*58b9f456SAndroid Build Coastguard Worker }
832*58b9f456SAndroid Build Coastguard Worker
__create_directories(const path & p,error_code * ec)833*58b9f456SAndroid Build Coastguard Worker bool __create_directories(const path& p, error_code* ec) {
834*58b9f456SAndroid Build Coastguard Worker ErrorHandler<bool> err("create_directories", ec, &p);
835*58b9f456SAndroid Build Coastguard Worker
836*58b9f456SAndroid Build Coastguard Worker error_code m_ec;
837*58b9f456SAndroid Build Coastguard Worker auto const st = detail::posix_stat(p, &m_ec);
838*58b9f456SAndroid Build Coastguard Worker if (!status_known(st))
839*58b9f456SAndroid Build Coastguard Worker return err.report(m_ec);
840*58b9f456SAndroid Build Coastguard Worker else if (is_directory(st))
841*58b9f456SAndroid Build Coastguard Worker return false;
842*58b9f456SAndroid Build Coastguard Worker else if (exists(st))
843*58b9f456SAndroid Build Coastguard Worker return err.report(errc::file_exists);
844*58b9f456SAndroid Build Coastguard Worker
845*58b9f456SAndroid Build Coastguard Worker const path parent = p.parent_path();
846*58b9f456SAndroid Build Coastguard Worker if (!parent.empty()) {
847*58b9f456SAndroid Build Coastguard Worker const file_status parent_st = status(parent, m_ec);
848*58b9f456SAndroid Build Coastguard Worker if (not status_known(parent_st))
849*58b9f456SAndroid Build Coastguard Worker return err.report(m_ec);
850*58b9f456SAndroid Build Coastguard Worker if (not exists(parent_st)) {
851*58b9f456SAndroid Build Coastguard Worker __create_directories(parent, ec);
852*58b9f456SAndroid Build Coastguard Worker if (ec && *ec) {
853*58b9f456SAndroid Build Coastguard Worker return false;
854*58b9f456SAndroid Build Coastguard Worker }
855*58b9f456SAndroid Build Coastguard Worker }
856*58b9f456SAndroid Build Coastguard Worker }
857*58b9f456SAndroid Build Coastguard Worker return __create_directory(p, ec);
858*58b9f456SAndroid Build Coastguard Worker }
859*58b9f456SAndroid Build Coastguard Worker
__create_directory(const path & p,error_code * ec)860*58b9f456SAndroid Build Coastguard Worker bool __create_directory(const path& p, error_code* ec) {
861*58b9f456SAndroid Build Coastguard Worker ErrorHandler<bool> err("create_directory", ec, &p);
862*58b9f456SAndroid Build Coastguard Worker
863*58b9f456SAndroid Build Coastguard Worker if (::mkdir(p.c_str(), static_cast<int>(perms::all)) == 0)
864*58b9f456SAndroid Build Coastguard Worker return true;
865*58b9f456SAndroid Build Coastguard Worker if (errno != EEXIST)
866*58b9f456SAndroid Build Coastguard Worker err.report(capture_errno());
867*58b9f456SAndroid Build Coastguard Worker return false;
868*58b9f456SAndroid Build Coastguard Worker }
869*58b9f456SAndroid Build Coastguard Worker
__create_directory(path const & p,path const & attributes,error_code * ec)870*58b9f456SAndroid Build Coastguard Worker bool __create_directory(path const& p, path const& attributes, error_code* ec) {
871*58b9f456SAndroid Build Coastguard Worker ErrorHandler<bool> err("create_directory", ec, &p, &attributes);
872*58b9f456SAndroid Build Coastguard Worker
873*58b9f456SAndroid Build Coastguard Worker StatT attr_stat;
874*58b9f456SAndroid Build Coastguard Worker error_code mec;
875*58b9f456SAndroid Build Coastguard Worker auto st = detail::posix_stat(attributes, attr_stat, &mec);
876*58b9f456SAndroid Build Coastguard Worker if (!status_known(st))
877*58b9f456SAndroid Build Coastguard Worker return err.report(mec);
878*58b9f456SAndroid Build Coastguard Worker if (!is_directory(st))
879*58b9f456SAndroid Build Coastguard Worker return err.report(errc::not_a_directory,
880*58b9f456SAndroid Build Coastguard Worker "the specified attribute path is invalid");
881*58b9f456SAndroid Build Coastguard Worker
882*58b9f456SAndroid Build Coastguard Worker if (::mkdir(p.c_str(), attr_stat.st_mode) == 0)
883*58b9f456SAndroid Build Coastguard Worker return true;
884*58b9f456SAndroid Build Coastguard Worker if (errno != EEXIST)
885*58b9f456SAndroid Build Coastguard Worker err.report(capture_errno());
886*58b9f456SAndroid Build Coastguard Worker return false;
887*58b9f456SAndroid Build Coastguard Worker }
888*58b9f456SAndroid Build Coastguard Worker
__create_directory_symlink(path const & from,path const & to,error_code * ec)889*58b9f456SAndroid Build Coastguard Worker void __create_directory_symlink(path const& from, path const& to,
890*58b9f456SAndroid Build Coastguard Worker error_code* ec) {
891*58b9f456SAndroid Build Coastguard Worker ErrorHandler<void> err("create_directory_symlink", ec, &from, &to);
892*58b9f456SAndroid Build Coastguard Worker if (::symlink(from.c_str(), to.c_str()) != 0)
893*58b9f456SAndroid Build Coastguard Worker return err.report(capture_errno());
894*58b9f456SAndroid Build Coastguard Worker }
895*58b9f456SAndroid Build Coastguard Worker
__create_hard_link(const path & from,const path & to,error_code * ec)896*58b9f456SAndroid Build Coastguard Worker void __create_hard_link(const path& from, const path& to, error_code* ec) {
897*58b9f456SAndroid Build Coastguard Worker ErrorHandler<void> err("create_hard_link", ec, &from, &to);
898*58b9f456SAndroid Build Coastguard Worker if (::link(from.c_str(), to.c_str()) == -1)
899*58b9f456SAndroid Build Coastguard Worker return err.report(capture_errno());
900*58b9f456SAndroid Build Coastguard Worker }
901*58b9f456SAndroid Build Coastguard Worker
__create_symlink(path const & from,path const & to,error_code * ec)902*58b9f456SAndroid Build Coastguard Worker void __create_symlink(path const& from, path const& to, error_code* ec) {
903*58b9f456SAndroid Build Coastguard Worker ErrorHandler<void> err("create_symlink", ec, &from, &to);
904*58b9f456SAndroid Build Coastguard Worker if (::symlink(from.c_str(), to.c_str()) == -1)
905*58b9f456SAndroid Build Coastguard Worker return err.report(capture_errno());
906*58b9f456SAndroid Build Coastguard Worker }
907*58b9f456SAndroid Build Coastguard Worker
__current_path(error_code * ec)908*58b9f456SAndroid Build Coastguard Worker path __current_path(error_code* ec) {
909*58b9f456SAndroid Build Coastguard Worker ErrorHandler<path> err("current_path", ec);
910*58b9f456SAndroid Build Coastguard Worker
911*58b9f456SAndroid Build Coastguard Worker auto size = ::pathconf(".", _PC_PATH_MAX);
912*58b9f456SAndroid Build Coastguard Worker _LIBCPP_ASSERT(size >= 0, "pathconf returned a 0 as max size");
913*58b9f456SAndroid Build Coastguard Worker
914*58b9f456SAndroid Build Coastguard Worker auto buff = unique_ptr<char[]>(new char[size + 1]);
915*58b9f456SAndroid Build Coastguard Worker char* ret;
916*58b9f456SAndroid Build Coastguard Worker if ((ret = ::getcwd(buff.get(), static_cast<size_t>(size))) == nullptr)
917*58b9f456SAndroid Build Coastguard Worker return err.report(capture_errno(), "call to getcwd failed");
918*58b9f456SAndroid Build Coastguard Worker
919*58b9f456SAndroid Build Coastguard Worker return {buff.get()};
920*58b9f456SAndroid Build Coastguard Worker }
921*58b9f456SAndroid Build Coastguard Worker
__current_path(const path & p,error_code * ec)922*58b9f456SAndroid Build Coastguard Worker void __current_path(const path& p, error_code* ec) {
923*58b9f456SAndroid Build Coastguard Worker ErrorHandler<void> err("current_path", ec, &p);
924*58b9f456SAndroid Build Coastguard Worker if (::chdir(p.c_str()) == -1)
925*58b9f456SAndroid Build Coastguard Worker err.report(capture_errno());
926*58b9f456SAndroid Build Coastguard Worker }
927*58b9f456SAndroid Build Coastguard Worker
__equivalent(const path & p1,const path & p2,error_code * ec)928*58b9f456SAndroid Build Coastguard Worker bool __equivalent(const path& p1, const path& p2, error_code* ec) {
929*58b9f456SAndroid Build Coastguard Worker ErrorHandler<bool> err("equivalent", ec, &p1, &p2);
930*58b9f456SAndroid Build Coastguard Worker
931*58b9f456SAndroid Build Coastguard Worker error_code ec1, ec2;
932*58b9f456SAndroid Build Coastguard Worker StatT st1 = {}, st2 = {};
933*58b9f456SAndroid Build Coastguard Worker auto s1 = detail::posix_stat(p1.native(), st1, &ec1);
934*58b9f456SAndroid Build Coastguard Worker if (!exists(s1))
935*58b9f456SAndroid Build Coastguard Worker return err.report(errc::not_supported);
936*58b9f456SAndroid Build Coastguard Worker auto s2 = detail::posix_stat(p2.native(), st2, &ec2);
937*58b9f456SAndroid Build Coastguard Worker if (!exists(s2))
938*58b9f456SAndroid Build Coastguard Worker return err.report(errc::not_supported);
939*58b9f456SAndroid Build Coastguard Worker
940*58b9f456SAndroid Build Coastguard Worker return detail::stat_equivalent(st1, st2);
941*58b9f456SAndroid Build Coastguard Worker }
942*58b9f456SAndroid Build Coastguard Worker
__file_size(const path & p,error_code * ec)943*58b9f456SAndroid Build Coastguard Worker uintmax_t __file_size(const path& p, error_code* ec) {
944*58b9f456SAndroid Build Coastguard Worker ErrorHandler<uintmax_t> err("file_size", ec, &p);
945*58b9f456SAndroid Build Coastguard Worker
946*58b9f456SAndroid Build Coastguard Worker error_code m_ec;
947*58b9f456SAndroid Build Coastguard Worker StatT st;
948*58b9f456SAndroid Build Coastguard Worker file_status fst = detail::posix_stat(p, st, &m_ec);
949*58b9f456SAndroid Build Coastguard Worker if (!exists(fst) || !is_regular_file(fst)) {
950*58b9f456SAndroid Build Coastguard Worker errc error_kind =
951*58b9f456SAndroid Build Coastguard Worker is_directory(fst) ? errc::is_a_directory : errc::not_supported;
952*58b9f456SAndroid Build Coastguard Worker if (!m_ec)
953*58b9f456SAndroid Build Coastguard Worker m_ec = make_error_code(error_kind);
954*58b9f456SAndroid Build Coastguard Worker return err.report(m_ec);
955*58b9f456SAndroid Build Coastguard Worker }
956*58b9f456SAndroid Build Coastguard Worker // is_regular_file(p) == true
957*58b9f456SAndroid Build Coastguard Worker return static_cast<uintmax_t>(st.st_size);
958*58b9f456SAndroid Build Coastguard Worker }
959*58b9f456SAndroid Build Coastguard Worker
__hard_link_count(const path & p,error_code * ec)960*58b9f456SAndroid Build Coastguard Worker uintmax_t __hard_link_count(const path& p, error_code* ec) {
961*58b9f456SAndroid Build Coastguard Worker ErrorHandler<uintmax_t> err("hard_link_count", ec, &p);
962*58b9f456SAndroid Build Coastguard Worker
963*58b9f456SAndroid Build Coastguard Worker error_code m_ec;
964*58b9f456SAndroid Build Coastguard Worker StatT st;
965*58b9f456SAndroid Build Coastguard Worker detail::posix_stat(p, st, &m_ec);
966*58b9f456SAndroid Build Coastguard Worker if (m_ec)
967*58b9f456SAndroid Build Coastguard Worker return err.report(m_ec);
968*58b9f456SAndroid Build Coastguard Worker return static_cast<uintmax_t>(st.st_nlink);
969*58b9f456SAndroid Build Coastguard Worker }
970*58b9f456SAndroid Build Coastguard Worker
__fs_is_empty(const path & p,error_code * ec)971*58b9f456SAndroid Build Coastguard Worker bool __fs_is_empty(const path& p, error_code* ec) {
972*58b9f456SAndroid Build Coastguard Worker ErrorHandler<bool> err("is_empty", ec, &p);
973*58b9f456SAndroid Build Coastguard Worker
974*58b9f456SAndroid Build Coastguard Worker error_code m_ec;
975*58b9f456SAndroid Build Coastguard Worker StatT pst;
976*58b9f456SAndroid Build Coastguard Worker auto st = detail::posix_stat(p, pst, &m_ec);
977*58b9f456SAndroid Build Coastguard Worker if (m_ec)
978*58b9f456SAndroid Build Coastguard Worker return err.report(m_ec);
979*58b9f456SAndroid Build Coastguard Worker else if (!is_directory(st) && !is_regular_file(st))
980*58b9f456SAndroid Build Coastguard Worker return err.report(errc::not_supported);
981*58b9f456SAndroid Build Coastguard Worker else if (is_directory(st)) {
982*58b9f456SAndroid Build Coastguard Worker auto it = ec ? directory_iterator(p, *ec) : directory_iterator(p);
983*58b9f456SAndroid Build Coastguard Worker if (ec && *ec)
984*58b9f456SAndroid Build Coastguard Worker return false;
985*58b9f456SAndroid Build Coastguard Worker return it == directory_iterator{};
986*58b9f456SAndroid Build Coastguard Worker } else if (is_regular_file(st))
987*58b9f456SAndroid Build Coastguard Worker return static_cast<uintmax_t>(pst.st_size) == 0;
988*58b9f456SAndroid Build Coastguard Worker
989*58b9f456SAndroid Build Coastguard Worker _LIBCPP_UNREACHABLE();
990*58b9f456SAndroid Build Coastguard Worker }
991*58b9f456SAndroid Build Coastguard Worker
__extract_last_write_time(const path & p,const StatT & st,error_code * ec)992*58b9f456SAndroid Build Coastguard Worker static file_time_type __extract_last_write_time(const path& p, const StatT& st,
993*58b9f456SAndroid Build Coastguard Worker error_code* ec) {
994*58b9f456SAndroid Build Coastguard Worker using detail::fs_time;
995*58b9f456SAndroid Build Coastguard Worker ErrorHandler<file_time_type> err("last_write_time", ec, &p);
996*58b9f456SAndroid Build Coastguard Worker
997*58b9f456SAndroid Build Coastguard Worker auto ts = detail::extract_mtime(st);
998*58b9f456SAndroid Build Coastguard Worker if (!fs_time::is_representable(ts))
999*58b9f456SAndroid Build Coastguard Worker return err.report(errc::value_too_large);
1000*58b9f456SAndroid Build Coastguard Worker
1001*58b9f456SAndroid Build Coastguard Worker return fs_time::convert_from_timespec(ts);
1002*58b9f456SAndroid Build Coastguard Worker }
1003*58b9f456SAndroid Build Coastguard Worker
__last_write_time(const path & p,error_code * ec)1004*58b9f456SAndroid Build Coastguard Worker file_time_type __last_write_time(const path& p, error_code* ec) {
1005*58b9f456SAndroid Build Coastguard Worker using namespace chrono;
1006*58b9f456SAndroid Build Coastguard Worker ErrorHandler<file_time_type> err("last_write_time", ec, &p);
1007*58b9f456SAndroid Build Coastguard Worker
1008*58b9f456SAndroid Build Coastguard Worker error_code m_ec;
1009*58b9f456SAndroid Build Coastguard Worker StatT st;
1010*58b9f456SAndroid Build Coastguard Worker detail::posix_stat(p, st, &m_ec);
1011*58b9f456SAndroid Build Coastguard Worker if (m_ec)
1012*58b9f456SAndroid Build Coastguard Worker return err.report(m_ec);
1013*58b9f456SAndroid Build Coastguard Worker return __extract_last_write_time(p, st, ec);
1014*58b9f456SAndroid Build Coastguard Worker }
1015*58b9f456SAndroid Build Coastguard Worker
__last_write_time(const path & p,file_time_type new_time,error_code * ec)1016*58b9f456SAndroid Build Coastguard Worker void __last_write_time(const path& p, file_time_type new_time, error_code* ec) {
1017*58b9f456SAndroid Build Coastguard Worker using detail::fs_time;
1018*58b9f456SAndroid Build Coastguard Worker ErrorHandler<void> err("last_write_time", ec, &p);
1019*58b9f456SAndroid Build Coastguard Worker
1020*58b9f456SAndroid Build Coastguard Worker error_code m_ec;
1021*58b9f456SAndroid Build Coastguard Worker array<TimeSpec, 2> tbuf;
1022*58b9f456SAndroid Build Coastguard Worker #if !defined(_LIBCPP_USE_UTIMENSAT)
1023*58b9f456SAndroid Build Coastguard Worker // This implementation has a race condition between determining the
1024*58b9f456SAndroid Build Coastguard Worker // last access time and attempting to set it to the same value using
1025*58b9f456SAndroid Build Coastguard Worker // ::utimes
1026*58b9f456SAndroid Build Coastguard Worker StatT st;
1027*58b9f456SAndroid Build Coastguard Worker file_status fst = detail::posix_stat(p, st, &m_ec);
1028*58b9f456SAndroid Build Coastguard Worker if (m_ec)
1029*58b9f456SAndroid Build Coastguard Worker return err.report(m_ec);
1030*58b9f456SAndroid Build Coastguard Worker tbuf[0] = detail::extract_atime(st);
1031*58b9f456SAndroid Build Coastguard Worker #else
1032*58b9f456SAndroid Build Coastguard Worker tbuf[0].tv_sec = 0;
1033*58b9f456SAndroid Build Coastguard Worker tbuf[0].tv_nsec = UTIME_OMIT;
1034*58b9f456SAndroid Build Coastguard Worker #endif
1035*58b9f456SAndroid Build Coastguard Worker if (!fs_time::convert_to_timespec(tbuf[1], new_time))
1036*58b9f456SAndroid Build Coastguard Worker return err.report(errc::value_too_large);
1037*58b9f456SAndroid Build Coastguard Worker
1038*58b9f456SAndroid Build Coastguard Worker detail::set_file_times(p, tbuf, m_ec);
1039*58b9f456SAndroid Build Coastguard Worker if (m_ec)
1040*58b9f456SAndroid Build Coastguard Worker return err.report(m_ec);
1041*58b9f456SAndroid Build Coastguard Worker }
1042*58b9f456SAndroid Build Coastguard Worker
__permissions(const path & p,perms prms,perm_options opts,error_code * ec)1043*58b9f456SAndroid Build Coastguard Worker void __permissions(const path& p, perms prms, perm_options opts,
1044*58b9f456SAndroid Build Coastguard Worker error_code* ec) {
1045*58b9f456SAndroid Build Coastguard Worker ErrorHandler<void> err("permissions", ec, &p);
1046*58b9f456SAndroid Build Coastguard Worker
1047*58b9f456SAndroid Build Coastguard Worker auto has_opt = [&](perm_options o) { return bool(o & opts); };
1048*58b9f456SAndroid Build Coastguard Worker const bool resolve_symlinks = !has_opt(perm_options::nofollow);
1049*58b9f456SAndroid Build Coastguard Worker const bool add_perms = has_opt(perm_options::add);
1050*58b9f456SAndroid Build Coastguard Worker const bool remove_perms = has_opt(perm_options::remove);
1051*58b9f456SAndroid Build Coastguard Worker _LIBCPP_ASSERT(
1052*58b9f456SAndroid Build Coastguard Worker (add_perms + remove_perms + has_opt(perm_options::replace)) == 1,
1053*58b9f456SAndroid Build Coastguard Worker "One and only one of the perm_options constants replace, add, or remove "
1054*58b9f456SAndroid Build Coastguard Worker "is present in opts");
1055*58b9f456SAndroid Build Coastguard Worker
1056*58b9f456SAndroid Build Coastguard Worker bool set_sym_perms = false;
1057*58b9f456SAndroid Build Coastguard Worker prms &= perms::mask;
1058*58b9f456SAndroid Build Coastguard Worker if (!resolve_symlinks || (add_perms || remove_perms)) {
1059*58b9f456SAndroid Build Coastguard Worker error_code m_ec;
1060*58b9f456SAndroid Build Coastguard Worker file_status st = resolve_symlinks ? detail::posix_stat(p, &m_ec)
1061*58b9f456SAndroid Build Coastguard Worker : detail::posix_lstat(p, &m_ec);
1062*58b9f456SAndroid Build Coastguard Worker set_sym_perms = is_symlink(st);
1063*58b9f456SAndroid Build Coastguard Worker if (m_ec)
1064*58b9f456SAndroid Build Coastguard Worker return err.report(m_ec);
1065*58b9f456SAndroid Build Coastguard Worker _LIBCPP_ASSERT(st.permissions() != perms::unknown,
1066*58b9f456SAndroid Build Coastguard Worker "Permissions unexpectedly unknown");
1067*58b9f456SAndroid Build Coastguard Worker if (add_perms)
1068*58b9f456SAndroid Build Coastguard Worker prms |= st.permissions();
1069*58b9f456SAndroid Build Coastguard Worker else if (remove_perms)
1070*58b9f456SAndroid Build Coastguard Worker prms = st.permissions() & ~prms;
1071*58b9f456SAndroid Build Coastguard Worker }
1072*58b9f456SAndroid Build Coastguard Worker const auto real_perms = detail::posix_convert_perms(prms);
1073*58b9f456SAndroid Build Coastguard Worker
1074*58b9f456SAndroid Build Coastguard Worker #if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD)
1075*58b9f456SAndroid Build Coastguard Worker const int flags = set_sym_perms ? AT_SYMLINK_NOFOLLOW : 0;
1076*58b9f456SAndroid Build Coastguard Worker if (::fchmodat(AT_FDCWD, p.c_str(), real_perms, flags) == -1) {
1077*58b9f456SAndroid Build Coastguard Worker return err.report(capture_errno());
1078*58b9f456SAndroid Build Coastguard Worker }
1079*58b9f456SAndroid Build Coastguard Worker #else
1080*58b9f456SAndroid Build Coastguard Worker if (set_sym_perms)
1081*58b9f456SAndroid Build Coastguard Worker return err.report(errc::operation_not_supported);
1082*58b9f456SAndroid Build Coastguard Worker if (::chmod(p.c_str(), real_perms) == -1) {
1083*58b9f456SAndroid Build Coastguard Worker return err.report(capture_errno());
1084*58b9f456SAndroid Build Coastguard Worker }
1085*58b9f456SAndroid Build Coastguard Worker #endif
1086*58b9f456SAndroid Build Coastguard Worker }
1087*58b9f456SAndroid Build Coastguard Worker
__read_symlink(const path & p,error_code * ec)1088*58b9f456SAndroid Build Coastguard Worker path __read_symlink(const path& p, error_code* ec) {
1089*58b9f456SAndroid Build Coastguard Worker ErrorHandler<path> err("read_symlink", ec, &p);
1090*58b9f456SAndroid Build Coastguard Worker
1091*58b9f456SAndroid Build Coastguard Worker char buff[PATH_MAX + 1];
1092*58b9f456SAndroid Build Coastguard Worker error_code m_ec;
1093*58b9f456SAndroid Build Coastguard Worker ::ssize_t ret;
1094*58b9f456SAndroid Build Coastguard Worker if ((ret = ::readlink(p.c_str(), buff, PATH_MAX)) == -1) {
1095*58b9f456SAndroid Build Coastguard Worker return err.report(capture_errno());
1096*58b9f456SAndroid Build Coastguard Worker }
1097*58b9f456SAndroid Build Coastguard Worker _LIBCPP_ASSERT(ret <= PATH_MAX, "TODO");
1098*58b9f456SAndroid Build Coastguard Worker _LIBCPP_ASSERT(ret > 0, "TODO");
1099*58b9f456SAndroid Build Coastguard Worker buff[ret] = 0;
1100*58b9f456SAndroid Build Coastguard Worker return {buff};
1101*58b9f456SAndroid Build Coastguard Worker }
1102*58b9f456SAndroid Build Coastguard Worker
__remove(const path & p,error_code * ec)1103*58b9f456SAndroid Build Coastguard Worker bool __remove(const path& p, error_code* ec) {
1104*58b9f456SAndroid Build Coastguard Worker ErrorHandler<bool> err("remove", ec, &p);
1105*58b9f456SAndroid Build Coastguard Worker if (::remove(p.c_str()) == -1) {
1106*58b9f456SAndroid Build Coastguard Worker if (errno != ENOENT)
1107*58b9f456SAndroid Build Coastguard Worker err.report(capture_errno());
1108*58b9f456SAndroid Build Coastguard Worker return false;
1109*58b9f456SAndroid Build Coastguard Worker }
1110*58b9f456SAndroid Build Coastguard Worker return true;
1111*58b9f456SAndroid Build Coastguard Worker }
1112*58b9f456SAndroid Build Coastguard Worker
1113*58b9f456SAndroid Build Coastguard Worker namespace {
1114*58b9f456SAndroid Build Coastguard Worker
remove_all_impl(path const & p,error_code & ec)1115*58b9f456SAndroid Build Coastguard Worker uintmax_t remove_all_impl(path const& p, error_code& ec) {
1116*58b9f456SAndroid Build Coastguard Worker const auto npos = static_cast<uintmax_t>(-1);
1117*58b9f456SAndroid Build Coastguard Worker const file_status st = __symlink_status(p, &ec);
1118*58b9f456SAndroid Build Coastguard Worker if (ec)
1119*58b9f456SAndroid Build Coastguard Worker return npos;
1120*58b9f456SAndroid Build Coastguard Worker uintmax_t count = 1;
1121*58b9f456SAndroid Build Coastguard Worker if (is_directory(st)) {
1122*58b9f456SAndroid Build Coastguard Worker for (directory_iterator it(p, ec); !ec && it != directory_iterator();
1123*58b9f456SAndroid Build Coastguard Worker it.increment(ec)) {
1124*58b9f456SAndroid Build Coastguard Worker auto other_count = remove_all_impl(it->path(), ec);
1125*58b9f456SAndroid Build Coastguard Worker if (ec)
1126*58b9f456SAndroid Build Coastguard Worker return npos;
1127*58b9f456SAndroid Build Coastguard Worker count += other_count;
1128*58b9f456SAndroid Build Coastguard Worker }
1129*58b9f456SAndroid Build Coastguard Worker if (ec)
1130*58b9f456SAndroid Build Coastguard Worker return npos;
1131*58b9f456SAndroid Build Coastguard Worker }
1132*58b9f456SAndroid Build Coastguard Worker if (!__remove(p, &ec))
1133*58b9f456SAndroid Build Coastguard Worker return npos;
1134*58b9f456SAndroid Build Coastguard Worker return count;
1135*58b9f456SAndroid Build Coastguard Worker }
1136*58b9f456SAndroid Build Coastguard Worker
1137*58b9f456SAndroid Build Coastguard Worker } // end namespace
1138*58b9f456SAndroid Build Coastguard Worker
__remove_all(const path & p,error_code * ec)1139*58b9f456SAndroid Build Coastguard Worker uintmax_t __remove_all(const path& p, error_code* ec) {
1140*58b9f456SAndroid Build Coastguard Worker ErrorHandler<uintmax_t> err("remove_all", ec, &p);
1141*58b9f456SAndroid Build Coastguard Worker
1142*58b9f456SAndroid Build Coastguard Worker error_code mec;
1143*58b9f456SAndroid Build Coastguard Worker auto count = remove_all_impl(p, mec);
1144*58b9f456SAndroid Build Coastguard Worker if (mec) {
1145*58b9f456SAndroid Build Coastguard Worker if (mec == errc::no_such_file_or_directory)
1146*58b9f456SAndroid Build Coastguard Worker return 0;
1147*58b9f456SAndroid Build Coastguard Worker return err.report(mec);
1148*58b9f456SAndroid Build Coastguard Worker }
1149*58b9f456SAndroid Build Coastguard Worker return count;
1150*58b9f456SAndroid Build Coastguard Worker }
1151*58b9f456SAndroid Build Coastguard Worker
__rename(const path & from,const path & to,error_code * ec)1152*58b9f456SAndroid Build Coastguard Worker void __rename(const path& from, const path& to, error_code* ec) {
1153*58b9f456SAndroid Build Coastguard Worker ErrorHandler<void> err("rename", ec, &from, &to);
1154*58b9f456SAndroid Build Coastguard Worker if (::rename(from.c_str(), to.c_str()) == -1)
1155*58b9f456SAndroid Build Coastguard Worker err.report(capture_errno());
1156*58b9f456SAndroid Build Coastguard Worker }
1157*58b9f456SAndroid Build Coastguard Worker
__resize_file(const path & p,uintmax_t size,error_code * ec)1158*58b9f456SAndroid Build Coastguard Worker void __resize_file(const path& p, uintmax_t size, error_code* ec) {
1159*58b9f456SAndroid Build Coastguard Worker ErrorHandler<void> err("resize_file", ec, &p);
1160*58b9f456SAndroid Build Coastguard Worker if (::truncate(p.c_str(), static_cast< ::off_t>(size)) == -1)
1161*58b9f456SAndroid Build Coastguard Worker return err.report(capture_errno());
1162*58b9f456SAndroid Build Coastguard Worker }
1163*58b9f456SAndroid Build Coastguard Worker
__space(const path & p,error_code * ec)1164*58b9f456SAndroid Build Coastguard Worker space_info __space(const path& p, error_code* ec) {
1165*58b9f456SAndroid Build Coastguard Worker ErrorHandler<void> err("space", ec, &p);
1166*58b9f456SAndroid Build Coastguard Worker space_info si;
1167*58b9f456SAndroid Build Coastguard Worker struct statvfs m_svfs = {};
1168*58b9f456SAndroid Build Coastguard Worker if (::statvfs(p.c_str(), &m_svfs) == -1) {
1169*58b9f456SAndroid Build Coastguard Worker err.report(capture_errno());
1170*58b9f456SAndroid Build Coastguard Worker si.capacity = si.free = si.available = static_cast<uintmax_t>(-1);
1171*58b9f456SAndroid Build Coastguard Worker return si;
1172*58b9f456SAndroid Build Coastguard Worker }
1173*58b9f456SAndroid Build Coastguard Worker // Multiply with overflow checking.
1174*58b9f456SAndroid Build Coastguard Worker auto do_mult = [&](uintmax_t& out, uintmax_t other) {
1175*58b9f456SAndroid Build Coastguard Worker out = other * m_svfs.f_frsize;
1176*58b9f456SAndroid Build Coastguard Worker if (other == 0 || out / other != m_svfs.f_frsize)
1177*58b9f456SAndroid Build Coastguard Worker out = static_cast<uintmax_t>(-1);
1178*58b9f456SAndroid Build Coastguard Worker };
1179*58b9f456SAndroid Build Coastguard Worker do_mult(si.capacity, m_svfs.f_blocks);
1180*58b9f456SAndroid Build Coastguard Worker do_mult(si.free, m_svfs.f_bfree);
1181*58b9f456SAndroid Build Coastguard Worker do_mult(si.available, m_svfs.f_bavail);
1182*58b9f456SAndroid Build Coastguard Worker return si;
1183*58b9f456SAndroid Build Coastguard Worker }
1184*58b9f456SAndroid Build Coastguard Worker
__status(const path & p,error_code * ec)1185*58b9f456SAndroid Build Coastguard Worker file_status __status(const path& p, error_code* ec) {
1186*58b9f456SAndroid Build Coastguard Worker return detail::posix_stat(p, ec);
1187*58b9f456SAndroid Build Coastguard Worker }
1188*58b9f456SAndroid Build Coastguard Worker
__symlink_status(const path & p,error_code * ec)1189*58b9f456SAndroid Build Coastguard Worker file_status __symlink_status(const path& p, error_code* ec) {
1190*58b9f456SAndroid Build Coastguard Worker return detail::posix_lstat(p, ec);
1191*58b9f456SAndroid Build Coastguard Worker }
1192*58b9f456SAndroid Build Coastguard Worker
__temp_directory_path(error_code * ec)1193*58b9f456SAndroid Build Coastguard Worker path __temp_directory_path(error_code* ec) {
1194*58b9f456SAndroid Build Coastguard Worker ErrorHandler<path> err("temp_directory_path", ec);
1195*58b9f456SAndroid Build Coastguard Worker
1196*58b9f456SAndroid Build Coastguard Worker const char* env_paths[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"};
1197*58b9f456SAndroid Build Coastguard Worker const char* ret = nullptr;
1198*58b9f456SAndroid Build Coastguard Worker
1199*58b9f456SAndroid Build Coastguard Worker for (auto& ep : env_paths)
1200*58b9f456SAndroid Build Coastguard Worker if ((ret = getenv(ep)))
1201*58b9f456SAndroid Build Coastguard Worker break;
1202*58b9f456SAndroid Build Coastguard Worker if (ret == nullptr)
1203*58b9f456SAndroid Build Coastguard Worker ret = "/tmp";
1204*58b9f456SAndroid Build Coastguard Worker
1205*58b9f456SAndroid Build Coastguard Worker path p(ret);
1206*58b9f456SAndroid Build Coastguard Worker error_code m_ec;
1207*58b9f456SAndroid Build Coastguard Worker file_status st = detail::posix_stat(p, &m_ec);
1208*58b9f456SAndroid Build Coastguard Worker if (!status_known(st))
1209*58b9f456SAndroid Build Coastguard Worker return err.report(m_ec, "cannot access path \"%s\"", p);
1210*58b9f456SAndroid Build Coastguard Worker
1211*58b9f456SAndroid Build Coastguard Worker if (!exists(st) || !is_directory(st))
1212*58b9f456SAndroid Build Coastguard Worker return err.report(errc::not_a_directory, "path \"%s\" is not a directory",
1213*58b9f456SAndroid Build Coastguard Worker p);
1214*58b9f456SAndroid Build Coastguard Worker
1215*58b9f456SAndroid Build Coastguard Worker return p;
1216*58b9f456SAndroid Build Coastguard Worker }
1217*58b9f456SAndroid Build Coastguard Worker
__weakly_canonical(const path & p,error_code * ec)1218*58b9f456SAndroid Build Coastguard Worker path __weakly_canonical(const path& p, error_code* ec) {
1219*58b9f456SAndroid Build Coastguard Worker ErrorHandler<path> err("weakly_canonical", ec, &p);
1220*58b9f456SAndroid Build Coastguard Worker
1221*58b9f456SAndroid Build Coastguard Worker if (p.empty())
1222*58b9f456SAndroid Build Coastguard Worker return __canonical("", ec);
1223*58b9f456SAndroid Build Coastguard Worker
1224*58b9f456SAndroid Build Coastguard Worker path result;
1225*58b9f456SAndroid Build Coastguard Worker path tmp;
1226*58b9f456SAndroid Build Coastguard Worker tmp.__reserve(p.native().size());
1227*58b9f456SAndroid Build Coastguard Worker auto PP = PathParser::CreateEnd(p.native());
1228*58b9f456SAndroid Build Coastguard Worker --PP;
1229*58b9f456SAndroid Build Coastguard Worker vector<string_view_t> DNEParts;
1230*58b9f456SAndroid Build Coastguard Worker
1231*58b9f456SAndroid Build Coastguard Worker while (PP.State != PathParser::PS_BeforeBegin) {
1232*58b9f456SAndroid Build Coastguard Worker tmp.assign(createView(p.native().data(), &PP.RawEntry.back()));
1233*58b9f456SAndroid Build Coastguard Worker error_code m_ec;
1234*58b9f456SAndroid Build Coastguard Worker file_status st = __status(tmp, &m_ec);
1235*58b9f456SAndroid Build Coastguard Worker if (!status_known(st)) {
1236*58b9f456SAndroid Build Coastguard Worker return err.report(m_ec);
1237*58b9f456SAndroid Build Coastguard Worker } else if (exists(st)) {
1238*58b9f456SAndroid Build Coastguard Worker result = __canonical(tmp, ec);
1239*58b9f456SAndroid Build Coastguard Worker break;
1240*58b9f456SAndroid Build Coastguard Worker }
1241*58b9f456SAndroid Build Coastguard Worker DNEParts.push_back(*PP);
1242*58b9f456SAndroid Build Coastguard Worker --PP;
1243*58b9f456SAndroid Build Coastguard Worker }
1244*58b9f456SAndroid Build Coastguard Worker if (PP.State == PathParser::PS_BeforeBegin)
1245*58b9f456SAndroid Build Coastguard Worker result = __canonical("", ec);
1246*58b9f456SAndroid Build Coastguard Worker if (ec)
1247*58b9f456SAndroid Build Coastguard Worker ec->clear();
1248*58b9f456SAndroid Build Coastguard Worker if (DNEParts.empty())
1249*58b9f456SAndroid Build Coastguard Worker return result;
1250*58b9f456SAndroid Build Coastguard Worker for (auto It = DNEParts.rbegin(); It != DNEParts.rend(); ++It)
1251*58b9f456SAndroid Build Coastguard Worker result /= *It;
1252*58b9f456SAndroid Build Coastguard Worker return result.lexically_normal();
1253*58b9f456SAndroid Build Coastguard Worker }
1254*58b9f456SAndroid Build Coastguard Worker
1255*58b9f456SAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
1256*58b9f456SAndroid Build Coastguard Worker // path definitions
1257*58b9f456SAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
1258*58b9f456SAndroid Build Coastguard Worker
1259*58b9f456SAndroid Build Coastguard Worker constexpr path::value_type path::preferred_separator;
1260*58b9f456SAndroid Build Coastguard Worker
replace_extension(path const & replacement)1261*58b9f456SAndroid Build Coastguard Worker path& path::replace_extension(path const& replacement) {
1262*58b9f456SAndroid Build Coastguard Worker path p = extension();
1263*58b9f456SAndroid Build Coastguard Worker if (not p.empty()) {
1264*58b9f456SAndroid Build Coastguard Worker __pn_.erase(__pn_.size() - p.native().size());
1265*58b9f456SAndroid Build Coastguard Worker }
1266*58b9f456SAndroid Build Coastguard Worker if (!replacement.empty()) {
1267*58b9f456SAndroid Build Coastguard Worker if (replacement.native()[0] != '.') {
1268*58b9f456SAndroid Build Coastguard Worker __pn_ += ".";
1269*58b9f456SAndroid Build Coastguard Worker }
1270*58b9f456SAndroid Build Coastguard Worker __pn_.append(replacement.__pn_);
1271*58b9f456SAndroid Build Coastguard Worker }
1272*58b9f456SAndroid Build Coastguard Worker return *this;
1273*58b9f456SAndroid Build Coastguard Worker }
1274*58b9f456SAndroid Build Coastguard Worker
1275*58b9f456SAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
1276*58b9f456SAndroid Build Coastguard Worker // path.decompose
1277*58b9f456SAndroid Build Coastguard Worker
__root_name() const1278*58b9f456SAndroid Build Coastguard Worker string_view_t path::__root_name() const {
1279*58b9f456SAndroid Build Coastguard Worker auto PP = PathParser::CreateBegin(__pn_);
1280*58b9f456SAndroid Build Coastguard Worker if (PP.State == PathParser::PS_InRootName)
1281*58b9f456SAndroid Build Coastguard Worker return *PP;
1282*58b9f456SAndroid Build Coastguard Worker return {};
1283*58b9f456SAndroid Build Coastguard Worker }
1284*58b9f456SAndroid Build Coastguard Worker
__root_directory() const1285*58b9f456SAndroid Build Coastguard Worker string_view_t path::__root_directory() const {
1286*58b9f456SAndroid Build Coastguard Worker auto PP = PathParser::CreateBegin(__pn_);
1287*58b9f456SAndroid Build Coastguard Worker if (PP.State == PathParser::PS_InRootName)
1288*58b9f456SAndroid Build Coastguard Worker ++PP;
1289*58b9f456SAndroid Build Coastguard Worker if (PP.State == PathParser::PS_InRootDir)
1290*58b9f456SAndroid Build Coastguard Worker return *PP;
1291*58b9f456SAndroid Build Coastguard Worker return {};
1292*58b9f456SAndroid Build Coastguard Worker }
1293*58b9f456SAndroid Build Coastguard Worker
__root_path_raw() const1294*58b9f456SAndroid Build Coastguard Worker string_view_t path::__root_path_raw() const {
1295*58b9f456SAndroid Build Coastguard Worker auto PP = PathParser::CreateBegin(__pn_);
1296*58b9f456SAndroid Build Coastguard Worker if (PP.State == PathParser::PS_InRootName) {
1297*58b9f456SAndroid Build Coastguard Worker auto NextCh = PP.peek();
1298*58b9f456SAndroid Build Coastguard Worker if (NextCh && *NextCh == '/') {
1299*58b9f456SAndroid Build Coastguard Worker ++PP;
1300*58b9f456SAndroid Build Coastguard Worker return createView(__pn_.data(), &PP.RawEntry.back());
1301*58b9f456SAndroid Build Coastguard Worker }
1302*58b9f456SAndroid Build Coastguard Worker return PP.RawEntry;
1303*58b9f456SAndroid Build Coastguard Worker }
1304*58b9f456SAndroid Build Coastguard Worker if (PP.State == PathParser::PS_InRootDir)
1305*58b9f456SAndroid Build Coastguard Worker return *PP;
1306*58b9f456SAndroid Build Coastguard Worker return {};
1307*58b9f456SAndroid Build Coastguard Worker }
1308*58b9f456SAndroid Build Coastguard Worker
ConsumeRootName(PathParser * PP)1309*58b9f456SAndroid Build Coastguard Worker static bool ConsumeRootName(PathParser *PP) {
1310*58b9f456SAndroid Build Coastguard Worker static_assert(PathParser::PS_BeforeBegin == 1 &&
1311*58b9f456SAndroid Build Coastguard Worker PathParser::PS_InRootName == 2,
1312*58b9f456SAndroid Build Coastguard Worker "Values for enums are incorrect");
1313*58b9f456SAndroid Build Coastguard Worker while (PP->State <= PathParser::PS_InRootName)
1314*58b9f456SAndroid Build Coastguard Worker ++(*PP);
1315*58b9f456SAndroid Build Coastguard Worker return PP->State == PathParser::PS_AtEnd;
1316*58b9f456SAndroid Build Coastguard Worker }
1317*58b9f456SAndroid Build Coastguard Worker
ConsumeRootDir(PathParser * PP)1318*58b9f456SAndroid Build Coastguard Worker static bool ConsumeRootDir(PathParser* PP) {
1319*58b9f456SAndroid Build Coastguard Worker static_assert(PathParser::PS_BeforeBegin == 1 &&
1320*58b9f456SAndroid Build Coastguard Worker PathParser::PS_InRootName == 2 &&
1321*58b9f456SAndroid Build Coastguard Worker PathParser::PS_InRootDir == 3, "Values for enums are incorrect");
1322*58b9f456SAndroid Build Coastguard Worker while (PP->State <= PathParser::PS_InRootDir)
1323*58b9f456SAndroid Build Coastguard Worker ++(*PP);
1324*58b9f456SAndroid Build Coastguard Worker return PP->State == PathParser::PS_AtEnd;
1325*58b9f456SAndroid Build Coastguard Worker }
1326*58b9f456SAndroid Build Coastguard Worker
__relative_path() const1327*58b9f456SAndroid Build Coastguard Worker string_view_t path::__relative_path() const {
1328*58b9f456SAndroid Build Coastguard Worker auto PP = PathParser::CreateBegin(__pn_);
1329*58b9f456SAndroid Build Coastguard Worker if (ConsumeRootDir(&PP))
1330*58b9f456SAndroid Build Coastguard Worker return {};
1331*58b9f456SAndroid Build Coastguard Worker return createView(PP.RawEntry.data(), &__pn_.back());
1332*58b9f456SAndroid Build Coastguard Worker }
1333*58b9f456SAndroid Build Coastguard Worker
__parent_path() const1334*58b9f456SAndroid Build Coastguard Worker string_view_t path::__parent_path() const {
1335*58b9f456SAndroid Build Coastguard Worker if (empty())
1336*58b9f456SAndroid Build Coastguard Worker return {};
1337*58b9f456SAndroid Build Coastguard Worker // Determine if we have a root path but not a relative path. In that case
1338*58b9f456SAndroid Build Coastguard Worker // return *this.
1339*58b9f456SAndroid Build Coastguard Worker {
1340*58b9f456SAndroid Build Coastguard Worker auto PP = PathParser::CreateBegin(__pn_);
1341*58b9f456SAndroid Build Coastguard Worker if (ConsumeRootDir(&PP))
1342*58b9f456SAndroid Build Coastguard Worker return __pn_;
1343*58b9f456SAndroid Build Coastguard Worker }
1344*58b9f456SAndroid Build Coastguard Worker // Otherwise remove a single element from the end of the path, and return
1345*58b9f456SAndroid Build Coastguard Worker // a string representing that path
1346*58b9f456SAndroid Build Coastguard Worker {
1347*58b9f456SAndroid Build Coastguard Worker auto PP = PathParser::CreateEnd(__pn_);
1348*58b9f456SAndroid Build Coastguard Worker --PP;
1349*58b9f456SAndroid Build Coastguard Worker if (PP.RawEntry.data() == __pn_.data())
1350*58b9f456SAndroid Build Coastguard Worker return {};
1351*58b9f456SAndroid Build Coastguard Worker --PP;
1352*58b9f456SAndroid Build Coastguard Worker return createView(__pn_.data(), &PP.RawEntry.back());
1353*58b9f456SAndroid Build Coastguard Worker }
1354*58b9f456SAndroid Build Coastguard Worker }
1355*58b9f456SAndroid Build Coastguard Worker
__filename() const1356*58b9f456SAndroid Build Coastguard Worker string_view_t path::__filename() const {
1357*58b9f456SAndroid Build Coastguard Worker if (empty())
1358*58b9f456SAndroid Build Coastguard Worker return {};
1359*58b9f456SAndroid Build Coastguard Worker {
1360*58b9f456SAndroid Build Coastguard Worker PathParser PP = PathParser::CreateBegin(__pn_);
1361*58b9f456SAndroid Build Coastguard Worker if (ConsumeRootDir(&PP))
1362*58b9f456SAndroid Build Coastguard Worker return {};
1363*58b9f456SAndroid Build Coastguard Worker }
1364*58b9f456SAndroid Build Coastguard Worker return *(--PathParser::CreateEnd(__pn_));
1365*58b9f456SAndroid Build Coastguard Worker }
1366*58b9f456SAndroid Build Coastguard Worker
__stem() const1367*58b9f456SAndroid Build Coastguard Worker string_view_t path::__stem() const {
1368*58b9f456SAndroid Build Coastguard Worker return parser::separate_filename(__filename()).first;
1369*58b9f456SAndroid Build Coastguard Worker }
1370*58b9f456SAndroid Build Coastguard Worker
__extension() const1371*58b9f456SAndroid Build Coastguard Worker string_view_t path::__extension() const {
1372*58b9f456SAndroid Build Coastguard Worker return parser::separate_filename(__filename()).second;
1373*58b9f456SAndroid Build Coastguard Worker }
1374*58b9f456SAndroid Build Coastguard Worker
1375*58b9f456SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////
1376*58b9f456SAndroid Build Coastguard Worker // path.gen
1377*58b9f456SAndroid Build Coastguard Worker
1378*58b9f456SAndroid Build Coastguard Worker enum PathPartKind : unsigned char {
1379*58b9f456SAndroid Build Coastguard Worker PK_None,
1380*58b9f456SAndroid Build Coastguard Worker PK_RootSep,
1381*58b9f456SAndroid Build Coastguard Worker PK_Filename,
1382*58b9f456SAndroid Build Coastguard Worker PK_Dot,
1383*58b9f456SAndroid Build Coastguard Worker PK_DotDot,
1384*58b9f456SAndroid Build Coastguard Worker PK_TrailingSep
1385*58b9f456SAndroid Build Coastguard Worker };
1386*58b9f456SAndroid Build Coastguard Worker
ClassifyPathPart(string_view_t Part)1387*58b9f456SAndroid Build Coastguard Worker static PathPartKind ClassifyPathPart(string_view_t Part) {
1388*58b9f456SAndroid Build Coastguard Worker if (Part.empty())
1389*58b9f456SAndroid Build Coastguard Worker return PK_TrailingSep;
1390*58b9f456SAndroid Build Coastguard Worker if (Part == ".")
1391*58b9f456SAndroid Build Coastguard Worker return PK_Dot;
1392*58b9f456SAndroid Build Coastguard Worker if (Part == "..")
1393*58b9f456SAndroid Build Coastguard Worker return PK_DotDot;
1394*58b9f456SAndroid Build Coastguard Worker if (Part == "/")
1395*58b9f456SAndroid Build Coastguard Worker return PK_RootSep;
1396*58b9f456SAndroid Build Coastguard Worker return PK_Filename;
1397*58b9f456SAndroid Build Coastguard Worker }
1398*58b9f456SAndroid Build Coastguard Worker
lexically_normal() const1399*58b9f456SAndroid Build Coastguard Worker path path::lexically_normal() const {
1400*58b9f456SAndroid Build Coastguard Worker if (__pn_.empty())
1401*58b9f456SAndroid Build Coastguard Worker return *this;
1402*58b9f456SAndroid Build Coastguard Worker
1403*58b9f456SAndroid Build Coastguard Worker using PartKindPair = pair<string_view_t, PathPartKind>;
1404*58b9f456SAndroid Build Coastguard Worker vector<PartKindPair> Parts;
1405*58b9f456SAndroid Build Coastguard Worker // Guess as to how many elements the path has to avoid reallocating.
1406*58b9f456SAndroid Build Coastguard Worker Parts.reserve(32);
1407*58b9f456SAndroid Build Coastguard Worker
1408*58b9f456SAndroid Build Coastguard Worker // Track the total size of the parts as we collect them. This allows the
1409*58b9f456SAndroid Build Coastguard Worker // resulting path to reserve the correct amount of memory.
1410*58b9f456SAndroid Build Coastguard Worker size_t NewPathSize = 0;
1411*58b9f456SAndroid Build Coastguard Worker auto AddPart = [&](PathPartKind K, string_view_t P) {
1412*58b9f456SAndroid Build Coastguard Worker NewPathSize += P.size();
1413*58b9f456SAndroid Build Coastguard Worker Parts.emplace_back(P, K);
1414*58b9f456SAndroid Build Coastguard Worker };
1415*58b9f456SAndroid Build Coastguard Worker auto LastPartKind = [&]() {
1416*58b9f456SAndroid Build Coastguard Worker if (Parts.empty())
1417*58b9f456SAndroid Build Coastguard Worker return PK_None;
1418*58b9f456SAndroid Build Coastguard Worker return Parts.back().second;
1419*58b9f456SAndroid Build Coastguard Worker };
1420*58b9f456SAndroid Build Coastguard Worker
1421*58b9f456SAndroid Build Coastguard Worker bool MaybeNeedTrailingSep = false;
1422*58b9f456SAndroid Build Coastguard Worker // Build a stack containing the remaining elements of the path, popping off
1423*58b9f456SAndroid Build Coastguard Worker // elements which occur before a '..' entry.
1424*58b9f456SAndroid Build Coastguard Worker for (auto PP = PathParser::CreateBegin(__pn_); PP; ++PP) {
1425*58b9f456SAndroid Build Coastguard Worker auto Part = *PP;
1426*58b9f456SAndroid Build Coastguard Worker PathPartKind Kind = ClassifyPathPart(Part);
1427*58b9f456SAndroid Build Coastguard Worker switch (Kind) {
1428*58b9f456SAndroid Build Coastguard Worker case PK_Filename:
1429*58b9f456SAndroid Build Coastguard Worker case PK_RootSep: {
1430*58b9f456SAndroid Build Coastguard Worker // Add all non-dot and non-dot-dot elements to the stack of elements.
1431*58b9f456SAndroid Build Coastguard Worker AddPart(Kind, Part);
1432*58b9f456SAndroid Build Coastguard Worker MaybeNeedTrailingSep = false;
1433*58b9f456SAndroid Build Coastguard Worker break;
1434*58b9f456SAndroid Build Coastguard Worker }
1435*58b9f456SAndroid Build Coastguard Worker case PK_DotDot: {
1436*58b9f456SAndroid Build Coastguard Worker // Only push a ".." element if there are no elements preceding the "..",
1437*58b9f456SAndroid Build Coastguard Worker // or if the preceding element is itself "..".
1438*58b9f456SAndroid Build Coastguard Worker auto LastKind = LastPartKind();
1439*58b9f456SAndroid Build Coastguard Worker if (LastKind == PK_Filename) {
1440*58b9f456SAndroid Build Coastguard Worker NewPathSize -= Parts.back().first.size();
1441*58b9f456SAndroid Build Coastguard Worker Parts.pop_back();
1442*58b9f456SAndroid Build Coastguard Worker } else if (LastKind != PK_RootSep)
1443*58b9f456SAndroid Build Coastguard Worker AddPart(PK_DotDot, "..");
1444*58b9f456SAndroid Build Coastguard Worker MaybeNeedTrailingSep = LastKind == PK_Filename;
1445*58b9f456SAndroid Build Coastguard Worker break;
1446*58b9f456SAndroid Build Coastguard Worker }
1447*58b9f456SAndroid Build Coastguard Worker case PK_Dot:
1448*58b9f456SAndroid Build Coastguard Worker case PK_TrailingSep: {
1449*58b9f456SAndroid Build Coastguard Worker MaybeNeedTrailingSep = true;
1450*58b9f456SAndroid Build Coastguard Worker break;
1451*58b9f456SAndroid Build Coastguard Worker }
1452*58b9f456SAndroid Build Coastguard Worker case PK_None:
1453*58b9f456SAndroid Build Coastguard Worker _LIBCPP_UNREACHABLE();
1454*58b9f456SAndroid Build Coastguard Worker }
1455*58b9f456SAndroid Build Coastguard Worker }
1456*58b9f456SAndroid Build Coastguard Worker // [fs.path.generic]p6.8: If the path is empty, add a dot.
1457*58b9f456SAndroid Build Coastguard Worker if (Parts.empty())
1458*58b9f456SAndroid Build Coastguard Worker return ".";
1459*58b9f456SAndroid Build Coastguard Worker
1460*58b9f456SAndroid Build Coastguard Worker // [fs.path.generic]p6.7: If the last filename is dot-dot, remove any
1461*58b9f456SAndroid Build Coastguard Worker // trailing directory-separator.
1462*58b9f456SAndroid Build Coastguard Worker bool NeedTrailingSep = MaybeNeedTrailingSep && LastPartKind() == PK_Filename;
1463*58b9f456SAndroid Build Coastguard Worker
1464*58b9f456SAndroid Build Coastguard Worker path Result;
1465*58b9f456SAndroid Build Coastguard Worker Result.__pn_.reserve(Parts.size() + NewPathSize + NeedTrailingSep);
1466*58b9f456SAndroid Build Coastguard Worker for (auto& PK : Parts)
1467*58b9f456SAndroid Build Coastguard Worker Result /= PK.first;
1468*58b9f456SAndroid Build Coastguard Worker
1469*58b9f456SAndroid Build Coastguard Worker if (NeedTrailingSep)
1470*58b9f456SAndroid Build Coastguard Worker Result /= "";
1471*58b9f456SAndroid Build Coastguard Worker
1472*58b9f456SAndroid Build Coastguard Worker return Result;
1473*58b9f456SAndroid Build Coastguard Worker }
1474*58b9f456SAndroid Build Coastguard Worker
DetermineLexicalElementCount(PathParser PP)1475*58b9f456SAndroid Build Coastguard Worker static int DetermineLexicalElementCount(PathParser PP) {
1476*58b9f456SAndroid Build Coastguard Worker int Count = 0;
1477*58b9f456SAndroid Build Coastguard Worker for (; PP; ++PP) {
1478*58b9f456SAndroid Build Coastguard Worker auto Elem = *PP;
1479*58b9f456SAndroid Build Coastguard Worker if (Elem == "..")
1480*58b9f456SAndroid Build Coastguard Worker --Count;
1481*58b9f456SAndroid Build Coastguard Worker else if (Elem != "." && Elem != "")
1482*58b9f456SAndroid Build Coastguard Worker ++Count;
1483*58b9f456SAndroid Build Coastguard Worker }
1484*58b9f456SAndroid Build Coastguard Worker return Count;
1485*58b9f456SAndroid Build Coastguard Worker }
1486*58b9f456SAndroid Build Coastguard Worker
lexically_relative(const path & base) const1487*58b9f456SAndroid Build Coastguard Worker path path::lexically_relative(const path& base) const {
1488*58b9f456SAndroid Build Coastguard Worker { // perform root-name/root-directory mismatch checks
1489*58b9f456SAndroid Build Coastguard Worker auto PP = PathParser::CreateBegin(__pn_);
1490*58b9f456SAndroid Build Coastguard Worker auto PPBase = PathParser::CreateBegin(base.__pn_);
1491*58b9f456SAndroid Build Coastguard Worker auto CheckIterMismatchAtBase = [&]() {
1492*58b9f456SAndroid Build Coastguard Worker return PP.State != PPBase.State &&
1493*58b9f456SAndroid Build Coastguard Worker (PP.inRootPath() || PPBase.inRootPath());
1494*58b9f456SAndroid Build Coastguard Worker };
1495*58b9f456SAndroid Build Coastguard Worker if (PP.inRootName() && PPBase.inRootName()) {
1496*58b9f456SAndroid Build Coastguard Worker if (*PP != *PPBase)
1497*58b9f456SAndroid Build Coastguard Worker return {};
1498*58b9f456SAndroid Build Coastguard Worker } else if (CheckIterMismatchAtBase())
1499*58b9f456SAndroid Build Coastguard Worker return {};
1500*58b9f456SAndroid Build Coastguard Worker
1501*58b9f456SAndroid Build Coastguard Worker if (PP.inRootPath())
1502*58b9f456SAndroid Build Coastguard Worker ++PP;
1503*58b9f456SAndroid Build Coastguard Worker if (PPBase.inRootPath())
1504*58b9f456SAndroid Build Coastguard Worker ++PPBase;
1505*58b9f456SAndroid Build Coastguard Worker if (CheckIterMismatchAtBase())
1506*58b9f456SAndroid Build Coastguard Worker return {};
1507*58b9f456SAndroid Build Coastguard Worker }
1508*58b9f456SAndroid Build Coastguard Worker
1509*58b9f456SAndroid Build Coastguard Worker // Find the first mismatching element
1510*58b9f456SAndroid Build Coastguard Worker auto PP = PathParser::CreateBegin(__pn_);
1511*58b9f456SAndroid Build Coastguard Worker auto PPBase = PathParser::CreateBegin(base.__pn_);
1512*58b9f456SAndroid Build Coastguard Worker while (PP && PPBase && PP.State == PPBase.State && *PP == *PPBase) {
1513*58b9f456SAndroid Build Coastguard Worker ++PP;
1514*58b9f456SAndroid Build Coastguard Worker ++PPBase;
1515*58b9f456SAndroid Build Coastguard Worker }
1516*58b9f456SAndroid Build Coastguard Worker
1517*58b9f456SAndroid Build Coastguard Worker // If there is no mismatch, return ".".
1518*58b9f456SAndroid Build Coastguard Worker if (!PP && !PPBase)
1519*58b9f456SAndroid Build Coastguard Worker return ".";
1520*58b9f456SAndroid Build Coastguard Worker
1521*58b9f456SAndroid Build Coastguard Worker // Otherwise, determine the number of elements, 'n', which are not dot or
1522*58b9f456SAndroid Build Coastguard Worker // dot-dot minus the number of dot-dot elements.
1523*58b9f456SAndroid Build Coastguard Worker int ElemCount = DetermineLexicalElementCount(PPBase);
1524*58b9f456SAndroid Build Coastguard Worker if (ElemCount < 0)
1525*58b9f456SAndroid Build Coastguard Worker return {};
1526*58b9f456SAndroid Build Coastguard Worker
1527*58b9f456SAndroid Build Coastguard Worker // if n == 0 and (a == end() || a->empty()), returns path("."); otherwise
1528*58b9f456SAndroid Build Coastguard Worker if (ElemCount == 0 && (PP.atEnd() || *PP == ""))
1529*58b9f456SAndroid Build Coastguard Worker return ".";
1530*58b9f456SAndroid Build Coastguard Worker
1531*58b9f456SAndroid Build Coastguard Worker // return a path constructed with 'n' dot-dot elements, followed by the the
1532*58b9f456SAndroid Build Coastguard Worker // elements of '*this' after the mismatch.
1533*58b9f456SAndroid Build Coastguard Worker path Result;
1534*58b9f456SAndroid Build Coastguard Worker // FIXME: Reserve enough room in Result that it won't have to re-allocate.
1535*58b9f456SAndroid Build Coastguard Worker while (ElemCount--)
1536*58b9f456SAndroid Build Coastguard Worker Result /= "..";
1537*58b9f456SAndroid Build Coastguard Worker for (; PP; ++PP)
1538*58b9f456SAndroid Build Coastguard Worker Result /= *PP;
1539*58b9f456SAndroid Build Coastguard Worker return Result;
1540*58b9f456SAndroid Build Coastguard Worker }
1541*58b9f456SAndroid Build Coastguard Worker
1542*58b9f456SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////
1543*58b9f456SAndroid Build Coastguard Worker // path.comparisons
CompareRootName(PathParser * LHS,PathParser * RHS)1544*58b9f456SAndroid Build Coastguard Worker static int CompareRootName(PathParser *LHS, PathParser *RHS) {
1545*58b9f456SAndroid Build Coastguard Worker if (!LHS->inRootName() && !RHS->inRootName())
1546*58b9f456SAndroid Build Coastguard Worker return 0;
1547*58b9f456SAndroid Build Coastguard Worker
1548*58b9f456SAndroid Build Coastguard Worker auto GetRootName = [](PathParser *Parser) -> string_view_t {
1549*58b9f456SAndroid Build Coastguard Worker return Parser->inRootName() ? **Parser : "";
1550*58b9f456SAndroid Build Coastguard Worker };
1551*58b9f456SAndroid Build Coastguard Worker int res = GetRootName(LHS).compare(GetRootName(RHS));
1552*58b9f456SAndroid Build Coastguard Worker ConsumeRootName(LHS);
1553*58b9f456SAndroid Build Coastguard Worker ConsumeRootName(RHS);
1554*58b9f456SAndroid Build Coastguard Worker return res;
1555*58b9f456SAndroid Build Coastguard Worker }
1556*58b9f456SAndroid Build Coastguard Worker
CompareRootDir(PathParser * LHS,PathParser * RHS)1557*58b9f456SAndroid Build Coastguard Worker static int CompareRootDir(PathParser *LHS, PathParser *RHS) {
1558*58b9f456SAndroid Build Coastguard Worker if (!LHS->inRootDir() && RHS->inRootDir())
1559*58b9f456SAndroid Build Coastguard Worker return -1;
1560*58b9f456SAndroid Build Coastguard Worker else if (LHS->inRootDir() && !RHS->inRootDir())
1561*58b9f456SAndroid Build Coastguard Worker return 1;
1562*58b9f456SAndroid Build Coastguard Worker else {
1563*58b9f456SAndroid Build Coastguard Worker ConsumeRootDir(LHS);
1564*58b9f456SAndroid Build Coastguard Worker ConsumeRootDir(RHS);
1565*58b9f456SAndroid Build Coastguard Worker return 0;
1566*58b9f456SAndroid Build Coastguard Worker }
1567*58b9f456SAndroid Build Coastguard Worker }
1568*58b9f456SAndroid Build Coastguard Worker
CompareRelative(PathParser * LHSPtr,PathParser * RHSPtr)1569*58b9f456SAndroid Build Coastguard Worker static int CompareRelative(PathParser *LHSPtr, PathParser *RHSPtr) {
1570*58b9f456SAndroid Build Coastguard Worker auto &LHS = *LHSPtr;
1571*58b9f456SAndroid Build Coastguard Worker auto &RHS = *RHSPtr;
1572*58b9f456SAndroid Build Coastguard Worker
1573*58b9f456SAndroid Build Coastguard Worker int res;
1574*58b9f456SAndroid Build Coastguard Worker while (LHS && RHS) {
1575*58b9f456SAndroid Build Coastguard Worker if ((res = (*LHS).compare(*RHS)) != 0)
1576*58b9f456SAndroid Build Coastguard Worker return res;
1577*58b9f456SAndroid Build Coastguard Worker ++LHS;
1578*58b9f456SAndroid Build Coastguard Worker ++RHS;
1579*58b9f456SAndroid Build Coastguard Worker }
1580*58b9f456SAndroid Build Coastguard Worker return 0;
1581*58b9f456SAndroid Build Coastguard Worker }
1582*58b9f456SAndroid Build Coastguard Worker
CompareEndState(PathParser * LHS,PathParser * RHS)1583*58b9f456SAndroid Build Coastguard Worker static int CompareEndState(PathParser *LHS, PathParser *RHS) {
1584*58b9f456SAndroid Build Coastguard Worker if (LHS->atEnd() && !RHS->atEnd())
1585*58b9f456SAndroid Build Coastguard Worker return -1;
1586*58b9f456SAndroid Build Coastguard Worker else if (!LHS->atEnd() && RHS->atEnd())
1587*58b9f456SAndroid Build Coastguard Worker return 1;
1588*58b9f456SAndroid Build Coastguard Worker return 0;
1589*58b9f456SAndroid Build Coastguard Worker }
1590*58b9f456SAndroid Build Coastguard Worker
__compare(string_view_t __s) const1591*58b9f456SAndroid Build Coastguard Worker int path::__compare(string_view_t __s) const {
1592*58b9f456SAndroid Build Coastguard Worker auto LHS = PathParser::CreateBegin(__pn_);
1593*58b9f456SAndroid Build Coastguard Worker auto RHS = PathParser::CreateBegin(__s);
1594*58b9f456SAndroid Build Coastguard Worker int res;
1595*58b9f456SAndroid Build Coastguard Worker
1596*58b9f456SAndroid Build Coastguard Worker if ((res = CompareRootName(&LHS, &RHS)) != 0)
1597*58b9f456SAndroid Build Coastguard Worker return res;
1598*58b9f456SAndroid Build Coastguard Worker
1599*58b9f456SAndroid Build Coastguard Worker if ((res = CompareRootDir(&LHS, &RHS)) != 0)
1600*58b9f456SAndroid Build Coastguard Worker return res;
1601*58b9f456SAndroid Build Coastguard Worker
1602*58b9f456SAndroid Build Coastguard Worker if ((res = CompareRelative(&LHS, &RHS)) != 0)
1603*58b9f456SAndroid Build Coastguard Worker return res;
1604*58b9f456SAndroid Build Coastguard Worker
1605*58b9f456SAndroid Build Coastguard Worker return CompareEndState(&LHS, &RHS);
1606*58b9f456SAndroid Build Coastguard Worker }
1607*58b9f456SAndroid Build Coastguard Worker
1608*58b9f456SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////
1609*58b9f456SAndroid Build Coastguard Worker // path.nonmembers
hash_value(const path & __p)1610*58b9f456SAndroid Build Coastguard Worker size_t hash_value(const path& __p) noexcept {
1611*58b9f456SAndroid Build Coastguard Worker auto PP = PathParser::CreateBegin(__p.native());
1612*58b9f456SAndroid Build Coastguard Worker size_t hash_value = 0;
1613*58b9f456SAndroid Build Coastguard Worker hash<string_view_t> hasher;
1614*58b9f456SAndroid Build Coastguard Worker while (PP) {
1615*58b9f456SAndroid Build Coastguard Worker hash_value = __hash_combine(hash_value, hasher(*PP));
1616*58b9f456SAndroid Build Coastguard Worker ++PP;
1617*58b9f456SAndroid Build Coastguard Worker }
1618*58b9f456SAndroid Build Coastguard Worker return hash_value;
1619*58b9f456SAndroid Build Coastguard Worker }
1620*58b9f456SAndroid Build Coastguard Worker
1621*58b9f456SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////
1622*58b9f456SAndroid Build Coastguard Worker // path.itr
begin() const1623*58b9f456SAndroid Build Coastguard Worker path::iterator path::begin() const {
1624*58b9f456SAndroid Build Coastguard Worker auto PP = PathParser::CreateBegin(__pn_);
1625*58b9f456SAndroid Build Coastguard Worker iterator it;
1626*58b9f456SAndroid Build Coastguard Worker it.__path_ptr_ = this;
1627*58b9f456SAndroid Build Coastguard Worker it.__state_ = static_cast<path::iterator::_ParserState>(PP.State);
1628*58b9f456SAndroid Build Coastguard Worker it.__entry_ = PP.RawEntry;
1629*58b9f456SAndroid Build Coastguard Worker it.__stashed_elem_.__assign_view(*PP);
1630*58b9f456SAndroid Build Coastguard Worker return it;
1631*58b9f456SAndroid Build Coastguard Worker }
1632*58b9f456SAndroid Build Coastguard Worker
end() const1633*58b9f456SAndroid Build Coastguard Worker path::iterator path::end() const {
1634*58b9f456SAndroid Build Coastguard Worker iterator it{};
1635*58b9f456SAndroid Build Coastguard Worker it.__state_ = path::iterator::_AtEnd;
1636*58b9f456SAndroid Build Coastguard Worker it.__path_ptr_ = this;
1637*58b9f456SAndroid Build Coastguard Worker return it;
1638*58b9f456SAndroid Build Coastguard Worker }
1639*58b9f456SAndroid Build Coastguard Worker
__increment()1640*58b9f456SAndroid Build Coastguard Worker path::iterator& path::iterator::__increment() {
1641*58b9f456SAndroid Build Coastguard Worker PathParser PP(__path_ptr_->native(), __entry_, __state_);
1642*58b9f456SAndroid Build Coastguard Worker ++PP;
1643*58b9f456SAndroid Build Coastguard Worker __state_ = static_cast<_ParserState>(PP.State);
1644*58b9f456SAndroid Build Coastguard Worker __entry_ = PP.RawEntry;
1645*58b9f456SAndroid Build Coastguard Worker __stashed_elem_.__assign_view(*PP);
1646*58b9f456SAndroid Build Coastguard Worker return *this;
1647*58b9f456SAndroid Build Coastguard Worker }
1648*58b9f456SAndroid Build Coastguard Worker
__decrement()1649*58b9f456SAndroid Build Coastguard Worker path::iterator& path::iterator::__decrement() {
1650*58b9f456SAndroid Build Coastguard Worker PathParser PP(__path_ptr_->native(), __entry_, __state_);
1651*58b9f456SAndroid Build Coastguard Worker --PP;
1652*58b9f456SAndroid Build Coastguard Worker __state_ = static_cast<_ParserState>(PP.State);
1653*58b9f456SAndroid Build Coastguard Worker __entry_ = PP.RawEntry;
1654*58b9f456SAndroid Build Coastguard Worker __stashed_elem_.__assign_view(*PP);
1655*58b9f456SAndroid Build Coastguard Worker return *this;
1656*58b9f456SAndroid Build Coastguard Worker }
1657*58b9f456SAndroid Build Coastguard Worker
1658*58b9f456SAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
1659*58b9f456SAndroid Build Coastguard Worker // directory entry definitions
1660*58b9f456SAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
1661*58b9f456SAndroid Build Coastguard Worker
1662*58b9f456SAndroid Build Coastguard Worker #ifndef _LIBCPP_WIN32API
__do_refresh()1663*58b9f456SAndroid Build Coastguard Worker error_code directory_entry::__do_refresh() noexcept {
1664*58b9f456SAndroid Build Coastguard Worker __data_.__reset();
1665*58b9f456SAndroid Build Coastguard Worker error_code failure_ec;
1666*58b9f456SAndroid Build Coastguard Worker
1667*58b9f456SAndroid Build Coastguard Worker StatT full_st;
1668*58b9f456SAndroid Build Coastguard Worker file_status st = detail::posix_lstat(__p_, full_st, &failure_ec);
1669*58b9f456SAndroid Build Coastguard Worker if (!status_known(st)) {
1670*58b9f456SAndroid Build Coastguard Worker __data_.__reset();
1671*58b9f456SAndroid Build Coastguard Worker return failure_ec;
1672*58b9f456SAndroid Build Coastguard Worker }
1673*58b9f456SAndroid Build Coastguard Worker
1674*58b9f456SAndroid Build Coastguard Worker if (!_VSTD_FS::exists(st) || !_VSTD_FS::is_symlink(st)) {
1675*58b9f456SAndroid Build Coastguard Worker __data_.__cache_type_ = directory_entry::_RefreshNonSymlink;
1676*58b9f456SAndroid Build Coastguard Worker __data_.__type_ = st.type();
1677*58b9f456SAndroid Build Coastguard Worker __data_.__non_sym_perms_ = st.permissions();
1678*58b9f456SAndroid Build Coastguard Worker } else { // we have a symlink
1679*58b9f456SAndroid Build Coastguard Worker __data_.__sym_perms_ = st.permissions();
1680*58b9f456SAndroid Build Coastguard Worker // Get the information about the linked entity.
1681*58b9f456SAndroid Build Coastguard Worker // Ignore errors from stat, since we don't want errors regarding symlink
1682*58b9f456SAndroid Build Coastguard Worker // resolution to be reported to the user.
1683*58b9f456SAndroid Build Coastguard Worker error_code ignored_ec;
1684*58b9f456SAndroid Build Coastguard Worker st = detail::posix_stat(__p_, full_st, &ignored_ec);
1685*58b9f456SAndroid Build Coastguard Worker
1686*58b9f456SAndroid Build Coastguard Worker __data_.__type_ = st.type();
1687*58b9f456SAndroid Build Coastguard Worker __data_.__non_sym_perms_ = st.permissions();
1688*58b9f456SAndroid Build Coastguard Worker
1689*58b9f456SAndroid Build Coastguard Worker // If we failed to resolve the link, then only partially populate the
1690*58b9f456SAndroid Build Coastguard Worker // cache.
1691*58b9f456SAndroid Build Coastguard Worker if (!status_known(st)) {
1692*58b9f456SAndroid Build Coastguard Worker __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved;
1693*58b9f456SAndroid Build Coastguard Worker return error_code{};
1694*58b9f456SAndroid Build Coastguard Worker }
1695*58b9f456SAndroid Build Coastguard Worker // Otherwise, we resolved the link, potentially as not existing.
1696*58b9f456SAndroid Build Coastguard Worker // That's OK.
1697*58b9f456SAndroid Build Coastguard Worker __data_.__cache_type_ = directory_entry::_RefreshSymlink;
1698*58b9f456SAndroid Build Coastguard Worker }
1699*58b9f456SAndroid Build Coastguard Worker
1700*58b9f456SAndroid Build Coastguard Worker if (_VSTD_FS::is_regular_file(st))
1701*58b9f456SAndroid Build Coastguard Worker __data_.__size_ = static_cast<uintmax_t>(full_st.st_size);
1702*58b9f456SAndroid Build Coastguard Worker
1703*58b9f456SAndroid Build Coastguard Worker if (_VSTD_FS::exists(st)) {
1704*58b9f456SAndroid Build Coastguard Worker __data_.__nlink_ = static_cast<uintmax_t>(full_st.st_nlink);
1705*58b9f456SAndroid Build Coastguard Worker
1706*58b9f456SAndroid Build Coastguard Worker // Attempt to extract the mtime, and fail if it's not representable using
1707*58b9f456SAndroid Build Coastguard Worker // file_time_type. For now we ignore the error, as we'll report it when
1708*58b9f456SAndroid Build Coastguard Worker // the value is actually used.
1709*58b9f456SAndroid Build Coastguard Worker error_code ignored_ec;
1710*58b9f456SAndroid Build Coastguard Worker __data_.__write_time_ =
1711*58b9f456SAndroid Build Coastguard Worker __extract_last_write_time(__p_, full_st, &ignored_ec);
1712*58b9f456SAndroid Build Coastguard Worker }
1713*58b9f456SAndroid Build Coastguard Worker
1714*58b9f456SAndroid Build Coastguard Worker return failure_ec;
1715*58b9f456SAndroid Build Coastguard Worker }
1716*58b9f456SAndroid Build Coastguard Worker #else
__do_refresh()1717*58b9f456SAndroid Build Coastguard Worker error_code directory_entry::__do_refresh() noexcept {
1718*58b9f456SAndroid Build Coastguard Worker __data_.__reset();
1719*58b9f456SAndroid Build Coastguard Worker error_code failure_ec;
1720*58b9f456SAndroid Build Coastguard Worker
1721*58b9f456SAndroid Build Coastguard Worker file_status st = _VSTD_FS::symlink_status(__p_, failure_ec);
1722*58b9f456SAndroid Build Coastguard Worker if (!status_known(st)) {
1723*58b9f456SAndroid Build Coastguard Worker __data_.__reset();
1724*58b9f456SAndroid Build Coastguard Worker return failure_ec;
1725*58b9f456SAndroid Build Coastguard Worker }
1726*58b9f456SAndroid Build Coastguard Worker
1727*58b9f456SAndroid Build Coastguard Worker if (!_VSTD_FS::exists(st) || !_VSTD_FS::is_symlink(st)) {
1728*58b9f456SAndroid Build Coastguard Worker __data_.__cache_type_ = directory_entry::_RefreshNonSymlink;
1729*58b9f456SAndroid Build Coastguard Worker __data_.__type_ = st.type();
1730*58b9f456SAndroid Build Coastguard Worker __data_.__non_sym_perms_ = st.permissions();
1731*58b9f456SAndroid Build Coastguard Worker } else { // we have a symlink
1732*58b9f456SAndroid Build Coastguard Worker __data_.__sym_perms_ = st.permissions();
1733*58b9f456SAndroid Build Coastguard Worker // Get the information about the linked entity.
1734*58b9f456SAndroid Build Coastguard Worker // Ignore errors from stat, since we don't want errors regarding symlink
1735*58b9f456SAndroid Build Coastguard Worker // resolution to be reported to the user.
1736*58b9f456SAndroid Build Coastguard Worker error_code ignored_ec;
1737*58b9f456SAndroid Build Coastguard Worker st = _VSTD_FS::status(__p_, ignored_ec);
1738*58b9f456SAndroid Build Coastguard Worker
1739*58b9f456SAndroid Build Coastguard Worker __data_.__type_ = st.type();
1740*58b9f456SAndroid Build Coastguard Worker __data_.__non_sym_perms_ = st.permissions();
1741*58b9f456SAndroid Build Coastguard Worker
1742*58b9f456SAndroid Build Coastguard Worker // If we failed to resolve the link, then only partially populate the
1743*58b9f456SAndroid Build Coastguard Worker // cache.
1744*58b9f456SAndroid Build Coastguard Worker if (!status_known(st)) {
1745*58b9f456SAndroid Build Coastguard Worker __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved;
1746*58b9f456SAndroid Build Coastguard Worker return error_code{};
1747*58b9f456SAndroid Build Coastguard Worker }
1748*58b9f456SAndroid Build Coastguard Worker __data_.__cache_type_ = directory_entry::_RefreshSymlink;
1749*58b9f456SAndroid Build Coastguard Worker }
1750*58b9f456SAndroid Build Coastguard Worker
1751*58b9f456SAndroid Build Coastguard Worker // FIXME: This is currently broken, and the implementation only a placeholder.
1752*58b9f456SAndroid Build Coastguard Worker // We need to cache last_write_time, file_size, and hard_link_count here before
1753*58b9f456SAndroid Build Coastguard Worker // the implementation actually works.
1754*58b9f456SAndroid Build Coastguard Worker
1755*58b9f456SAndroid Build Coastguard Worker return failure_ec;
1756*58b9f456SAndroid Build Coastguard Worker }
1757*58b9f456SAndroid Build Coastguard Worker #endif
1758*58b9f456SAndroid Build Coastguard Worker
1759*58b9f456SAndroid Build Coastguard Worker _LIBCPP_END_NAMESPACE_FILESYSTEM
1760