Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Support/Path.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- Path.cpp - Implement OS Path Concept ------------------------------===//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
//
10
//  This file implements the operating system Path API.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "llvm/Support/Path.h"
15
#include "llvm/ADT/ArrayRef.h"
16
#include "llvm/Support/Endian.h"
17
#include "llvm/Support/Errc.h"
18
#include "llvm/Support/ErrorHandling.h"
19
#include "llvm/Support/FileSystem.h"
20
#include "llvm/Support/Process.h"
21
#include <cctype>
22
#include <cstring>
23
24
#if !defined(_MSC_VER) && !defined(__MINGW32__)
25
#include <unistd.h>
26
#else
27
#include <io.h>
28
#endif
29
30
using namespace llvm;
31
using namespace llvm::support::endian;
32
33
namespace {
34
  using llvm::StringRef;
35
  using llvm::sys::path::is_separator;
36
  using llvm::sys::path::Style;
37
38
109M
  inline Style real_style(Style style) {
39
#ifdef LLVM_ON_WIN32
40
    return (style == Style::posix) ? Style::posix : Style::windows;
41
#else
42
109M
    return (style == Style::windows) ? 
Style::windows637
:
Style::posix109M
;
43
109M
#endif
44
109M
  }
45
46
16.0M
  inline const char *separators(Style style) {
47
16.0M
    if (real_style(style) == Style::windows)
48
80
      return "\\/";
49
16.0M
    return "/";
50
16.0M
  }
51
52
3.35M
  inline char preferred_separator(Style style) {
53
3.35M
    if (real_style(style) == Style::windows)
54
10
      return '\\';
55
3.35M
    return '/';
56
3.35M
  }
57
58
9.70M
  StringRef find_first_component(StringRef path, Style style) {
59
9.70M
    // Look for this first component in the following order.
60
9.70M
    // * empty (in this case we return an empty string)
61
9.70M
    // * either C: or {//,\\}net.
62
9.70M
    // * {/,\}
63
9.70M
    // * {file,directory}name
64
9.70M
65
9.70M
    if (path.empty())
66
395k
      return path;
67
9.30M
68
9.30M
    
if (9.30M
real_style(style) == Style::windows9.30M
) {
69
41
      // C:
70
41
      if (path.size() >= 2 &&
71
41
          
std::isalpha(static_cast<unsigned char>(path[0]))34
&&
path[1] == ':'2
)
72
1
        return path.substr(0, 2);
73
9.30M
    }
74
9.30M
75
9.30M
    // //net
76
9.30M
    
if (9.30M
(path.size() > 2) && 9.30M
is_separator(path[0], style)9.07M
&&
77
9.30M
        
path[0] == path[1]2.74M
&&
!is_separator(path[2], style)824
) {
78
804
      // Find the next directory separator.
79
804
      size_t end = path.find_first_of(separators(style), 2);
80
804
      return path.substr(0, end);
81
804
    }
82
9.30M
83
9.30M
    // {/,\}
84
9.30M
    
if (9.30M
is_separator(path[0], style)9.30M
)
85
2.74M
      return path.substr(0, 1);
86
6.55M
87
6.55M
    // * {file,directory}name
88
6.55M
    size_t end = path.find_first_of(separators(style));
89
6.55M
    return path.substr(0, end);
90
6.55M
  }
91
92
6.41M
  size_t filename_pos(StringRef str, Style style) {
93
6.41M
    if (
str.size() == 2 && 6.41M
is_separator(str[0], style)65
&&
str[0] == str[1]14
)
94
0
      return 0;
95
6.41M
96
6.41M
    
if (6.41M
str.size() > 0 && 6.41M
is_separator(str[str.size() - 1], style)6.38M
)
97
142k
      return str.size() - 1;
98
6.27M
99
6.27M
    size_t pos = str.find_last_of(separators(style), str.size() - 1);
100
6.27M
101
6.27M
    if (
real_style(style) == Style::windows6.27M
) {
102
9
      if (pos == StringRef::npos)
103
0
        pos = str.find_last_of(':', str.size() - 2);
104
9
    }
105
6.27M
106
6.27M
    if (
pos == StringRef::npos || 6.27M
(pos == 1 && 6.14M
is_separator(str[0], style)10.1k
))
107
122k
      return 0;
108
6.14M
109
6.14M
    return pos + 1;
110
6.14M
  }
111
112
6.46M
  size_t root_dir_start(StringRef str, Style style) {
113
6.46M
    // case "c:/"
114
6.46M
    if (
real_style(style) == Style::windows6.46M
) {
115
15
      if (
str.size() > 2 && 15
str[1] == ':'15
&&
is_separator(str[2], style)7
)
116
7
        return 2;
117
6.46M
    }
118
6.46M
119
6.46M
    // case "//"
120
6.46M
    
if (6.46M
str.size() == 2 && 6.46M
is_separator(str[0], style)10.1k
&&
str[0] == str[1]10
)
121
0
      return StringRef::npos;
122
6.46M
123
6.46M
    // case "//net"
124
6.46M
    
if (6.46M
str.size() > 3 && 6.46M
is_separator(str[0], style)6.28M
&&
str[0] == str[1]5.85M
&&
125
6.46M
        
!is_separator(str[2], style)258
) {
126
226
      return str.find_first_of(separators(style), 2);
127
226
    }
128
6.46M
129
6.46M
    // case "/"
130
6.46M
    
if (6.46M
str.size() > 0 && 6.46M
is_separator(str[0], style)6.36M
)
131
5.92M
      return 0;
132
536k
133
536k
    return StringRef::npos;
134
536k
  }
135
136
2.74M
  size_t parent_path_end(StringRef path, Style style) {
137
2.74M
    size_t end_pos = filename_pos(path, style);
138
2.74M
139
2.74M
    bool filename_was_sep =
140
2.73M
        path.size() > 0 && is_separator(path[end_pos], style);
141
2.74M
142
2.74M
    // Skip separators except for root dir.
143
2.74M
    size_t root_dir_pos = root_dir_start(path.substr(0, end_pos), style);
144
2.74M
145
5.30M
    while (
end_pos > 0 && 5.30M
(end_pos - 1) != root_dir_pos5.23M
&&
146
5.19M
           is_separator(path[end_pos - 1], style))
147
2.56M
      --end_pos;
148
2.74M
149
2.74M
    if (
end_pos == 1 && 2.74M
root_dir_pos == 043.1k
&&
filename_was_sep33.0k
)
150
0
      return StringRef::npos;
151
2.74M
152
2.74M
    return end_pos;
153
2.74M
  }
154
} // end unnamed namespace
155
156
enum FSEntity {
157
  FS_Dir,
158
  FS_File,
159
  FS_Name
160
};
161
162
static std::error_code createUniqueEntity(const Twine &Model, int &ResultFD,
163
                                          SmallVectorImpl<char> &ResultPath,
164
                                          bool MakeAbsolute, unsigned Mode,
165
34.2k
                                          FSEntity Type) {
166
34.2k
  SmallString<128> ModelStorage;
167
34.2k
  Model.toVector(ModelStorage);
168
34.2k
169
34.2k
  if (
MakeAbsolute34.2k
) {
170
6.55k
    // Make model absolute by prepending a temp directory if it's not already.
171
6.55k
    if (
!sys::path::is_absolute(Twine(ModelStorage))6.55k
) {
172
6.55k
      SmallString<128> TDir;
173
6.55k
      sys::path::system_temp_directory(true, TDir);
174
6.55k
      sys::path::append(TDir, Twine(ModelStorage));
175
6.55k
      ModelStorage.swap(TDir);
176
6.55k
    }
177
6.55k
  }
178
34.2k
179
34.2k
  // From here on, DO NOT modify model. It may be needed if the randomly chosen
180
34.2k
  // path already exists.
181
34.2k
  ResultPath = ModelStorage;
182
34.2k
  // Null terminate.
183
34.2k
  ResultPath.push_back(0);
184
34.2k
  ResultPath.pop_back();
185
34.2k
186
34.2k
retry_random_path:
187
34.2k
  // Replace '%' with random chars.
188
3.82M
  for (unsigned i = 0, e = ModelStorage.size(); 
i != e3.82M
;
++i3.78M
) {
189
3.78M
    if (ModelStorage[i] == '%')
190
255k
      ResultPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15];
191
3.78M
  }
192
34.2k
193
34.2k
  // Try to open + create the file.
194
34.2k
  switch (Type) {
195
27.3k
  case FS_File: {
196
27.3k
    if (std::error_code EC =
197
27.3k
            sys::fs::openFileForWrite(Twine(ResultPath.begin()), ResultFD,
198
73
                                      sys::fs::F_RW | sys::fs::F_Excl, Mode)) {
199
73
      if (EC == errc::file_exists)
200
0
        goto retry_random_path;
201
73
      return EC;
202
73
    }
203
27.3k
204
27.3k
    return std::error_code();
205
27.3k
  }
206
27.3k
207
6.82k
  case FS_Name: {
208
6.82k
    std::error_code EC =
209
6.82k
        sys::fs::access(ResultPath.begin(), sys::fs::AccessMode::Exist);
210
6.82k
    if (EC == errc::no_such_file_or_directory)
211
6.82k
      return std::error_code();
212
0
    
if (0
EC0
)
213
0
      return EC;
214
0
    goto retry_random_path;
215
0
  }
216
0
217
33
  case FS_Dir: {
218
33
    if (std::error_code EC =
219
0
            sys::fs::create_directory(ResultPath.begin(), false)) {
220
0
      if (EC == errc::file_exists)
221
0
        goto retry_random_path;
222
0
      return EC;
223
0
    }
224
33
    return std::error_code();
225
33
  }
226
0
  }
227
0
  
llvm_unreachable0
("Invalid Type");
228
0
}
229
230
namespace llvm {
231
namespace sys  {
232
namespace path {
233
234
9.70M
const_iterator begin(StringRef path, Style style) {
235
9.70M
  const_iterator i;
236
9.70M
  i.Path      = path;
237
9.70M
  i.Component = find_first_component(path, style);
238
9.70M
  i.Position  = 0;
239
9.70M
  i.S = style;
240
9.70M
  return i;
241
9.70M
}
242
243
9.70M
const_iterator end(StringRef path) {
244
9.70M
  const_iterator i;
245
9.70M
  i.Path      = path;
246
9.70M
  i.Position  = path.size();
247
9.70M
  return i;
248
9.70M
}
249
250
4.92M
const_iterator &const_iterator::operator++() {
251
4.92M
  assert(Position < Path.size() && "Tried to increment past end!");
252
4.92M
253
4.92M
  // Increment Position to past the current component
254
4.92M
  Position += Component.size();
255
4.92M
256
4.92M
  // Check for end.
257
4.92M
  if (
Position == Path.size()4.92M
) {
258
1.91M
    Component = StringRef();
259
1.91M
    return *this;
260
1.91M
  }
261
3.00M
262
3.00M
  // Both POSIX and Windows treat paths that begin with exactly two separators
263
3.00M
  // specially.
264
3.00M
  
bool was_net = Component.size() > 2 && 3.00M
is_separator(Component[0], S)2.89M
&&
265
3.00M
                 
Component[1] == Component[0]790
&&
!is_separator(Component[2], S)790
;
266
3.00M
267
3.00M
  // Handle separators.
268
3.00M
  if (
is_separator(Path[Position], S)3.00M
) {
269
2.92M
    // Root dir.
270
2.92M
    if (was_net ||
271
2.92M
        // c:/
272
2.92M
        
(real_style(S) == Style::windows && 2.92M
Component.endswith(":")28
)) {
273
791
      Component = Path.substr(Position, 1);
274
791
      return *this;
275
791
    }
276
2.92M
277
2.92M
    // Skip extra separators.
278
5.84M
    
while (2.92M
Position != Path.size() && 5.84M
is_separator(Path[Position], S)5.84M
) {
279
2.92M
      ++Position;
280
2.92M
    }
281
2.92M
282
2.92M
    // Treat trailing '/' as a '.'.
283
2.92M
    if (
Position == Path.size()2.92M
) {
284
57
      --Position;
285
57
      Component = ".";
286
57
      return *this;
287
57
    }
288
3.00M
  }
289
3.00M
290
3.00M
  // Find next component.
291
3.00M
  size_t end_pos = Path.find_first_of(separators(S), Position);
292
3.00M
  Component = Path.slice(Position, end_pos);
293
3.00M
294
3.00M
  return *this;
295
3.00M
}
296
297
15.3M
bool const_iterator::operator==(const const_iterator &RHS) const {
298
15.3M
  return Path.begin() == RHS.Path.begin() && Position == RHS.Position;
299
15.3M
}
300
301
240
ptrdiff_t const_iterator::operator-(const const_iterator &RHS) const {
302
240
  return Position - RHS.Position;
303
240
}
304
305
1.99M
reverse_iterator rbegin(StringRef Path, Style style) {
306
1.99M
  reverse_iterator I;
307
1.99M
  I.Path = Path;
308
1.99M
  I.Position = Path.size();
309
1.99M
  I.S = style;
310
1.99M
  return ++I;
311
1.99M
}
312
313
831k
reverse_iterator rend(StringRef Path) {
314
831k
  reverse_iterator I;
315
831k
  I.Path = Path;
316
831k
  I.Component = Path.substr(0, 0);
317
831k
  I.Position = 0;
318
831k
  return I;
319
831k
}
320
321
3.72M
reverse_iterator &reverse_iterator::operator++() {
322
3.72M
  // If we're at the end and the previous char was a '/', return '.' unless
323
3.72M
  // we are the root path.
324
3.72M
  size_t root_dir_pos = root_dir_start(Path, S);
325
3.72M
  if (
Position == Path.size() && 3.72M
Path.size() > root_dir_pos + 11.99M
&&
326
3.72M
      
is_separator(Path[Position - 1], S)1.92M
) {
327
74.7k
    --Position;
328
74.7k
    Component = ".";
329
74.7k
    return *this;
330
74.7k
  }
331
3.65M
332
3.65M
  // Skip separators unless it's the root directory.
333
3.65M
  size_t end_pos = Position;
334
3.65M
335
5.38M
  while (
end_pos > 0 && 5.38M
(end_pos - 1) != root_dir_pos5.35M
&&
336
5.32M
         is_separator(Path[end_pos - 1], S))
337
1.73M
    --end_pos;
338
3.72M
339
3.72M
  // Find next separator.
340
3.72M
  size_t start_pos = filename_pos(Path.substr(0, end_pos), S);
341
3.72M
  Component = Path.slice(start_pos, end_pos);
342
3.72M
  Position = start_pos;
343
3.72M
  return *this;
344
3.72M
}
345
346
1.73M
bool reverse_iterator::operator==(const reverse_iterator &RHS) const {
347
1.73M
  return Path.begin() == RHS.Path.begin() && Component == RHS.Component &&
348
163
         Position == RHS.Position;
349
1.73M
}
350
351
3
ptrdiff_t reverse_iterator::operator-(const reverse_iterator &RHS) const {
352
3
  return Position - RHS.Position;
353
3
}
354
355
3.29M
StringRef root_path(StringRef path, Style style) {
356
3.29M
  const_iterator b = begin(path, style), pos = b, e = end(path);
357
3.29M
  if (
b != e3.29M
) {
358
3.12M
    bool has_net =
359
3.12M
        b->size() > 2 && 
is_separator((*b)[0], style)566k
&&
(*b)[1] == (*b)[0]415
;
360
16
    bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
361
3.12M
362
3.12M
    if (
has_net || 3.12M
has_drive3.12M
) {
363
415
      if (
(++pos != e) && 415
is_separator((*pos)[0], style)411
) {
364
411
        // {C:/,//net/}, so get the first two components.
365
411
        return path.substr(0, b->size() + pos->size());
366
0
      } else {
367
4
        // just {C:,//net}, return the first component.
368
4
        return *b;
369
4
      }
370
3.12M
    }
371
3.12M
372
3.12M
    // POSIX style root directory.
373
3.12M
    
if (3.12M
is_separator((*b)[0], style)3.12M
) {
374
2.43M
      return *b;
375
2.43M
    }
376
859k
  }
377
859k
378
859k
  return StringRef();
379
859k
}
380
381
3.48M
StringRef root_name(StringRef path, Style style) {
382
3.48M
  const_iterator b = begin(path, style), e = end(path);
383
3.48M
  if (
b != e3.48M
) {
384
3.40M
    bool has_net =
385
3.40M
        b->size() > 2 && 
is_separator((*b)[0], style)3.33M
&&
(*b)[1] == (*b)[0]6
;
386
13
    bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
387
3.40M
388
3.40M
    if (
has_net || 3.40M
has_drive3.40M
) {
389
6
      // just {C:,//net}, return the first component.
390
6
      return *b;
391
6
    }
392
3.48M
  }
393
3.48M
394
3.48M
  // No path or no name.
395
3.48M
  return StringRef();
396
3.48M
}
397
398
1.73M
StringRef root_directory(StringRef path, Style style) {
399
1.73M
  const_iterator b = begin(path, style), pos = b, e = end(path);
400
1.73M
  if (
b != e1.73M
) {
401
1.62M
    bool has_net =
402
1.62M
        b->size() > 2 && 
is_separator((*b)[0], style)1.32M
&&
(*b)[1] == (*b)[0]277
;
403
3
    bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
404
1.62M
405
1.62M
    if (
(has_net || 1.62M
has_drive1.62M
) &&
406
1.62M
        // {C:,//net}, skip to the next component.
407
1.62M
        
(++pos != e)277
&&
is_separator((*pos)[0], style)270
) {
408
270
      return *pos;
409
270
    }
410
1.62M
411
1.62M
    // POSIX style root directory.
412
1.62M
    
if (1.62M
!has_net && 1.62M
is_separator((*b)[0], style)1.62M
) {
413
228k
      return *b;
414
228k
    }
415
1.50M
  }
416
1.50M
417
1.50M
  // No path or no root.
418
1.50M
  return StringRef();
419
1.50M
}
420
421
448k
StringRef relative_path(StringRef path, Style style) {
422
448k
  StringRef root = root_path(path, style);
423
448k
  return path.substr(root.size());
424
448k
}
425
426
void append(SmallVectorImpl<char> &path, Style style, const Twine &a,
427
3.59M
            const Twine &b, const Twine &c, const Twine &d) {
428
3.59M
  SmallString<32> a_storage;
429
3.59M
  SmallString<32> b_storage;
430
3.59M
  SmallString<32> c_storage;
431
3.59M
  SmallString<32> d_storage;
432
3.59M
433
3.59M
  SmallVector<StringRef, 4> components;
434
3.59M
  if (
!a.isTriviallyEmpty()3.59M
)
components.push_back(a.toStringRef(a_storage))3.59M
;
435
3.59M
  if (
!b.isTriviallyEmpty()3.59M
)
components.push_back(b.toStringRef(b_storage))406k
;
436
3.59M
  if (
!c.isTriviallyEmpty()3.59M
)
components.push_back(c.toStringRef(c_storage))361k
;
437
3.59M
  if (
!d.isTriviallyEmpty()3.59M
)
components.push_back(d.toStringRef(d_storage))136k
;
438
3.59M
439
4.50M
  for (auto &component : components) {
440
4.50M
    bool path_has_sep =
441
3.69M
        !path.empty() && is_separator(path[path.size() - 1], style);
442
4.50M
    if (
path_has_sep4.50M
) {
443
258k
      // Strip separators from beginning of component.
444
258k
      size_t loc = component.find_first_not_of(separators(style));
445
258k
      StringRef c = component.substr(loc);
446
258k
447
258k
      // Append it.
448
258k
      path.append(c.begin(), c.end());
449
258k
      continue;
450
258k
    }
451
4.24M
452
4.24M
    bool component_has_sep =
453
3.84M
        !component.empty() && is_separator(component[0], style);
454
4.24M
    if (!component_has_sep &&
455
4.24M
        
!(path.empty() || 3.95M
has_root_name(component, style)3.35M
)) {
456
3.35M
      // Add a separator.
457
3.35M
      path.push_back(preferred_separator(style));
458
3.35M
    }
459
4.50M
460
4.50M
    path.append(component.begin(), component.end());
461
4.50M
  }
462
3.59M
}
463
464
void append(SmallVectorImpl<char> &path, const Twine &a, const Twine &b,
465
2.91M
            const Twine &c, const Twine &d) {
466
2.91M
  append(path, Style::native, a, b, c, d);
467
2.91M
}
468
469
void append(SmallVectorImpl<char> &path, const_iterator begin,
470
38
            const_iterator end, Style style) {
471
329
  for (; 
begin != end329
;
++begin291
)
472
291
    path::append(path, style, *begin);
473
38
}
474
475
2.72M
StringRef parent_path(StringRef path, Style style) {
476
2.72M
  size_t end_pos = parent_path_end(path, style);
477
2.72M
  if (end_pos == StringRef::npos)
478
0
    return StringRef();
479
2.72M
  else
480
2.72M
    return path.substr(0, end_pos);
481
0
}
482
483
17.4k
void remove_filename(SmallVectorImpl<char> &path, Style style) {
484
17.4k
  size_t end_pos = parent_path_end(StringRef(path.begin(), path.size()), style);
485
17.4k
  if (end_pos != StringRef::npos)
486
17.4k
    path.set_size(end_pos);
487
17.4k
}
488
489
void replace_extension(SmallVectorImpl<char> &path, const Twine &extension,
490
22.7k
                       Style style) {
491
22.7k
  StringRef p(path.begin(), path.size());
492
22.7k
  SmallString<32> ext_storage;
493
22.7k
  StringRef ext = extension.toStringRef(ext_storage);
494
22.7k
495
22.7k
  // Erase existing extension.
496
22.7k
  size_t pos = p.find_last_of('.');
497
22.7k
  if (
pos != StringRef::npos && 22.7k
pos >= filename_pos(p, style)22.2k
)
498
21.1k
    path.set_size(pos);
499
22.7k
500
22.7k
  // Append '.' if needed.
501
22.7k
  if (
ext.size() > 0 && 22.7k
ext[0] != '.'22.0k
)
502
21.4k
    path.push_back('.');
503
22.7k
504
22.7k
  // Append extension.
505
22.7k
  path.append(ext.begin(), ext.end());
506
22.7k
}
507
508
void replace_path_prefix(SmallVectorImpl<char> &Path,
509
                         const StringRef &OldPrefix, const StringRef &NewPrefix,
510
18
                         Style style) {
511
18
  if (
OldPrefix.empty() && 18
NewPrefix.empty()1
)
512
0
    return;
513
18
514
18
  StringRef OrigPath(Path.begin(), Path.size());
515
18
  if (!OrigPath.startswith(OldPrefix))
516
3
    return;
517
15
518
15
  // If prefixes have the same size we can simply copy the new one over.
519
15
  
if (15
OldPrefix.size() == NewPrefix.size()15
) {
520
2
    std::copy(NewPrefix.begin(), NewPrefix.end(), Path.begin());
521
2
    return;
522
2
  }
523
13
524
13
  StringRef RelPath = OrigPath.substr(OldPrefix.size());
525
13
  SmallString<256> NewPath;
526
13
  path::append(NewPath, style, NewPrefix);
527
13
  path::append(NewPath, style, RelPath);
528
13
  Path.swap(NewPath);
529
13
}
530
531
503
void native(const Twine &path, SmallVectorImpl<char> &result, Style style) {
532
503
  assert((!path.isSingleStringRef() ||
533
503
          path.getSingleStringRef().data() != result.data()) &&
534
503
         "path and result are not allowed to overlap!");
535
503
  // Clear result.
536
503
  result.clear();
537
503
  path.toVector(result);
538
503
  native(result, style);
539
503
}
540
541
2.03k
void native(SmallVectorImpl<char> &Path, Style style) {
542
2.03k
  if (Path.empty())
543
1
    return;
544
2.02k
  
if (2.02k
real_style(style) == Style::windows2.02k
) {
545
113
    std::replace(Path.begin(), Path.end(), '/', '\\');
546
113
    if (
Path[0] == '~' && 113
(Path.size() == 1 || 0
is_separator(Path[1], style)0
)) {
547
0
      SmallString<128> PathHome;
548
0
      home_directory(PathHome);
549
0
      PathHome.append(Path.begin() + 1, Path.end());
550
0
      Path = PathHome;
551
0
    }
552
2.02k
  } else {
553
185k
    for (auto PI = Path.begin(), PE = Path.end(); 
PI < PE185k
;
++PI183k
) {
554
183k
      if (
*PI == '\\'183k
) {
555
20
        auto PN = PI + 1;
556
20
        if (
PN < PE && 20
*PN == '\\'16
)
557
1
          ++PI; // increment once, the for loop will move over the escaped slash
558
20
        else
559
19
          *PI = '/';
560
20
      }
561
183k
    }
562
1.91k
  }
563
2.03k
}
564
565
103
std::string convert_to_slash(StringRef path, Style style) {
566
103
  if (real_style(style) != Style::windows)
567
103
    return path;
568
0
569
0
  std::string s = path.str();
570
0
  std::replace(s.begin(), s.end(), '\\', '/');
571
0
  return s;
572
0
}
573
574
1.15M
StringRef filename(StringRef path, Style style) { return *rbegin(path, style); }
575
576
134k
StringRef stem(StringRef path, Style style) {
577
134k
  StringRef fname = filename(path, style);
578
134k
  size_t pos = fname.find_last_of('.');
579
134k
  if (pos == StringRef::npos)
580
50.1k
    return fname;
581
134k
  else
582
84.1k
    
if (84.1k
(fname.size() == 1 && 84.1k
fname == "."32
) ||
583
84.0k
        
(fname.size() == 2 && 84.0k
fname == ".."8
))
584
40
      return fname;
585
84.1k
    else
586
84.0k
      return fname.substr(0, pos);
587
0
}
588
589
519k
StringRef extension(StringRef path, Style style) {
590
519k
  StringRef fname = filename(path, style);
591
519k
  size_t pos = fname.find_last_of('.');
592
519k
  if (pos == StringRef::npos)
593
361k
    return StringRef();
594
519k
  else
595
157k
    
if (157k
(fname.size() == 1 && 157k
fname == "."45
) ||
596
157k
        
(fname.size() == 2 && 157k
fname == ".."26
))
597
71
      return StringRef();
598
157k
    else
599
157k
      return fname.substr(pos);
600
0
}
601
602
86.5M
bool is_separator(char value, Style style) {
603
86.5M
  if (value == '/')
604
30.9M
    return true;
605
55.5M
  
if (55.5M
real_style(style) == Style::windows55.5M
)
606
294
    return value == '\\';
607
55.5M
  return false;
608
55.5M
}
609
610
10.2k
StringRef get_separator(Style style) {
611
10.2k
  if (real_style(style) == Style::windows)
612
12
    return "\\";
613
10.2k
  return "/";
614
10.2k
}
615
616
3.35M
bool has_root_name(const Twine &path, Style style) {
617
3.35M
  SmallString<128> path_storage;
618
3.35M
  StringRef p = path.toStringRef(path_storage);
619
3.35M
620
3.35M
  return !root_name(p, style).empty();
621
3.35M
}
622
623
1.60M
bool has_root_directory(const Twine &path, Style style) {
624
1.60M
  SmallString<128> path_storage;
625
1.60M
  StringRef p = path.toStringRef(path_storage);
626
1.60M
627
1.60M
  return !root_directory(p, style).empty();
628
1.60M
}
629
630
40
bool has_root_path(const Twine &path, Style style) {
631
40
  SmallString<128> path_storage;
632
40
  StringRef p = path.toStringRef(path_storage);
633
40
634
40
  return !root_path(p, style).empty();
635
40
}
636
637
0
bool has_relative_path(const Twine &path, Style style) {
638
0
  SmallString<128> path_storage;
639
0
  StringRef p = path.toStringRef(path_storage);
640
0
641
0
  return !relative_path(p, style).empty();
642
0
}
643
644
40
bool has_filename(const Twine &path, Style style) {
645
40
  SmallString<128> path_storage;
646
40
  StringRef p = path.toStringRef(path_storage);
647
40
648
40
  return !filename(p, style).empty();
649
40
}
650
651
1.28k
bool has_parent_path(const Twine &path, Style style) {
652
1.28k
  SmallString<128> path_storage;
653
1.28k
  StringRef p = path.toStringRef(path_storage);
654
1.28k
655
1.28k
  return !parent_path(p, style).empty();
656
1.28k
}
657
658
52
bool has_stem(const Twine &path, Style style) {
659
52
  SmallString<128> path_storage;
660
52
  StringRef p = path.toStringRef(path_storage);
661
52
662
52
  return !stem(p, style).empty();
663
52
}
664
665
414
bool has_extension(const Twine &path, Style style) {
666
414
  SmallString<128> path_storage;
667
414
  StringRef p = path.toStringRef(path_storage);
668
414
669
414
  return !extension(p, style).empty();
670
414
}
671
672
1.45M
bool is_absolute(const Twine &path, Style style) {
673
1.45M
  SmallString<128> path_storage;
674
1.45M
  StringRef p = path.toStringRef(path_storage);
675
1.45M
676
1.45M
  bool rootDir = has_root_directory(p, style);
677
1.45M
  bool rootName =
678
3
      (real_style(style) != Style::windows) || has_root_name(p, style);
679
1.45M
680
176k
  return rootDir && rootName;
681
1.45M
}
682
683
23.5k
bool is_relative(const Twine &path, Style style) {
684
23.5k
  return !is_absolute(path, style);
685
23.5k
}
686
687
73.2k
StringRef remove_leading_dotslash(StringRef Path, Style style) {
688
73.2k
  // Remove leading "./" (or ".//" or "././" etc.)
689
73.2k
  while (
Path.size() > 2 && 73.2k
Path[0] == '.'73.2k
&&
is_separator(Path[1], style)13
) {
690
13
    Path = Path.substr(2);
691
19
    while (
Path.size() > 0 && 19
is_separator(Path[0], style)18
)
692
6
      Path = Path.substr(1);
693
13
  }
694
73.2k
  return Path;
695
73.2k
}
696
697
static SmallString<256> remove_dots(StringRef path, bool remove_dot_dot,
698
203k
                                    Style style) {
699
203k
  SmallVector<StringRef, 16> components;
700
203k
701
203k
  // Skip the root path, then look for traversal in the components.
702
203k
  StringRef rel = path::relative_path(path, style);
703
203k
  for (StringRef C :
704
712k
       llvm::make_range(path::begin(rel, style), path::end(rel))) {
705
712k
    if (C == ".")
706
28.2k
      continue;
707
684k
    // Leading ".." will remain in the path unless it's at the root.
708
684k
    
if (684k
remove_dot_dot && 684k
C == ".."430k
) {
709
705
      if (
!components.empty() && 705
components.back() != ".."698
) {
710
696
        components.pop_back();
711
696
        continue;
712
696
      }
713
9
      
if (9
path::is_absolute(path, style)9
)
714
3
        continue;
715
683k
    }
716
683k
    components.push_back(C);
717
683k
  }
718
203k
719
203k
  SmallString<256> buffer = path::root_path(path, style);
720
203k
  for (StringRef C : components)
721
682k
    path::append(buffer, style, C);
722
203k
  return buffer;
723
203k
}
724
725
bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot,
726
203k
                 Style style) {
727
203k
  StringRef p(path.data(), path.size());
728
203k
729
203k
  SmallString<256> result = remove_dots(p, remove_dot_dot, style);
730
203k
  if (result == path)
731
175k
    return false;
732
28.7k
733
28.7k
  path.swap(result);
734
28.7k
  return true;
735
28.7k
}
736
737
} // end namespace path
738
739
namespace fs {
740
741
3.00k
std::error_code getUniqueID(const Twine Path, UniqueID &Result) {
742
3.00k
  file_status Status;
743
3.00k
  std::error_code EC = status(Path, Status);
744
3.00k
  if (EC)
745
0
    return EC;
746
3.00k
  Result = Status.getUniqueID();
747
3.00k
  return std::error_code();
748
3.00k
}
749
750
std::error_code createUniqueFile(const Twine &Model, int &ResultFd,
751
                                 SmallVectorImpl<char> &ResultPath,
752
27.2k
                                 unsigned Mode) {
753
27.2k
  return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File);
754
27.2k
}
755
756
std::error_code createUniqueFile(const Twine &Model,
757
470
                                 SmallVectorImpl<char> &ResultPath) {
758
470
  int Dummy;
759
470
  return createUniqueEntity(Model, Dummy, ResultPath, false, 0, FS_Name);
760
470
}
761
762
static std::error_code
763
createTemporaryFile(const Twine &Model, int &ResultFD,
764
6.52k
                    llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) {
765
6.52k
  SmallString<128> Storage;
766
6.52k
  StringRef P = Model.toNullTerminatedStringRef(Storage);
767
6.52k
  assert(P.find_first_of(separators(Style::native)) == StringRef::npos &&
768
6.52k
         "Model must be a simple filename.");
769
6.52k
  // Use P.begin() so that createUniqueEntity doesn't need to recreate Storage.
770
6.52k
  return createUniqueEntity(P.begin(), ResultFD, ResultPath,
771
6.52k
                            true, owner_read | owner_write, Type);
772
6.52k
}
773
774
static std::error_code
775
createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD,
776
6.52k
                    llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) {
777
6.52k
  const char *Middle = Suffix.empty() ? 
"-%%%%%%"20
:
"-%%%%%%."6.50k
;
778
6.52k
  return createTemporaryFile(Prefix + Middle + Suffix, ResultFD, ResultPath,
779
6.52k
                             Type);
780
6.52k
}
781
782
std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
783
                                    int &ResultFD,
784
173
                                    SmallVectorImpl<char> &ResultPath) {
785
173
  return createTemporaryFile(Prefix, Suffix, ResultFD, ResultPath, FS_File);
786
173
}
787
788
std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
789
6.35k
                                    SmallVectorImpl<char> &ResultPath) {
790
6.35k
  int Dummy;
791
6.35k
  return createTemporaryFile(Prefix, Suffix, Dummy, ResultPath, FS_Name);
792
6.35k
}
793
794
795
// This is a mkdtemp with a different pattern. We use createUniqueEntity mostly
796
// for consistency. We should try using mkdtemp.
797
std::error_code createUniqueDirectory(const Twine &Prefix,
798
33
                                      SmallVectorImpl<char> &ResultPath) {
799
33
  int Dummy;
800
33
  return createUniqueEntity(Prefix + "-%%%%%%", Dummy, ResultPath,
801
33
                            true, 0, FS_Dir);
802
33
}
803
804
static std::error_code make_absolute(const Twine &current_directory,
805
                                     SmallVectorImpl<char> &path,
806
152k
                                     bool use_current_directory) {
807
152k
  StringRef p(path.data(), path.size());
808
152k
809
152k
  bool rootDirectory = path::has_root_directory(p);
810
152k
  bool rootName =
811
0
      (real_style(Style::native) != Style::windows) || path::has_root_name(p);
812
152k
813
152k
  // Already absolute.
814
152k
  if (
rootName && 152k
rootDirectory152k
)
815
31.1k
    return std::error_code();
816
121k
817
121k
  // All of the following conditions will need the current directory.
818
121k
  SmallString<128> current_dir;
819
121k
  if (use_current_directory)
820
121k
    current_directory.toVector(current_dir);
821
111
  else 
if (std::error_code 111
ec111
= current_path(current_dir))
822
0
    return ec;
823
121k
824
121k
  // Relative path. Prepend the current directory.
825
121k
  
if (121k
!rootName && 121k
!rootDirectory0
) {
826
0
    // Append path to the current directory.
827
0
    path::append(current_dir, p);
828
0
    // Set path to the result.
829
0
    path.swap(current_dir);
830
0
    return std::error_code();
831
0
  }
832
121k
833
121k
  
if (121k
!rootName && 121k
rootDirectory0
) {
834
0
    StringRef cdrn = path::root_name(current_dir);
835
0
    SmallString<128> curDirRootName(cdrn.begin(), cdrn.end());
836
0
    path::append(curDirRootName, p);
837
0
    // Set path to the result.
838
0
    path.swap(curDirRootName);
839
0
    return std::error_code();
840
0
  }
841
121k
842
121k
  
if (121k
rootName && 121k
!rootDirectory121k
) {
843
121k
    StringRef pRootName      = path::root_name(p);
844
121k
    StringRef bRootDirectory = path::root_directory(current_dir);
845
121k
    StringRef bRelativePath  = path::relative_path(current_dir);
846
121k
    StringRef pRelativePath  = path::relative_path(p);
847
121k
848
121k
    SmallString<128> res;
849
121k
    path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath);
850
121k
    path.swap(res);
851
121k
    return std::error_code();
852
121k
  }
853
0
854
0
  
llvm_unreachable0
("All rootName and rootDirectory combinations should have "
855
0
                   "occurred above!");
856
0
}
857
858
std::error_code make_absolute(const Twine &current_directory,
859
121k
                              SmallVectorImpl<char> &path) {
860
121k
  return make_absolute(current_directory, path, true);
861
121k
}
862
863
31.2k
std::error_code make_absolute(SmallVectorImpl<char> &path) {
864
31.2k
  return make_absolute(Twine(), path, false);
865
31.2k
}
866
867
std::error_code create_directories(const Twine &Path, bool IgnoreExisting,
868
2.41k
                                   perms Perms) {
869
2.41k
  SmallString<128> PathStorage;
870
2.41k
  StringRef P = Path.toStringRef(PathStorage);
871
2.41k
872
2.41k
  // Be optimistic and try to create the directory
873
2.41k
  std::error_code EC = create_directory(P, IgnoreExisting, Perms);
874
2.41k
  // If we succeeded, or had any error other than the parent not existing, just
875
2.41k
  // return it.
876
2.41k
  if (EC != errc::no_such_file_or_directory)
877
1.80k
    return EC;
878
618
879
618
  // We failed because of a no_such_file_or_directory, try to create the
880
618
  // parent.
881
618
  StringRef Parent = path::parent_path(P);
882
618
  if (Parent.empty())
883
0
    return EC;
884
618
885
618
  
if (618
(EC = create_directories(Parent, IgnoreExisting, Perms))618
)
886
0
      return EC;
887
618
888
618
  return create_directory(P, IgnoreExisting, Perms);
889
618
}
890
891
514
std::error_code copy_file(const Twine &From, const Twine &To) {
892
514
  int ReadFD, WriteFD;
893
514
  if (std::error_code EC = openFileForRead(From, ReadFD))
894
4
    return EC;
895
510
  
if (std::error_code 510
EC510
= openFileForWrite(To, WriteFD, F_None)) {
896
0
    close(ReadFD);
897
0
    return EC;
898
0
  }
899
510
900
510
  const size_t BufSize = 4096;
901
510
  char *Buf = new char[BufSize];
902
510
  int BytesRead = 0, BytesWritten = 0;
903
2.39k
  for (;;) {
904
2.39k
    BytesRead = read(ReadFD, Buf, BufSize);
905
2.39k
    if (BytesRead <= 0)
906
510
      break;
907
3.76k
    
while (1.88k
BytesRead3.76k
) {
908
1.88k
      BytesWritten = write(WriteFD, Buf, BytesRead);
909
1.88k
      if (BytesWritten < 0)
910
0
        break;
911
1.88k
      BytesRead -= BytesWritten;
912
1.88k
    }
913
1.88k
    if (BytesWritten < 0)
914
0
      break;
915
510
  }
916
510
  close(ReadFD);
917
510
  close(WriteFD);
918
510
  delete[] Buf;
919
510
920
510
  if (
BytesRead < 0 || 510
BytesWritten < 0510
)
921
0
    return std::error_code(errno, std::generic_category());
922
510
  return std::error_code();
923
510
}
924
925
1
ErrorOr<MD5::MD5Result> md5_contents(int FD) {
926
1
  MD5 Hash;
927
1
928
1
  constexpr size_t BufSize = 4096;
929
1
  std::vector<uint8_t> Buf(BufSize);
930
1
  int BytesRead = 0;
931
2
  for (;;) {
932
2
    BytesRead = read(FD, Buf.data(), BufSize);
933
2
    if (BytesRead <= 0)
934
1
      break;
935
1
    Hash.update(makeArrayRef(Buf.data(), BytesRead));
936
1
  }
937
1
938
1
  if (BytesRead < 0)
939
0
    return std::error_code(errno, std::generic_category());
940
1
  MD5::MD5Result Result;
941
1
  Hash.final(Result);
942
1
  return Result;
943
1
}
944
945
0
ErrorOr<MD5::MD5Result> md5_contents(const Twine &Path) {
946
0
  int FD;
947
0
  if (auto EC = openFileForRead(Path, FD))
948
0
    return EC;
949
0
950
0
  auto Result = md5_contents(FD);
951
0
  close(FD);
952
0
  return Result;
953
0
}
954
955
21.1k
bool exists(file_status status) {
956
21.1k
  return status_known(status) && status.type() != file_type::file_not_found;
957
21.1k
}
958
959
21.1k
bool status_known(file_status s) {
960
21.1k
  return s.type() != file_type::status_error;
961
21.1k
}
962
963
0
file_type get_file_type(const Twine &Path, bool Follow) {
964
0
  file_status st;
965
0
  if (status(Path, st, Follow))
966
0
    return file_type::status_error;
967
0
  return st.type();
968
0
}
969
970
4.10k
bool is_directory(file_status status) {
971
4.10k
  return status.type() == file_type::directory_file;
972
4.10k
}
973
974
4.31k
std::error_code is_directory(const Twine &path, bool &result) {
975
4.31k
  file_status st;
976
4.31k
  if (std::error_code ec = status(path, st))
977
290
    return ec;
978
4.02k
  result = is_directory(st);
979
4.02k
  return std::error_code();
980
4.02k
}
981
982
3.00k
bool is_regular_file(file_status status) {
983
3.00k
  return status.type() == file_type::regular_file;
984
3.00k
}
985
986
2.03k
std::error_code is_regular_file(const Twine &path, bool &result) {
987
2.03k
  file_status st;
988
2.03k
  if (std::error_code ec = status(path, st))
989
0
    return ec;
990
2.03k
  result = is_regular_file(st);
991
2.03k
  return std::error_code();
992
2.03k
}
993
994
0
bool is_symlink_file(file_status status) {
995
0
  return status.type() == file_type::symlink_file;
996
0
}
997
998
0
std::error_code is_symlink_file(const Twine &path, bool &result) {
999
0
  file_status st;
1000
0
  if (std::error_code ec = status(path, st, false))
1001
0
    return ec;
1002
0
  result = is_symlink_file(st);
1003
0
  return std::error_code();
1004
0
}
1005
1006
0
bool is_other(file_status status) {
1007
0
  return exists(status) &&
1008
0
         !is_regular_file(status) &&
1009
0
         !is_directory(status);
1010
0
}
1011
1012
0
std::error_code is_other(const Twine &Path, bool &Result) {
1013
0
  file_status FileStatus;
1014
0
  if (std::error_code EC = status(Path, FileStatus))
1015
0
    return EC;
1016
0
  Result = is_other(FileStatus);
1017
0
  return std::error_code();
1018
0
}
1019
1020
8.94k
void directory_entry::replace_filename(const Twine &filename, file_status st) {
1021
8.94k
  SmallString<128> path = path::parent_path(Path);
1022
8.94k
  path::append(path, filename);
1023
8.94k
  Path = path.str();
1024
8.94k
  Status = st;
1025
8.94k
}
1026
1027
6.29k
std::error_code directory_entry::status(file_status &result) const {
1028
6.29k
  return fs::status(Path, result, FollowSymlinks);
1029
6.29k
}
1030
1031
25
ErrorOr<perms> getPermissions(const Twine &Path) {
1032
25
  file_status Status;
1033
25
  if (std::error_code EC = status(Path, Status))
1034
0
    return EC;
1035
25
1036
25
  return Status.permissions();
1037
25
}
1038
1039
} // end namespace fs
1040
} // end namespace sys
1041
} // end namespace llvm
1042
1043
// Include the truly platform-specific parts.
1044
#if defined(LLVM_ON_UNIX)
1045
#include "Unix/Path.inc"
1046
#endif
1047
#if defined(LLVM_ON_WIN32)
1048
#include "Windows/Path.inc"
1049
#endif
1050
1051
namespace llvm {
1052
namespace sys {
1053
namespace path {
1054
1055
bool user_cache_directory(SmallVectorImpl<char> &Result, const Twine &Path1,
1056
4
                          const Twine &Path2, const Twine &Path3) {
1057
4
  if (
getUserCacheDir(Result)4
) {
1058
4
    append(Result, Path1, Path2, Path3);
1059
4
    return true;
1060
4
  }
1061
0
  return false;
1062
0
}
1063
1064
} // end namespace path
1065
} // end namsspace sys
1066
} // end namespace llvm