mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-19 04:32:19 +00:00
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
This commit is contained in:
parent
5a7df60619
commit
bee0c38f59
@ -12,6 +12,7 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/Support/PathV2.h"
|
#include "llvm/Support/PathV2.h"
|
||||||
|
#include "llvm/Support/FileSystem.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
|
||||||
@ -666,9 +667,13 @@ error_code is_relative(const Twine &path, bool &result) {
|
|||||||
return ec;
|
return ec;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // end namespace path
|
||||||
}
|
|
||||||
}
|
namespace fs {
|
||||||
|
|
||||||
|
} // end namespace fs
|
||||||
|
} // end namespace sys
|
||||||
|
} // end namespace llvm
|
||||||
|
|
||||||
// Include the truly platform-specific parts.
|
// Include the truly platform-specific parts.
|
||||||
#if defined(LLVM_ON_UNIX)
|
#if defined(LLVM_ON_UNIX)
|
||||||
|
@ -17,6 +17,35 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "Unix.h"
|
#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 llvm {
|
||||||
namespace sys {
|
namespace sys {
|
||||||
@ -35,5 +64,68 @@ error_code current_path(SmallVectorImpl<char> &result) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace path
|
} // 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 sys
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
@ -18,6 +18,36 @@
|
|||||||
|
|
||||||
#include "Windows.h"
|
#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 llvm {
|
||||||
namespace sys {
|
namespace sys {
|
||||||
namespace path {
|
namespace path {
|
||||||
@ -67,5 +97,32 @@ retry_cur_dir:
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace path
|
} // 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 sys
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
Loading…
x
Reference in New Issue
Block a user