aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt7
-rw-r--r--include/winapi/file.hpp37
-rw-r--r--src/file.cpp42
3 files changed, 86 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8553200..035ea3a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -17,6 +17,13 @@ target_link_libraries(winapi_common PUBLIC Boost::disable_autolinking Boost::boo
install(TARGETS winapi_common ARCHIVE DESTINATION lib)
install(DIRECTORY include/winapi DESTINATION include)
+if(MINGW)
+ # FILE_ID_INFO and friends require at least 0x0602:
+ target_compile_definitions(winapi_common PUBLIC
+ NTDDI_VERSION=NTDDI_WIN8
+ _WIN32_WINNT=_WIN32_WINNT_WIN8)
+endif()
+
if(WINAPI_COMMON_TESTS)
add_subdirectory(test)
endif()
diff --git a/include/winapi/file.hpp b/include/winapi/file.hpp
index b9688e9..78187d9 100644
--- a/include/winapi/file.hpp
+++ b/include/winapi/file.hpp
@@ -8,15 +8,34 @@
#include "handle.hpp"
#include "path.hpp"
+#include <boost/functional/hash.hpp>
+
+#include <windows.h>
+
+#include <cstddef>
+#include <functional>
#include <string>
#include <utility>
namespace winapi {
+bool operator==(const FILE_ID_128& a, const FILE_ID_128& b);
+
class File : private Handle {
public:
+ struct ID {
+ const FILE_ID_INFO impl;
+
+ bool operator==(const ID& other) const {
+ return impl.VolumeSerialNumber == other.impl.VolumeSerialNumber &&
+ impl.FileId == other.impl.FileId;
+ }
+ };
+
static Handle open_r(const std::string&);
static Handle open_r(const CanonicalPath&);
+ static Handle open_read_attributes(const std::string&);
+ static Handle open_read_attributes(const CanonicalPath&);
static Handle open_w(const std::string&);
static Handle open_w(const CanonicalPath&);
@@ -29,6 +48,24 @@ public:
using Handle::read;
using Handle::write;
+
+ std::size_t get_size() const;
+
+ ID query_id() const;
};
} // namespace winapi
+
+namespace std {
+
+template <>
+struct hash<winapi::File::ID> {
+ std::size_t operator()(const winapi::File::ID& id) const {
+ std::size_t seed = 0;
+ boost::hash_combine(seed, id.impl.VolumeSerialNumber);
+ boost::hash_combine(seed, id.impl.FileId.Identifier);
+ return seed;
+ }
+};
+
+} // namespace std
diff --git a/src/file.cpp b/src/file.cpp
index 165f36e..2b04f80 100644
--- a/src/file.cpp
+++ b/src/file.cpp
@@ -9,7 +9,10 @@
#include <winapi/path.hpp>
#include <winapi/utf8.hpp>
+#include <cstddef>
+#include <cstdint>
#include <cstring>
+#include <stdexcept>
#include <string>
namespace winapi {
@@ -32,6 +35,13 @@ struct CreateFileParams {
return params;
}
+ static CreateFileParams read_attributes() {
+ auto params = read();
+ params.dwDesiredAccess = FILE_READ_ATTRIBUTES;
+ params.dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ return params;
+ }
+
static CreateFileParams write() {
CreateFileParams params;
params.dwDesiredAccess = GENERIC_WRITE;
@@ -87,6 +97,38 @@ Handle File::open_r(const CanonicalPath& path) {
return open_file(to_system_path(path), CreateFileParams::read());
}
+Handle File::open_read_attributes(const std::string& path) {
+ return open_file(to_system_path(path), CreateFileParams::read_attributes());
+}
+
+Handle File::open_read_attributes(const CanonicalPath& path) {
+ return open_file(to_system_path(path), CreateFileParams::read_attributes());
+}
+
+std::size_t File::get_size() const {
+ LARGE_INTEGER size;
+
+ if (!GetFileSizeEx(get(), &size))
+ throw error::windows(GetLastError(), "GetFileSizeEx");
+
+ if (size.QuadPart < 0 || size.QuadPart > SIZE_MAX)
+ throw std::runtime_error{"invalid file size"};
+ return static_cast<std::size_t>(size.QuadPart);
+}
+
+bool operator==(const FILE_ID_128& a, const FILE_ID_128& b) {
+ return 0 == std::memcmp(a.Identifier, b.Identifier, sizeof(a.Identifier));
+}
+
+File::ID File::query_id() const {
+ FILE_ID_INFO id;
+
+ if (!GetFileInformationByHandleEx(get(), FileIdInfo, &id, sizeof(id)))
+ throw error::windows(GetLastError(), "GetFileInformationByHandleEx");
+
+ return {id};
+}
+
Handle File::open_w(const std::string& path) {
return open_file(to_system_path(path), CreateFileParams::write());
}