LLVM: lib/Support/VirtualFileSystem.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

24#include "llvm/Config/llvm-config.h"

40#include

41#include

42#include

43#include

44#include

45#include

46#include

47#include

48#include

49#include <system_error>

50#include

51#include

52

53using namespace llvm;

55

62

67

71 : Name(Name.str()), UID(UID), MTime(MTime), User(User), Group(Group),

72 Size(Size), Type(Type), Perms(Perms) {}

73

75 return Status(In.getName(), In.getUniqueID(), In.getLastModificationTime(),

76 In.getUser(), In.getGroup(), NewSize, In.getType(),

77 In.getPermissions());

78}

79

81 return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),

82 In.getUser(), In.getGroup(), In.getSize(), In.getType(),

83 In.getPermissions());

84}

85

87 return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),

88 In.getUser(), In.getGroup(), In.getSize(), In.type(),

89 In.permissions());

90}

91

96

98

100

104

106

108

110 return isStatusKnown() && Type != file_type::file_not_found;

111}

112

114

116

119 bool RequiresNullTerminator, bool IsVolatile,

120 bool IsText) {

122 if (F)

123 return F.getError();

124

125 return (*F)->getBuffer(Name, FileSize, RequiresNullTerminator, IsVolatile);

126}

127

130 return {};

131

133 if (!WorkingDir)

134 return WorkingDir.getError();

135

137 return {};

138}

139

144

148

153

155 auto StatusA = status(A);

156 if (!StatusA)

157 return StatusA.getError();

158 auto StatusB = status(B);

159 if (!StatusB)

160 return StatusB.getError();

161 return StatusA->equivalent(*StatusB);

162}

163

164#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

166#endif

167

168#ifndef NDEBUG

170 return Component == ".." || Component == ".";

171}

172

175

178 return true;

179 return false;

180}

181#endif

182

183

184

185

186

187namespace {

188

189

190class RealFile : public File {

191 friend class RealFileSystem;

192

194 Status S;

195 std::string RealName;

196

197 RealFile(file_t RawFD, StringRef NewName, StringRef NewRealPathName)

198 : FD(RawFD), S(NewName, {}, {}, {}, {}, {},

200 RealName(NewRealPathName.str()) {

202 }

203

204public:

205 ~RealFile() override;

206

207 ErrorOr status() override;

208 ErrorOrstd::string getName() override;

209 ErrorOr<std::unique_ptr> getBuffer(const Twine &Name,

210 int64_t FileSize,

211 bool RequiresNullTerminator,

212 bool IsVolatile) override;

213 std::error_code close() override;

214 void setPath(const Twine &Path) override;

215};

216

217}

218

219RealFile::~RealFile() { close(); }

220

221ErrorOr RealFile::status() {

223 if (!S.isStatusKnown()) {

224 file_status RealStatus;

225 if (std::error_code EC = sys::fs::status(FD, RealStatus))

226 return EC;

228 }

229 return S;

230}

231

232ErrorOrstd::string RealFile::getName() {

233 return RealName.empty() ? S.getName().str() : RealName;

234}

235

236ErrorOr<std::unique_ptr>

237RealFile::getBuffer(const Twine &Name, int64_t FileSize,

238 bool RequiresNullTerminator, bool IsVolatile) {

241 IsVolatile);

242}

243

244std::error_code RealFile::close() {

247 return EC;

248}

249

250void RealFile::setPath(const Twine &Path) {

251 RealName = Path.str();

254}

255

256namespace {

257

258

259

260

261

262

263

264

265

266class RealFileSystem : public FileSystem {

267public:

268 explicit RealFileSystem(bool LinkCWDToProcess) {

269 if (!LinkCWDToProcess) {

270 SmallString<128> PWD, RealPWD;

272 WD = EC;

274 WD = WorkingDirectory{PWD, PWD};

275 else

276 WD = WorkingDirectory{PWD, RealPWD};

277 }

278 }

279

280 ErrorOr status(const Twine &Path) override;

281 ErrorOr<std::unique_ptr> openFileForRead(const Twine &Path) override;

282 ErrorOr<std::unique_ptr>

283 openFileForReadBinary(const Twine &Path) override;

284 directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;

285

286 llvm::ErrorOrstd::string getCurrentWorkingDirectory() const override;

287 std::error_code setCurrentWorkingDirectory(const Twine &Path) override;

288 std::error_code isLocal(const Twine &Path, bool &Result) override;

289 std::error_code getRealPath(const Twine &Path,

290 SmallVectorImpl &Output) override;

291

292protected:

294 unsigned IndentLevel) const override;

295

296private:

297

298

299 Twine adjustPath(const Twine &Path, SmallVectorImpl &Storage) const {

300 if (!WD || !*WD)

302 Path.toVector(Storage);

304 return Storage;

305 }

306

307 ErrorOr<std::unique_ptr>

308 openFileForReadWithFlags(const Twine &Name, sys::fs::OpenFlags Flags) {

309 SmallString<256> RealName, Storage;

311 adjustPath(Name, Storage), Flags, &RealName);

312 if (!FDOrErr)

314 return std::unique_ptr(

315 new RealFile(*FDOrErr, Name.str(), RealName.str()));

316 }

317

318 struct WorkingDirectory {

319

320 SmallString<128> Specified;

321

323 };

324 std::optional<llvm::ErrorOr> WD;

325};

326

327}

328

329ErrorOr RealFileSystem::status(const Twine &Path) {

330 SmallString<256> Storage;

331 sys::fs::file_status RealStatus;

332 if (std::error_code EC =

334 return EC;

336}

337

338ErrorOr<std::unique_ptr>

339RealFileSystem::openFileForRead(const Twine &Name) {

341}

342

343ErrorOr<std::unique_ptr>

344RealFileSystem::openFileForReadBinary(const Twine &Name) {

346}

347

348llvm::ErrorOrstd::string RealFileSystem::getCurrentWorkingDirectory() const {

349 if (WD && *WD)

350 return std::string(WD->get().Specified);

351 if (WD)

352 return WD->getError();

353

354 SmallString<128> Dir;

356 return EC;

357 return std::string(Dir);

358}

359

360std::error_code RealFileSystem::setCurrentWorkingDirectory(const Twine &Path) {

361 if (!WD)

363

365 adjustPath(Path, Storage).toVector(Absolute);

366 bool IsDir;

368 return Err;

369 if (!IsDir)

370 return std::make_error_code(std::errc::not_a_directory);

372 return Err;

374 return std::error_code();

375}

376

377std::error_code RealFileSystem::isLocal(const Twine &Path, bool &Result) {

378 SmallString<256> Storage;

380}

381

382std::error_code RealFileSystem::getRealPath(const Twine &Path,

383 SmallVectorImpl &Output) {

384 SmallString<256> Storage;

386}

387

388void RealFileSystem::printImpl(raw_ostream &OS, PrintType Type,

389 unsigned IndentLevel) const {

390 printIndent(OS, IndentLevel);

391 OS << "RealFileSystem using ";

392 if (WD)

393 OS << "own";

394 else

395 OS << "process";

396 OS << " CWD\n";

397}

398

404

406 return std::make_unique(false);

407}

408

409namespace {

410

413

414public:

415 RealFSDirIter(const Twine &Path, std::error_code &EC) : Iter(Path, EC) {

418 }

419

420 std::error_code increment() override {

421 std::error_code EC;

426 return EC;

427 }

428};

429

430}

431

433 std::error_code &EC) {

434 SmallString<128> Storage;

436 std::make_shared(adjustPath(Dir, Storage), EC));

437}

438

439

440

441

442

444 FSList.push_back(std::move(BaseFS));

445}

446

448 FSList.push_back(FS);

449

450

452}

453

463

465

467 if ((*I)->exists(Path))

468 return true;

469 }

470 return false;

471}

472

475

477 auto Result = (*I)->openFileForRead(Path);

479 return Result;

480 }

482}

483

486

487 return FSList.front()->getCurrentWorkingDirectory();

488}

489

490std::error_code

492 for (auto &FS : FSList)

493 if (std::error_code EC = FS->setCurrentWorkingDirectory(Path))

494 return EC;

495 return {};

496}

497

499 for (auto &FS : FSList)

500 if (FS->exists(Path))

501 return FS->isLocal(Path, Result);

503}

504

507 for (const auto &FS : FSList)

508 if (FS->exists(Path))

509 return FS->getRealPath(Path, Output);

511}

512

515 Callback(*FS);

516 FS->visitChildFileSystems(Callback);

517 }

518}

519

521 unsigned IndentLevel) const {

522 printIndent(OS, IndentLevel);

523 OS << "OverlayFileSystem\n";

524 if (Type == PrintType::Summary)

525 return;

526

527 if (Type == PrintType::Contents)

528 Type = PrintType::Summary;

530 FS->print(OS, Type, IndentLevel + 1);

531}

532

534

535namespace {

536

537

540

541

543

545

547

548

549

550 std::error_code incrementIter(bool IsFirstTime) {

551 while (!IterList.empty()) {

552 CurrentDirIter = IterList.back();

555 break;

556 }

557

560 return {};

561 }

562

563 std::error_code incrementDirIter(bool IsFirstTime) {

564 assert((IsFirstTime || CurrentDirIter != directory_iterator()) &&

565 "incrementing past end");

566 std::error_code EC;

567 if (!IsFirstTime)

569 if (!EC && CurrentDirIter == directory_iterator())

570 EC = incrementIter(IsFirstTime);

571 return EC;

572 }

573

574 std::error_code incrementImpl(bool IsFirstTime) {

575 while (true) {

576 std::error_code EC = incrementDirIter(IsFirstTime);

577 if (EC || CurrentDirIter == directory_iterator()) {

578 CurrentEntry = directory_entry();

579 return EC;

580 }

581 CurrentEntry = *CurrentDirIter;

583 if (SeenNames.insert(Name).second)

584 return EC;

585 }

587 }

588

589public:

591 std::error_code &EC) {

592 for (const auto &FS : FileSystems) {

593 std::error_code FEC;

594 directory_iterator Iter = FS->dir_begin(Dir, FEC);

595 if (FEC && FEC != errc::no_such_file_or_directory) {

596 EC = FEC;

597 return;

598 }

599 if (!FEC)

601 }

602 EC = incrementImpl(true);

603 }

604

606 std::error_code &EC)

607 : IterList(DirIters) {

608 EC = incrementImpl(true);

609 }

610

611 std::error_code increment() override { return incrementImpl(false); }

612};

613

614}

615

617 std::error_code &EC) {

619 std::make_shared(FSList, Dir.str(), EC));

620 if (EC)

621 return {};

622 return Combined;

623}

624

625void ProxyFileSystem::anchor() {}

626

627namespace llvm {

628namespace vfs {

629

631

638

639

640

643 std::string FileName;

644

645public:

647 : Kind(Kind), FileName(std::string(llvm::sys::path::filename(FileName))) {

648 }

650

651

652

653

655

656

659 virtual std::string toString(unsigned Indent) const = 0;

660};

661

664 std::unique_ptrllvm::MemoryBuffer Buffer;

665

666public:

670

675

676 std::string toString(unsigned Indent) const override {

677 return (std::string(Indent, ' ') + Stat.getName() + "\n").str();

678 }

679

683};

684

685namespace {

686

687class InMemoryHardLink : public InMemoryNode {

688 const InMemoryFile &ResolvedFile;

689

690public:

691 InMemoryHardLink(StringRef Path, const InMemoryFile &ResolvedFile)

692 : InMemoryNode(Path, IME_HardLink), ResolvedFile(ResolvedFile) {}

693 const InMemoryFile &getResolvedFile() const { return ResolvedFile; }

694

695 Status getStatus(const Twine &RequestedName) const override {

696 return ResolvedFile.getStatus(RequestedName);

697 }

698

699 std::string toString(unsigned Indent) const override {

700 return std::string(Indent, ' ') + "HardLink to -> " +

701 ResolvedFile.toString(0);

702 }

703

704 static bool classof(const InMemoryNode *N) {

706 }

707};

708

709class InMemorySymbolicLink : public InMemoryNode {

710 std::string TargetPath;

711 Status Stat;

712

713public:

714 InMemorySymbolicLink(StringRef Path, StringRef TargetPath, Status Stat)

716 Stat(Stat) {}

717

718 std::string toString(unsigned Indent) const override {

719 return std::string(Indent, ' ') + "SymbolicLink to -> " + TargetPath;

720 }

721

722 Status getStatus(const Twine &RequestedName) const override {

724 }

725

726 StringRef getTargetPath() const { return TargetPath; }

727

728 static bool classof(const InMemoryNode *N) {

730 }

731};

732

733

734

735

736class InMemoryFileAdaptor : public File {

737 const InMemoryFile &Node;

738

739 std::string RequestedName;

740

741public:

742 explicit InMemoryFileAdaptor(const InMemoryFile &Node,

743 std::string RequestedName)

744 : Node(Node), RequestedName(std::move(RequestedName)) {}

745

746 llvm::ErrorOr status() override {

747 return Node.getStatus(RequestedName);

748 }

749

750 llvm::ErrorOr<std::unique_ptrllvm::MemoryBuffer>

751 getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,

752 bool IsVolatile) override {

753 llvm::MemoryBuffer *Buf = Node.getBuffer();

756 }

757

758 std::error_code close() override { return {}; }

759

760 void setPath(const Twine &Path) override { RequestedName = Path.str(); }

761};

762}

763

766 std::map<std::string, std::unique_ptr, std::less<>> Entries;

767

768public:

771

772

773

774

778

780

782 auto I = Entries.find(Name);

783 if (I != Entries.end())

784 return I->second.get();

785 return nullptr;

786 }

787

789 return Entries.emplace(Name, std::move(Child)).first->second.get();

790 }

791

793

796

797 std::string toString(unsigned Indent) const override {

798 std::string Result =

799 (std::string(Indent, ' ') + Stat.getName() + "\n").str();

800 for (const auto &Entry : Entries)

801 Result += Entry.second->toString(Indent + 2);

802 return Result;

803 }

804

808};

809

810}

811

812

813

814

828

838

840 : Root(new detail::InMemoryDirectory(

845 UseNormalizedPaths(UseNormalizedPaths) {}

846

848

850 return Root->toString(0);

851}

852

853bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,

854 std::unique_ptrllvm::MemoryBuffer Buffer,

855 std::optional<uint32_t> User,

856 std::optional<uint32_t> Group,

857 std::optionalllvm::sys::fs::file\_type Type,

858 std::optionalllvm::sys::fs::perms Perms,

859 MakeNodeFn MakeNode) {

861 P.toVector(Path);

862

863

866 (void)EC;

867

870

871 if (Path.empty())

872 return false;

873

876 const auto ResolvedUser = User.value_or(0);

877 const auto ResolvedGroup = Group.value_or(0);

880

881

883

885 while (true) {

886 Name = *I;

887 ++I;

888 if (I == E)

889 break;

892

894 StringRef(Path.str().begin(), Name.end() - Path.str().begin()),

899 Name, std::make_uniquedetail::InMemoryDirectory(std::move(Stat))));

900 continue;

901 }

902

904 return false;

906 }

910 MakeNode({Dir->getUniqueID(), Path, Name, ModificationTime,

911 std::move(Buffer), ResolvedUser, ResolvedGroup,

912 ResolvedType, ResolvedPerms}));

913 return true;

914 }

917

920 "Must be either file, hardlink or directory!");

921

922

924 return Link->getResolvedFile().getBuffer()->getBuffer() ==

925 Buffer->getBuffer();

926 }

928 Buffer->getBuffer();

929}

930

931bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,

932 std::unique_ptrllvm::MemoryBuffer Buffer,

933 std::optional<uint32_t> User,

934 std::optional<uint32_t> Group,

935 std::optionalllvm::sys::fs::file\_type Type,

936 std::optionalllvm::sys::fs::perms Perms) {

937 return addFile(P, ModificationTime, std::move(Buffer), User, Group, Type,

938 Perms,

940 -> std::unique_ptrdetail::InMemoryNode {

943 return std::make_uniquedetail::InMemoryDirectory(Stat);

944 return std::make_uniquedetail::InMemoryFile(

945 Stat, std::move(NNI.Buffer));

946 });

947}

948

950 const Twine &P, time_t ModificationTime,

952 std::optional<uint32_t> Group, std::optionalllvm::sys::fs::file\_type Type,

953 std::optionalllvm::sys::fs::perms Perms) {

955 std::move(User), std::move(Group), std::move(Type),

956 std::move(Perms),

958 -> std::unique_ptrdetail::InMemoryNode {

961 return std::make_uniquedetail::InMemoryDirectory(Stat);

962 return std::make_uniquedetail::InMemoryFile(

963 Stat, std::move(NNI.Buffer));

964 });

965}

966

968InMemoryFileSystem::lookupNode(const Twine &P, bool FollowFinalSymlink,

969 size_t SymlinkDepth) const {

971 P.toVector(Path);

972

973

976 (void)EC;

977

980

982 if (Path.empty())

984

986 while (true) {

988 ++I;

991

993

994

995 if (I == E && !FollowFinalSymlink)

997

1000

1002 if (std::error_code EC = makeAbsolute(TargetPath))

1003 return EC;

1004

1005

1006

1007

1008

1010 lookupNode(TargetPath, true, SymlinkDepth + 1);

1013

1016

1017

1019 continue;

1020 }

1021

1022

1024 if (I == E)

1027 }

1028

1029

1031 if (I == E)

1034 }

1035

1037 if (I == E)

1038 return detail::NamedNodeOrError(Path, Dir);

1039 }

1040}

1041

1044 auto NewLinkNode = lookupNode(NewLink, false);

1045

1046

1047

1048 auto TargetNode = lookupNode(Target, true);

1049

1050

1052 return false;

1053 return addFile(NewLink, 0, nullptr, std::nullopt, std::nullopt, std::nullopt,

1055 return std::make_uniquedetail::InMemoryHardLink(

1058 });

1059}

1060

1062 const Twine &NewLink, const Twine &Target, time_t ModificationTime,

1063 std::optional<uint32_t> User, std::optional<uint32_t> Group,

1064 std::optionalllvm::sys::fs::perms Perms) {

1065 auto NewLinkNode = lookupNode(NewLink, false);

1066 if (NewLinkNode)

1067 return false;

1068

1070 NewLink.toVector(NewLinkStr);

1071 Target.toVector(TargetStr);

1072

1073 return addFile(NewLinkStr, ModificationTime, nullptr, User, Group,

1076 return std::make_uniquedetail::InMemorySymbolicLink(

1077 NewLinkStr, TargetStr, NNI.makeStatus());

1078 });

1079}

1080

1082 auto Node = lookupNode(Path, true);

1084 return (*Node)->getStatus(Path);

1085 return Node.getError();

1086}

1087

1090 auto Node = lookupNode(Path,true);

1092 return Node.getError();

1093

1094

1095

1097 return std::unique_ptr(

1098 new detail::InMemoryFileAdaptor(*F, Path.str()));

1099

1100

1102}

1103

1104

1109 std::string RequestedDirName;

1110

1111 void setCurrentEntry() {

1112 if (I != E) {

1116 switch (I->second->getKind()) {

1120 break;

1123 break;

1125 if (auto SymlinkTarget =

1126 FS->lookupNode(Path, true)) {

1127 Path = SymlinkTarget.getName();

1128 Type = (*SymlinkTarget)->getStatus(Path).getType();

1129 }

1130 break;

1131 }

1133 } else {

1134

1135

1137 }

1138 }

1139

1140public:

1142

1145 std::string RequestedDirName)

1146 : FS(FS), I(Dir.begin()), E(Dir.end()),

1147 RequestedDirName(std::move(RequestedDirName)) {

1148 setCurrentEntry();

1149 }

1150

1152 ++I;

1153 setCurrentEntry();

1154 return {};

1155 }

1156};

1157

1159 std::error_code &EC) {

1160 auto Node = lookupNode(Dir, true);

1161 if (Node) {

1162 EC = Node.getError();

1164 }

1165

1168 std::make_shared(this, *DirNode, Dir.str()));

1169

1172}

1173

1176 P.toVector(Path);

1177

1178

1181 (void)EC;

1182

1185

1186 if (!Path.empty())

1187 WorkingDirectory = std::string(Path);

1188 return {};

1189}

1190

1194 if (!CWD || CWD->empty())

1196 Path.toVector(Output);

1198 return EC;

1200 return {};

1201}

1202

1204 Result = false;

1205 return {};

1206}

1207

1209 unsigned IndentLevel) const {

1210 printIndent(OS, IndentLevel);

1211 OS << "InMemoryFileSystem\n";

1212}

1213

1214}

1215}

1216

1217

1218

1219

1220

1221namespace {

1222

1224

1226 const size_t n = Path.find_first_of("/\\");

1227

1228 if (n != static_cast<size_t>(-1))

1230 : llvm::sys::path::Style::windows_backslash;

1231 return style;

1232}

1233

1234

1236

1238

1239

1240

1244 return result;

1245}

1246

1247

1248static bool isFileNotFound(std::error_code EC,

1251 return false;

1253}

1254

1255}

1256

1257

1260 if (ExternalFS)

1261 if (auto ExternalWorkingDirectory =

1262 ExternalFS->getCurrentWorkingDirectory()) {

1263 WorkingDirectory = *ExternalWorkingDirectory;

1264 }

1265}

1266

1267

1268

1271 std::string Dir;

1273

1274 std::error_code incrementImpl(bool IsFirstTime) {

1275 assert((IsFirstTime || Current != End) && "cannot iterate past end");

1276 if (!IsFirstTime)

1277 ++Current;

1278 if (Current != End) {

1282 switch ((*Current)->getKind()) {

1284 [[fallthrough]];

1287 break;

1290 break;

1291 }

1293 } else {

1295 }

1296 return {};

1297 };

1298

1299public:

1303 : Dir(Path.str()), Current(Begin), End(End) {

1304 EC = incrementImpl(true);

1305 }

1306

1308 return incrementImpl(false);

1309 }

1310};

1311

1312namespace {

1313

1314

1315

1317 std::string Dir;

1320

1321public:

1322 RedirectingFSDirRemapIterImpl(std::string DirPath,

1324 : Dir(std::move(DirPath)), DirStyle(getExistingStyle(Dir)),

1325 ExternalIter(ExtIter) {

1327 setCurrentEntry();

1328 }

1329

1330 void setCurrentEntry() {

1334

1337

1338 CurrentEntry = directory_entry(std::string(NewPath), ExternalIter->type());

1339 }

1340

1341 std::error_code increment() override {

1342 std::error_code EC;

1344 if (!EC && ExternalIter != llvm::vfs::directory_iterator())

1345 setCurrentEntry();

1346 else

1347 CurrentEntry = directory_entry();

1348 return EC;

1349 }

1350};

1351}

1352

1353llvm::ErrorOrstd::string

1355 return WorkingDirectory;

1356}

1357

1358std::error_code

1360

1363

1365 Path.toVector(AbsolutePath);

1366 if (std::error_code EC = makeAbsolute(AbsolutePath))

1367 return EC;

1368 WorkingDirectory = std::string(AbsolutePath);

1369 return {};

1370}

1371

1373 bool &Result) {

1376

1377 if (makeAbsolute(Path))

1378 return {};

1379

1380 return ExternalFS->isLocal(Path, Result);

1381}

1382

1384

1388

1389

1390

1391 return {};

1392

1394 if (!WorkingDir)

1395 return WorkingDir.getError();

1396

1397 return makeAbsolute(WorkingDir.get(), Path);

1398}

1399

1400std::error_code

1401RedirectingFileSystem::makeAbsolute(StringRef WorkingDir,

1403

1404

1405

1406

1407 if (!WorkingDir.empty() &&

1411 return std::error_code();

1412 }

1416 } else {

1417

1418

1421 }

1422

1423 std::string Result = std::string(WorkingDir);

1424 StringRef Dir(Result);

1427 }

1428

1429

1430

1431

1432

1435

1436 return {};

1437}

1438

1440 std::error_code &EC) {

1443

1444 EC = makeAbsolute(Path);

1445 if (EC)

1446 return {};

1447

1449 if (!Result) {

1451 isFileNotFound(Result.getError()))

1452 return ExternalFS->dir_begin(Path, EC);

1453

1454 EC = Result.getError();

1455 return {};

1456 }

1457

1458

1460 if (!S) {

1462 isFileNotFound(S.getError(), Result->E))

1463 return ExternalFS->dir_begin(Dir, EC);

1464

1466 return {};

1467 }

1468

1469 if (!S->isDirectory()) {

1471 return {};

1472 }

1473

1474

1475

1477 std::error_code RedirectEC;

1478 if (auto ExtRedirect = Result->getExternalRedirect()) {

1480 RedirectIter = ExternalFS->dir_begin(*ExtRedirect, RedirectEC);

1481

1482 if (!RE->useExternalName(UseExternalNames)) {

1483

1484 RedirectIter =

1486 std::string(Path), RedirectIter));

1487 }

1488 } else {

1490 RedirectIter =

1492 Path, DE->contents_begin(), DE->contents_end(), RedirectEC));

1493 }

1494

1495 if (RedirectEC) {

1497 EC = RedirectEC;

1498 return {};

1499 }

1500 RedirectIter = {};

1501 }

1502

1504 EC = RedirectEC;

1505 return RedirectIter;

1506 }

1507

1508 std::error_code ExternalEC;

1509 directory_iterator ExternalIter = ExternalFS->dir_begin(Path, ExternalEC);

1510 if (ExternalEC) {

1512 EC = ExternalEC;

1513 return {};

1514 }

1515 ExternalIter = {};

1516 }

1517

1519 switch (Redirection) {

1523 break;

1527 break;

1528 default:

1530 }

1531

1533 std::make_shared(Iters, EC)};

1534 if (EC)

1535 return {};

1536 return Combined;

1537}

1538

1540 OverlayFileDir = Dir.str();

1541}

1542

1544 return OverlayFileDir;

1545}

1546

1550 } else {

1552 }

1553}

1554

1557 Redirection = Kind;

1558}

1559

1561 std::vector R;

1562 R.reserve(Roots.size());

1563 for (const auto &Root : Roots)

1564 R.push_back(Root->getName());

1565 return R;

1566}

1567

1569 unsigned IndentLevel) const {

1571 OS << "RedirectingFileSystem (UseExternalNames: "

1572 << (UseExternalNames ? "true" : "false") << ")\n";

1574 return;

1575

1576 for (const auto &Root : Roots)

1577 printEntry(OS, Root.get(), IndentLevel);

1578

1580 OS << "ExternalFS:\n";

1582 IndentLevel + 1);

1583}

1584

1587 unsigned IndentLevel) const {

1589 OS << "'" << E->getName() << "'";

1590

1591 switch (E->getKind()) {

1594

1595 OS << "\n";

1596 for (std::unique_ptr &SubEntry :

1598 printEntry(OS, SubEntry.get(), IndentLevel + 1);

1599 break;

1600 }

1604 OS << " -> '" << RE->getExternalContentsPath() << "'";

1605 switch (RE->getUseName()) {

1607 break;

1609 OS << " (UseExternalName: true)";

1610 break;

1612 OS << " (UseExternalName: false)";

1613 break;

1614 }

1615 OS << "\n";

1616 break;

1617 }

1618 }

1619}

1620

1622 if (ExternalFS) {

1623 Callback(*ExternalFS);

1624 ExternalFS->visitChildFileSystems(Callback);

1625 }

1626}

1627

1628

1631

1633

1634

1638

1639 if (!S) {

1640 error(N, "expected string");

1641 return false;

1642 }

1643 Result = S->getValue(Storage);

1644 return true;

1645 }

1646

1647

1648 bool parseScalarBool(yaml::Node *N, bool &Result) {

1651 if (!parseScalarString(N, Value, Storage))

1652 return false;

1653

1654 if (Value.equals_insensitive("true") || Value.equals_insensitive("on") ||

1655 Value.equals_insensitive("yes") || Value == "1") {

1656 Result = true;

1657 return true;

1658 } else if (Value.equals_insensitive("false") ||

1659 Value.equals_insensitive("off") ||

1660 Value.equals_insensitive("no") || Value == "0") {

1661 Result = false;

1662 return true;

1663 }

1664

1665 error(N, "expected boolean value");

1666 return false;

1667 }

1668

1669 std::optionalRedirectingFileSystem::RedirectKind

1673 if (!parseScalarString(N, Value, Storage))

1674 return std::nullopt;

1675

1676 if (Value.equals_insensitive("fallthrough")) {

1678 } else if (Value.equals_insensitive("fallback")) {

1680 } else if (Value.equals_insensitive("redirect-only")) {

1682 }

1683 return std::nullopt;

1684 }

1685

1686 std::optionalRedirectingFileSystem::RootRelativeKind

1690 if (!parseScalarString(N, Value, Storage))

1691 return std::nullopt;

1692 if (Value.equals_insensitive("cwd")) {

1694 } else if (Value.equals_insensitive("overlay-dir")) {

1696 }

1697 return std::nullopt;

1698 }

1699

1700 struct KeyStatus {

1702 bool Seen = false;

1703

1705 };

1706

1707 using KeyStatusPair = std::pair<StringRef, KeyStatus>;

1708

1709

1712 auto It = Keys.find(Key);

1713 if (It == Keys.end()) {

1714 error(KeyNode, "unknown key");

1715 return false;

1716 }

1717 KeyStatus &S = It->second;

1718 if (S.Seen) {

1719 error(KeyNode, Twine("duplicate key '") + Key + "'");

1720 return false;

1721 }

1722 S.Seen = true;

1723 return true;

1724 }

1725

1726

1728 for (const auto &I : Keys) {

1729 if (I.second.Required && I.second.Seen) {

1730 error(Obj, Twine("missing key '") + I.first + "'");

1731 return false;

1732 }

1733 }

1734 return true;

1735 }

1736

1737public:

1741 if (!ParentEntry) {

1742 for (const auto &Root : FS->Roots) {

1743 if (Name == Root->getName()) {

1744 ParentEntry = Root.get();

1745 return ParentEntry;

1746 }

1747 }

1748 } else {

1750 for (std::unique_ptrRedirectingFileSystem::Entry &Content :

1751 llvm::make_range(DE->contents_begin(), DE->contents_end())) {

1752 auto *DirContent =

1754 if (DirContent && Name == Content->getName())

1755 return DirContent;

1756 }

1757 }

1758

1759

1760 std::unique_ptrRedirectingFileSystem::Entry E =

1761 std::make_uniqueRedirectingFileSystem::DirectoryEntry(

1763 std::chrono::system_clock::now(), 0, 0, 0,

1765

1766 if (!ParentEntry) {

1767 FS->Roots.push_back(std::move(E));

1768 ParentEntry = FS->Roots.back().get();

1769 return ParentEntry;

1770 }

1771

1773 DE->addContent(std::move(E));

1774 return DE->getLastContent();

1775 }

1776

1777private:

1782 switch (SrcE->getKind()) {

1785

1786

1787

1788 if (!Name.empty())

1789 NewParentE = lookupOrCreateEntry(FS, Name, NewParentE);

1790 for (std::unique_ptrRedirectingFileSystem::Entry &SubEntry :

1792 uniqueOverlayTree(FS, SubEntry.get(), NewParentE);

1793 break;

1794 }

1796 assert(NewParentE && "Parent entry must exist");

1799 DE->addContent(

1800 std::make_uniqueRedirectingFileSystem::DirectoryRemapEntry(

1801 Name, DR->getExternalContentsPath(), DR->getUseName()));

1802 break;

1803 }

1805 assert(NewParentE && "Parent entry must exist");

1808 DE->addContent(std::make_uniqueRedirectingFileSystem::FileEntry(

1809 Name, FE->getExternalContentsPath(), FE->getUseName()));

1810 break;

1811 }

1812 }

1813 }

1814

1815 std::unique_ptrRedirectingFileSystem::Entry

1816 parseEntry(yaml::Node *N, RedirectingFileSystem *FS, bool IsRootEntry) {

1818 if (!M) {

1819 error(N, "expected mapping node for file or directory entry");

1820 return nullptr;

1821 }

1822

1823 KeyStatusPair Fields[] = {

1824 KeyStatusPair("name", true),

1825 KeyStatusPair("type", true),

1826 KeyStatusPair("contents", false),

1827 KeyStatusPair("external-contents", false),

1828 KeyStatusPair("use-external-name", false),

1829 };

1830

1831 DenseMap<StringRef, KeyStatus> Keys(std::begin(Fields), std::end(Fields));

1832

1833 enum { CF_NotSet, CF_List, CF_External } ContentsField = CF_NotSet;

1834 std::vector<std::unique_ptrRedirectingFileSystem::Entry>

1835 EntryArrayContents;

1836 SmallString<256> ExternalContentsPath;

1837 SmallString<256> Name;

1838 yaml::Node *NameValueNode = nullptr;

1841

1842 for (auto &I : *M) {

1843 StringRef Key;

1844

1845

1846 SmallString<256> Buffer;

1847 if (!parseScalarString(I.getKey(), Key, Buffer))

1848 return nullptr;

1849

1850 if (!checkDuplicateOrUnknownKey(I.getKey(), Key, Keys))

1851 return nullptr;

1852

1853 StringRef Value;

1854 if (Key == "name") {

1855 if (!parseScalarString(I.getValue(), Value, Buffer))

1856 return nullptr;

1857

1858 NameValueNode = I.getValue();

1859

1860

1861 Name = canonicalize(Value).str();

1862 } else if (Key == "type") {

1863 if (!parseScalarString(I.getValue(), Value, Buffer))

1864 return nullptr;

1865 if (Value == "file")

1867 else if (Value == "directory")

1869 else if (Value == "directory-remap")

1871 else {

1872 error(I.getValue(), "unknown value for 'type'");

1873 return nullptr;

1874 }

1875 } else if (Key == "contents") {

1876 if (ContentsField != CF_NotSet) {

1878 "entry already has 'contents' or 'external-contents'");

1879 return nullptr;

1880 }

1881 ContentsField = CF_List;

1883 if (!Contents) {

1884

1885 error(I.getValue(), "expected array");

1886 return nullptr;

1887 }

1888

1889 for (auto &I : *Contents) {

1890 if (std::unique_ptrRedirectingFileSystem::Entry E =

1891 parseEntry(&I, FS, false))

1892 EntryArrayContents.push_back(std::move(E));

1893 else

1894 return nullptr;

1895 }

1896 } else if (Key == "external-contents") {

1897 if (ContentsField != CF_NotSet) {

1899 "entry already has 'contents' or 'external-contents'");

1900 return nullptr;

1901 }

1902 ContentsField = CF_External;

1903 if (!parseScalarString(I.getValue(), Value, Buffer))

1904 return nullptr;

1905

1906 SmallString<256> FullPath;

1907 if (FS->IsRelativeOverlay) {

1908 FullPath = FS->getOverlayFileDir();

1910 "External contents prefix directory must exist");

1911 SmallString<256> AbsFullPath = Value;

1912 if (FS->makeAbsolute(FullPath, AbsFullPath)) {

1913 error(N, "failed to make 'external-contents' absolute");

1914 return nullptr;

1915 }

1916 FullPath = AbsFullPath;

1917 } else {

1918 FullPath = Value;

1919 }

1920

1921

1922

1923 FullPath = canonicalize(FullPath);

1924 ExternalContentsPath = FullPath.str();

1925 } else if (Key == "use-external-name") {

1926 bool Val;

1927 if (!parseScalarBool(I.getValue(), Val))

1928 return nullptr;

1931 } else {

1933 }

1934 }

1935

1936 if (Stream.failed())

1937 return nullptr;

1938

1939

1940 if (ContentsField == CF_NotSet) {

1941 error(N, "missing key 'contents' or 'external-contents'");

1942 return nullptr;

1943 }

1944 if (!checkMissingKeys(N, Keys))

1945 return nullptr;

1946

1947

1950 error(N, "'use-external-name' is not supported for 'directory' entries");

1951 return nullptr;

1952 }

1953

1955 ContentsField == CF_List) {

1956 error(N, "'contents' is not supported for 'directory-remap' entries");

1957 return nullptr;

1958 }

1959

1961 if (IsRootEntry) {

1962

1963

1965 path_style = sys::path::Style::posix;

1967 sys::path::Style::windows_backslash)) {

1968 path_style = sys::path::Style::windows_backslash;

1969 } else {

1970

1971

1972

1973 std::error_code EC;

1974 if (FS->RootRelative ==

1975 RedirectingFileSystem::RootRelativeKind::OverlayDir) {

1976 StringRef FullPath = FS->getOverlayFileDir();

1977 assert(!FullPath.empty() && "Overlay file directory must exist");

1978 EC = FS->makeAbsolute(FullPath, Name);

1979 Name = canonicalize(Name);

1980 } else {

1981 EC = FS->makeAbsolute(Name);

1982 }

1983 if (EC) {

1984 assert(NameValueNode && "Name presence should be checked earlier");

1986 NameValueNode,

1987 "entry with relative path at the root level is not discoverable");

1988 return nullptr;

1989 }

1991 ? sys::path::Style::posix

1992 : sys::path::Style::windows_backslash;

1993 }

1994

1995

1996

1997 if (path_style == sys::path::Style::windows_backslash &&

1998 getExistingStyle(Name) != sys::path::Style::windows_backslash)

1999 path_style = sys::path::Style::windows_slash;

2000 }

2001

2002

2003 StringRef Trimmed = Name;

2005 while (Trimmed.size() > RootPathLen &&

2007 Trimmed = Trimmed.slice(0, Trimmed.size() - 1);

2008

2009

2011

2012 std::unique_ptrRedirectingFileSystem::Entry Result;

2013 switch (Kind) {

2015 Result = std::make_uniqueRedirectingFileSystem::FileEntry(

2016 LastComponent, std::move(ExternalContentsPath), UseExternalName);

2017 break;

2019 Result = std::make_uniqueRedirectingFileSystem::DirectoryRemapEntry(

2020 LastComponent, std::move(ExternalContentsPath), UseExternalName);

2021 break;

2023 Result = std::make_uniqueRedirectingFileSystem::DirectoryEntry(

2024 LastComponent, std::move(EntryArrayContents),

2027 break;

2028 }

2029

2031 if (Parent.empty())

2033

2034

2035 for (sys::path::reverse_iterator I = sys::path::rbegin(Parent, path_style),

2037 I != E; ++I) {

2038 std::vector<std::unique_ptrRedirectingFileSystem::Entry> Entries;

2039 Entries.push_back(std::move(Result));

2040 Result = std::make_uniqueRedirectingFileSystem::DirectoryEntry(

2041 *I, std::move(Entries),

2044 }

2046 }

2047

2048public:

2050

2051

2054 if (!Top) {

2055 error(Root, "expected mapping node");

2056 return false;

2057 }

2058

2059 KeyStatusPair Fields[] = {

2060 KeyStatusPair("version", true),

2061 KeyStatusPair("case-sensitive", false),

2062 KeyStatusPair("use-external-names", false),

2063 KeyStatusPair("root-relative", false),

2064 KeyStatusPair("overlay-relative", false),

2065 KeyStatusPair("fallthrough", false),

2066 KeyStatusPair("redirecting-with", false),

2067 KeyStatusPair("roots", true),

2068 };

2069

2071 std::vector<std::unique_ptrRedirectingFileSystem::Entry> RootEntries;

2072

2073

2074 for (auto &I : *Top) {

2077 if (!parseScalarString(I.getKey(), Key, KeyBuffer))

2078 return false;

2079

2080 if (!checkDuplicateOrUnknownKey(I.getKey(), Key, Keys))

2081 return false;

2082

2083 if (Key == "roots") {

2085 if (!Roots) {

2086 error(I.getValue(), "expected array");

2087 return false;

2088 }

2089

2090 for (auto &I : *Roots) {

2091 if (std::unique_ptrRedirectingFileSystem::Entry E =

2092 parseEntry(&I, FS, true))

2093 RootEntries.push_back(std::move(E));

2094 else

2095 return false;

2096 }

2097 } else if (Key == "version") {

2100 if (!parseScalarString(I.getValue(), VersionString, Storage))

2101 return false;

2104 error(I.getValue(), "expected integer");

2105 return false;

2106 }

2108 error(I.getValue(), "invalid version number");

2109 return false;

2110 }

2112 error(I.getValue(), "version mismatch, expected 0");

2113 return false;

2114 }

2115 } else if (Key == "case-sensitive") {

2116 if (!parseScalarBool(I.getValue(), FS->CaseSensitive))

2117 return false;

2118 } else if (Key == "overlay-relative") {

2119 if (!parseScalarBool(I.getValue(), FS->IsRelativeOverlay))

2120 return false;

2121 } else if (Key == "use-external-names") {

2122 if (!parseScalarBool(I.getValue(), FS->UseExternalNames))

2123 return false;

2124 } else if (Key == "fallthrough") {

2125 if (Keys["redirecting-with"].Seen) {

2127 "'fallthrough' and 'redirecting-with' are mutually exclusive");

2128 return false;

2129 }

2130

2131 bool ShouldFallthrough = false;

2132 if (!parseScalarBool(I.getValue(), ShouldFallthrough))

2133 return false;

2134

2135 if (ShouldFallthrough) {

2137 } else {

2139 }

2140 } else if (Key == "redirecting-with") {

2141 if (Keys["fallthrough"].Seen) {

2143 "'fallthrough' and 'redirecting-with' are mutually exclusive");

2144 return false;

2145 }

2146

2147 if (auto Kind = parseRedirectKind(I.getValue())) {

2148 FS->Redirection = *Kind;

2149 } else {

2150 error(I.getValue(), "expected valid redirect kind");

2151 return false;

2152 }

2153 } else if (Key == "root-relative") {

2154 if (auto Kind = parseRootRelativeKind(I.getValue())) {

2155 FS->RootRelative = *Kind;

2156 } else {

2157 error(I.getValue(), "expected valid root-relative kind");

2158 return false;

2159 }

2160 } else {

2162 }

2163 }

2164

2165 if (Stream.failed())

2166 return false;

2167

2168 if (!checkMissingKeys(Top, Keys))

2169 return false;

2170

2171

2172

2173

2174 for (auto &E : RootEntries)

2175 uniqueOverlayTree(FS, E.get());

2176

2177 return true;

2178 }

2179};

2180

2181std::unique_ptr

2184 StringRef YAMLFilePath, void *DiagContext,

2187 yaml::Stream Stream(Buffer->getMemBufferRef(), SM);

2188

2192 if (DI == Stream.end() || !Root) {

2194 return nullptr;

2195 }

2196

2198

2199 std::unique_ptr FS(

2200 new RedirectingFileSystem(ExternalFS));

2201

2202 if (!YAMLFilePath.empty()) {

2203

2204

2205

2206

2207

2208

2209

2210

2212 std::error_code EC = FS->makeAbsolute(OverlayAbsDir);

2213 assert(!EC && "Overlay dir final path must be absolute");

2214 (void)EC;

2215 FS->setOverlayFileDir(OverlayAbsDir);

2216 }

2217

2218 if (P.parse(Root, FS.get()))

2219 return nullptr;

2220

2221 return FS;

2222}

2223

2225 ArrayRef<std::pair<std::string, std::string>> RemappedFiles,

2227 std::unique_ptr FS(

2228 new RedirectingFileSystem(ExternalFS));

2229 FS->UseExternalNames = UseExternalNames;

2230

2232

2233 for (auto &Mapping : llvm::reverse(RemappedFiles)) {

2236 {

2237 auto EC = ExternalFS->makeAbsolute(From);

2238 (void)EC;

2239 assert(!EC && "Could not make absolute path");

2240 }

2241

2242

2243

2245 if (ToEntry)

2246 continue;

2247

2248

2253 I != E; ++I) {

2255 Parent);

2256 }

2257 assert(Parent && "File without a directory?");

2258 {

2259 auto EC = ExternalFS->makeAbsolute(To);

2260 (void)EC;

2261 assert(!EC && "Could not make absolute path");

2262 }

2263

2264

2265 auto NewFile = std::make_uniqueRedirectingFileSystem::FileEntry(

2269 ToEntry = NewFile.get();

2271 std::move(NewFile));

2272 }

2273

2274 return FS;

2275}

2276

2279 : E(E) {

2281

2282

2283

2287 getExistingStyle(DRE->getExternalContentsPath()));

2288 ExternalRedirect = std::string(Redirect);

2289 }

2290}

2291

2294 Result.clear();

2298}

2299

2300std::error_code RedirectingFileSystem::makeCanonicalForLookup(

2302 if (std::error_code EC = makeAbsolute(Path))

2303 return EC;

2304

2306 canonicalize(StringRef(Path.data(), Path.size()));

2307 if (CanonicalPath.empty())

2309

2310 Path.assign(CanonicalPath.begin(), CanonicalPath.end());

2311 return {};

2312}

2313

2317 if (std::error_code EC = makeCanonicalForLookup(CanonicalPath))

2318 return EC;

2319

2320

2322 HasBeenUsed = true;

2323

2327 for (const auto &Root : Roots) {

2329 lookupPathImpl(Start, End, Root.get(), Entries);

2330 if (UsageTrackingActive && Result && isa(Result->E))

2331 HasBeenUsed = true;

2333 Result->Parents = std::move(Entries);

2334 return Result;

2335 }

2336 }

2338}

2339

2341RedirectingFileSystem::lookupPathImpl(

2347 "Paths should not contain traversal components");

2348

2350

2351

2352 if (!FromName.empty()) {

2353 if (!pathComponentMatches(*Start, FromName))

2355

2356 ++Start;

2357

2358 if (Start == End) {

2359

2360 return LookupResult(From, Start, End);

2361 }

2362 }

2363

2366

2368 return LookupResult(From, Start, End);

2369

2371 for (const std::unique_ptrRedirectingFileSystem::Entry &DirEntry :

2372 llvm::make_range(DE->contents_begin(), DE->contents_end())) {

2375 lookupPathImpl(Start, End, DirEntry.get(), Entries);

2377 return Result;

2379 }

2380

2382}

2383

2385 bool UseExternalNames,

2386 Status ExternalStatus) {

2387

2388

2390 return ExternalStatus;

2391

2392 Status S = ExternalStatus;

2393 if (!UseExternalNames)

2395 else

2397 return S;

2398}

2399

2400ErrorOr RedirectingFileSystem::status(

2401 const Twine &LookupPath, const Twine &OriginalPath,

2402 const RedirectingFileSystem::LookupResult &Result) {

2403 if (std::optional ExtRedirect = Result.getExternalRedirect()) {

2404 SmallString<256> RemappedPath((*ExtRedirect).str());

2405 if (std::error_code EC = makeAbsolute(RemappedPath))

2406 return EC;

2407

2408 ErrorOr S = ExternalFS->status(RemappedPath);

2409 if (!S)

2410 return S;

2414 RE->useExternalName(UseExternalNames), *S);

2415 }

2416

2419}

2420

2421ErrorOr

2422RedirectingFileSystem::getExternalStatus(const Twine &LookupPath,

2423 const Twine &OriginalPath) const {

2424 auto Result = ExternalFS->status(LookupPath);

2425

2426

2427

2428 if (!Result || Result->ExposesExternalVFSPath)

2431}

2432

2435 OriginalPath.toVector(Path);

2436

2437 if (std::error_code EC = makeAbsolute(Path))

2438 return EC;

2439

2441

2442

2443 ErrorOr S = getExternalStatus(Path, OriginalPath);

2444 if (S)

2445 return S;

2446 }

2447

2449 if (!Result) {

2450

2451

2453 isFileNotFound(Result.getError()))

2454 return getExternalStatus(Path, OriginalPath);

2455 return Result.getError();

2456 }

2457

2458 ErrorOr S = status(Path, OriginalPath, *Result);

2460 isFileNotFound(S.getError(), Result->E)) {

2461

2462

2463

2464 return getExternalStatus(Path, OriginalPath);

2465 }

2466

2467 return S;

2468}

2469

2472 OriginalPath.toVector(Path);

2473

2474 if (makeAbsolute(Path))

2475 return false;

2476

2478

2479

2480 if (ExternalFS->exists(Path))

2481 return true;

2482 }

2483

2485 if (!Result) {

2486

2487

2489 isFileNotFound(Result.getError()))

2490 return ExternalFS->exists(Path);

2491 return false;

2492 }

2493

2494 std::optional ExtRedirect = Result->getExternalRedirect();

2495 if (!ExtRedirect) {

2497 return true;

2498 }

2499

2501 if (makeAbsolute(RemappedPath))

2502 return false;

2503

2504 if (ExternalFS->exists(RemappedPath))

2505 return true;

2506

2508

2509

2510

2511 return ExternalFS->exists(Path);

2512 }

2513

2514 return false;

2515}

2516

2517namespace {

2518

2519

2520class FileWithFixedStatus : public File {

2521 std::unique_ptr InnerFile;

2523

2524public:

2525 FileWithFixedStatus(std::unique_ptr InnerFile, Status S)

2526 : InnerFile(std::move(InnerFile)), S(std::move(S)) {}

2527

2530

2531 getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,

2532 bool IsVolatile) override {

2533 return InnerFile->getBuffer(Name, FileSize, RequiresNullTerminator,

2534 IsVolatile);

2535 }

2536

2537 std::error_code close() override { return InnerFile->close(); }

2538

2539 void setPath(const Twine &Path) override { S = S.copyWithNewName(S, Path); }

2540};

2541

2542}

2543

2544ErrorOr<std::unique_ptr>

2546

2547

2548 if (!Result || (*Result)->status()->ExposesExternalVFSPath)

2549 return Result;

2550

2552 auto Name = F->get()->getName();

2553 if (Name && Name.get() != P.str())

2554 F->get()->setPath(P);

2555 return F;

2556}

2557

2561 OriginalPath.toVector(Path);

2562

2563 if (std::error_code EC = makeAbsolute(Path))

2564 return EC;

2565

2567

2568

2569 auto F = File::getWithPath(ExternalFS->openFileForRead(Path), OriginalPath);

2570 if (F)

2571 return F;

2572 }

2573

2575 if (!Result) {

2576

2577

2579 isFileNotFound(Result.getError()))

2580 return File::getWithPath(ExternalFS->openFileForRead(Path), OriginalPath);

2581 return Result.getError();

2582 }

2583

2584 if (!Result->getExternalRedirect())

2586

2587 StringRef ExtRedirect = *Result->getExternalRedirect();

2589 if (std::error_code EC = makeAbsolute(RemappedPath))

2590 return EC;

2591

2593

2594 auto ExternalFile =

2595 File::getWithPath(ExternalFS->openFileForRead(RemappedPath), ExtRedirect);

2596 if (!ExternalFile) {

2598 isFileNotFound(ExternalFile.getError(), Result->E)) {

2599

2600

2601

2602 return File::getWithPath(ExternalFS->openFileForRead(Path), OriginalPath);

2603 }

2604 return ExternalFile;

2605 }

2606

2607 auto ExternalStatus = (*ExternalFile)->status();

2608 if (!ExternalStatus)

2609 return ExternalStatus.getError();

2610

2611

2612

2614 OriginalPath, RE->useExternalName(UseExternalNames), *ExternalStatus);

2615 return std::unique_ptr(

2616 std::make_unique(std::move(*ExternalFile), S));

2617}

2618

2619std::error_code

2623 OriginalPath.toVector(Path);

2624

2625 if (std::error_code EC = makeAbsolute(Path))

2626 return EC;

2627

2629

2630

2631 std::error_code EC = ExternalFS->getRealPath(Path, Output);

2632 if (!EC)

2633 return EC;

2634 }

2635

2637 if (!Result) {

2638

2639

2641 isFileNotFound(Result.getError()))

2642 return ExternalFS->getRealPath(Path, Output);

2643 return Result.getError();

2644 }

2645

2646

2647

2648 if (auto ExtRedirect = Result->getExternalRedirect()) {

2649 auto P = ExternalFS->getRealPath(*ExtRedirect, Output);

2651 isFileNotFound(P, Result->E)) {

2652

2653

2654

2655 return ExternalFS->getRealPath(Path, Output);

2656 }

2657 return P;

2658 }

2659

2660

2661

2663 Result->getPath(Output);

2664 return {};

2665 }

2667}

2668

2669std::unique_ptr

2672 StringRef YAMLFilePath, void *DiagContext,

2675 YAMLFilePath, DiagContext,

2676 std::move(ExternalFS));

2677}

2678

2682 auto Kind = SrcE->getKind();

2685 assert(DE && "Must be a directory");

2686 for (std::unique_ptrRedirectingFileSystem::Entry &SubEntry :

2687 llvm::make_range(DE->contents_begin(), DE->contents_end())) {

2688 Path.push_back(SubEntry->getName());

2690 Path.pop_back();

2691 }

2692 return;

2693 }

2694

2697 assert(DR && "Must be a directory remap");

2699 for (auto &Comp : Path)

2703 return;

2704 }

2705

2708 assert(FE && "Must be a file");

2710 for (auto &Comp : Path)

2713}

2714

2718 if (!RootResult)

2719 return;

2722 getVFSEntries(RootResult->E, Components, CollectedEntries);

2723}

2724

2726 static std::atomic UID;

2727 unsigned ID = ++UID;

2728

2729

2730 return UniqueID(std::numeric_limits<uint64_t>::max(), ID);

2731}

2732

2733void YAMLVFSWriter::addEntry(StringRef VirtualPath, StringRef RealPath,

2734 bool IsDirectory) {

2738 Mappings.emplace_back(VirtualPath, RealPath, IsDirectory);

2739}

2740

2742 addEntry(VirtualPath, RealPath, false);

2743}

2744

2747 addEntry(VirtualPath, RealPath, true);

2748}

2749

2750namespace {

2751

2752class JSONWriter {

2755

2756 unsigned getDirIndent() { return 4 * DirStack.size(); }

2757 unsigned getFileIndent() { return 4 * (DirStack.size() + 1); }

2760 void startDirectory(StringRef Path);

2761 void endDirectory();

2763

2764public:

2766

2768 std::optional UseExternalNames,

2769 std::optional IsCaseSensitive,

2770 std::optional IsOverlayRelative, StringRef OverlayDir);

2771};

2772

2773}

2774

2775bool JSONWriter::containedIn(StringRef Parent, StringRef Path) {

2776 using namespace llvm::sys;

2777

2778

2781 IParent != EParent && IChild != EChild; ++IParent, ++IChild) {

2782 if (*IParent != *IChild)

2783 return false;

2784 }

2785

2786 return IParent == EParent;

2787}

2788

2789StringRef JSONWriter::containedPart(StringRef Parent, StringRef Path) {

2791 assert(containedIn(Parent, Path));

2792 return Path.substr(Parent.size() + 1);

2793}

2794

2795void JSONWriter::startDirectory(StringRef Path) {

2796 StringRef Name =

2797 DirStack.empty() ? Path : containedPart(DirStack.back(), Path);

2799 unsigned Indent = getDirIndent();

2800 OS.indent(Indent) << "{\n";

2801 OS.indent(Indent + 2) << "'type': 'directory',\n";

2803 OS.indent(Indent + 2) << "'contents': [\n";

2804}

2805

2806void JSONWriter::endDirectory() {

2807 unsigned Indent = getDirIndent();

2808 OS.indent(Indent + 2) << "]\n";

2809 OS.indent(Indent) << "}";

2810

2812}

2813

2814void JSONWriter::writeEntry(StringRef VPath, StringRef RPath) {

2815 unsigned Indent = getFileIndent();

2816 OS.indent(Indent) << "{\n";

2817 OS.indent(Indent + 2) << "'type': 'file',\n";

2819 OS.indent(Indent + 2) << "'external-contents': \""

2821 OS.indent(Indent) << "}";

2822}

2823

2825 std::optional UseExternalNames,

2826 std::optional IsCaseSensitive,

2827 std::optional IsOverlayRelative,

2829 using namespace llvm::sys;

2830

2831 OS << "{\n"

2832 " 'version': 0,\n";

2833 if (IsCaseSensitive)

2834 OS << " 'case-sensitive': '" << (*IsCaseSensitive ? "true" : "false")

2835 << "',\n";

2836 if (UseExternalNames)

2837 OS << " 'use-external-names': '" << (*UseExternalNames ? "true" : "false")

2838 << "',\n";

2839 bool UseOverlayRelative = false;

2840 if (IsOverlayRelative) {

2841 UseOverlayRelative = *IsOverlayRelative;

2842 OS << " 'overlay-relative': '" << (UseOverlayRelative ? "true" : "false")

2843 << "',\n";

2844 }

2845 OS << " 'roots': [\n";

2846

2847 if (!Entries.empty()) {

2848 const YAMLVFSEntry &Entry = Entries.front();

2849

2850 startDirectory(

2852 );

2853

2855 if (UseOverlayRelative) {

2857 "Overlay dir must be contained in RPath");

2859 }

2860

2861 bool IsCurrentDirEmpty = true;

2862 if (Entry.IsDirectory) {

2864 IsCurrentDirEmpty = false;

2865 }

2866

2867 for (const auto &Entry : Entries.slice(1)) {

2868 StringRef Dir =

2870 if (Dir == DirStack.back()) {

2871 if (!IsCurrentDirEmpty) {

2872 OS << ",\n";

2873 }

2874 } else {

2875 bool IsDirPoppedFromStack = false;

2876 while (!DirStack.empty() && !containedIn(DirStack.back(), Dir)) {

2877 OS << "\n";

2878 endDirectory();

2879 IsDirPoppedFromStack = true;

2880 }

2881 if (IsDirPoppedFromStack || !IsCurrentDirEmpty) {

2882 OS << ",\n";

2883 }

2884 startDirectory(Dir);

2885 IsCurrentDirEmpty = true;

2886 }

2888 if (UseOverlayRelative) {

2890 "Overlay dir must be contained in RPath");

2892 }

2893 if (Entry.IsDirectory) {

2895 IsCurrentDirEmpty = false;

2896 }

2897 }

2898

2899 while (!DirStack.empty()) {

2900 OS << "\n";

2901 endDirectory();

2902 }

2903 OS << "\n";

2904 }

2905

2906 OS << " ]\n"

2907 << "}\n";

2908}

2909

2912 return LHS.VPath < RHS.VPath;

2913 });

2914

2915 JSONWriter(OS).write(Mappings, UseExternalNames, IsCaseSensitive,

2916 IsOverlayRelative, OverlayDir);

2917}

2918

2920 FileSystem &FS_, const Twine &Path, std::error_code &EC)

2921 : FS(&FS_) {

2924 State = std::make_shareddetail::RecDirIterState();

2925 State->Stack.push_back(I);

2926 }

2927}

2928

2931 assert(FS && State && !State->Stack.empty() && "incrementing past end");

2932 assert(!State->Stack.back()->path().empty() && "non-canonical end iterator");

2934

2935 if (State->HasNoPushRequest)

2936 State->HasNoPushRequest = false;

2937 else {

2940 FS->dir_begin(State->Stack.back()->path(), EC);

2941 if (I != End) {

2942 State->Stack.push_back(I);

2943 return *this;

2944 }

2945 }

2946 }

2947

2948 while (!State->Stack.empty() && State->Stack.back().increment(EC) == End)

2949 State->Stack.pop_back();

2950

2951 if (State->Stack.empty())

2952 State.reset();

2953

2954 return *this;

2955}

2956

2958 unsigned IndentLevel) const {

2959 printIndent(OS, IndentLevel);

2960 OS << "TracingFileSystem\n";

2961 if (Type == PrintType::Summary)

2962 return;

2963

2964 printIndent(OS, IndentLevel);

2966 printIndent(OS, IndentLevel);

2968 printIndent(OS, IndentLevel);

2970 printIndent(OS, IndentLevel);

2972 printIndent(OS, IndentLevel);

2974 printIndent(OS, IndentLevel);

2976

2977 if (Type == PrintType::Contents)

2978 Type = PrintType::Summary;

2979 getUnderlyingFS().print(OS, Type, IndentLevel + 1);

2980}

2981

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

This file defines the DenseMap class.

Provides ErrorOr smart pointer.

static void makeAbsolute(vfs::FileSystem &VFS, SmallVectorImpl< char > &Path)

Make Path absolute.

This file defines the RefCountedBase, ThreadSafeRefCountedBase, and IntrusiveRefCntPtr classes.

static void printImpl(const MCAsmInfo &MAI, raw_ostream &OS, const MCSpecifierExpr &Expr)

static StringRef getName(Value *V)

This file defines the SmallString class.

This file defines the SmallVector class.

StringSet - A set-like wrapper for the StringMap.

static void DiagHandler(const SMDiagnostic &Diag, void *Context)

LLVM_ABI const file_t kInvalidFile

static void getVFSEntries(RedirectingFileSystem::Entry *SrcE, SmallVectorImpl< StringRef > &Path, SmallVectorImpl< YAMLVFSEntry > &Entries)

Definition VirtualFileSystem.cpp:2679

static Status getRedirectedFileStatus(const Twine &OriginalPath, bool UseExternalNames, Status ExternalStatus)

Definition VirtualFileSystem.cpp:2384

static bool pathHasTraversal(StringRef Path)

Definition VirtualFileSystem.cpp:173

static bool isTraversalComponent(StringRef Component)

Definition VirtualFileSystem.cpp:169

Defines the virtual file system interface vfs::FileSystem.

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

const T & front() const

front - Get the first element.

bool empty() const

empty - Check if the array is empty.

ArrayRef< T > slice(size_t N, size_t M) const

slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.

iterator find(const_arg_type_t< KeyT > Val)

Represents either an error or a value T.

std::error_code getError() const

Error takeError()

Take ownership of the stored error.

A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...

This interface provides simple read-only access to a block of memory, and provides simple methods for...

static ErrorOr< std::unique_ptr< MemoryBuffer > > getOpenFile(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)

Given an already-open file descriptor, read the file and return a MemoryBuffer.

static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)

Open the specified memory range as a MemoryBuffer.

virtual StringRef getBufferIdentifier() const

Return an identifier for this buffer, typically the filename it was read from.

StringRef getBuffer() const

Represents a location in source code.

SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...

StringRef str() const

Explicit conversion to StringRef.

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.

LLVM_ABI void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef< SMRange > Ranges={}, ArrayRef< SMFixIt > FixIts={}, bool ShowColors=true) const

Emit a message about the specified location with the specified string.

void(*)(const SMDiagnostic &, void *Context) DiagHandlerTy

Clients that want to handle their own diagnostics in a custom way can register a function pointer+con...

void setDiagHandler(DiagHandlerTy DH, void *Ctx=nullptr)

Specify a diagnostic handler to be invoked every time PrintMessage is called.

StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...

StringRef - Represent a constant reference to a string, i.e.

bool getAsInteger(unsigned Radix, T &Result) const

Parse the current string as an integer of the specified radix.

std::string str() const

str - Get the contents as an std::string.

constexpr bool empty() const

empty - Check if the string is empty.

char back() const

back - Get the last character in the string.

StringRef slice(size_t Start, size_t End) const

Return a reference to the substring from [Start, End).

constexpr size_t size() const

size - Get the string size.

StringSet - A wrapper for StringMap that provides set-like functionality.

std::pair< typename Base::iterator, bool > insert(StringRef key)

Target - Wrapper for Target specific information.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

LLVM_ABI std::string str() const

Return the twine contents as a std::string.

LLVM_ABI void toVector(SmallVectorImpl< char > &Out) const

Append the concatenated string into the given SmallString or SmallVector.

The instances of the Type class are immutable: once they are created, they are never changed.

LLVM_ABI void print(raw_ostream &O, bool IsForDebug=false, bool NoDetails=false) const

Print the current type.

LLVM Value Representation.

An opaque object representing a hash code.

This class implements an extremely fast bulk output stream that can only output to a stream.

raw_ostream & write(unsigned char C)

raw_ostream & indent(unsigned NumSpaces)

indent - Insert 'NumSpaces' spaces.

const std::string & path() const

directory_iterator - Iterates through the entries in path.

directory_iterator & increment(std::error_code &ec)

Represents the result of a call to sys::fs::status().

The virtual file system interface.

llvm::function_ref< void(FileSystem &)> VisitCallbackTy

virtual llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const =0

Get the working directory of this file system.

virtual bool exists(const Twine &Path)

Check whether Path exists.

Definition VirtualFileSystem.cpp:149

virtual llvm::ErrorOr< std::unique_ptr< File > > openFileForReadBinary(const Twine &Path)

Get a File object for the binary file at Path, if one exists.

virtual std::error_code makeAbsolute(SmallVectorImpl< char > &Path) const

Make Path an absolute path.

Definition VirtualFileSystem.cpp:128

virtual llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path)=0

Get a File object for the text file at Path, if one exists.

virtual std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output)

Gets real path of Path e.g.

Definition VirtualFileSystem.cpp:140

void printIndent(raw_ostream &OS, unsigned IndentLevel) const

LLVM_DUMP_METHOD void dump() const

Definition VirtualFileSystem.cpp:165

void print(raw_ostream &OS, PrintType Type=PrintType::Contents, unsigned IndentLevel=0) const

llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(const Twine &Name, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatile=false, bool IsText=true)

This is a convenience method that opens a file, gets its content and then closes the file.

Definition VirtualFileSystem.cpp:118

llvm::ErrorOr< bool > equivalent(const Twine &A, const Twine &B)

Definition VirtualFileSystem.cpp:154

virtual std::error_code isLocal(const Twine &Path, bool &Result)

Is the file mounted on a local filesystem?

Definition VirtualFileSystem.cpp:145

virtual llvm::ErrorOr< Status > status(const Twine &Path)=0

Get the status of the entry at Path, if one exists.

static ErrorOr< std::unique_ptr< File > > getWithPath(ErrorOr< std::unique_ptr< File > > Result, const Twine &P)

Definition VirtualFileSystem.cpp:2545

virtual ~File()

Destroy the file after closing it (if open).

Adaptor from InMemoryDir::iterator to directory_iterator.

Definition VirtualFileSystem.cpp:1105

DirIterator(const InMemoryFileSystem *FS, const detail::InMemoryDirectory &Dir, std::string RequestedDirName)

Definition VirtualFileSystem.cpp:1143

std::error_code increment() override

Sets CurrentEntry to the next entry in the directory on success, to directory_entry() at end,...

Definition VirtualFileSystem.cpp:1151

std::error_code isLocal(const Twine &Path, bool &Result) override

Definition VirtualFileSystem.cpp:1203

directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override

Definition VirtualFileSystem.cpp:1158

std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) override

Canonicalizes Path by combining with the current working directory and normalizing the path (e....

Definition VirtualFileSystem.cpp:1191

~InMemoryFileSystem() override

static constexpr size_t MaxSymlinkDepth

Arbitrary max depth to search through symlinks.

InMemoryFileSystem(bool UseNormalizedPaths=true)

Definition VirtualFileSystem.cpp:839

bool useNormalizedPaths() const

Return true if this file system normalizes . and .. in paths.

void printImpl(raw_ostream &OS, PrintType Type, unsigned IndentLevel) const override

Definition VirtualFileSystem.cpp:1208

llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override

bool addHardLink(const Twine &NewLink, const Twine &Target)

Add a hard link to a file.

Definition VirtualFileSystem.cpp:1042

std::string toString() const

Definition VirtualFileSystem.cpp:849

bool addFileNoOwn(const Twine &Path, time_t ModificationTime, const llvm::MemoryBufferRef &Buffer, std::optional< uint32_t > User=std::nullopt, std::optional< uint32_t > Group=std::nullopt, std::optional< llvm::sys::fs::file_type > Type=std::nullopt, std::optional< llvm::sys::fs::perms > Perms=std::nullopt)

Add a buffer to the VFS with a path.

Definition VirtualFileSystem.cpp:949

bool addSymbolicLink(const Twine &NewLink, const Twine &Target, time_t ModificationTime, std::optional< uint32_t > User=std::nullopt, std::optional< uint32_t > Group=std::nullopt, std::optional< llvm::sys::fs::perms > Perms=std::nullopt)

Add a symbolic link.

Definition VirtualFileSystem.cpp:1061

std::error_code setCurrentWorkingDirectory(const Twine &Path) override

Definition VirtualFileSystem.cpp:1174

llvm::ErrorOr< Status > status(const Twine &Path) override

Definition VirtualFileSystem.cpp:1081

llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override

Definition VirtualFileSystem.cpp:1089

directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override

Definition VirtualFileSystem.cpp:616

void visitChildFileSystems(VisitCallbackTy Callback) override

Definition VirtualFileSystem.cpp:513

llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override

Definition VirtualFileSystem.cpp:474

std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) override

Definition VirtualFileSystem.cpp:505

std::error_code setCurrentWorkingDirectory(const Twine &Path) override

Definition VirtualFileSystem.cpp:491

void pushOverlay(IntrusiveRefCntPtr< FileSystem > FS)

Pushes a file system on top of the stack.

Definition VirtualFileSystem.cpp:447

OverlayFileSystem(IntrusiveRefCntPtr< FileSystem > Base)

Definition VirtualFileSystem.cpp:443

llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override

Definition VirtualFileSystem.cpp:485

iterator overlays_end()

Get an iterator pointing one-past the least recently added file system.

std::error_code isLocal(const Twine &Path, bool &Result) override

Definition VirtualFileSystem.cpp:498

bool exists(const Twine &Path) override

Definition VirtualFileSystem.cpp:464

llvm::ErrorOr< Status > status(const Twine &Path) override

Definition VirtualFileSystem.cpp:454

iterator overlays_begin()

Get an iterator pointing to the most recently added file system.

FileSystemList::reverse_iterator iterator

void printImpl(raw_ostream &OS, PrintType Type, unsigned IndentLevel) const override

Definition VirtualFileSystem.cpp:520

Directory iterator implementation for RedirectingFileSystem's directory entries.

Definition VirtualFileSystem.cpp:1270

std::error_code increment() override

Sets CurrentEntry to the next entry in the directory on success, to directory_entry() at end,...

Definition VirtualFileSystem.cpp:1307

RedirectingFSDirIterImpl(const Twine &Path, RedirectingFileSystem::DirectoryEntry::iterator Begin, RedirectingFileSystem::DirectoryEntry::iterator End, std::error_code &EC)

Definition VirtualFileSystem.cpp:1300

A helper class to hold the common YAML parsing state.

Definition VirtualFileSystem.cpp:1629

RedirectingFileSystemParser(yaml::Stream &S)

Definition VirtualFileSystem.cpp:2049

static RedirectingFileSystem::Entry * lookupOrCreateEntry(RedirectingFileSystem *FS, StringRef Name, RedirectingFileSystem::Entry *ParentEntry=nullptr)

Definition VirtualFileSystem.cpp:1739

bool parse(yaml::Node *Root, RedirectingFileSystem *FS)

Definition VirtualFileSystem.cpp:2052

decltype(Contents)::iterator iterator

A single file or directory in the VFS.

StringRef getName() const

EntryKind getKind() const

A virtual file system parsed from a YAML file.

@ OverlayDir

The roots are relative to the directory where the Overlay YAML file.

@ CWD

The roots are relative to the current working directory.

bool exists(const Twine &Path) override

Check whether Path exists.

Definition VirtualFileSystem.cpp:2470

void printImpl(raw_ostream &OS, PrintType Type, unsigned IndentLevel) const override

Definition VirtualFileSystem.cpp:1568

friend class RedirectingFileSystemParser

std::vector< llvm::StringRef > getRoots() const

Definition VirtualFileSystem.cpp:1560

directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override

Get a directory_iterator for Dir.

Definition VirtualFileSystem.cpp:1439

ErrorOr< LookupResult > lookupPath(StringRef Path) const

Looks up Path in Roots and returns a LookupResult giving the matched entry and, if the entry was a Fi...

Definition VirtualFileSystem.cpp:2315

RedirectKind

The type of redirection to perform.

@ Fallthrough

Lookup the redirected path first (ie.

@ Fallback

Lookup the provided path first and if that fails, "fallback" to a lookup of the redirected path.

@ RedirectOnly

Only lookup the redirected path, do not lookup the originally provided path.

void setFallthrough(bool Fallthrough)

Sets the redirection kind to Fallthrough if true or RedirectOnly otherwise.

Definition VirtualFileSystem.cpp:1547

void visitChildFileSystems(VisitCallbackTy Callback) override

Definition VirtualFileSystem.cpp:1621

std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) override

Gets real path of Path e.g.

Definition VirtualFileSystem.cpp:2620

ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override

Get a File object for the text file at Path, if one exists.

Definition VirtualFileSystem.cpp:2559

void setOverlayFileDir(StringRef PrefixDir)

Definition VirtualFileSystem.cpp:1539

llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override

Get the working directory of this file system.

Definition VirtualFileSystem.cpp:1354

void setRedirection(RedirectingFileSystem::RedirectKind Kind)

Definition VirtualFileSystem.cpp:1555

std::error_code isLocal(const Twine &Path, bool &Result) override

Is the file mounted on a local filesystem?

Definition VirtualFileSystem.cpp:1372

static std::unique_ptr< RedirectingFileSystem > create(std::unique_ptr< MemoryBuffer > Buffer, SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath, void *DiagContext, IntrusiveRefCntPtr< FileSystem > ExternalFS)

Parses Buffer, which is expected to be in YAML format and returns a virtual file system representing ...

Definition VirtualFileSystem.cpp:2182

std::error_code setCurrentWorkingDirectory(const Twine &Path) override

Set the working directory.

Definition VirtualFileSystem.cpp:1359

StringRef getOverlayFileDir() const

Definition VirtualFileSystem.cpp:1543

void printEntry(raw_ostream &OS, Entry *E, unsigned IndentLevel=0) const

Definition VirtualFileSystem.cpp:1585

The result of a status operation.

llvm::sys::fs::UniqueID getUniqueID() const

LLVM_ABI bool equivalent(const Status &Other) const

Definition VirtualFileSystem.cpp:92

static LLVM_ABI Status copyWithNewName(const Status &In, const Twine &NewName)

Get a copy of a Status with a different name.

Definition VirtualFileSystem.cpp:80

LLVM_ABI bool isStatusKnown() const

Definition VirtualFileSystem.cpp:107

LLVM_ABI bool exists() const

Definition VirtualFileSystem.cpp:109

bool ExposesExternalVFSPath

Whether this entity has an external path different from the virtual path, and the external path is ex...

uint32_t getGroup() const

static LLVM_ABI Status copyWithNewSize(const Status &In, uint64_t NewSize)

Get a copy of a Status with a different size.

Definition VirtualFileSystem.cpp:74

LLVM_ABI bool isOther() const

Definition VirtualFileSystem.cpp:101

LLVM_ABI bool isSymlink() const

Definition VirtualFileSystem.cpp:105

llvm::sys::TimePoint getLastModificationTime() const

llvm::sys::fs::file_type getType() const

LLVM_ABI bool isRegularFile() const

Definition VirtualFileSystem.cpp:99

LLVM_ABI bool isDirectory() const

Definition VirtualFileSystem.cpp:97

std::size_t NumOpenFileForReadCalls

std::size_t NumIsLocalCalls

std::size_t NumExistsCalls

void printImpl(raw_ostream &OS, PrintType Type, unsigned IndentLevel) const override

Definition VirtualFileSystem.cpp:2957

std::size_t NumDirBeginCalls

std::size_t NumGetRealPathCalls

std::size_t NumStatusCalls

LLVM_ABI void addFileMapping(StringRef VirtualPath, StringRef RealPath)

Definition VirtualFileSystem.cpp:2741

LLVM_ABI void write(llvm::raw_ostream &OS)

Definition VirtualFileSystem.cpp:2910

LLVM_ABI void addDirectoryMapping(StringRef VirtualPath, StringRef RealPath)

Definition VirtualFileSystem.cpp:2745

InMemoryDirectory(Status Stat)

Definition VirtualFileSystem.cpp:769

InMemoryNode * addChild(StringRef Name, std::unique_ptr< InMemoryNode > Child)

Definition VirtualFileSystem.cpp:788

Status getStatus(const Twine &RequestedName) const override

Return the Status for this node.

Definition VirtualFileSystem.cpp:775

const_iterator end() const

Definition VirtualFileSystem.cpp:795

static bool classof(const InMemoryNode *N)

Definition VirtualFileSystem.cpp:805

InMemoryNode * getChild(StringRef Name) const

Definition VirtualFileSystem.cpp:781

const_iterator begin() const

Definition VirtualFileSystem.cpp:794

UniqueID getUniqueID() const

Definition VirtualFileSystem.cpp:779

decltype(Entries)::const_iterator const_iterator

Definition VirtualFileSystem.cpp:792

std::string toString(unsigned Indent) const override

Definition VirtualFileSystem.cpp:797

Status getStatus(const Twine &RequestedName) const override

Return the Status for this node.

Definition VirtualFileSystem.cpp:671

std::string toString(unsigned Indent) const override

Definition VirtualFileSystem.cpp:676

InMemoryFile(Status Stat, std::unique_ptr< llvm::MemoryBuffer > Buffer)

Definition VirtualFileSystem.cpp:667

static bool classof(const InMemoryNode *N)

Definition VirtualFileSystem.cpp:680

llvm::MemoryBuffer * getBuffer() const

Definition VirtualFileSystem.cpp:674

The in memory file system is a tree of Nodes.

Definition VirtualFileSystem.cpp:641

StringRef getFileName() const

Get the filename of this node (the name without the directory part).

Definition VirtualFileSystem.cpp:657

InMemoryNodeKind getKind() const

Definition VirtualFileSystem.cpp:658

virtual ~InMemoryNode()=default

InMemoryNode(llvm::StringRef FileName, InMemoryNodeKind Kind)

Definition VirtualFileSystem.cpp:646

virtual std::string toString(unsigned Indent) const =0

virtual Status getStatus(const Twine &RequestedName) const =0

Return the Status for this node.

A member of a directory, yielded by a directory_iterator.

llvm::StringRef path() const

llvm::sys::fs::file_type type() const

An input iterator over the entries in a virtual path, similar to llvm::sys::fs::directory_iterator.

directory_iterator & increment(std::error_code &EC)

Equivalent to operator++, with an error code.

An input iterator over the recursive contents of a virtual path, similar to llvm::sys::fs::recursive_...

recursive_directory_iterator()=default

Construct an 'end' iterator.

LLVM_ABI recursive_directory_iterator & increment(std::error_code &EC)

Equivalent to operator++, with an error code.

Definition VirtualFileSystem.cpp:2930

Abstract base class for all Nodes.

This class represents a YAML stream potentially containing multiple documents.

LLVM_ABI document_iterator end()

LLVM_ABI document_iterator begin()

LLVM_ABI void printError(Node *N, const Twine &Msg, SourceMgr::DiagKind Kind=SourceMgr::DK_Error)

Iterator abstraction for Documents over a Stream.

This provides a very simple, boring adaptor for a begin and end iterator into a range type.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

@ Resolved

Queried, materialization begun.

LLVM_ABI std::error_code closeFile(file_t &F)

Close the file object.

LLVM_ABI const file_t kInvalidFile

@ OF_Text

The file should be opened in text mode on platforms like z/OS that make this distinction.

file_type

An enumeration for the file system's view of the type.

LLVM_ABI std::error_code set_current_path(const Twine &path)

Set the current path.

LLVM_ABI std::error_code real_path(const Twine &path, SmallVectorImpl< char > &output, bool expand_tilde=false)

Collapse all .

LLVM_ABI Expected< file_t > openNativeFileForRead(const Twine &Name, OpenFlags Flags=OF_None, SmallVectorImpl< char > *RealPath=nullptr)

Opens the file with the given name in a read-only mode, returning its open file descriptor.

LLVM_ABI std::error_code current_path(SmallVectorImpl< char > &result)

Get the current path.

LLVM_ABI std::error_code status(const Twine &path, file_status &result, bool follow=true)

Get file status as if by POSIX stat().

LLVM_ABI std::error_code is_local(const Twine &path, bool &result)

Is the file mounted on a local filesystem?

LLVM_ABI std::error_code openFileForRead(const Twine &Name, int &ResultFD, OpenFlags Flags=OF_None, SmallVectorImpl< char > *RealPath=nullptr)

Opens the file with the given name in a read-only mode, returning its open file descriptor.

LLVM_ABI bool is_directory(const basic_file_status &status)

Does status represent a directory?

LLVM_ABI StringRef get_separator(Style style=Style::native)

Return the preferred separator for this platform.

LLVM_ABI StringRef root_path(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)

Get root path.

LLVM_ABI const_iterator begin(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)

Get begin iterator over path.

LLVM_ABI bool remove_dots(SmallVectorImpl< char > &path, bool remove_dot_dot=false, Style style=Style::native)

In-place remove any '.

LLVM_ABI StringRef parent_path(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)

Get parent path.

LLVM_ABI void make_absolute(const Twine &current_directory, SmallVectorImpl< char > &path)

Make path an absolute path.

LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)

Get filename.

LLVM_ABI StringRef remove_leading_dotslash(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)

Remove redundant leading "./" pieces and consecutive separators.

LLVM_ABI bool is_absolute(const Twine &path, Style style=Style::native)

Is path absolute?

LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")

Append to path.

LLVM_ABI reverse_iterator rend(StringRef path LLVM_LIFETIME_BOUND)

Get reverse end iterator over path.

LLVM_ABI reverse_iterator rbegin(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)

Get reverse begin iterator over path.

LLVM_ABI const_iterator end(StringRef path LLVM_LIFETIME_BOUND)

Get end iterator over path.

LLVM_ABI bool is_separator(char value, Style style=Style::native)

Check whether the given char is a path separator on the host OS.

std::chrono::time_point< std::chrono::system_clock, D > TimePoint

A time point on the system clock.

TimePoint< std::chrono::seconds > toTimePoint(std::time_t T)

Convert a std::time_t to a TimePoint.

InMemoryNodeKind

Definition VirtualFileSystem.cpp:632

@ IME_File

Definition VirtualFileSystem.cpp:633

@ IME_HardLink

Definition VirtualFileSystem.cpp:635

@ IME_Directory

Definition VirtualFileSystem.cpp:634

@ IME_SymbolicLink

Definition VirtualFileSystem.cpp:636

std::error_code make_error_code(OutputErrorCode EV)

LLVM_ABI void collectVFSEntries(RedirectingFileSystem &VFS, SmallVectorImpl< YAMLVFSEntry > &CollectedEntries)

Collect all pairs of <virtual path, real path> entries from the VFS.

Definition VirtualFileSystem.cpp:2715

LLVM_ABI std::unique_ptr< FileSystem > createPhysicalFileSystem()

Create an vfs::FileSystem for the 'real' file system, as seen by the operating system.

Definition VirtualFileSystem.cpp:405

static sys::fs::UniqueID getFileID(sys::fs::UniqueID Parent, llvm::StringRef Name, llvm::StringRef Contents)

Definition VirtualFileSystem.cpp:819

LLVM_ABI llvm::sys::fs::UniqueID getNextVirtualUniqueID()

Get a globally unique ID for a virtual file or directory.

Definition VirtualFileSystem.cpp:2725

static sys::fs::UniqueID getUniqueID(hash_code Hash)

Definition VirtualFileSystem.cpp:815

LLVM_ABI IntrusiveRefCntPtr< FileSystem > getRealFileSystem()

Gets an vfs::FileSystem for the 'real' file system, as seen by the operating system.

Definition VirtualFileSystem.cpp:399

LLVM_ABI std::unique_ptr< FileSystem > getVFSFromYAML(std::unique_ptr< llvm::MemoryBuffer > Buffer, llvm::SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath, void *DiagContext=nullptr, IntrusiveRefCntPtr< FileSystem > ExternalFS=getRealFileSystem())

Gets a FileSystem for a virtual file system described in YAML format.

static sys::fs::UniqueID getDirectoryID(sys::fs::UniqueID Parent, llvm::StringRef Name)

Definition VirtualFileSystem.cpp:824

LLVM_ABI std::string escape(StringRef Input, bool EscapePrintable=true)

Escape Input for a double quoted scalar; if EscapePrintable is true, all UTF8 sequences will be escap...

This is an optimization pass for GlobalISel generic memory operations.

FunctionAddr VTableAddr Value

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

iterator_range< T > make_range(T x, T y)

Convenience function for iterating over sub-ranges.

IntrusiveRefCntPtr< T > makeIntrusiveRefCnt(Args &&...A)

Factory function for creating intrusive ref counted pointers.

@ no_such_file_or_directory

@ operation_not_permitted

FunctionAddr VTableAddr uintptr_t uintptr_t Version

auto reverse(ContainerTy &&C)

decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)

void sort(IteratorTy Start, IteratorTy End)

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key

ArrayRef(const T &OneElt) -> ArrayRef< T >

std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)

OutputIt move(R &&Range, OutputIt Out)

Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.

LLVM_ABI Error write(MCStreamer &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue, Dwarf64StrOffsetsPromotion StrOffsetsOptValue)

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

hash_code hash_combine(const Ts &...args)

Combine values into a single hash_code.

LLVM_ABI std::error_code errorToErrorCode(Error Err)

Helper for converting an ECError to a std::error_code.

Implement std::hash so that hash_code can be used in STL containers.

Entry * E

The entry the looked-up path corresponds to.

LLVM_ABI LookupResult(Entry *E, sys::path::const_iterator Start, sys::path::const_iterator End)

Definition VirtualFileSystem.cpp:2277

LLVM_ABI void getPath(llvm::SmallVectorImpl< char > &Path) const

Get the (canonical) path of the found entry.

Definition VirtualFileSystem.cpp:2292

llvm::SmallVector< Entry *, 32 > Parents

Chain of parent directory entries for E.

An interface for virtual file systems to provide an iterator over the (non-recursive) contents of a d...

directory_entry CurrentEntry

LLVM_ABI Status makeStatus() const

Definition VirtualFileSystem.cpp:829

llvm::sys::fs::file_type Type

std::unique_ptr< llvm::MemoryBuffer > Buffer

llvm::sys::fs::perms Perms

llvm::sys::fs::UniqueID DirUID