aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
authorEgor Tensin <Egor.Tensin@gmail.com>2020-10-16 18:13:24 +0300
committerEgor Tensin <Egor.Tensin@gmail.com>2020-10-16 21:20:11 +0300
commit182bff76382d59f44f0ac3c69beb55dacde75eb5 (patch)
treea1a90b748831594eeb14def8eef1c13c98ca5aa6 /src
parentProcess: add get_exit_code() (diff)
downloadwinapi-common-182bff76382d59f44f0ac3c69beb55dacde75eb5.tar.gz
winapi-common-182bff76382d59f44f0ac3c69beb55dacde75eb5.zip
add path.hpp: CanonicalPath class, etc.
Apparently, relative paths in the Win32 namespace (e.g. \\?\test.txt) are not a thing.
Diffstat (limited to 'src')
-rw-r--r--src/file.cpp27
-rw-r--r--src/path.cpp47
-rw-r--r--src/stream.cpp7
3 files changed, 75 insertions, 6 deletions
diff --git a/src/file.cpp b/src/file.cpp
index cb9be81..a299d70 100644
--- a/src/file.cpp
+++ b/src/file.cpp
@@ -6,6 +6,7 @@
#include <winapi/error.hpp>
#include <winapi/file.hpp>
#include <winapi/handle.hpp>
+#include <winapi/path.hpp>
#include <winapi/utf8.hpp>
#include <cstring>
@@ -14,6 +15,14 @@
namespace winapi {
namespace {
+std::wstring to_system_path(const std::string& path) {
+ return widen(path);
+}
+
+std::wstring to_system_path(const CanonicalPath& path) {
+ return widen(R"(\\?\)" + path.get());
+}
+
struct CreateFileParams {
static CreateFileParams read() {
CreateFileParams params;
@@ -39,15 +48,13 @@ private:
CreateFileParams() = default;
};
-Handle open_file(const std::string& path, const CreateFileParams& params) {
- const auto unicode_path = LR"(\\?\)" + widen(path);
-
+Handle open_file(const std::wstring& path, const CreateFileParams& params) {
SECURITY_ATTRIBUTES attributes;
std::memset(&attributes, 0, sizeof(attributes));
attributes.nLength = sizeof(attributes);
attributes.bInheritHandle = TRUE;
- const auto handle = ::CreateFileW(unicode_path.c_str(),
+ const auto handle = ::CreateFileW(path.c_str(),
params.dwDesiredAccess,
params.dwShareMode,
&attributes,
@@ -65,11 +72,19 @@ Handle open_file(const std::string& path, const CreateFileParams& params) {
} // namespace
Handle File::open_for_reading(const std::string& path) {
- return open_file(path, CreateFileParams::read());
+ return open_file(to_system_path(path), CreateFileParams::read());
+}
+
+Handle File::open_for_reading(const CanonicalPath& path) {
+ return open_file(to_system_path(path), CreateFileParams::read());
}
Handle File::open_for_writing(const std::string& path) {
- return open_file(path, CreateFileParams::write());
+ return open_file(to_system_path(path), CreateFileParams::write());
+}
+
+Handle File::open_for_writing(const CanonicalPath& path) {
+ return open_file(to_system_path(path), CreateFileParams::write());
}
} // namespace winapi
diff --git a/src/path.cpp b/src/path.cpp
new file mode 100644
index 0000000..2c2deda
--- /dev/null
+++ b/src/path.cpp
@@ -0,0 +1,47 @@
+// Copyright (c) 2020 Egor Tensin <Egor.Tensin@gmail.com>
+// This file is part of the "winapi-common" project.
+// For details, see https://github.com/egor-tensin/winapi-common.
+// Distributed under the MIT License.
+
+#include <winapi/error.hpp>
+#include <winapi/path.hpp>
+#include <winapi/utf8.hpp>
+
+#include <windows.h>
+
+#include <string>
+#include <vector>
+
+namespace winapi {
+namespace {
+
+std::wstring do_canonicalize(const std::wstring& path) {
+ std::vector<wchar_t> buffer;
+ buffer.resize(MAX_PATH);
+
+ while (true) {
+ const auto nch = ::GetFullPathNameW(path.c_str(), buffer.size(), buffer.data(), NULL);
+
+ if (nch == 0) {
+ throw error::windows(GetLastError(), "GetFullPathNameW");
+ }
+
+ if (nch < buffer.size()) {
+ return {buffer.data(), nch};
+ }
+
+ if (nch > buffer.size()) {
+ buffer.resize(2 * buffer.size());
+ }
+ }
+}
+
+} // namespace
+
+CanonicalPath::CanonicalPath(const std::string& path) : m_path(canonicalize(path)) {}
+
+std::string CanonicalPath::canonicalize(const std::string& path) {
+ return narrow(do_canonicalize(widen(path)));
+}
+
+} // namespace winapi
diff --git a/src/stream.cpp b/src/stream.cpp
index b31635e..f9285e6 100644
--- a/src/stream.cpp
+++ b/src/stream.cpp
@@ -5,6 +5,7 @@
#include <winapi/file.hpp>
#include <winapi/handle.hpp>
+#include <winapi/path.hpp>
#include <winapi/stream.hpp>
#include <string>
@@ -21,10 +22,16 @@ Stderr::Stderr() : Stream{Handle::std_err()} {}
Stdin::Stdin(const std::string& path) : Stream{File::open_for_reading(path)} {}
+Stdin::Stdin(const CanonicalPath& path) : Stream{File::open_for_reading(path)} {}
+
Stdout::Stdout(const std::string& path) : Stream{File::open_for_writing(path)} {}
+Stdout::Stdout(const CanonicalPath& path) : Stream{File::open_for_writing(path)} {}
+
Stderr::Stderr(const std::string& path) : Stream{File::open_for_writing(path)} {}
+Stderr::Stderr(const CanonicalPath& path) : Stream{File::open_for_writing(path)} {}
+
Stdin::Stdin(Pipe& pipe) : Stream{std::move(pipe.read_end())} {
pipe.write_end().dont_inherit();
}