Coverage Report

Created: 2025-11-16 07:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/keystone/llvm/lib/Support/Path.cpp
Line
Count
Source
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/COFF.h"
15
#include "llvm/Support/MachO.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/Path.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_ks;
31
using namespace llvm_ks::support::endian;
32
33
namespace {
34
  using llvm_ks::StringRef;
35
  using llvm_ks::sys::path::is_separator;
36
37
#ifdef LLVM_ON_WIN32
38
  const char *separators = "\\/";
39
  const char preferred_separator = '\\';
40
#else
41
  const char  separators = '/';
42
  const char preferred_separator = '/';
43
#endif
44
45
117k
  StringRef find_first_component(StringRef path) {
46
    // Look for this first component in the following order.
47
    // * empty (in this case we return an empty string)
48
    // * either C: or {//,\\}net.
49
    // * {/,\}
50
    // * {file,directory}name
51
52
117k
    if (path.empty())
53
0
      return path;
54
55
#ifdef LLVM_ON_WIN32
56
    // C:
57
    if (path.size() >= 2 && std::isalpha(static_cast<unsigned char>(path[0])) &&
58
        path[1] == ':')
59
      return path.substr(0, 2);
60
#endif
61
62
    // //net
63
117k
    if ((path.size() > 2) &&
64
117k
        is_separator(path[0]) &&
65
117k
        path[0] == path[1] &&
66
0
        !is_separator(path[2])) {
67
      // Find the next directory separator.
68
0
      size_t end = path.find_first_of(separators, 2);
69
0
      return path.substr(0, end);
70
0
    }
71
72
    // {/,\}
73
117k
    if (is_separator(path[0]))
74
117k
      return path.substr(0, 1);
75
76
    // * {file,directory}name
77
0
    size_t end = path.find_first_of(separators);
78
0
    return path.substr(0, end);
79
117k
  }
80
81
0
  size_t filename_pos(StringRef str) {
82
0
    if (str.size() == 2 &&
83
0
        is_separator(str[0]) &&
84
0
        str[0] == str[1])
85
0
      return 0;
86
87
0
    if (str.size() > 0 && is_separator(str[str.size() - 1]))
88
0
      return str.size() - 1;
89
90
0
    size_t pos = str.find_last_of(separators, str.size() - 1);
91
92
#ifdef LLVM_ON_WIN32
93
    if (pos == StringRef::npos)
94
      pos = str.find_last_of(':', str.size() - 2);
95
#endif
96
97
0
    if (pos == StringRef::npos ||
98
0
        (pos == 1 && is_separator(str[0])))
99
0
      return 0;
100
101
0
    return pos + 1;
102
0
  }
103
104
0
  size_t root_dir_start(StringRef str) {
105
    // case "c:/"
106
#ifdef LLVM_ON_WIN32
107
    if (str.size() > 2 &&
108
        str[1] == ':' &&
109
        is_separator(str[2]))
110
      return 2;
111
#endif
112
113
    // case "//"
114
0
    if (str.size() == 2 &&
115
0
        is_separator(str[0]) &&
116
0
        str[0] == str[1])
117
0
      return StringRef::npos;
118
119
    // case "//net"
120
0
    if (str.size() > 3 &&
121
0
        is_separator(str[0]) &&
122
0
        str[0] == str[1] &&
123
0
        !is_separator(str[2])) {
124
0
      return str.find_first_of(separators, 2);
125
0
    }
126
127
    // case "/"
128
0
    if (str.size() > 0 && is_separator(str[0]))
129
0
      return 0;
130
131
0
    return StringRef::npos;
132
0
  }
133
134
0
  size_t parent_path_end(StringRef path) {
135
0
    size_t end_pos = filename_pos(path);
136
137
0
    bool filename_was_sep = path.size() > 0 && is_separator(path[end_pos]);
138
139
    // Skip separators except for root dir.
140
0
    size_t root_dir_pos = root_dir_start(path.substr(0, end_pos));
141
142
0
    while(end_pos > 0 &&
143
0
          (end_pos - 1) != root_dir_pos &&
144
0
          is_separator(path[end_pos - 1]))
145
0
      --end_pos;
146
147
0
    if (end_pos == 1 && root_dir_pos == 0 && filename_was_sep)
148
0
      return StringRef::npos;
149
150
0
    return end_pos;
151
0
  }
152
} // end unnamed namespace
153
154
enum FSEntity {
155
  FS_Dir,
156
  FS_File,
157
  FS_Name
158
};
159
160
static std::error_code createUniqueEntity(const Twine &Model, int &ResultFD,
161
                                          SmallVectorImpl<char> &ResultPath,
162
                                          bool MakeAbsolute, unsigned Mode,
163
0
                                          FSEntity Type) {
164
0
  SmallString<128> ModelStorage;
165
0
  Model.toVector(ModelStorage);
166
167
0
  if (MakeAbsolute) {
168
    // Make model absolute by prepending a temp directory if it's not already.
169
0
    if (!sys::path::is_absolute(Twine(ModelStorage))) {
170
0
      SmallString<128> TDir;
171
0
      sys::path::system_temp_directory(true, TDir);
172
0
      sys::path::append(TDir, Twine(ModelStorage));
173
0
      ModelStorage.swap(TDir);
174
0
    }
175
0
  }
176
177
  // From here on, DO NOT modify model. It may be needed if the randomly chosen
178
  // path already exists.
179
0
  ResultPath = ModelStorage;
180
  // Null terminate.
181
0
  ResultPath.push_back(0);
182
0
  ResultPath.pop_back();
183
184
0
retry_random_path:
185
  // Replace '%' with random chars.
186
0
  for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) {
187
0
    if (ModelStorage[i] == '%')
188
0
      ResultPath[i] = "0123456789abcdef"[8888 & 15];
189
0
  }
190
191
  // Try to open + create the file.
192
0
  switch (Type) {
193
0
  case FS_File: {
194
0
    if (std::error_code EC =
195
0
            sys::fs::openFileForWrite(Twine(ResultPath.begin()), ResultFD,
196
0
                                      sys::fs::F_RW | sys::fs::F_Excl, Mode)) {
197
0
      if (EC == errc::file_exists)
198
0
        goto retry_random_path;
199
0
      return EC;
200
0
    }
201
202
0
    return std::error_code();
203
0
  }
204
205
0
  case FS_Name: {
206
0
    std::error_code EC =
207
0
        sys::fs::access(ResultPath.begin(), sys::fs::AccessMode::Exist);
208
0
    if (EC == errc::no_such_file_or_directory)
209
0
      return std::error_code();
210
0
    if (EC)
211
0
      return EC;
212
0
    goto retry_random_path;
213
0
  }
214
215
0
  case FS_Dir: {
216
0
    if (std::error_code EC =
217
0
            sys::fs::create_directory(ResultPath.begin(), false)) {
218
0
      if (EC == errc::file_exists)
219
0
        goto retry_random_path;
220
0
      return EC;
221
0
    }
222
0
    return std::error_code();
223
0
  }
224
0
  }
225
0
  llvm_unreachable("Invalid Type");
226
0
}
227
228
namespace llvm_ks {
229
namespace sys  {
230
namespace path {
231
232
117k
const_iterator begin(StringRef path) {
233
117k
  const_iterator i;
234
117k
  i.Path      = path;
235
117k
  i.Component = find_first_component(path);
236
117k
  i.Position  = 0;
237
117k
  return i;
238
117k
}
239
240
117k
const_iterator end(StringRef path) {
241
117k
  const_iterator i;
242
117k
  i.Path      = path;
243
117k
  i.Position  = path.size();
244
117k
  return i;
245
117k
}
246
247
0
const_iterator &const_iterator::operator++() {
248
0
  assert(Position < Path.size() && "Tried to increment past end!");
249
250
  // Increment Position to past the current component
251
0
  Position += Component.size();
252
253
  // Check for end.
254
0
  if (Position == Path.size()) {
255
0
    Component = StringRef();
256
0
    return *this;
257
0
  }
258
259
  // Both POSIX and Windows treat paths that begin with exactly two separators
260
  // specially.
261
0
  bool was_net = Component.size() > 2 &&
262
0
    is_separator(Component[0]) &&
263
0
    Component[1] == Component[0] &&
264
0
    !is_separator(Component[2]);
265
266
  // Handle separators.
267
0
  if (is_separator(Path[Position])) {
268
    // Root dir.
269
0
    if (was_net
270
#ifdef LLVM_ON_WIN32
271
        // c:/
272
        || Component.endswith(":")
273
#endif
274
0
        ) {
275
0
      Component = Path.substr(Position, 1);
276
0
      return *this;
277
0
    }
278
279
    // Skip extra separators.
280
0
    while (Position != Path.size() &&
281
0
           is_separator(Path[Position])) {
282
0
      ++Position;
283
0
    }
284
285
    // Treat trailing '/' as a '.'.
286
0
    if (Position == Path.size()) {
287
0
      --Position;
288
0
      Component = ".";
289
0
      return *this;
290
0
    }
291
0
  }
292
293
  // Find next component.
294
0
  size_t end_pos = Path.find_first_of(separators, Position);
295
0
  Component = Path.slice(Position, end_pos);
296
297
0
  return *this;
298
0
}
299
300
117k
bool const_iterator::operator==(const const_iterator &RHS) const {
301
117k
  return Path.begin() == RHS.Path.begin() && Position == RHS.Position;
302
117k
}
303
304
0
ptrdiff_t const_iterator::operator-(const const_iterator &RHS) const {
305
0
  return Position - RHS.Position;
306
0
}
307
308
0
reverse_iterator rbegin(StringRef Path) {
309
0
  reverse_iterator I;
310
0
  I.Path = Path;
311
0
  I.Position = Path.size();
312
0
  return ++I;
313
0
}
314
315
0
reverse_iterator rend(StringRef Path) {
316
0
  reverse_iterator I;
317
0
  I.Path = Path;
318
0
  I.Component = Path.substr(0, 0);
319
0
  I.Position = 0;
320
0
  return I;
321
0
}
322
323
0
reverse_iterator &reverse_iterator::operator++() {
324
  // If we're at the end and the previous char was a '/', return '.' unless
325
  // we are the root path.
326
0
  size_t root_dir_pos = root_dir_start(Path);
327
0
  if (Position == Path.size() &&
328
0
      Path.size() > root_dir_pos + 1 &&
329
0
      is_separator(Path[Position - 1])) {
330
0
    --Position;
331
0
    Component = ".";
332
0
    return *this;
333
0
  }
334
335
  // Skip separators unless it's the root directory.
336
0
  size_t end_pos = Position;
337
338
0
  while(end_pos > 0 &&
339
0
        (end_pos - 1) != root_dir_pos &&
340
0
        is_separator(Path[end_pos - 1]))
341
0
    --end_pos;
342
343
  // Find next separator.
344
0
  size_t start_pos = filename_pos(Path.substr(0, end_pos));
345
0
  Component = Path.slice(start_pos, end_pos);
346
0
  Position = start_pos;
347
0
  return *this;
348
0
}
349
350
0
bool reverse_iterator::operator==(const reverse_iterator &RHS) const {
351
0
  return Path.begin() == RHS.Path.begin() && Component == RHS.Component &&
352
0
         Position == RHS.Position;
353
0
}
354
355
0
StringRef root_path(StringRef path) {
356
0
  const_iterator b = begin(path),
357
0
                 pos = b,
358
0
                 e = end(path);
359
0
  if (b != e) {
360
0
    bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0];
361
0
    bool has_drive =
362
#ifdef LLVM_ON_WIN32
363
      b->endswith(":");
364
#else
365
0
      false;
366
0
#endif
367
368
0
    if (has_net || has_drive) {
369
0
      if ((++pos != e) && is_separator((*pos)[0])) {
370
        // {C:/,//net/}, so get the first two components.
371
0
        return path.substr(0, b->size() + pos->size());
372
0
      } else {
373
        // just {C:,//net}, return the first component.
374
0
        return *b;
375
0
      }
376
0
    }
377
378
    // POSIX style root directory.
379
0
    if (is_separator((*b)[0])) {
380
0
      return *b;
381
0
    }
382
0
  }
383
384
0
  return StringRef();
385
0
}
386
387
0
StringRef root_name(StringRef path) {
388
0
  const_iterator b = begin(path),
389
0
                 e = end(path);
390
0
  if (b != e) {
391
0
    bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0];
392
0
    bool has_drive =
393
#ifdef LLVM_ON_WIN32
394
      b->endswith(":");
395
#else
396
0
      false;
397
0
#endif
398
399
0
    if (has_net || has_drive) {
400
      // just {C:,//net}, return the first component.
401
0
      return *b;
402
0
    }
403
0
  }
404
405
  // No path or no name.
406
0
  return StringRef();
407
0
}
408
409
117k
StringRef root_directory(StringRef path) {
410
117k
  const_iterator b = begin(path),
411
117k
                 pos = b,
412
117k
                 e = end(path);
413
117k
  if (b != e) {
414
117k
    bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0];
415
117k
    bool has_drive =
416
#ifdef LLVM_ON_WIN32
417
      b->endswith(":");
418
#else
419
117k
      false;
420
117k
#endif
421
422
117k
    if ((has_net || has_drive) &&
423
        // {C:,//net}, skip to the next component.
424
0
        (++pos != e) && is_separator((*pos)[0])) {
425
0
      return *pos;
426
0
    }
427
428
    // POSIX style root directory.
429
117k
    if (!has_net && is_separator((*b)[0])) {
430
117k
      return *b;
431
117k
    }
432
117k
  }
433
434
  // No path or no root.
435
0
  return StringRef();
436
117k
}
437
438
0
StringRef relative_path(StringRef path) {
439
0
  StringRef root = root_path(path);
440
0
  return path.substr(root.size());
441
0
}
442
443
void append(SmallVectorImpl<char> &path, const Twine &a,
444
                                         const Twine &b,
445
                                         const Twine &c,
446
0
                                         const Twine &d) {
447
0
  SmallString<32> a_storage;
448
0
  SmallString<32> b_storage;
449
0
  SmallString<32> c_storage;
450
0
  SmallString<32> d_storage;
451
452
0
  SmallVector<StringRef, 4> components;
453
0
  if (!a.isTriviallyEmpty()) components.push_back(a.toStringRef(a_storage));
454
0
  if (!b.isTriviallyEmpty()) components.push_back(b.toStringRef(b_storage));
455
0
  if (!c.isTriviallyEmpty()) components.push_back(c.toStringRef(c_storage));
456
0
  if (!d.isTriviallyEmpty()) components.push_back(d.toStringRef(d_storage));
457
458
0
  for (auto &component : components) {
459
0
    bool path_has_sep = !path.empty() && is_separator(path[path.size() - 1]);
460
0
    bool component_has_sep = !component.empty() && is_separator(component[0]);
461
0
    bool is_root_name = has_root_name(component);
462
463
0
    if (path_has_sep) {
464
      // Strip separators from beginning of component.
465
0
      size_t loc = component.find_first_not_of(separators);
466
0
      StringRef c = component.substr(loc);
467
468
      // Append it.
469
0
      path.append(c.begin(), c.end());
470
0
      continue;
471
0
    }
472
473
0
    if (!component_has_sep && !(path.empty() || is_root_name)) {
474
      // Add a separator.
475
0
      path.push_back(preferred_separator);
476
0
    }
477
478
0
    path.append(component.begin(), component.end());
479
0
  }
480
0
}
481
482
void append(SmallVectorImpl<char> &path,
483
0
            const_iterator begin, const_iterator end) {
484
0
  for (; begin != end; ++begin)
485
0
    path::append(path, *begin);
486
0
}
487
488
0
StringRef parent_path(StringRef path) {
489
0
  size_t end_pos = parent_path_end(path);
490
0
  if (end_pos == StringRef::npos)
491
0
    return StringRef();
492
0
  else
493
0
    return path.substr(0, end_pos);
494
0
}
495
496
0
void remove_filename(SmallVectorImpl<char> &path) {
497
0
  size_t end_pos = parent_path_end(StringRef(path.begin(), path.size()));
498
0
  if (end_pos != StringRef::npos)
499
0
    path.set_size(end_pos);
500
0
}
501
502
0
void replace_extension(SmallVectorImpl<char> &path, const Twine &extension) {
503
0
  StringRef p(path.begin(), path.size());
504
0
  SmallString<32> ext_storage;
505
0
  StringRef ext = extension.toStringRef(ext_storage);
506
507
  // Erase existing extension.
508
0
  size_t pos = p.find_last_of('.');
509
0
  if (pos != StringRef::npos && pos >= filename_pos(p))
510
0
    path.set_size(pos);
511
512
  // Append '.' if needed.
513
0
  if (ext.size() > 0 && ext[0] != '.')
514
0
    path.push_back('.');
515
516
  // Append extension.
517
0
  path.append(ext.begin(), ext.end());
518
0
}
519
520
0
void native(const Twine &path, SmallVectorImpl<char> &result) {
521
0
  assert((!path.isSingleStringRef() ||
522
0
          path.getSingleStringRef().data() != result.data()) &&
523
0
         "path and result are not allowed to overlap!");
524
  // Clear result.
525
0
  result.clear();
526
0
  path.toVector(result);
527
0
  native(result);
528
0
}
529
530
0
void native(SmallVectorImpl<char> &Path) {
531
#ifdef LLVM_ON_WIN32
532
  std::replace(Path.begin(), Path.end(), '/', '\\');
533
#else
534
0
  for (auto PI = Path.begin(), PE = Path.end(); PI < PE; ++PI) {
535
0
    if (*PI == '\\') {
536
0
      auto PN = PI + 1;
537
0
      if (PN < PE && *PN == '\\')
538
0
        ++PI; // increment once, the for loop will move over the escaped slash
539
0
      else
540
0
        *PI = '/';
541
0
    }
542
0
  }
543
0
#endif
544
0
}
545
546
0
StringRef filename(StringRef path) {
547
0
  return *rbegin(path);
548
0
}
549
550
0
StringRef stem(StringRef path) {
551
0
  StringRef fname = filename(path);
552
0
  size_t pos = fname.find_last_of('.');
553
0
  if (pos == StringRef::npos)
554
0
    return fname;
555
0
  else
556
0
    if ((fname.size() == 1 && fname == ".") ||
557
0
        (fname.size() == 2 && fname == ".."))
558
0
      return fname;
559
0
    else
560
0
      return fname.substr(0, pos);
561
0
}
562
563
0
StringRef extension(StringRef path) {
564
0
  StringRef fname = filename(path);
565
0
  size_t pos = fname.find_last_of('.');
566
0
  if (pos == StringRef::npos)
567
0
    return StringRef();
568
0
  else
569
0
    if ((fname.size() == 1 && fname == ".") ||
570
0
        (fname.size() == 2 && fname == ".."))
571
0
      return StringRef();
572
0
    else
573
0
      return fname.substr(pos);
574
0
}
575
576
351k
bool is_separator(char value) {
577
351k
  switch(value) {
578
#ifdef LLVM_ON_WIN32
579
    case '\\': // fall through
580
#endif
581
351k
    case '/': return true;
582
0
    default: return false;
583
351k
  }
584
351k
}
585
586
static const char preferred_separator_string[] = { preferred_separator, '\0' };
587
588
0
StringRef get_separator() {
589
0
  return preferred_separator_string;
590
0
}
591
592
0
bool has_root_name(const Twine &path) {
593
0
  SmallString<128> path_storage;
594
0
  StringRef p = path.toStringRef(path_storage);
595
596
0
  return !root_name(p).empty();
597
0
}
598
599
117k
bool has_root_directory(const Twine &path) {
600
117k
  SmallString<128> path_storage;
601
117k
  StringRef p = path.toStringRef(path_storage);
602
603
117k
  return !root_directory(p).empty();
604
117k
}
605
606
0
bool has_root_path(const Twine &path) {
607
0
  SmallString<128> path_storage;
608
0
  StringRef p = path.toStringRef(path_storage);
609
610
0
  return !root_path(p).empty();
611
0
}
612
613
0
bool has_relative_path(const Twine &path) {
614
0
  SmallString<128> path_storage;
615
0
  StringRef p = path.toStringRef(path_storage);
616
617
0
  return !relative_path(p).empty();
618
0
}
619
620
0
bool has_filename(const Twine &path) {
621
0
  SmallString<128> path_storage;
622
0
  StringRef p = path.toStringRef(path_storage);
623
624
0
  return !filename(p).empty();
625
0
}
626
627
0
bool has_parent_path(const Twine &path) {
628
0
  SmallString<128> path_storage;
629
0
  StringRef p = path.toStringRef(path_storage);
630
631
0
  return !parent_path(p).empty();
632
0
}
633
634
0
bool has_stem(const Twine &path) {
635
0
  SmallString<128> path_storage;
636
0
  StringRef p = path.toStringRef(path_storage);
637
638
0
  return !stem(p).empty();
639
0
}
640
641
0
bool has_extension(const Twine &path) {
642
0
  SmallString<128> path_storage;
643
0
  StringRef p = path.toStringRef(path_storage);
644
645
0
  return !extension(p).empty();
646
0
}
647
648
117k
bool is_absolute(const Twine &path) {
649
117k
  SmallString<128> path_storage;
650
117k
  StringRef p = path.toStringRef(path_storage);
651
652
117k
  bool rootDir = has_root_directory(p),
653
#ifdef LLVM_ON_WIN32
654
       rootName = has_root_name(p);
655
#else
656
117k
       rootName = true;
657
117k
#endif
658
659
117k
  return rootDir && rootName;
660
117k
}
661
662
0
bool is_relative(const Twine &path) { return !is_absolute(path); }
663
664
0
StringRef remove_leading_dotslash(StringRef Path) {
665
  // Remove leading "./" (or ".//" or "././" etc.)
666
0
  while (Path.size() > 2 && Path[0] == '.' && is_separator(Path[1])) {
667
0
    Path = Path.substr(2);
668
0
    while (Path.size() > 0 && is_separator(Path[0]))
669
0
      Path = Path.substr(1);
670
0
  }
671
0
  return Path;
672
0
}
673
674
0
static SmallString<256> remove_dots(StringRef path, bool remove_dot_dot) {
675
0
  SmallVector<StringRef, 16> components;
676
677
  // Skip the root path, then look for traversal in the components.
678
0
  StringRef rel = path::relative_path(path);
679
0
  for (StringRef C : llvm_ks::make_range(path::begin(rel), path::end(rel))) {
680
0
    if (C == ".")
681
0
      continue;
682
0
    if (remove_dot_dot) {
683
0
      if (C == "..") {
684
0
        if (!components.empty())
685
0
          components.pop_back();
686
0
        continue;
687
0
      }
688
0
    }
689
0
    components.push_back(C);
690
0
  }
691
692
0
  SmallString<256> buffer = path::root_path(path);
693
0
  for (StringRef C : components)
694
0
    path::append(buffer, C);
695
0
  return buffer;
696
0
}
697
698
0
bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot) {
699
0
  StringRef p(path.data(), path.size());
700
701
0
  SmallString<256> result = remove_dots(p, remove_dot_dot);
702
0
  if (result == path)
703
0
    return false;
704
705
0
  path.swap(result);
706
0
  return true;
707
0
}
708
709
} // end namespace path
710
711
namespace fs {
712
713
0
std::error_code getUniqueID(const Twine Path, UniqueID &Result) {
714
0
  file_status Status;
715
0
  std::error_code EC = status(Path, Status);
716
0
  if (EC)
717
0
    return EC;
718
0
  Result = Status.getUniqueID();
719
0
  return std::error_code();
720
0
}
721
722
std::error_code createUniqueFile(const Twine &Model, int &ResultFd,
723
                                 SmallVectorImpl<char> &ResultPath,
724
0
                                 unsigned Mode) {
725
0
  return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File);
726
0
}
727
728
std::error_code createUniqueFile(const Twine &Model,
729
0
                                 SmallVectorImpl<char> &ResultPath) {
730
0
  int Dummy;
731
0
  return createUniqueEntity(Model, Dummy, ResultPath, false, 0, FS_Name);
732
0
}
733
734
static std::error_code
735
createTemporaryFile(const Twine &Model, int &ResultFD,
736
0
                    llvm_ks::SmallVectorImpl<char> &ResultPath, FSEntity Type) {
737
0
  SmallString<128> Storage;
738
0
  StringRef P = Model.toNullTerminatedStringRef(Storage);
739
0
  assert(P.find_first_of(separators) == StringRef::npos &&
740
0
         "Model must be a simple filename.");
741
  // Use P.begin() so that createUniqueEntity doesn't need to recreate Storage.
742
0
  return createUniqueEntity(P.begin(), ResultFD, ResultPath,
743
0
                            true, owner_read | owner_write, Type);
744
0
}
745
746
static std::error_code
747
createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD,
748
0
                    llvm_ks::SmallVectorImpl<char> &ResultPath, FSEntity Type) {
749
0
  const char *Middle = Suffix.empty() ? "-%%%%%%" : "-%%%%%%.";
750
0
  return createTemporaryFile(Prefix + Middle + Suffix, ResultFD, ResultPath,
751
0
                             Type);
752
0
}
753
754
std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
755
                                    int &ResultFD,
756
0
                                    SmallVectorImpl<char> &ResultPath) {
757
0
  return createTemporaryFile(Prefix, Suffix, ResultFD, ResultPath, FS_File);
758
0
}
759
760
std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
761
0
                                    SmallVectorImpl<char> &ResultPath) {
762
0
  int Dummy;
763
0
  return createTemporaryFile(Prefix, Suffix, Dummy, ResultPath, FS_Name);
764
0
}
765
766
767
// This is a mkdtemp with a different pattern. We use createUniqueEntity mostly
768
// for consistency. We should try using mkdtemp.
769
std::error_code createUniqueDirectory(const Twine &Prefix,
770
0
                                      SmallVectorImpl<char> &ResultPath) {
771
0
  int Dummy;
772
0
  return createUniqueEntity(Prefix + "-%%%%%%", Dummy, ResultPath,
773
0
                            true, 0, FS_Dir);
774
0
}
775
776
static std::error_code make_absolute(const Twine &current_directory,
777
                                     SmallVectorImpl<char> &path,
778
0
                                     bool use_current_directory) {
779
0
  StringRef p(path.data(), path.size());
780
781
0
  bool rootDirectory = path::has_root_directory(p),
782
#ifdef LLVM_ON_WIN32
783
       rootName = path::has_root_name(p);
784
#else
785
0
       rootName = true;
786
0
#endif
787
788
  // Already absolute.
789
0
  if (rootName && rootDirectory)
790
0
    return std::error_code();
791
792
  // All of the following conditions will need the current directory.
793
0
  SmallString<128> current_dir;
794
0
  if (use_current_directory)
795
0
    current_directory.toVector(current_dir);
796
0
  else if (std::error_code ec = current_path(current_dir))
797
0
    return ec;
798
799
  // Relative path. Prepend the current directory.
800
0
  if (!rootName && !rootDirectory) {
801
    // Append path to the current directory.
802
0
    path::append(current_dir, p);
803
    // Set path to the result.
804
0
    path.swap(current_dir);
805
0
    return std::error_code();
806
0
  }
807
808
0
  if (!rootName && rootDirectory) {
809
0
    StringRef cdrn = path::root_name(current_dir);
810
0
    SmallString<128> curDirRootName(cdrn.begin(), cdrn.end());
811
0
    path::append(curDirRootName, p);
812
    // Set path to the result.
813
0
    path.swap(curDirRootName);
814
0
    return std::error_code();
815
0
  }
816
817
0
  if (rootName && !rootDirectory) {
818
0
    StringRef pRootName      = path::root_name(p);
819
0
    StringRef bRootDirectory = path::root_directory(current_dir);
820
0
    StringRef bRelativePath  = path::relative_path(current_dir);
821
0
    StringRef pRelativePath  = path::relative_path(p);
822
823
0
    SmallString<128> res;
824
0
    path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath);
825
0
    path.swap(res);
826
0
    return std::error_code();
827
0
  }
828
829
0
  llvm_unreachable("All rootName and rootDirectory combinations should have "
830
0
                   "occurred above!");
831
0
}
832
833
std::error_code make_absolute(const Twine &current_directory,
834
0
                              SmallVectorImpl<char> &path) {
835
0
  return make_absolute(current_directory, path, true);
836
0
}
837
838
0
std::error_code make_absolute(SmallVectorImpl<char> &path) {
839
0
  return make_absolute(Twine(), path, false);
840
0
}
841
842
std::error_code create_directories(const Twine &Path, bool IgnoreExisting,
843
0
                                   perms Perms) {
844
0
  SmallString<128> PathStorage;
845
0
  StringRef P = Path.toStringRef(PathStorage);
846
847
  // Be optimistic and try to create the directory
848
0
  std::error_code EC = create_directory(P, IgnoreExisting, Perms);
849
  // If we succeeded, or had any error other than the parent not existing, just
850
  // return it.
851
0
  if (EC != errc::no_such_file_or_directory)
852
0
    return EC;
853
854
  // We failed because of a no_such_file_or_directory, try to create the
855
  // parent.
856
0
  StringRef Parent = path::parent_path(P);
857
0
  if (Parent.empty())
858
0
    return EC;
859
860
0
  if ((EC = create_directories(Parent, IgnoreExisting, Perms)))
861
0
      return EC;
862
863
0
  return create_directory(P, IgnoreExisting, Perms);
864
0
}
865
866
0
std::error_code copy_file(const Twine &From, const Twine &To) {
867
0
  int ReadFD, WriteFD;
868
0
  if (std::error_code EC = openFileForRead(From, ReadFD))
869
0
    return EC;
870
0
  if (std::error_code EC = openFileForWrite(To, WriteFD, F_None)) {
871
0
    close(ReadFD);
872
0
    return EC;
873
0
  }
874
875
0
  const size_t BufSize = 4096;
876
0
  char *Buf = new char[BufSize];
877
0
  int BytesRead = 0, BytesWritten = 0;
878
0
  for (;;) {
879
0
    BytesRead = read(ReadFD, Buf, BufSize);
880
0
    if (BytesRead <= 0)
881
0
      break;
882
0
    while (BytesRead) {
883
0
      BytesWritten = write(WriteFD, Buf, BytesRead);
884
0
      if (BytesWritten < 0)
885
0
        break;
886
0
      BytesRead -= BytesWritten;
887
0
    }
888
0
    if (BytesWritten < 0)
889
0
      break;
890
0
  }
891
0
  close(ReadFD);
892
0
  close(WriteFD);
893
0
  delete[] Buf;
894
895
0
  if (BytesRead < 0 || BytesWritten < 0)
896
0
    return std::error_code(errno, std::generic_category());
897
0
  return std::error_code();
898
0
}
899
900
0
bool exists(file_status status) {
901
0
  return status_known(status) && status.type() != file_type::file_not_found;
902
0
}
903
904
0
bool status_known(file_status s) {
905
0
  return s.type() != file_type::status_error;
906
0
}
907
908
0
bool is_directory(file_status status) {
909
0
  return status.type() == file_type::directory_file;
910
0
}
911
912
0
std::error_code is_directory(const Twine &path, bool &result) {
913
0
  file_status st;
914
0
  if (std::error_code ec = status(path, st))
915
0
    return ec;
916
0
  result = is_directory(st);
917
0
  return std::error_code();
918
0
}
919
920
0
bool is_regular_file(file_status status) {
921
0
  return status.type() == file_type::regular_file;
922
0
}
923
924
0
std::error_code is_regular_file(const Twine &path, bool &result) {
925
0
  file_status st;
926
0
  if (std::error_code ec = status(path, st))
927
0
    return ec;
928
0
  result = is_regular_file(st);
929
0
  return std::error_code();
930
0
}
931
932
0
bool is_other(file_status status) {
933
0
  return exists(status) &&
934
0
         !is_regular_file(status) &&
935
0
         !is_directory(status);
936
0
}
937
938
0
std::error_code is_other(const Twine &Path, bool &Result) {
939
0
  file_status FileStatus;
940
0
  if (std::error_code EC = status(Path, FileStatus))
941
0
    return EC;
942
0
  Result = is_other(FileStatus);
943
0
  return std::error_code();
944
0
}
945
946
0
void directory_entry::replace_filename(const Twine &filename, file_status st) {
947
0
  SmallString<128> path = path::parent_path(Path);
948
0
  path::append(path, filename);
949
0
  Path = path.str();
950
0
  Status = st;
951
0
}
952
953
/// @brief Identify the magic in magic.
954
0
file_magic identify_magic(StringRef Magic) {
955
0
  if (Magic.size() < 4)
956
0
    return file_magic::unknown;
957
0
  switch ((unsigned char)Magic[0]) {
958
0
    case 0x00: {
959
      // COFF bigobj or short import library file
960
0
      if (Magic[1] == (char)0x00 && Magic[2] == (char)0xff &&
961
0
          Magic[3] == (char)0xff) {
962
0
        size_t MinSize = offsetof(COFF::BigObjHeader, UUID) + sizeof(COFF::BigObjMagic);
963
0
        if (Magic.size() < MinSize)
964
0
          return file_magic::coff_import_library;
965
966
0
        int BigObjVersion = read16le(
967
0
            Magic.data() + offsetof(COFF::BigObjHeader, Version));
968
0
        if (BigObjVersion < COFF::BigObjHeader::MinBigObjectVersion)
969
0
          return file_magic::coff_import_library;
970
971
0
        const char *Start = Magic.data() + offsetof(COFF::BigObjHeader, UUID);
972
0
        if (memcmp(Start, COFF::BigObjMagic, sizeof(COFF::BigObjMagic)) != 0)
973
0
          return file_magic::coff_import_library;
974
0
        return file_magic::coff_object;
975
0
      }
976
      // Windows resource file
977
0
      const char Expected[] = { 0, 0, 0, 0, '\x20', 0, 0, 0, '\xff' };
978
0
      if (Magic.size() >= sizeof(Expected) &&
979
0
          memcmp(Magic.data(), Expected, sizeof(Expected)) == 0)
980
0
        return file_magic::windows_resource;
981
      // 0x0000 = COFF unknown machine type
982
0
      if (Magic[1] == 0)
983
0
        return file_magic::coff_object;
984
0
      break;
985
0
    }
986
0
    case 0xDE:  // 0x0B17C0DE = BC wraper
987
0
      if (Magic[1] == (char)0xC0 && Magic[2] == (char)0x17 &&
988
0
          Magic[3] == (char)0x0B)
989
0
        return file_magic::bitcode;
990
0
      break;
991
0
    case 'B':
992
0
      if (Magic[1] == 'C' && Magic[2] == (char)0xC0 && Magic[3] == (char)0xDE)
993
0
        return file_magic::bitcode;
994
0
      break;
995
0
    case '!':
996
0
      if (Magic.size() >= 8)
997
0
        if (memcmp(Magic.data(), "!<arch>\n", 8) == 0 ||
998
0
            memcmp(Magic.data(), "!<thin>\n", 8) == 0)
999
0
          return file_magic::archive;
1000
0
      break;
1001
1002
0
    case '\177':
1003
0
      if (Magic.size() >= 18 && Magic[1] == 'E' && Magic[2] == 'L' &&
1004
0
          Magic[3] == 'F') {
1005
0
        bool Data2MSB = Magic[5] == 2;
1006
0
        unsigned high = Data2MSB ? 16 : 17;
1007
0
        unsigned low  = Data2MSB ? 17 : 16;
1008
0
        if (Magic[high] == 0)
1009
0
          switch (Magic[low]) {
1010
0
            default: return file_magic::elf;
1011
0
            case 1: return file_magic::elf_relocatable;
1012
0
            case 2: return file_magic::elf_executable;
1013
0
            case 3: return file_magic::elf_shared_object;
1014
0
            case 4: return file_magic::elf_core;
1015
0
          }
1016
0
        else
1017
          // It's still some type of ELF file.
1018
0
          return file_magic::elf;
1019
0
      }
1020
0
      break;
1021
1022
0
    case 0xCA:
1023
0
      if (Magic[1] == char(0xFE) && Magic[2] == char(0xBA) &&
1024
0
          Magic[3] == char(0xBE)) {
1025
        // This is complicated by an overlap with Java class files.
1026
        // See the Mach-O section in /usr/share/file/magic for details.
1027
0
        if (Magic.size() >= 8 && Magic[7] < 43)
1028
0
          return file_magic::macho_universal_binary;
1029
0
      }
1030
0
      break;
1031
1032
      // The two magic numbers for mach-o are:
1033
      // 0xfeedface - 32-bit mach-o
1034
      // 0xfeedfacf - 64-bit mach-o
1035
0
    case 0xFE:
1036
0
    case 0xCE:
1037
0
    case 0xCF: {
1038
0
      uint16_t type = 0;
1039
0
      if (Magic[0] == char(0xFE) && Magic[1] == char(0xED) &&
1040
0
          Magic[2] == char(0xFA) &&
1041
0
          (Magic[3] == char(0xCE) || Magic[3] == char(0xCF))) {
1042
        /* Native endian */
1043
0
        size_t MinSize;
1044
0
        if (Magic[3] == char(0xCE))
1045
0
          MinSize = sizeof(MachO::mach_header);
1046
0
        else
1047
0
          MinSize = sizeof(MachO::mach_header_64);
1048
0
        if (Magic.size() >= MinSize)
1049
0
          type = Magic[12] << 24 | Magic[13] << 12 | Magic[14] << 8 | Magic[15];
1050
0
      } else if ((Magic[0] == char(0xCE) || Magic[0] == char(0xCF)) &&
1051
0
                 Magic[1] == char(0xFA) && Magic[2] == char(0xED) &&
1052
0
                 Magic[3] == char(0xFE)) {
1053
        /* Reverse endian */
1054
0
        size_t MinSize;
1055
0
        if (Magic[0] == char(0xCE))
1056
0
          MinSize = sizeof(MachO::mach_header);
1057
0
        else
1058
0
          MinSize = sizeof(MachO::mach_header_64);
1059
0
        if (Magic.size() >= MinSize)
1060
0
          type = Magic[15] << 24 | Magic[14] << 12 |Magic[13] << 8 | Magic[12];
1061
0
      }
1062
0
      switch (type) {
1063
0
        default: break;
1064
0
        case 1: return file_magic::macho_object;
1065
0
        case 2: return file_magic::macho_executable;
1066
0
        case 3: return file_magic::macho_fixed_virtual_memory_shared_lib;
1067
0
        case 4: return file_magic::macho_core;
1068
0
        case 5: return file_magic::macho_preload_executable;
1069
0
        case 6: return file_magic::macho_dynamically_linked_shared_lib;
1070
0
        case 7: return file_magic::macho_dynamic_linker;
1071
0
        case 8: return file_magic::macho_bundle;
1072
0
        case 9: return file_magic::macho_dynamically_linked_shared_lib_stub;
1073
0
        case 10: return file_magic::macho_dsym_companion;
1074
0
        case 11: return file_magic::macho_kext_bundle;
1075
0
      }
1076
0
      break;
1077
0
    }
1078
0
    case 0xF0: // PowerPC Windows
1079
0
    case 0x83: // Alpha 32-bit
1080
0
    case 0x84: // Alpha 64-bit
1081
0
    case 0x66: // MPS R4000 Windows
1082
0
    case 0x50: // mc68K
1083
0
    case 0x4c: // 80386 Windows
1084
0
    case 0xc4: // ARMNT Windows
1085
0
      if (Magic[1] == 0x01)
1086
0
        return file_magic::coff_object;
1087
1088
0
    case 0x90: // PA-RISC Windows
1089
0
    case 0x68: // mc68K Windows
1090
0
      if (Magic[1] == 0x02)
1091
0
        return file_magic::coff_object;
1092
0
      break;
1093
1094
0
    case 'M': // Possible MS-DOS stub on Windows PE file
1095
0
      if (Magic[1] == 'Z') {
1096
0
        uint32_t off = read32le(Magic.data() + 0x3c);
1097
        // PE/COFF file, either EXE or DLL.
1098
0
        if (off < Magic.size() &&
1099
0
            memcmp(Magic.data()+off, COFF::PEMagic, sizeof(COFF::PEMagic)) == 0)
1100
0
          return file_magic::pecoff_executable;
1101
0
      }
1102
0
      break;
1103
1104
0
    case 0x64: // x86-64 Windows.
1105
0
      if (Magic[1] == char(0x86))
1106
0
        return file_magic::coff_object;
1107
0
      break;
1108
1109
0
    default:
1110
0
      break;
1111
0
  }
1112
0
  return file_magic::unknown;
1113
0
}
1114
1115
0
std::error_code identify_magic(const Twine &Path, file_magic &Result) {
1116
0
  int FD;
1117
0
  if (std::error_code EC = openFileForRead(Path, FD))
1118
0
    return EC;
1119
1120
0
  char Buffer[32];
1121
0
  int Length = read(FD, Buffer, sizeof(Buffer));
1122
0
  if (close(FD) != 0 || Length < 0)
1123
0
    return std::error_code(errno, std::generic_category());
1124
1125
0
  Result = identify_magic(StringRef(Buffer, Length));
1126
0
  return std::error_code();
1127
0
}
1128
1129
0
std::error_code directory_entry::status(file_status &result) const {
1130
0
  return fs::status(Path, result);
1131
0
}
1132
1133
} // end namespace fs
1134
} // end namespace sys
1135
} // end namespace llvm_ks
1136
1137
// Include the truly platform-specific parts.
1138
#if defined(LLVM_ON_UNIX)
1139
#include "Unix/Path.inc"
1140
#endif
1141
#if defined(LLVM_ON_WIN32)
1142
#include "Windows/Path.inc"
1143
#endif
1144
1145
namespace llvm_ks {
1146
namespace sys {
1147
namespace path {
1148
1149
bool user_cache_directory(SmallVectorImpl<char> &Result, const Twine &Path1,
1150
0
                          const Twine &Path2, const Twine &Path3) {
1151
0
  if (getUserCacheDir(Result)) {
1152
0
    append(Result, Path1, Path2, Path3);
1153
0
    return true;
1154
0
  }
1155
0
  return false;
1156
0
}
1157
1158
} // end namespace path
1159
} // end namsspace sys
1160
} // end namespace llvm_ks