Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/windirstat/llfio.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiall Douglas (s [underscore] sourceforge {at} nedprod [dot] com) <spamtrap@nedprod.com>2017-08-04 01:20:35 +0300
committerNiall Douglas (s [underscore] sourceforge {at} nedprod [dot] com) <spamtrap@nedprod.com>2017-08-04 01:20:35 +0300
commitb74c9234c65d73a955c6230559e72931a4ab46d6 (patch)
tree15c2ddb4dfee2a9890bbefc61966ad9a5e3c4c5f
parent7097eb9dd2b9fbd52c702e4dd4b19c0f01a0e0dc (diff)
Split stuff which would be shared with directory_handle out of file_handle into a new fs_handle common base class
-rw-r--r--.travis.yml2
-rw-r--r--cmake/headers.cmake3
-rw-r--r--include/afio/revision.hpp6
-rw-r--r--include/afio/v2.0/async_file_handle.hpp9
-rw-r--r--include/afio/v2.0/detail/impl/posix/file_handle.ipp113
-rw-r--r--include/afio/v2.0/detail/impl/posix/fs_handle.ipp146
-rw-r--r--include/afio/v2.0/detail/impl/windows/file_handle.ipp84
-rw-r--r--include/afio/v2.0/detail/impl/windows/fs_handle.ipp119
-rw-r--r--include/afio/v2.0/file_handle.hpp105
-rw-r--r--include/afio/v2.0/fs_handle.hpp237
-rw-r--r--include/afio/v2.0/handle.hpp12
-rw-r--r--include/afio/v2.0/path_handle.hpp4
12 files changed, 528 insertions, 312 deletions
diff --git a/.travis.yml b/.travis.yml
index 8b3590e1..2e9f54ce 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -73,7 +73,7 @@ script:
if [ "$__" = "cmake tests" ]; then
if [ "$CXX" = "g++" ]; then export CXX=g++-7; export NAME=TravisLinuxWorkerGCC; fi;
if [ "$CXX" = "clang++" ]; then export CXX=clang++-4.0; export NAME=TravisLinuxWorkerClang; fi;
- ctest -S .ci.cmake -V --timeout 300;
+ ctest -S .ci.cmake -V --timeout 300 -E shared_fs_mutex;
fi
-
if [ "$__" = "Documentation" ]; then
diff --git a/cmake/headers.cmake b/cmake/headers.cmake
index efcaca80..46965fc3 100644
--- a/cmake/headers.cmake
+++ b/cmake/headers.cmake
@@ -18,6 +18,7 @@ set(afio_HEADERS
"include/afio/v2.0/detail/impl/posix/import.hpp"
"include/afio/v2.0/detail/impl/windows/import.hpp"
"include/afio/v2.0/file_handle.hpp"
+ "include/afio/v2.0/fs_handle.hpp"
"include/afio/v2.0/handle.hpp"
"include/afio/v2.0/hash.hpp"
"include/afio/v2.0/io_handle.hpp"
@@ -37,6 +38,7 @@ set(afio_HEADERS
"include/afio/ntkernel-error-category/include/detail/ntkernel_category_impl.ipp"
"include/afio/v2.0/detail/impl/posix/async_file_handle.ipp"
"include/afio/v2.0/detail/impl/posix/file_handle.ipp"
+ "include/afio/v2.0/detail/impl/posix/fs_handle.ipp"
"include/afio/v2.0/detail/impl/posix/handle.ipp"
"include/afio/v2.0/detail/impl/posix/io_handle.ipp"
"include/afio/v2.0/detail/impl/posix/io_service.ipp"
@@ -49,6 +51,7 @@ set(afio_HEADERS
"include/afio/v2.0/detail/impl/storage_profile.ipp"
"include/afio/v2.0/detail/impl/windows/async_file_handle.ipp"
"include/afio/v2.0/detail/impl/windows/file_handle.ipp"
+ "include/afio/v2.0/detail/impl/windows/fs_handle.ipp"
"include/afio/v2.0/detail/impl/windows/handle.ipp"
"include/afio/v2.0/detail/impl/windows/io_handle.ipp"
"include/afio/v2.0/detail/impl/windows/io_service.ipp"
diff --git a/include/afio/revision.hpp b/include/afio/revision.hpp
index 39524c97..52f52985 100644
--- a/include/afio/revision.hpp
+++ b/include/afio/revision.hpp
@@ -1,4 +1,4 @@
// Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time
-#define AFIO_PREVIOUS_COMMIT_REF d43d50996920718ae8d523a7586c9da70a8e017c
-#define AFIO_PREVIOUS_COMMIT_DATE "2017-08-02 23:41:37 +00:00"
-#define AFIO_PREVIOUS_COMMIT_UNIQUE d43d5099
+#define AFIO_PREVIOUS_COMMIT_REF 7097eb9dd2b9fbd52c702e4dd4b19c0f01a0e0dc
+#define AFIO_PREVIOUS_COMMIT_DATE "2017-08-03 12:05:25 +00:00"
+#define AFIO_PREVIOUS_COMMIT_UNIQUE 7097eb9d
diff --git a/include/afio/v2.0/async_file_handle.hpp b/include/afio/v2.0/async_file_handle.hpp
index cade40b2..3ea0b6b8 100644
--- a/include/afio/v2.0/async_file_handle.hpp
+++ b/include/afio/v2.0/async_file_handle.hpp
@@ -311,11 +311,9 @@ using the given io_service.
\errors Any of the values POSIX open() or CreateFile() can return.
*/
-inline result<async_file_handle> async_file(io_service &service, const path_handle &base, async_file_handle::path_view_type _path, async_file_handle::mode _mode = async_file_handle::mode::read, async_file_handle::creation _creation = async_file_handle::creation::open_existing,
- async_file_handle::caching _caching = async_file_handle::caching::all, async_file_handle::flag flags = async_file_handle::flag::none) noexcept
+inline result<async_file_handle> async_file(io_service &service, const path_handle &base, async_file_handle::path_view_type _path, async_file_handle::mode _mode = async_file_handle::mode::read, async_file_handle::creation _creation = async_file_handle::creation::open_existing, async_file_handle::caching _caching = async_file_handle::caching::all, async_file_handle::flag flags = async_file_handle::flag::none) noexcept
{
- return async_file_handle::async_file(std::forward<decltype(service)>(service), std::forward<decltype(base)>(base), std::forward<decltype(_path)>(_path), std::forward<decltype(_mode)>(_mode), std::forward<decltype(_creation)>(_creation), std::forward<decltype(_caching)>(_caching),
- std::forward<decltype(flags)>(flags));
+ return async_file_handle::async_file(std::forward<decltype(service)>(service), std::forward<decltype(base)>(base), std::forward<decltype(_path)>(_path), std::forward<decltype(_mode)>(_mode), std::forward<decltype(_creation)>(_creation), std::forward<decltype(_caching)>(_caching), std::forward<decltype(flags)>(flags));
}
/*! Create an async file handle creating a randomly named file on a path.
The file is opened exclusively with `creation::only_if_not_exist` so it
@@ -344,8 +342,7 @@ to use. Use `temp_inode()` instead, it is far more secure.
\errors Any of the values POSIX open() or CreateFile() can return.
*/
-inline result<async_file_handle> async_temp_file(io_service &service, async_file_handle::path_view_type name = async_file_handle::path_view_type(), async_file_handle::mode _mode = async_file_handle::mode::write, async_file_handle::creation _creation = async_file_handle::creation::if_needed,
- async_file_handle::caching _caching = async_file_handle::caching::temporary, async_file_handle::flag flags = async_file_handle::flag::unlink_on_close) noexcept
+inline result<async_file_handle> async_temp_file(io_service &service, async_file_handle::path_view_type name = async_file_handle::path_view_type(), async_file_handle::mode _mode = async_file_handle::mode::write, async_file_handle::creation _creation = async_file_handle::creation::if_needed, async_file_handle::caching _caching = async_file_handle::caching::temporary, async_file_handle::flag flags = async_file_handle::flag::unlink_on_close) noexcept
{
return async_file_handle::async_temp_file(std::forward<decltype(service)>(service), std::forward<decltype(name)>(name), std::forward<decltype(_mode)>(_mode), std::forward<decltype(_creation)>(_creation), std::forward<decltype(_caching)>(_caching), std::forward<decltype(flags)>(flags));
}
diff --git a/include/afio/v2.0/detail/impl/posix/file_handle.ipp b/include/afio/v2.0/detail/impl/posix/file_handle.ipp
index c231b573..6239264d 100644
--- a/include/afio/v2.0/detail/impl/posix/file_handle.ipp
+++ b/include/afio/v2.0/detail/impl/posix/file_handle.ipp
@@ -24,7 +24,6 @@ Distributed under the Boost Software License, Version 1.0.
#include "../../../file_handle.hpp"
-#include "../../../stat.hpp"
#include "import.hpp"
AFIO_V2_NAMESPACE_BEGIN
@@ -45,11 +44,11 @@ AFIO_HEADERS_ONLY_FUNC_SPEC path_view temporary_files_directory() noexcept
if(buffer[len - 1] == '/')
buffer.resize(--len);
buffer.append("/afio_tempfile_probe_file.tmp");
- int h = open(buffer.c_str(), O_WRONLY | O_CREAT, 0666);
+ int h = ::open(buffer.c_str(), O_WRONLY | O_CREAT, 0666);
if(-1 != h)
{
- unlink(buffer.c_str());
- close(h);
+ ::unlink(buffer.c_str());
+ ::close(h);
buffer.resize(len);
temporary_files_directory_ = std::move(buffer);
return true;
@@ -97,79 +96,6 @@ AFIO_HEADERS_ONLY_FUNC_SPEC path_view temporary_files_directory() noexcept
return temporary_files_directory_;
}
-result<void> file_handle::_fetch_inode() noexcept
-{
- stat_t s;
- OUTCOME_TRYV(s.fill(*this, stat_t::want::dev | stat_t::want::ino));
- _devid = s.st_dev;
- _inode = s.st_ino;
- return success();
-}
-
-inline result<path_handle> containing_directory(filesystem::path &filename, const file_handle &h, deadline d) noexcept
-{
-#ifdef AFIO_DISABLE_RACE_FREE_PATH_FUNCTIONS
- return std::errc::function_not_supported;
-#endif
- std::chrono::steady_clock::time_point began_steady;
- std::chrono::system_clock::time_point end_utc;
- if(d)
- {
- if(d.steady)
- began_steady = std::chrono::steady_clock::now();
- else
- end_utc = d.to_time_point();
- }
- try
- {
- for(;;)
- {
- // Get current path for handle and open its containing dir
- auto currentpath_ = h.current_path();
- if(!currentpath_)
- continue;
- filesystem::path currentpath = std::move(currentpath_.value());
- // If current path is empty, it's been deleted
- if(currentpath.empty())
- return std::errc::no_such_file_or_directory;
- filename = currentpath.filename();
- currentpath.remove_filename();
- auto currentdirh_ = path_handle::path(currentpath);
- if(!currentdirh_)
- continue;
- path_handle currentdirh = std::move(currentdirh_.value());
- if(h.flags() & handle::flag::disable_safety_unlinks)
- return success(std::move(currentdirh));
- // Open the same file name, and compare dev and inode
- auto nh_ = file_handle::file(currentdirh, filename);
- if(!nh_)
- continue;
- file_handle nh = std::move(nh_.value());
- // If the same, we know for a fact that this is the correct containing dir for now at least
- if(nh.st_dev() == h.st_dev() && nh.st_ino() == h.st_ino())
- return success(std::move(currentdirh));
- // Check timeout
- if(d)
- {
- if(d.steady)
- {
- if(std::chrono::steady_clock::now() >= (began_steady + std::chrono::nanoseconds(d.nsecs)))
- return std::errc::timed_out;
- }
- else
- {
- if(std::chrono::system_clock::now() >= end_utc)
- return std::errc::timed_out;
- }
- }
- }
- }
- catch(...)
- {
- return error_from_exception();
- }
-}
-
result<file_handle> file_handle::file(const path_handle &base, file_handle::path_view_type path, file_handle::mode _mode, file_handle::creation _creation, file_handle::caching _caching, file_handle::flag flags) noexcept
{
result<file_handle> ret(file_handle(native_handle_type(), 0, 0, _caching, flags));
@@ -313,39 +239,6 @@ result<file_handle> file_handle::clone() const noexcept
return ret;
}
-result<void> file_handle::relink(const path_handle &base, path_view_type path, deadline d) noexcept
-{
- AFIO_LOG_FUNCTION_CALL(this);
- path_view::c_str zpath(path);
-#ifdef O_TMPFILE
- // If the handle was created with O_TMPFILE, we need a different approach
- if(path.empty() && (_caching == file_handle::caching::temporary))
- {
- char _path[PATH_MAX];
- snprintf(_path, PATH_MAX, "/proc/self/fd/%d", _v.fd);
- if(-1 == ::linkat(AT_FDCWD, _path, base.is_valid() ? base.native_handle().fd : AT_FDCWD, zpath.buffer, AT_SYMLINK_FOLLOW))
- return {errno, std::system_category()};
- }
-#endif
- // Open our containing directory
- filesystem::path filename;
- OUTCOME_TRY(dirh, containing_directory(filename, *this, d));
- if(-1 == ::renameat(dirh.native_handle().fd, filename.c_str(), base.is_valid() ? base.native_handle().fd : AT_FDCWD, zpath.buffer))
- return {errno, std::system_category()};
- return success();
-}
-
-result<void> file_handle::unlink(deadline d) noexcept
-{
- AFIO_LOG_FUNCTION_CALL(this);
- // Open our containing directory
- filesystem::path filename;
- OUTCOME_TRY(dirh, containing_directory(filename, *this, d));
- if(-1 == ::unlinkat(dirh.native_handle().fd, filename.c_str(), 0))
- return {errno, std::system_category()};
- return success();
-}
-
result<file_handle::extent_type> file_handle::length() const noexcept
{
AFIO_LOG_FUNCTION_CALL(this);
diff --git a/include/afio/v2.0/detail/impl/posix/fs_handle.ipp b/include/afio/v2.0/detail/impl/posix/fs_handle.ipp
new file mode 100644
index 00000000..18f90397
--- /dev/null
+++ b/include/afio/v2.0/detail/impl/posix/fs_handle.ipp
@@ -0,0 +1,146 @@
+/* A filing system handle
+(C) 2017 Niall Douglas <http://www.nedproductions.biz/> (20 commits)
+File Created: Aug 2017
+
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License in the accompanying file
+Licence.txt or at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file Licence.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#include "../../../fs_handle.hpp"
+#include "../../../stat.hpp"
+#include "../../../utils.hpp"
+#include "import.hpp"
+
+#include <limits.h> // for PATH_MAX
+
+AFIO_V2_NAMESPACE_BEGIN
+
+result<void> fs_handle::_fetch_inode() noexcept
+{
+ stat_t s;
+ OUTCOME_TRYV(s.fill(_get_handle(), stat_t::want::dev | stat_t::want::ino));
+ _devid = s.st_dev;
+ _inode = s.st_ino;
+ return success();
+}
+
+inline result<path_handle> containing_directory(filesystem::path &filename, const handle &h, const fs_handle &fsh, deadline d) noexcept
+{
+#ifdef AFIO_DISABLE_RACE_FREE_PATH_FUNCTIONS
+ return std::errc::function_not_supported;
+#endif
+ std::chrono::steady_clock::time_point began_steady;
+ std::chrono::system_clock::time_point end_utc;
+ if(d)
+ {
+ if(d.steady)
+ began_steady = std::chrono::steady_clock::now();
+ else
+ end_utc = d.to_time_point();
+ }
+ try
+ {
+ for(;;)
+ {
+ // Get current path for handle and open its containing dir
+ auto currentpath_ = h.current_path();
+ if(!currentpath_)
+ continue;
+ filesystem::path currentpath = std::move(currentpath_.value());
+ // If current path is empty, it's been deleted
+ if(currentpath.empty())
+ return std::errc::no_such_file_or_directory;
+ filename = currentpath.filename();
+ currentpath.remove_filename();
+ auto currentdirh_ = path_handle::path(currentpath);
+ if(!currentdirh_)
+ continue;
+ path_handle currentdirh = std::move(currentdirh_.value());
+ if(h.flags() & handle::flag::disable_safety_unlinks)
+ return success(std::move(currentdirh));
+ // Open the same file name, and compare dev and inode
+ int fd = ::openat(currentdirh.native_handle().fd, filename.c_str(), 0);
+ if(fd == -1)
+ continue;
+ auto unfd = undoer([fd] { ::close(fd); });
+ (void) unfd;
+ struct stat s;
+ if(-1 == ::fstat(fd, &s))
+ continue;
+ // If the same, we know for a fact that this is the correct containing dir for now at least
+ if(s.st_dev == fsh.st_dev() && s.st_ino == fsh.st_ino())
+ return success(std::move(currentdirh));
+ // Check timeout
+ if(d)
+ {
+ if(d.steady)
+ {
+ if(std::chrono::steady_clock::now() >= (began_steady + std::chrono::nanoseconds(d.nsecs)))
+ return std::errc::timed_out;
+ }
+ else
+ {
+ if(std::chrono::system_clock::now() >= end_utc)
+ return std::errc::timed_out;
+ }
+ }
+ }
+ }
+ catch(...)
+ {
+ return error_from_exception();
+ }
+}
+
+result<void> fs_handle::relink(const path_handle &base, path_view_type path, deadline d) noexcept
+{
+ AFIO_LOG_FUNCTION_CALL(this);
+ auto &h = _get_handle();
+ path_view::c_str zpath(path);
+#ifdef O_TMPFILE
+ // If the handle was created with O_TMPFILE, we need a different approach
+ if(path.empty() && (h.kernel_caching() == handle::caching::temporary))
+ {
+ char _path[PATH_MAX];
+ snprintf(_path, PATH_MAX, "/proc/self/fd/%d", h.native_handle().fd);
+ if(-1 == ::linkat(AT_FDCWD, _path, base.is_valid() ? base.native_handle().fd : AT_FDCWD, zpath.buffer, AT_SYMLINK_FOLLOW))
+ return {errno, std::system_category()};
+ }
+#endif
+ // Open our containing directory
+ filesystem::path filename;
+ OUTCOME_TRY(dirh, containing_directory(filename, h, *this, d));
+ if(-1 == ::renameat(dirh.native_handle().fd, filename.c_str(), base.is_valid() ? base.native_handle().fd : AT_FDCWD, zpath.buffer))
+ return {errno, std::system_category()};
+ return success();
+}
+
+result<void> fs_handle::unlink(deadline d) noexcept
+{
+ AFIO_LOG_FUNCTION_CALL(this);
+ auto &h = _get_handle();
+ // Open our containing directory
+ filesystem::path filename;
+ OUTCOME_TRY(dirh, containing_directory(filename, h, *this, d));
+ if(-1 == ::unlinkat(dirh.native_handle().fd, filename.c_str(), 0))
+ return {errno, std::system_category()};
+ return success();
+}
+
+AFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/detail/impl/windows/file_handle.ipp b/include/afio/v2.0/detail/impl/windows/file_handle.ipp
index e46f278a..be946e95 100644
--- a/include/afio/v2.0/detail/impl/windows/file_handle.ipp
+++ b/include/afio/v2.0/detail/impl/windows/file_handle.ipp
@@ -23,7 +23,6 @@ Distributed under the Boost Software License, Version 1.0.
*/
#include "../../../file_handle.hpp"
-#include "../../../stat.hpp"
#include "import.hpp"
AFIO_V2_NAMESPACE_BEGIN
@@ -106,15 +105,6 @@ AFIO_HEADERS_ONLY_FUNC_SPEC path_view temporary_files_directory() noexcept
return temporary_files_directory_;
}
-result<void> file_handle::_fetch_inode() noexcept
-{
- stat_t s;
- OUTCOME_TRYV(s.fill(*this, stat_t::want::dev | stat_t::want::ino));
- _devid = s.st_dev;
- _inode = s.st_ino;
- return success();
-}
-
result<file_handle> file_handle::file(const path_handle &base, file_handle::path_view_type path, file_handle::mode _mode, file_handle::creation _creation, file_handle::caching _caching, file_handle::flag flags) noexcept
{
windows_nt_kernel::init();
@@ -337,80 +327,6 @@ result<file_handle> file_handle::clone() const noexcept
return ret;
}
-result<void> file_handle::relink(const path_handle &base, path_view_type path, deadline /*unused*/) noexcept
-{
- windows_nt_kernel::init();
- using namespace windows_nt_kernel;
- AFIO_LOG_FUNCTION_CALL(this);
-
- path_view::c_str zpath(path);
- UNICODE_STRING _path;
- _path.Buffer = const_cast<wchar_t *>(zpath.buffer);
- _path.MaximumLength = (_path.Length = (USHORT)(zpath.length * sizeof(wchar_t))) + sizeof(wchar_t);
- if(zpath.length >= 4 && _path.Buffer[0] == '\\' && _path.Buffer[1] == '\\' && _path.Buffer[2] == '.' && _path.Buffer[3] == '\\')
- {
- _path.Buffer += 3;
- _path.Length -= 3 * sizeof(wchar_t);
- _path.MaximumLength -= 3 * sizeof(wchar_t);
- }
-
- IO_STATUS_BLOCK isb = make_iostatus();
- alignas(8) char buffer[sizeof(FILE_RENAME_INFORMATION) + 65536];
- FILE_RENAME_INFORMATION *fni = (FILE_RENAME_INFORMATION *) buffer;
- fni->ReplaceIfExists = true;
- fni->RootDirectory = base.is_valid() ? base.native_handle().h : nullptr;
- fni->FileNameLength = _path.Length;
- memcpy(fni->FileName, _path.Buffer, fni->FileNameLength);
- NtSetInformationFile(_v.h, &isb, fni, sizeof(FILE_RENAME_INFORMATION) + fni->FileNameLength, FileRenameInformation);
- if(_flags & flag::overlapped)
- ntwait(_v.h, isb, deadline());
- if(STATUS_SUCCESS != isb.Status)
- return {(int) isb.Status, ntkernel_category()};
- return success();
-}
-
-result<void> file_handle::unlink(deadline /*unused*/) noexcept
-{
- windows_nt_kernel::init();
- using namespace windows_nt_kernel;
- AFIO_LOG_FUNCTION_CALL(this);
- if(!(_flags & flag::win_disable_unlink_emulation))
- {
- // Rename it to something random to emulate immediate unlinking
- auto randomname = utils::random_string(32);
- randomname.append(".deleted");
- OUTCOME_TRY(cpath, current_path());
- cpath.remove_filename();
- OUTCOME_TRY(dirh, path_handle::path(cpath));
- OUTCOME_TRYV(relink(dirh, randomname));
- }
- // No point marking it for deletion if it's already been so
- if(!(_flags & flag::unlink_on_close))
- {
- // Hide the item in Explorer and the command line
- {
- IO_STATUS_BLOCK isb = make_iostatus();
- FILE_BASIC_INFORMATION fbi;
- memset(&fbi, 0, sizeof(fbi));
- fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
- NtSetInformationFile(_v.h, &isb, &fbi, sizeof(fbi), FileBasicInformation);
- if(_flags & flag::overlapped)
- ntwait(_v.h, isb, deadline());
- }
- // Mark the item as delete on close
- IO_STATUS_BLOCK isb = make_iostatus();
- FILE_DISPOSITION_INFORMATION fdi;
- memset(&fdi, 0, sizeof(fdi));
- fdi._DeleteFile = true;
- NtSetInformationFile(_v.h, &isb, &fdi, sizeof(fdi), FileDispositionInformation);
- if(_flags & flag::overlapped)
- ntwait(_v.h, isb, deadline());
- if(STATUS_SUCCESS != isb.Status)
- return {(int) isb.Status, ntkernel_category()};
- }
- return success();
-}
-
result<file_handle::extent_type> file_handle::length() const noexcept
{
AFIO_LOG_FUNCTION_CALL(this);
diff --git a/include/afio/v2.0/detail/impl/windows/fs_handle.ipp b/include/afio/v2.0/detail/impl/windows/fs_handle.ipp
new file mode 100644
index 00000000..6fc46afb
--- /dev/null
+++ b/include/afio/v2.0/detail/impl/windows/fs_handle.ipp
@@ -0,0 +1,119 @@
+/* A filing system handle
+(C) 2017 Niall Douglas <http://www.nedproductions.biz/> (20 commits)
+File Created: Aug 2017
+
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License in the accompanying file
+Licence.txt or at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file Licence.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#include "../../../fs_handle.hpp"
+#include "../../../stat.hpp"
+#include "../../../utils.hpp"
+#include "import.hpp"
+
+AFIO_V2_NAMESPACE_BEGIN
+
+result<void> fs_handle::_fetch_inode() noexcept
+{
+ stat_t s;
+ OUTCOME_TRYV(s.fill(_get_handle(), stat_t::want::dev | stat_t::want::ino));
+ _devid = s.st_dev;
+ _inode = s.st_ino;
+ return success();
+}
+
+result<void> fs_handle::relink(const path_handle &base, path_view_type path, deadline /*unused*/) noexcept
+{
+ using flag = handle::flag;
+ windows_nt_kernel::init();
+ using namespace windows_nt_kernel;
+ AFIO_LOG_FUNCTION_CALL(this);
+ auto &h = _get_handle();
+
+ path_view::c_str zpath(path);
+ UNICODE_STRING _path;
+ _path.Buffer = const_cast<wchar_t *>(zpath.buffer);
+ _path.MaximumLength = (_path.Length = (USHORT)(zpath.length * sizeof(wchar_t))) + sizeof(wchar_t);
+ if(zpath.length >= 4 && _path.Buffer[0] == '\\' && _path.Buffer[1] == '\\' && _path.Buffer[2] == '.' && _path.Buffer[3] == '\\')
+ {
+ _path.Buffer += 3;
+ _path.Length -= 3 * sizeof(wchar_t);
+ _path.MaximumLength -= 3 * sizeof(wchar_t);
+ }
+
+ IO_STATUS_BLOCK isb = make_iostatus();
+ alignas(8) char buffer[sizeof(FILE_RENAME_INFORMATION) + 65536];
+ FILE_RENAME_INFORMATION *fni = (FILE_RENAME_INFORMATION *) buffer;
+ fni->ReplaceIfExists = true;
+ fni->RootDirectory = base.is_valid() ? base.native_handle().h : nullptr;
+ fni->FileNameLength = _path.Length;
+ memcpy(fni->FileName, _path.Buffer, fni->FileNameLength);
+ NtSetInformationFile(h.native_handle().h, &isb, fni, sizeof(FILE_RENAME_INFORMATION) + fni->FileNameLength, FileRenameInformation);
+ if(h.flags() & flag::overlapped)
+ ntwait(h.native_handle().h, isb, deadline());
+ if(STATUS_SUCCESS != isb.Status)
+ return {(int) isb.Status, ntkernel_category()};
+ return success();
+}
+
+result<void> fs_handle::unlink(deadline /*unused*/) noexcept
+{
+ using flag = handle::flag;
+ windows_nt_kernel::init();
+ using namespace windows_nt_kernel;
+ AFIO_LOG_FUNCTION_CALL(this);
+ auto &h = _get_handle();
+ if((h.is_regular() || h.is_symlink()) && !(h.flags() & flag::win_disable_unlink_emulation))
+ {
+ // Rename it to something random to emulate immediate unlinking
+ auto randomname = utils::random_string(32);
+ randomname.append(".deleted");
+ OUTCOME_TRY(cpath, h.current_path());
+ cpath.remove_filename();
+ OUTCOME_TRY(dirh, path_handle::path(cpath));
+ OUTCOME_TRYV(relink(dirh, randomname));
+ }
+ // No point marking it for deletion if it's already been so
+ if(!(h.flags() & flag::unlink_on_close))
+ {
+ // Hide the item in Explorer and the command line
+ {
+ IO_STATUS_BLOCK isb = make_iostatus();
+ FILE_BASIC_INFORMATION fbi;
+ memset(&fbi, 0, sizeof(fbi));
+ fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
+ NtSetInformationFile(h.native_handle().h, &isb, &fbi, sizeof(fbi), FileBasicInformation);
+ if(h.flags() & flag::overlapped)
+ ntwait(h.native_handle().h, isb, deadline());
+ }
+ // Mark the item as delete on close
+ IO_STATUS_BLOCK isb = make_iostatus();
+ FILE_DISPOSITION_INFORMATION fdi;
+ memset(&fdi, 0, sizeof(fdi));
+ fdi._DeleteFile = true;
+ NtSetInformationFile(h.native_handle().h, &isb, &fdi, sizeof(fdi), FileDispositionInformation);
+ if(h.flags() & flag::overlapped)
+ ntwait(h.native_handle().h, isb, deadline());
+ if(STATUS_SUCCESS != isb.Status)
+ return {(int) isb.Status, ntkernel_category()};
+ }
+ return success();
+}
+
+AFIO_V2_NAMESPACE_END
diff --git a/include/afio/v2.0/file_handle.hpp b/include/afio/v2.0/file_handle.hpp
index 00f8efd3..8794c5dd 100644
--- a/include/afio/v2.0/file_handle.hpp
+++ b/include/afio/v2.0/file_handle.hpp
@@ -25,9 +25,8 @@ Distributed under the Boost Software License, Version 1.0.
#ifndef AFIO_FILE_HANDLE_H
#define AFIO_FILE_HANDLE_H
+#include "fs_handle.hpp"
#include "io_handle.hpp"
-#include "path_handle.hpp"
-#include "path_view.hpp"
#include "utils.hpp"
//! \file file_handle.hpp Provides file_handle
@@ -58,13 +57,13 @@ class io_service;
\brief A handle to a regular file or device, kept data layout compatible with
async_file_handle.
*/
-class AFIO_DECL file_handle : public io_handle
+class AFIO_DECL file_handle : public io_handle, public fs_handle
{
+ AFIO_HEADERS_ONLY_VIRTUAL_SPEC const handle &_get_handle() const noexcept override final { return *this; }
public:
using path_type = io_handle::path_type;
using extent_type = io_handle::extent_type;
using size_type = io_handle::size_type;
- using unique_id_type = io_handle::unique_id_type;
using mode = io_handle::mode;
using creation = io_handle::creation;
using caching = io_handle::caching;
@@ -75,65 +74,34 @@ public:
using const_buffers_type = io_handle::const_buffers_type;
template <class T> using io_request = io_handle::io_request<T>;
template <class T> using io_result = io_handle::io_result<T>;
-
- using dev_t = uint64_t;
- using ino_t = uint64_t;
- //! The path view type used by this handle
- using path_view_type = path_view;
+ using dev_t = fs_handle::dev_t;
+ using ino_t = fs_handle::ino_t;
+ using path_view_type = fs_handle::path_view_type;
protected:
- dev_t _devid;
- ino_t _inode;
-#ifdef __FreeBSD__ // FreeBSD can't look up the current path of file, only a directory
- path_handle _pathbase;
- path_type _path;
-#error TODO: Finish FreeBSD support
-#endif
io_service *_service;
- //! Fill in _devid and _inode from the handle via fstat()
- AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<void> _fetch_inode() noexcept;
-
public:
//! Default constructor
constexpr file_handle()
: io_handle()
- , _devid(0)
- , _inode(0)
+ , fs_handle()
, _service(nullptr)
{
}
//! Construct a handle from a supplied native handle
constexpr file_handle(native_handle_type h, dev_t devid, ino_t inode, caching caching = caching::none, flag flags = flag::none)
: io_handle(std::move(h), std::move(caching), std::move(flags))
- , _devid(devid)
- , _inode(inode)
+ , fs_handle(devid, inode)
, _service(nullptr)
{
}
//! Implicit move construction of file_handle permitted
- constexpr file_handle(file_handle &&o) noexcept : io_handle(std::move(o)),
- _devid(o._devid),
- _inode(o._inode),
-#ifdef __FreeBSD__
- _pathbase(std::move(o._pathbase)),
- _path(std::move(o._path)),
-#endif
- _service(o._service)
- {
- o._devid = 0;
- o._inode = 0;
- o._service = nullptr;
- }
+ constexpr file_handle(file_handle &&o) noexcept : io_handle(std::move(o)), fs_handle(std::move(o)), _service(o._service) { o._service = nullptr; }
//! Explicit conversion from handle and io_handle permitted
- explicit constexpr file_handle(handle &&o, dev_t devid, ino_t inode) noexcept : io_handle(std::move(o)), _devid(devid), _inode(inode), _service(nullptr) {}
+ explicit constexpr file_handle(handle &&o, dev_t devid, ino_t inode) noexcept : io_handle(std::move(o)), fs_handle(devid, inode), _service(nullptr) {}
//! Move assignment of file_handle permitted
- file_handle &operator=(file_handle &&o) noexcept
- {
- this->~file_handle();
- new(this) file_handle(std::move(o));
- return *this;
- }
+ file_handle &operator=(file_handle &&o) noexcept = default;
//! Swap with another instance
void swap(file_handle &o) noexcept
{
@@ -209,17 +177,6 @@ public:
AFIO_MAKE_FREE_FUNCTION
static AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<file_handle> temp_inode(path_view_type dirpath = temporary_files_directory(), mode _mode = mode::write, flag flags = flag::none) noexcept;
- //! Unless `flag::disable_safety_unlinks` is set, the device id of the file when opened
- dev_t st_dev() const noexcept { return _devid; }
- //! Unless `flag::disable_safety_unlinks` is set, the inode of the file when opened. When combined with st_dev(), forms a unique identifer on this system
- ino_t st_ino() const noexcept { return _inode; }
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC unique_id_type unique_id() const noexcept override
- {
- unique_id_type ret(nullptr);
- ret.as_longlongs[0] = _devid;
- ret.as_longlongs[1] = _inode;
- return ret;
- }
AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> close() noexcept override
{
AFIO_LOG_FUNCTION_CALL(this);
@@ -243,46 +200,6 @@ public:
*/
AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<file_handle> clone() const noexcept;
- /*! Atomically relinks the current path of this open handle to the new path specified,
- \b atomically and silently replacing any item at the new path specified. This operation
- is both atomic and silent matching POSIX behaviour even on Microsoft Windows where
- no Win32 API can match POSIX semantics.
-
- \warning Some operating systems provide a race free syscall for renaming an open handle (Windows).
- On all other operating systems this call is \b racy and can result in the wrong file entry being
- relinked. Note that unless `flag::disable_safety_unlinks` is set, this implementation opens a
- `path_handle` to the source containing directory first, then checks before relinking that the item
- about to be relinked has the same inode as the open file handle. It will retry this matching until
- success until the deadline given. This should prevent most unmalicious accidental loss of data.
-
- \param base Base for any relative path.
- \param newpath The relative or absolute new path to relink to.
- \param d The deadline by which the matching of the containing directory to the open handle's inode
- must succeed, else `std::errc::timed_out` will be returned. Not used on platforms with race free
- syscalls for renaming open handles (Windows).
- */
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> relink(const path_handle &base, path_view_type newpath, deadline d = std::chrono::seconds(30)) noexcept;
-
- /*! Unlinks the current path of this open handle, causing its entry to immediately disappear from the filing system.
- On Windows unless `flag::win_disable_unlink_emulation` is set, this behaviour is
- simulated by renaming the file to something random and setting its delete-on-last-close flag.
- After the next handle to that file closes, it will become permanently unopenable by anyone
- else until the last handle is closed, whereupon the entry will be eventually removed by the
- operating system.
-
- \warning Some operating systems provide a race free syscall for unlinking an open handle (Windows).
- On all other operating systems this call is \b racy and can result in the wrong file entry being
- unlinked. Note that unless `flag::disable_safety_unlinks` is set, this implementation opens a
- `path_handle` to the containing directory first, then checks that the item about to be unlinked
- has the same inode as the open file handle. It will retry this matching until success until the
- deadline given. This should prevent most unmalicious accidental loss of data.
-
- \param d The deadline by which the matching of the containing directory to the open handle's inode
- must succeed, else `std::errc::timed_out` will be returned. Not used on platforms with race free
- syscalls for unlinking open handles (Windows).
- */
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> unlink(deadline d = std::chrono::seconds(30)) noexcept;
-
//! The i/o service this handle is attached to, if any
io_service *service() const noexcept { return _service; }
diff --git a/include/afio/v2.0/fs_handle.hpp b/include/afio/v2.0/fs_handle.hpp
new file mode 100644
index 00000000..ad950bc2
--- /dev/null
+++ b/include/afio/v2.0/fs_handle.hpp
@@ -0,0 +1,237 @@
+/* A filing system handle
+(C) 2017 Niall Douglas <http://www.nedproductions.biz/> (20 commits)
+File Created: Aug 2017
+
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License in the accompanying file
+Licence.txt or at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file Licence.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef AFIO_FS_HANDLE_H
+#define AFIO_FS_HANDLE_H
+
+#include "path_handle.hpp"
+#include "path_view.hpp"
+
+#include "../quickcpplib/include/uint128.hpp"
+
+//! \file fs_handle.hpp Provides fs_handle
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4251) // dll interface
+#endif
+
+AFIO_V2_NAMESPACE_EXPORT_BEGIN
+
+/*! \class fs_handle
+\brief A handle to something with a device and inode number.
+*/
+class AFIO_DECL fs_handle
+{
+public:
+ using dev_t = uint64_t;
+ using ino_t = uint64_t;
+ //! The path view type used by this handle
+ using path_view_type = path_view;
+ //! The unique identifier type used by this handle
+ using unique_id_type = QUICKCPPLIB_NAMESPACE::integers128::uint128;
+
+protected:
+ dev_t _devid;
+ ino_t _inode;
+#ifdef __FreeBSD__ // FreeBSD can't look up the current path of file, only a directory
+ path_handle _pathbase;
+ path_type _path;
+#error TODO: Finish FreeBSD support
+#endif
+
+ //! Fill in _devid and _inode from the handle via fstat()
+ AFIO_HEADERS_ONLY_MEMFUNC_SPEC result<void> _fetch_inode() noexcept;
+
+ AFIO_HEADERS_ONLY_VIRTUAL_SPEC const handle &_get_handle() const noexcept = 0;
+
+protected:
+ //! Default constructor
+ constexpr fs_handle()
+ : _devid(0)
+ , _inode(0)
+ {
+ }
+ //! Construct a handle
+ constexpr fs_handle(dev_t devid, ino_t inode)
+ : _devid(devid)
+ , _inode(inode)
+ {
+ }
+#ifdef __FreeBSD__
+ AFIO_HEADERS_ONLY_VIRTUAL_SPEC ~fs_handle() {}
+#endif
+ //! No copy construction (use clone())
+ fs_handle(const fs_handle &) = delete;
+ //! No copy assignment
+ fs_handle &operator=(const fs_handle &o) = delete;
+ //! Implicit move construction of fs_handle permitted
+ constexpr fs_handle(fs_handle &&o) noexcept : _devid(o._devid),
+ _inode(o._inode)
+#ifdef __FreeBSD__
+ ,
+ _pathbase(std::move(o._pathbase)),
+ _path(std::move(o._path))
+#endif
+ {
+ o._devid = 0;
+ o._inode = 0;
+ }
+ //! Move assignment of fs_handle permitted
+ fs_handle &operator=(fs_handle &&o) noexcept
+ {
+ _devid = o._devid;
+ _inode = o._inode;
+#ifdef __FreeBSD__
+ _pathbase = std::move(o._pathbase);
+ _path = std::move(o._path);
+#endif
+ o._devid = 0;
+ o._inode = 0;
+ return *this;
+ }
+
+public:
+ //! Unless `flag::disable_safety_unlinks` is set, the device id of the file when opened
+ dev_t st_dev() const noexcept { return _devid; }
+ //! Unless `flag::disable_safety_unlinks` is set, the inode of the file when opened. When combined with st_dev(), forms a unique identifer on this system
+ ino_t st_ino() const noexcept { return _inode; }
+ //! A unique identifier for this handle in this process (native handle). Subclasses like `file_handle` make this a unique identifier across the entire system.
+ unique_id_type unique_id() const noexcept
+ {
+ unique_id_type ret(nullptr);
+ ret.as_longlongs[0] = _devid;
+ ret.as_longlongs[1] = _inode;
+ return ret;
+ }
+
+ /*! Atomically relinks the current path of this open handle to the new path specified,
+ \b atomically and silently replacing any item at the new path specified. This operation
+ is both atomic and silent matching POSIX behaviour even on Microsoft Windows where
+ no Win32 API can match POSIX semantics.
+
+ \warning Some operating systems provide a race free syscall for renaming an open handle (Windows).
+ On all other operating systems this call is \b racy and can result in the wrong file entry being
+ relinked. Note that unless `flag::disable_safety_unlinks` is set, this implementation opens a
+ `path_handle` to the source containing directory first, then checks before relinking that the item
+ about to be relinked has the same inode as the open file handle. It will retry this matching until
+ success until the deadline given. This should prevent most unmalicious accidental loss of data.
+
+ \param base Base for any relative path.
+ \param newpath The relative or absolute new path to relink to.
+ \param d The deadline by which the matching of the containing directory to the open handle's inode
+ must succeed, else `std::errc::timed_out` will be returned. Not used on platforms with race free
+ syscalls for renaming open handles (Windows).
+ */
+ AFIO_MAKE_FREE_FUNCTION
+ result<void> relink(const path_handle &base, path_view_type newpath, deadline d = std::chrono::seconds(30)) noexcept;
+
+ /*! Unlinks the current path of this open handle, causing its entry to immediately disappear from the filing system.
+ On Windows unless `flag::win_disable_unlink_emulation` is set, this behaviour is
+ simulated by renaming the file to something random and setting its delete-on-last-close flag.
+ After the next handle to that file closes, it will become permanently unopenable by anyone
+ else until the last handle is closed, whereupon the entry will be eventually removed by the
+ operating system.
+
+ \warning Some operating systems provide a race free syscall for unlinking an open handle (Windows).
+ On all other operating systems this call is \b racy and can result in the wrong file entry being
+ unlinked. Note that unless `flag::disable_safety_unlinks` is set, this implementation opens a
+ `path_handle` to the containing directory first, then checks that the item about to be unlinked
+ has the same inode as the open file handle. It will retry this matching until success until the
+ deadline given. This should prevent most unmalicious accidental loss of data.
+
+ \param d The deadline by which the matching of the containing directory to the open handle's inode
+ must succeed, else `std::errc::timed_out` will be returned. Not used on platforms with race free
+ syscalls for unlinking open handles (Windows).
+ */
+ AFIO_MAKE_FREE_FUNCTION
+ result<void> unlink(deadline d = std::chrono::seconds(30)) noexcept;
+};
+
+// BEGIN make_free_functions.py
+/*! Atomically relinks the current path of this open handle to the new path specified,
+\b atomically and silently replacing any item at the new path specified. This operation
+is both atomic and silent matching POSIX behaviour even on Microsoft Windows where
+no Win32 API can match POSIX semantics.
+
+\warning Some operating systems provide a race free syscall for renaming an open handle (Windows).
+On all other operating systems this call is \b racy and can result in the wrong file entry being
+relinked. Note that unless `flag::disable_safety_unlinks` is set, this implementation opens a
+`path_handle` to the source containing directory first, then checks before relinking that the item
+about to be relinked has the same inode as the open file handle. It will retry this matching until
+success until the deadline given. This should prevent most unmalicious accidental loss of data.
+
+\param self The object whose member function to call.
+\param base Base for any relative path.
+\param newpath The relative or absolute new path to relink to.
+\param d The deadline by which the matching of the containing directory to the open handle's inode
+must succeed, else `std::errc::timed_out` will be returned. Not used on platforms with race free
+syscalls for renaming open handles (Windows).
+*/
+inline result<void> relink(fs_handle &self, const path_handle &base, fs_handle::path_view_type newpath, deadline d = std::chrono::seconds(30)) noexcept
+{
+ return self.relink(std::forward<decltype(base)>(base), std::forward<decltype(newpath)>(newpath), std::forward<decltype(d)>(d));
+}
+/*! Unlinks the current path of this open handle, causing its entry to immediately disappear from the filing system.
+On Windows unless `flag::win_disable_unlink_emulation` is set, this behaviour is
+simulated by renaming the file to something random and setting its delete-on-last-close flag.
+After the next handle to that file closes, it will become permanently unopenable by anyone
+else until the last handle is closed, whereupon the entry will be eventually removed by the
+operating system.
+
+\warning Some operating systems provide a race free syscall for unlinking an open handle (Windows).
+On all other operating systems this call is \b racy and can result in the wrong file entry being
+unlinked. Note that unless `flag::disable_safety_unlinks` is set, this implementation opens a
+`path_handle` to the containing directory first, then checks that the item about to be unlinked
+has the same inode as the open file handle. It will retry this matching until success until the
+deadline given. This should prevent most unmalicious accidental loss of data.
+
+\param self The object whose member function to call.
+\param d The deadline by which the matching of the containing directory to the open handle's inode
+must succeed, else `std::errc::timed_out` will be returned. Not used on platforms with race free
+syscalls for unlinking open handles (Windows).
+*/
+inline result<void> unlink(fs_handle &self, deadline d = std::chrono::seconds(30)) noexcept
+{
+ return self.unlink(std::forward<decltype(d)>(d));
+}
+// END make_free_functions.py
+
+AFIO_V2_NAMESPACE_END
+
+#if AFIO_HEADERS_ONLY == 1 && !defined(DOXYGEN_SHOULD_SKIP_THIS)
+#define AFIO_INCLUDED_BY_HEADER 1
+#ifdef _WIN32
+#include "detail/impl/windows/fs_handle.ipp"
+#else
+#include "detail/impl/posix/fs_handle.ipp"
+#endif
+#undef AFIO_INCLUDED_BY_HEADER
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+#endif
diff --git a/include/afio/v2.0/handle.hpp b/include/afio/v2.0/handle.hpp
index 82686596..16266d8b 100644
--- a/include/afio/v2.0/handle.hpp
+++ b/include/afio/v2.0/handle.hpp
@@ -28,10 +28,7 @@ Distributed under the Boost Software License, Version 1.0.
#include "deadline.h"
#include "native_handle_type.hpp"
-#include "../quickcpplib/include/uint128.hpp"
-
#include <algorithm> // for std::count
-#include <utility> // for pair<>
//! \file handle.hpp Provides handle
@@ -56,8 +53,6 @@ public:
using extent_type = unsigned long long;
//! The memory extent type used by this handle
using size_type = size_t;
- //! The unique identifier type used by this handle
- using unique_id_type = QUICKCPPLIB_NAMESPACE::integers128::uint128;
//! The behaviour of the handle: does it read, read and write, or atomic append?
enum class mode : unsigned char // bit 0 set means writable
@@ -182,13 +177,6 @@ public:
o = std::move(temp);
}
- //! A unique identifier for this handle in this process (native handle). Subclasses like `file_handle` make this a unique identifier across the entire system.
- AFIO_HEADERS_ONLY_VIRTUAL_SPEC unique_id_type unique_id() const noexcept
- {
- unique_id_type ret(nullptr);
- ret.as_longlongs[0] = _v._init;
- return ret;
- }
/*! Returns the current path of the open handle as said by the operating system. Note
that you are NOT guaranteed that any path refreshed bears any resemblance to the original,
many operating systems will return some different path which still reaches the same inode
diff --git a/include/afio/v2.0/path_handle.hpp b/include/afio/v2.0/path_handle.hpp
index 5a4926b0..5c7b1375 100644
--- a/include/afio/v2.0/path_handle.hpp
+++ b/include/afio/v2.0/path_handle.hpp
@@ -61,8 +61,8 @@ public:
//! Default constructor
path_handle() = default;
//! Construct a handle from a supplied native handle
- explicit constexpr path_handle(native_handle_type h)
- : handle(h, caching::all, flag::none)
+ explicit constexpr path_handle(native_handle_type h, caching caching = caching::all, flag flags = flag::none)
+ : handle(h, caching, flags)
{
}
//! Explicit conversion from handle permitted