//===----------------------------------------------------------------------===//
#include "Unix.h"
-#include "llvm/Support/Process.h"
+#include <limits.h>
+#include <stdio.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
# include <ndir.h>
# endif
#endif
-#if HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#if HAVE_LIMITS_H
-#include <limits.h>
-#endif
#ifdef __APPLE__
#include <mach-o/dyld.h>
operator int() const {return FileDescriptor;}
};
+}
- error_code TempDir(SmallVectorImpl<char> &result) {
- // FIXME: Don't use TMPDIR if program is SUID or SGID enabled.
- const char *dir = 0;
- (dir = std::getenv("TMPDIR" )) ||
- (dir = std::getenv("TMP" )) ||
- (dir = std::getenv("TEMP" )) ||
- (dir = std::getenv("TEMPDIR")) ||
+static error_code TempDir(SmallVectorImpl<char> &result) {
+ // FIXME: Don't use TMPDIR if program is SUID or SGID enabled.
+ const char *dir = 0;
+ (dir = std::getenv("TMPDIR")) || (dir = std::getenv("TMP")) ||
+ (dir = std::getenv("TEMP")) || (dir = std::getenv("TEMPDIR")) ||
#ifdef P_tmpdir
- (dir = P_tmpdir) ||
+ (dir = P_tmpdir) ||
#endif
- (dir = "/tmp");
-
- result.clear();
- StringRef d(dir);
- result.append(d.begin(), d.end());
- return error_code::success();
- }
-}
-
-static error_code createUniqueEntity(const Twine &Model, int &ResultFD,
- SmallVectorImpl<char> &ResultPath,
- bool MakeAbsolute, unsigned Mode,
- FSEntity Type) {
- SmallString<128> ModelStorage;
- Model.toVector(ModelStorage);
-
- if (MakeAbsolute) {
- // Make model absolute by prepending a temp directory if it's not already.
- bool absolute = sys::path::is_absolute(Twine(ModelStorage));
- if (!absolute) {
- SmallString<128> TDir;
- if (error_code ec = TempDir(TDir)) return ec;
- sys::path::append(TDir, Twine(ModelStorage));
- ModelStorage.swap(TDir);
- }
- }
-
- // From here on, DO NOT modify model. It may be needed if the randomly chosen
- // path already exists.
- ResultPath = ModelStorage;
- // Null terminate.
- ResultPath.push_back(0);
- ResultPath.pop_back();
-
-retry_random_path:
- // Replace '%' with random chars.
- for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) {
- if (ModelStorage[i] == '%')
- ResultPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15];
- }
-
- // Try to open + create the file.
- switch (Type) {
- case FS_File: {
- int RandomFD = ::open(ResultPath.begin(), O_RDWR | O_CREAT | O_EXCL, Mode);
- if (RandomFD == -1) {
- int SavedErrno = errno;
- // If the file existed, try again, otherwise, error.
- if (SavedErrno == errc::file_exists)
- goto retry_random_path;
- return error_code(SavedErrno, system_category());
- }
-
- ResultFD = RandomFD;
- return error_code::success();
- }
-
- case FS_Name: {
- bool Exists;
- error_code EC = sys::fs::exists(ResultPath.begin(), Exists);
- if (EC)
- return EC;
- if (Exists)
- goto retry_random_path;
- return error_code::success();
- }
+ (dir = "/tmp");
- case FS_Dir: {
- bool Existed;
- error_code EC = sys::fs::create_directory(ResultPath.begin(), Existed);
- if (EC)
- return EC;
- if (Existed)
- goto retry_random_path;
- return error_code::success();
- }
- }
- llvm_unreachable("Invalid Type");
+ result.clear();
+ StringRef d(dir);
+ result.append(d.begin(), d.end());
+ return error_code::success();
}
namespace llvm {
namespace fs {
#if defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \
defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__) || \
- defined(__linux__) || defined(__CYGWIN__)
+ defined(__linux__) || defined(__CYGWIN__) || defined(__DragonFly__)
static int
-test_dir(char buf[PATH_MAX], char ret[PATH_MAX],
- const char *dir, const char *bin)
-{
+test_dir(char ret[PATH_MAX], const char *dir, const char *bin)
+{
struct stat sb;
+ char fullpath[PATH_MAX];
- snprintf(buf, PATH_MAX, "%s/%s", dir, bin);
- if (realpath(buf, ret) == NULL)
+ snprintf(fullpath, PATH_MAX, "%s/%s", dir, bin);
+ if (realpath(fullpath, ret) == NULL)
return (1);
- if (stat(buf, &sb) != 0)
+ if (stat(fullpath, &sb) != 0)
return (1);
return (0);
static char *
getprogpath(char ret[PATH_MAX], const char *bin)
{
- char *pv, *s, *t, buf[PATH_MAX];
+ char *pv, *s, *t;
/* First approach: absolute path. */
if (bin[0] == '/') {
- if (test_dir(buf, ret, "/", bin) == 0)
+ if (test_dir(ret, "/", bin) == 0)
return (ret);
return (NULL);
}
/* Second approach: relative path. */
if (strchr(bin, '/') != NULL) {
- if (getcwd(buf, PATH_MAX) == NULL)
+ char cwd[PATH_MAX];
+ if (getcwd(cwd, PATH_MAX) == NULL)
return (NULL);
- if (test_dir(buf, ret, buf, bin) == 0)
+ if (test_dir(ret, cwd, bin) == 0)
return (ret);
return (NULL);
}
if (pv == NULL)
return (NULL);
while ((t = strsep(&s, ":")) != NULL) {
- if (test_dir(buf, ret, t, bin) == 0) {
+ if (test_dir(ret, t, bin) == 0) {
free(pv);
return (ret);
}
return link_path;
}
#elif defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \
- defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__)
+ defined(__OpenBSD__) || defined(__minix) || defined(__DragonFly__) || \
+ defined(__FreeBSD_kernel__)
char exe_path[PATH_MAX];
if (getprogpath(exe_path, argv0) != NULL)
return Ret;
}
+UniqueID file_status::getUniqueID() const {
+ return UniqueID(fs_st_dev, fs_st_ino);
+}
+
error_code current_path(SmallVectorImpl<char> &result) {
+ result.clear();
+
+ const char *pwd = ::getenv("PWD");
+ llvm::sys::fs::file_status PWDStatus, DotStatus;
+ if (pwd && llvm::sys::path::is_absolute(pwd) &&
+ !llvm::sys::fs::status(pwd, PWDStatus) &&
+ !llvm::sys::fs::status(".", DotStatus) &&
+ PWDStatus.getUniqueID() == DotStatus.getUniqueID()) {
+ result.append(pwd, pwd + strlen(pwd));
+ return error_code::success();
+ }
+
#ifdef MAXPATHLEN
result.reserve(MAXPATHLEN);
#else
return error_code::success();
}
-error_code copy_file(const Twine &from, const Twine &to, copy_option copt) {
- // Get arguments.
- SmallString<128> from_storage;
- SmallString<128> to_storage;
- StringRef f = from.toNullTerminatedStringRef(from_storage);
- StringRef t = to.toNullTerminatedStringRef(to_storage);
-
- const size_t buf_sz = 32768;
- char buffer[buf_sz];
- int from_file = -1, to_file = -1;
-
- // Open from.
- if ((from_file = ::open(f.begin(), O_RDONLY)) < 0)
- return error_code(errno, system_category());
- AutoFD from_fd(from_file);
-
- // Stat from.
- struct stat from_stat;
- if (::stat(f.begin(), &from_stat) != 0)
- return error_code(errno, system_category());
-
- // Setup to flags.
- int to_flags = O_CREAT | O_WRONLY;
- if (copt == copy_option::fail_if_exists)
- to_flags |= O_EXCL;
-
- // Open to.
- if ((to_file = ::open(t.begin(), to_flags, from_stat.st_mode)) < 0)
- return error_code(errno, system_category());
- AutoFD to_fd(to_file);
-
- // Copy!
- ssize_t sz, sz_read = 1, sz_write;
- while (sz_read > 0 &&
- (sz_read = ::read(from_fd, buffer, buf_sz)) > 0) {
- // Allow for partial writes - see Advanced Unix Programming (2nd Ed.),
- // Marc Rochkind, Addison-Wesley, 2004, page 94
- sz_write = 0;
- do {
- if ((sz = ::write(to_fd, buffer + sz_write, sz_read - sz_write)) < 0) {
- sz_read = sz; // cause read loop termination.
- break; // error.
- }
- sz_write += sz;
- } while (sz_write < sz_read);
- }
-
- // After all the file operations above the return value of close actually
- // matters.
- if (::close(from_fd.take()) < 0) sz_read = -1;
- if (::close(to_fd.take()) < 0) sz_read = -1;
-
- // Check for errors.
- if (sz_read < 0)
- return error_code(errno, system_category());
-
- return error_code::success();
-}
-
-error_code create_directory(const Twine &path, bool &existed) {
+error_code create_directory(const Twine &path, bool IgnoreExisting) {
SmallString<128> path_storage;
StringRef p = path.toNullTerminatedStringRef(path_storage);
if (::mkdir(p.begin(), S_IRWXU | S_IRWXG) == -1) {
- if (errno != errc::file_exists)
+ if (errno != errc::file_exists || !IgnoreExisting)
return error_code(errno, system_category());
- existed = true;
- } else
- existed = false;
+ }
return error_code::success();
}
return error_code::success();
}
-error_code create_symlink(const Twine &to, const Twine &from) {
- // Get arguments.
- SmallString<128> from_storage;
- SmallString<128> to_storage;
- StringRef f = from.toNullTerminatedStringRef(from_storage);
- StringRef t = to.toNullTerminatedStringRef(to_storage);
-
- if (::symlink(t.begin(), f.begin()) == -1)
- return error_code(errno, system_category());
-
- return error_code::success();
-}
-
-error_code remove(const Twine &path, bool &existed) {
+error_code remove(const Twine &path, bool IgnoreNonExisting) {
SmallString<128> path_storage;
StringRef p = path.toNullTerminatedStringRef(path_storage);
struct stat buf;
if (stat(p.begin(), &buf) != 0) {
- if (errno != errc::no_such_file_or_directory)
+ if (errno != errc::no_such_file_or_directory || !IgnoreNonExisting)
return error_code(errno, system_category());
- existed = false;
return error_code::success();
}
return make_error_code(errc::operation_not_permitted);
if (::remove(p.begin()) == -1) {
- if (errno != errc::no_such_file_or_directory)
+ if (errno != errc::no_such_file_or_directory || !IgnoreNonExisting)
return error_code(errno, system_category());
- existed = false;
- } else
- existed = true;
+ }
return error_code::success();
}
return error_code::success();
}
-error_code getUniqueID(const Twine Path, uint64_t &Result) {
- SmallString<128> Storage;
- StringRef P = Path.toNullTerminatedStringRef(Storage);
-
- struct stat Status;
- if (::stat(P.begin(), &Status) != 0)
- return error_code(errno, system_category());
-
- Result = Status.st_ino;
- return error_code::success();
-}
-
static error_code fillStatus(int StatRet, const struct stat &Status,
file_status &Result) {
if (StatRet != 0) {
error_code setLastModificationAndAccessTime(int FD, TimeValue Time) {
#if defined(HAVE_FUTIMENS)
timespec Times[2];
- Times[0].tv_sec = Time.toPosixTime();
+ Times[0].tv_sec = Time.toEpochTime();
Times[0].tv_nsec = 0;
Times[1] = Times[0];
if (::futimens(FD, Times))
+ return error_code(errno, system_category());
+ return error_code::success();
#elif defined(HAVE_FUTIMES)
timeval Times[2];
- Times[0].tv_sec = Time.toPosixTime();
+ Times[0].tv_sec = Time.toEpochTime();
Times[0].tv_usec = 0;
Times[1] = Times[0];
if (::futimes(FD, Times))
-#else
-#error Missing futimes() and futimens()
-#endif
return error_code(errno, system_category());
return error_code::success();
+#else
+#warning Missing futimes() and futimens()
+ return make_error_code(errc::not_supported);
+#endif
}
error_code mapped_file_region::init(int FD, bool CloseFD, uint64_t Offset) {
::munmap(Mapping, Size);
}
-#if LLVM_HAS_RVALUE_REFERENCES
mapped_file_region::mapped_file_region(mapped_file_region &&other)
: Mode(other.Mode), Size(other.Size), Mapping(other.Mapping) {
other.Mapping = 0;
}
-#endif
mapped_file_region::mapmode mapped_file_region::flags() const {
assert(Mapping && "Mapping failed but used anyway!");
char *mapped_file_region::data() const {
assert(Mapping && "Mapping failed but used anyway!");
- assert(Mode != readonly && "Cannot get non const data for readonly mapping!");
+ assert(Mode != readonly && "Cannot get non-const data for readonly mapping!");
return reinterpret_cast<char*>(Mapping);
}
return error_code::success();
}
+error_code openFileForRead(const Twine &Name, int &ResultFD) {
+ SmallString<128> Storage;
+ StringRef P = Name.toNullTerminatedStringRef(Storage);
+ while ((ResultFD = open(P.begin(), O_RDONLY)) < 0) {
+ if (errno != EINTR)
+ return error_code(errno, system_category());
+ }
+ return error_code::success();
+}
+
+error_code openFileForWrite(const Twine &Name, int &ResultFD,
+ sys::fs::OpenFlags Flags, unsigned Mode) {
+ // Verify that we don't have both "append" and "excl".
+ assert((!(Flags & sys::fs::F_Excl) || !(Flags & sys::fs::F_Append)) &&
+ "Cannot specify both 'excl' and 'append' file creation flags!");
+
+ int OpenFlags = O_CREAT;
+
+ if (Flags & F_RW)
+ OpenFlags |= O_RDWR;
+ else
+ OpenFlags |= O_WRONLY;
+
+ if (Flags & F_Append)
+ OpenFlags |= O_APPEND;
+ else
+ OpenFlags |= O_TRUNC;
+
+ if (Flags & F_Excl)
+ OpenFlags |= O_EXCL;
+
+ SmallString<128> Storage;
+ StringRef P = Name.toNullTerminatedStringRef(Storage);
+ while ((ResultFD = open(P.begin(), OpenFlags, Mode)) < 0) {
+ if (errno != EINTR)
+ return error_code(errno, system_category());
+ }
+ return error_code::success();
+}
} // end namespace fs
+
+namespace path {
+
+bool home_directory(SmallVectorImpl<char> &result) {
+ if (char *RequestedDir = getenv("HOME")) {
+ result.clear();
+ result.append(RequestedDir, RequestedDir + strlen(RequestedDir));
+ return true;
+ }
+
+ return false;
+}
+
+} // end namespace path
+
} // end namespace sys
} // end namespace llvm