aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorMichael J. Spencer <bigcheesegs@gmail.com>2010-12-01 19:32:01 +0000
committerMichael J. Spencer <bigcheesegs@gmail.com>2010-12-01 19:32:01 +0000
commitbee0c38f595f52d424161dc1db9c0bfe61421957 (patch)
tree7960210198d9c6a272adaba4a42cbe3cb7e6db4c /lib
parent5a7df60619d88a2c804b0dbdf68b0b502941bba3 (diff)
downloadexternal_llvm-bee0c38f595f52d424161dc1db9c0bfe61421957.zip
external_llvm-bee0c38f595f52d424161dc1db9c0bfe61421957.tar.gz
external_llvm-bee0c38f595f52d424161dc1db9c0bfe61421957.tar.bz2
Support/FileSystem: Add copy_file implementation. Not tests yet because the
file creation APIs aren't implemented. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120593 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Support/PathV2.cpp11
-rw-r--r--lib/Support/Unix/PathV2.inc92
-rw-r--r--lib/Support/Windows/PathV2.inc57
3 files changed, 157 insertions, 3 deletions
diff --git a/lib/Support/PathV2.cpp b/lib/Support/PathV2.cpp
index a4a3f38..dbfde54 100644
--- a/lib/Support/PathV2.cpp
+++ b/lib/Support/PathV2.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/PathV2.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/ErrorHandling.h"
#include <cctype>
@@ -666,9 +667,13 @@ error_code is_relative(const Twine &path, bool &result) {
return ec;
}
-}
-}
-}
+} // end namespace path
+
+namespace fs {
+
+} // end namespace fs
+} // end namespace sys
+} // end namespace llvm
// Include the truly platform-specific parts.
#if defined(LLVM_ON_UNIX)
diff --git a/lib/Support/Unix/PathV2.inc b/lib/Support/Unix/PathV2.inc
index bcd93f0..d12cd16 100644
--- a/lib/Support/Unix/PathV2.inc
+++ b/lib/Support/Unix/PathV2.inc
@@ -17,6 +17,35 @@
//===----------------------------------------------------------------------===//
#include "Unix.h"
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+namespace {
+ struct AutoFD {
+ int FileDescriptor;
+
+ AutoFD(int fd) : FileDescriptor(fd) {}
+ ~AutoFD() {
+ if (FileDescriptor >= 0)
+ ::close(FileDescriptor);
+ }
+
+ int take() {
+ int ret = FileDescriptor;
+ FileDescriptor = -1;
+ return ret;
+ }
+
+ operator int() const {return FileDescriptor;}
+ };
+}
namespace llvm {
namespace sys {
@@ -35,5 +64,68 @@ error_code current_path(SmallVectorImpl<char> &result) {
}
} // end namespace path
+
+namespace fs{
+
+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.toStringRef(from_storage);
+ StringRef t = to.toStringRef(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 make_error_code(errc::success);
+}
+
+} // end namespace fs
} // end namespace sys
} // end namespace llvm
diff --git a/lib/Support/Windows/PathV2.inc b/lib/Support/Windows/PathV2.inc
index 9c15e26..cb80731 100644
--- a/lib/Support/Windows/PathV2.inc
+++ b/lib/Support/Windows/PathV2.inc
@@ -18,6 +18,36 @@
#include "Windows.h"
+using namespace llvm;
+
+namespace {
+ error_code UTF8ToUTF16(const StringRef &utf8,
+ SmallVectorImpl<wchar_t> &utf16) {
+ int len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
+ utf8.begin(), utf8.size(),
+ utf16.begin(), 0);
+
+ if (len == 0)
+ return make_error_code(windows_error(::GetLastError()));
+
+ utf16.reserve(len + 1);
+ utf16.set_size(len);
+
+ len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
+ utf8.begin(), utf8.size(),
+ utf16.begin(), utf16.size());
+
+ if (len == 0)
+ return make_error_code(windows_error(::GetLastError()));
+
+ // Make utf16 null terminated.
+ utf16.push_back(0);
+ utf16.pop_back();
+
+ return make_error_code(errc::success);
+ }
+}
+
namespace llvm {
namespace sys {
namespace path {
@@ -67,5 +97,32 @@ retry_cur_dir:
}
} // end namespace path
+
+namespace fs {
+
+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.toStringRef(from_storage);
+ StringRef t = to.toStringRef(to_storage);
+
+ // Convert to utf-16.
+ SmallVector<wchar_t, 128> wide_from;
+ SmallVector<wchar_t, 128> wide_to;
+ if (error_code ec = UTF8ToUTF16(f, wide_from)) return ec;
+ if (error_code ec = UTF8ToUTF16(t, wide_to)) return ec;
+
+ // Copy the file.
+ BOOL res = ::CopyFileW(wide_from.begin(), wide_to.begin(),
+ copt != copy_option::overwrite_if_exists);
+
+ if (res == 0)
+ return make_error_code(windows_error(::GetLastError()));
+
+ return make_error_code(errc::success);
+}
+
+} // end namespace fs
} // end namespace sys
} // end namespace llvm