From dcccba655fe848564e961b3f285ce3a82d3ac73a Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Sat, 7 Mar 2020 14:07:28 +0300 Subject: Add more support for symlinks on Windows See mksymlink() for details of the symlinks support on Windows. --- libbutl/win32-utility.hxx | 81 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) (limited to 'libbutl/win32-utility.hxx') diff --git a/libbutl/win32-utility.hxx b/libbutl/win32-utility.hxx index 70aafc4..b71eb1a 100644 --- a/libbutl/win32-utility.hxx +++ b/libbutl/win32-utility.hxx @@ -43,6 +43,86 @@ namespace butl { namespace win32 { + // RAII type for handles. Note that failure to close the handle is + // silently ignored by both the destructor and reset(). + // + // The handle can be INVALID_HANDLE_VALUE. Such a handle is treated as + // unopened and is not closed. + // + struct nullhandle_t + { + constexpr explicit nullhandle_t (HANDLE) {} + operator HANDLE () const {return INVALID_HANDLE_VALUE;} + }; + + LIBBUTL_SYMEXPORT extern const nullhandle_t nullhandle; + + class LIBBUTL_SYMEXPORT auto_handle + { + public: + auto_handle (nullhandle_t = nullhandle) noexcept + : handle_ (INVALID_HANDLE_VALUE) {} + + explicit + auto_handle (HANDLE h) noexcept: handle_ (h) {} + + auto_handle (auto_handle&& h) noexcept: handle_ (h.release ()) {} + auto_handle& operator= (auto_handle&&) noexcept; + + auto_handle (const auto_handle&) = delete; + auto_handle& operator= (const auto_handle&) = delete; + + ~auto_handle () noexcept; + + HANDLE + get () const noexcept {return handle_;} + + void + reset (HANDLE h = INVALID_HANDLE_VALUE) noexcept; + + HANDLE + release () noexcept + { + HANDLE r (handle_); + handle_ = INVALID_HANDLE_VALUE; + return r; + } + + // Close an open handle. Throw std::system_error on the underlying OS + // error. Reset the descriptor to INVALID_HANDLE_VALUE whether the + // exception is thrown or not. + // + void + close (); + + private: + HANDLE handle_; + }; + + inline bool + operator== (const auto_handle& x, const auto_handle& y) + { + return x.get () == y.get (); + } + + inline bool + operator!= (const auto_handle& x, const auto_handle& y) + { + return !(x == y); + } + + inline bool + operator== (const auto_handle& x, nullhandle_t) + { + return x.get () == INVALID_HANDLE_VALUE; + } + + inline bool + operator!= (const auto_handle& x, nullhandle_t y) + { + return !(x == y); + } + LIBBUTL_SYMEXPORT std::string error_msg (DWORD code); @@ -51,4 +131,5 @@ namespace butl } }; +#include #endif // _WIN32 -- cgit v1.1