From b5c2f74f455935cb0461110f1ff84b2244b03ae1 Mon Sep 17 00:00:00 2001 From: Froster <34234343+Fros1er@users.noreply.github.com> Date: Fri, 17 Feb 2023 03:17:55 +0800 Subject: [PATCH] change sopen_s to wsopen_s (fmtlib#3234) (#3293) --- include/fmt/os.h | 5 +++++ src/os.cc | 28 +++++++++++++++++++++------- test/os-test.cc | 11 +++++++++++ test/posix-mock-test.cc | 8 +------- test/posix-mock.h | 2 -- 5 files changed, 38 insertions(+), 16 deletions(-) diff --git a/include/fmt/os.h b/include/fmt/os.h index d94075a8..e39f38cd 100644 --- a/include/fmt/os.h +++ b/include/fmt/os.h @@ -337,6 +337,11 @@ class FMT_API file { // Creates a buffered_file object associated with this file and detaches // this file object from the file. buffered_file fdopen(const char* mode); + + # if defined(_WIN32) && !defined(__MINGW32__) + // Opens a file and constructs a file object representing this file by wcstring_view filename. Windows only. + static file open_windows_file(wcstring_view path, int oflag); + #endif }; // Returns the memory page size. diff --git a/src/os.cc b/src/os.cc index d9b9d827..9aff7e47 100644 --- a/src/os.cc +++ b/src/os.cc @@ -217,21 +217,23 @@ int buffered_file::descriptor() const { } #if FMT_USE_FCNTL -file::file(cstring_view path, int oflag) { # ifdef _WIN32 - using mode_t = int; +using mode_t = int; # endif - constexpr mode_t mode = - S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; +constexpr mode_t default_open_mode = + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; + +file::file(cstring_view path, int oflag) { # if defined(_WIN32) && !defined(__MINGW32__) fd_ = -1; - FMT_POSIX_CALL(sopen_s(&fd_, path.c_str(), oflag, _SH_DENYNO, mode)); + auto converted = detail::utf8_to_utf16(string_view(path.c_str())); + *this = file::open_windows_file(converted.c_str(), oflag); # else - FMT_RETRY(fd_, FMT_POSIX_CALL(open(path.c_str(), oflag, mode))); -# endif + FMT_RETRY(fd_, FMT_POSIX_CALL(open(path.c_str(), oflag, default_open_mode))); if (fd_ == -1) FMT_THROW( system_error(errno, FMT_STRING("cannot open file {}"), path.c_str())); +# endif } file::~file() noexcept { @@ -357,6 +359,18 @@ buffered_file file::fdopen(const char* mode) { return bf; } +# if defined(_WIN32) && !defined(__MINGW32__) +file file::open_windows_file(wcstring_view path, int oflag) { + int fd_ = -1; + auto err = + _wsopen_s(&fd_, path.c_str(), oflag, _SH_DENYNO, default_open_mode); + if (fd_ == -1) + FMT_THROW(system_error(err, FMT_STRING("cannot open file {}"), + detail::utf16_to_utf8(path.c_str()).c_str())); + return file(fd_); +} +# endif + long getpagesize() { # ifdef _WIN32 SYSTEM_INFO si; diff --git a/test/os-test.cc b/test/os-test.cc index d93c553d..6ebcffcc 100644 --- a/test/os-test.cc +++ b/test/os-test.cc @@ -127,6 +127,17 @@ TEST(os_test, report_windows_error) { fmt::to_string(out)); } +# if FMT_USE_FCNTL && !defined(__MINGW32__) +TEST(file_test, open_windows_file) { + using fmt::file; + file out = file::open_windows_file(L"test-file", + file::WRONLY | file::CREATE | file::TRUNC); + out.write("x", 1); + file in = file::open_windows_file(L"test-file", file::RDONLY); + EXPECT_READ(in, "x"); +} +# endif // FMT_USE_FCNTL && !defined(__MINGW32__) + #endif // _WIN32 #if FMT_USE_FCNTL diff --git a/test/posix-mock-test.cc b/test/posix-mock-test.cc index 819a94df..32078bf8 100644 --- a/test/posix-mock-test.cc +++ b/test/posix-mock-test.cc @@ -72,12 +72,6 @@ int test::open(const char* path, int oflag, int mode) { EMULATE_EINTR(open, -1); return ::open(path, oflag, mode); } -#else -errno_t test::sopen_s(int* pfh, const char* filename, int oflag, int shflag, - int pmode) { - EMULATE_EINTR(open, EINTR); - return _sopen_s(pfh, filename, oflag, shflag, pmode); -} #endif #ifndef _WIN32 @@ -220,11 +214,11 @@ TEST(os_test, getpagesize) { } TEST(file_test, open_retry) { +# ifndef _WIN32 write_file("temp", "there must be something here"); std::unique_ptr f{nullptr}; EXPECT_RETRY(f.reset(new file("temp", file::RDONLY)), open, "cannot open file temp"); -# ifndef _WIN32 char c = 0; f->read(&c, 1); # endif diff --git a/test/posix-mock.h b/test/posix-mock.h index e76af700..4f2a42c1 100644 --- a/test/posix-mock.h +++ b/test/posix-mock.h @@ -37,8 +37,6 @@ int fstat(int fd, struct stat* buf); #else typedef unsigned size_t; typedef int ssize_t; -errno_t sopen_s(int* pfh, const char* filename, int oflag, int shflag, - int pmode); #endif #ifndef _WIN32