aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Support/Unix/Path.inc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Support/Unix/Path.inc')
-rw-r--r--lib/Support/Unix/Path.inc138
1 files changed, 83 insertions, 55 deletions
diff --git a/lib/Support/Unix/Path.inc b/lib/Support/Unix/Path.inc
index 623547a..634d404 100644
--- a/lib/Support/Unix/Path.inc
+++ b/lib/Support/Unix/Path.inc
@@ -87,22 +87,6 @@ namespace {
};
}
-static std::error_code TempDir(SmallVectorImpl<char> &result) {
- // FIXME: Don't use TMPDIR if program is SUID or SGID enabled.
- const char *dir = nullptr;
- (dir = std::getenv("TMPDIR")) || (dir = std::getenv("TMP")) ||
- (dir = std::getenv("TEMP")) || (dir = std::getenv("TEMPDIR")) ||
-#ifdef P_tmpdir
- (dir = P_tmpdir) ||
-#endif
- (dir = "/tmp");
-
- result.clear();
- StringRef d(dir);
- result.append(d.begin(), d.end());
- return std::error_code();
-}
-
namespace llvm {
namespace sys {
namespace fs {
@@ -272,19 +256,6 @@ std::error_code create_directory(const Twine &path, bool IgnoreExisting) {
return std::error_code();
}
-std::error_code normalize_separators(SmallVectorImpl<char> &Path) {
- for (auto PI = Path.begin(), PE = Path.end(); PI < PE; ++PI) {
- if (*PI == '\\') {
- auto PN = PI + 1;
- if (PN < PE && *PN == '\\')
- ++PI; // increment once, the for loop will move over the escaped slash
- else
- *PI = '/';
- }
- }
- return std::error_code();
-}
-
// Note that we are using symbolic link because hard links are not supported by
// all filesystems (SMB doesn't).
std::error_code create_link(const Twine &to, const Twine &from) {
@@ -350,38 +321,35 @@ std::error_code resize_file(const Twine &path, uint64_t size) {
return std::error_code();
}
-std::error_code exists(const Twine &path, bool &result) {
- SmallString<128> path_storage;
- StringRef p = path.toNullTerminatedStringRef(path_storage);
-
- if (::access(p.begin(), F_OK) == -1) {
- if (errno != ENOENT)
- return std::error_code(errno, std::generic_category());
- result = false;
- } else
- result = true;
-
- return std::error_code();
+static int convertAccessMode(AccessMode Mode) {
+ switch (Mode) {
+ case AccessMode::Exist:
+ return F_OK;
+ case AccessMode::Write:
+ return W_OK;
+ case AccessMode::Execute:
+ return R_OK | X_OK; // scripts also need R_OK.
+ }
+ llvm_unreachable("invalid enum");
}
-bool can_write(const Twine &Path) {
+std::error_code access(const Twine &Path, AccessMode Mode) {
SmallString<128> PathStorage;
StringRef P = Path.toNullTerminatedStringRef(PathStorage);
- return 0 == access(P.begin(), W_OK);
-}
-bool can_execute(const Twine &Path) {
- SmallString<128> PathStorage;
- StringRef P = Path.toNullTerminatedStringRef(PathStorage);
+ if (::access(P.begin(), convertAccessMode(Mode)) == -1)
+ return std::error_code(errno, std::generic_category());
- if (0 != access(P.begin(), R_OK | X_OK))
- return false;
- struct stat buf;
- if (0 != stat(P.begin(), &buf))
- return false;
- if (!S_ISREG(buf.st_mode))
- return false;
- return true;
+ if (Mode == AccessMode::Execute) {
+ // Don't say that directories are executable.
+ struct stat buf;
+ if (0 != stat(P.begin(), &buf))
+ return errc::permission_denied;
+ if (!S_ISREG(buf.st_mode))
+ return errc::permission_denied;
+ }
+
+ return std::error_code();
}
bool equivalent(file_status A, file_status B) {
@@ -678,6 +646,66 @@ bool home_directory(SmallVectorImpl<char> &result) {
return false;
}
+static const char *getEnvTempDir() {
+ // Check whether the temporary directory is specified by an environment
+ // variable.
+ const char *EnvironmentVariables[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"};
+ for (const char *Env : EnvironmentVariables) {
+ if (const char *Dir = std::getenv(Env))
+ return Dir;
+ }
+
+ return nullptr;
+}
+
+static const char *getDefaultTempDir(bool ErasedOnReboot) {
+#ifdef P_tmpdir
+ if ((bool)P_tmpdir)
+ return P_tmpdir;
+#endif
+
+ if (ErasedOnReboot)
+ return "/tmp";
+ return "/var/tmp";
+}
+
+void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) {
+ Result.clear();
+
+ if (ErasedOnReboot) {
+ // There is no env variable for the cache directory.
+ if (const char *RequestedDir = getEnvTempDir()) {
+ Result.append(RequestedDir, RequestedDir + strlen(RequestedDir));
+ return;
+ }
+ }
+
+#if defined(_CS_DARWIN_USER_TEMP_DIR) && defined(_CS_DARWIN_USER_CACHE_DIR)
+ // On Darwin, use DARWIN_USER_TEMP_DIR or DARWIN_USER_CACHE_DIR.
+ // macros defined in <unistd.h> on darwin >= 9
+ int ConfName = ErasedOnReboot? _CS_DARWIN_USER_TEMP_DIR
+ : _CS_DARWIN_USER_CACHE_DIR;
+ size_t ConfLen = confstr(ConfName, nullptr, 0);
+ if (ConfLen > 0) {
+ do {
+ Result.resize(ConfLen);
+ ConfLen = confstr(ConfName, Result.data(), Result.size());
+ } while (ConfLen > 0 && ConfLen != Result.size());
+
+ if (ConfLen > 0) {
+ assert(Result.back() == 0);
+ Result.pop_back();
+ return;
+ }
+
+ Result.clear();
+ }
+#endif
+
+ const char *RequestedDir = getDefaultTempDir(ErasedOnReboot);
+ Result.append(RequestedDir, RequestedDir + strlen(RequestedDir));
+}
+
} // end namespace path
} // end namespace sys