static FileDescriptor create(const path* p, error_code& ec, Args... args) {
ec.clear();
int fd;
- if ((fd = detail::open(p->c_str(), args...)) == -1) {
+#ifdef _LIBCPP_WIN32API
+ // TODO: most of the filesystem implementation uses native Win32 calls
+ // (mostly via posix_compat.h). However, here we use the C-runtime APIs to
+ // open a file, because we subsequently pass the C-runtime fd to
+ // `std::[io]fstream::__open(int fd)` in order to implement copy_file.
+ //
+ // Because we're calling the windows C-runtime, win32 error codes are
+ // translated into C error numbers by the C runtime, and returned in errno,
+ // rather than being accessible directly via GetLastError.
+ //
+ // Ideally copy_file should be calling the Win32 CopyFile2 function, which
+ // works on paths, not open files -- at which point this FileDescriptor type
+ // will no longer be needed on windows at all.
+ fd = ::_wopen(p->c_str(), args...);
+#else
+ fd = open(p->c_str(), args...);
+#endif
+
+ if (fd == -1) {
ec = capture_errno();
return FileDescriptor{p};
}
file_status refresh_status(error_code& ec);
void close() noexcept {
- if (fd != -1)
- detail::close(fd);
+ if (fd != -1) {
+#ifdef _LIBCPP_WIN32API
+ ::_close(fd);
+#else
+ ::close(fd);
+#endif
+ // FIXME: shouldn't this return an error_code?
+ }
fd = -1;
}
inline int mkdir(const wchar_t *path, int permissions) {
(void)permissions;
- return _wmkdir(path);
+ if (!CreateDirectoryW(path, nullptr))
+ return set_errno();
+ return 0;
}
inline int symlink_file_dir(const wchar_t *oldname, const wchar_t *newname,
return 0;
}
-template <class... Args> int open(const wchar_t *filename, Args... args) {
- return _wopen(filename, args...);
+inline int chdir(const wchar_t* path) {
+ if (!SetCurrentDirectoryW(path))
+ return set_errno();
+ return 0;
}
-inline int close(int fd) { return _close(fd); }
-inline int chdir(const wchar_t *path) { return _wchdir(path); }
struct StatVFS {
uint64_t f_frsize;
return 0;
}
-inline wchar_t *getcwd(wchar_t *buff, size_t size) { return _wgetcwd(buff, size); }
+inline wchar_t* getcwd([[maybe_unused]] wchar_t* in_buf, [[maybe_unused]] size_t in_size) {
+ // Only expected to be used with us allocating the buffer.
+ _LIBCPP_ASSERT(in_buf == nullptr, "Windows getcwd() assumes in_buf==nullptr");
+ _LIBCPP_ASSERT(in_size == 0, "Windows getcwd() assumes in_size==0");
+
+ size_t buff_size = MAX_PATH + 10;
+ std::unique_ptr<wchar_t, decltype(&::free)> buff(static_cast<wchar_t*>(malloc(buff_size * sizeof(wchar_t))), &::free);
+ DWORD retval = GetCurrentDirectoryW(buff_size, buff.get());
+ if (retval > buff_size) {
+ buff_size = retval;
+ buff.reset(static_cast<wchar_t*>(malloc(buff_size * sizeof(wchar_t))));
+ retval = GetCurrentDirectoryW(buff_size, buff.get());
+ }
+ if (!retval) {
+ set_errno();
+ return nullptr;
+ }
+ return buff.release();
+}
inline wchar_t *realpath(const wchar_t *path, [[maybe_unused]] wchar_t *resolved_name) {
// Only expected to be used with us allocating the buffer.
return ::symlink(oldname, newname);
}
using ::chdir;
-using ::close;
using ::fchmod;
#if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD)
using ::fchmodat;
using ::link;
using ::lstat;
using ::mkdir;
-using ::open;
using ::readlink;
using ::realpath;
using ::remove;