1 //===-- FileSystemPosix.cpp -----------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/Host/FileSystem.h" 10 11 // C includes 12 #include <fcntl.h> 13 #include <unistd.h> 14 15 // lldb Includes 16 #include "lldb/Host/Host.h" 17 #include "lldb/Utility/Status.h" 18 #include "lldb/Utility/StreamString.h" 19 20 #include "llvm/Support/Errno.h" 21 #include "llvm/Support/FileSystem.h" 22 23 using namespace lldb; 24 using namespace lldb_private; 25 26 const char *FileSystem::DEV_NULL = "/dev/null"; 27 28 Status FileSystem::Symlink(const FileSpec &src, const FileSpec &dst) { 29 Status error; 30 if (::symlink(dst.GetPath().c_str(), src.GetPath().c_str()) == -1) 31 return Status::FromErrno(); 32 return error; 33 } 34 35 Status FileSystem::Readlink(const FileSpec &src, FileSpec &dst) { 36 Status error; 37 char buf[PATH_MAX]; 38 ssize_t count = ::readlink(src.GetPath().c_str(), buf, sizeof(buf) - 1); 39 if (count < 0) 40 return Status::FromErrno(); 41 42 buf[count] = '\0'; // Success 43 dst.SetFile(buf, FileSpec::Style::native); 44 45 return error; 46 } 47 48 Status FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst) { 49 char resolved_path[PATH_MAX]; 50 if (!src.GetPath(resolved_path, sizeof(resolved_path))) { 51 return Status::FromErrorStringWithFormat( 52 "Couldn't get the canonical path for %s", src.GetPath().c_str()); 53 } 54 55 char real_path[PATH_MAX + 1]; 56 if (realpath(resolved_path, real_path) == nullptr) { 57 return Status::FromErrno(); 58 } 59 60 dst = FileSpec(real_path); 61 62 return Status(); 63 } 64 65 FILE *FileSystem::Fopen(const char *path, const char *mode) { 66 return llvm::sys::RetryAfterSignal(nullptr, ::fopen, path, mode); 67 } 68 69 int FileSystem::Open(const char *path, int flags, int mode) { 70 // Call ::open in a lambda to avoid overload resolution in RetryAfterSignal 71 // when open is overloaded, such as in Bionic. 72 auto lambda = [&]() { return ::open(path, flags, mode); }; 73 return llvm::sys::RetryAfterSignal(-1, lambda); 74 } 75