mirror of
https://github.com/boostorg/filesystem.git
synced 2025-05-12 13:41:47 +00:00
Updated space() behavior to match C++20. Add support for file paths on Windows.
space() now initializes space_info members to -1 values, which is used when the structure is returned in case of error. On Windows, check if the path refers to a directory, and use the parent directory if not. In order to make sure we return space information for the target filesystem, we have to resolve symlinks in this case. Fixes https://github.com/boostorg/filesystem/issues/73.
This commit is contained in:
parent
ee6604657d
commit
a26ead7402
@ -47,6 +47,8 @@
|
||||
<li><code>copy_file</code> on POSIX systems will now also copy the source file permissions to the target file, if the target file is overwritten.</li>
|
||||
<li><code>equivalent</code> on POSIX systems now returns the actual error code from the OS if one of the paths does not resolve to a file. Previously the function would return an error code of 1. (<a href="https://github.com/boostorg/filesystem/issues/141">#141</a>)</li>
|
||||
<li><code>equivalent</code> no longer considers file size and last modification time in order to test whether the two paths refer to the same file. These checks could result in a false negative if the file was modified during the <code>equivalent</code> call.</li>
|
||||
<li><code>space</code> now initializes the <code>space_info</code> structure members to -1 values on error, as required by C++20 ([fs.op.space]/1).</li>
|
||||
<li><code>space</code> on Windows now accepts paths referring to arbitrary files, not only directories. This is similar to POSIX systems and corresponds to the operation description in C++20. (<a href="https://github.com/boostorg/filesystem/issues/73">#73</a>)</li>
|
||||
</ul>
|
||||
|
||||
<h2>1.72.0</h2>
|
||||
|
@ -1497,7 +1497,7 @@ void permissions(const path& p, perms prms, system::error_code* ec)
|
||||
if (local_ec)
|
||||
{
|
||||
if (ec == 0)
|
||||
BOOST_FILESYSTEM_THROW(filesystem_error(
|
||||
BOOST_FILESYSTEM_THROW(filesystem_error(
|
||||
"boost::filesystem::permissions", p, local_ec));
|
||||
else
|
||||
*ec = local_ec;
|
||||
@ -1734,45 +1734,79 @@ void resize_file(const path& p, uintmax_t size, system::error_code* ec)
|
||||
BOOST_FILESYSTEM_DECL
|
||||
space_info space(const path& p, error_code* ec)
|
||||
{
|
||||
# ifdef BOOST_POSIX_API
|
||||
struct BOOST_STATVFS vfs;
|
||||
space_info info;
|
||||
// Initialize members to -1, as required by C++20 [fs.op.space]/1 in case of error
|
||||
info.capacity = static_cast<boost::uintmax_t>(-1);
|
||||
info.free = static_cast<boost::uintmax_t>(-1);
|
||||
info.available = static_cast<boost::uintmax_t>(-1);
|
||||
|
||||
if (ec)
|
||||
ec->clear();
|
||||
|
||||
# ifdef BOOST_POSIX_API
|
||||
|
||||
struct BOOST_STATVFS vfs;
|
||||
if (!error(::BOOST_STATVFS(p.c_str(), &vfs) ? BOOST_ERRNO : 0,
|
||||
p, ec, "boost::filesystem::space"))
|
||||
{
|
||||
info.capacity
|
||||
= static_cast<boost::uintmax_t>(vfs.f_blocks)* BOOST_STATVFS_F_FRSIZE;
|
||||
= static_cast<boost::uintmax_t>(vfs.f_blocks) * BOOST_STATVFS_F_FRSIZE;
|
||||
info.free
|
||||
= static_cast<boost::uintmax_t>(vfs.f_bfree)* BOOST_STATVFS_F_FRSIZE;
|
||||
= static_cast<boost::uintmax_t>(vfs.f_bfree) * BOOST_STATVFS_F_FRSIZE;
|
||||
info.available
|
||||
= static_cast<boost::uintmax_t>(vfs.f_bavail)* BOOST_STATVFS_F_FRSIZE;
|
||||
= static_cast<boost::uintmax_t>(vfs.f_bavail) * BOOST_STATVFS_F_FRSIZE;
|
||||
}
|
||||
|
||||
# else
|
||||
|
||||
ULARGE_INTEGER avail, total, free;
|
||||
space_info info;
|
||||
// GetDiskFreeSpaceExW requires a directory path, which is unlike statvfs, which accepts any file.
|
||||
// To work around this, test if the path refers to a directory and use the parent directory if not.
|
||||
file_status status = detail::status(p, ec);
|
||||
if (ec && *ec)
|
||||
return info;
|
||||
|
||||
if (!error(::GetDiskFreeSpaceExW(p.c_str(), &avail, &total, &free)== 0,
|
||||
path dir_path = p;
|
||||
if (!is_directory(status))
|
||||
{
|
||||
path cur_path = detail::current_path(ec);
|
||||
if (ec && *ec)
|
||||
return info;
|
||||
|
||||
status = detail::symlink_status(p, ec);
|
||||
if (ec && *ec)
|
||||
return info;
|
||||
if (is_symlink(status))
|
||||
{
|
||||
// We need to resolve the symlink so that we report the space for the symlink target
|
||||
dir_path = detail::canonical(p, cur_path, ec);
|
||||
if (ec && *ec)
|
||||
return info;
|
||||
}
|
||||
|
||||
dir_path = dir_path.parent_path();
|
||||
if (dir_path.empty())
|
||||
{
|
||||
// The original path was just a filename, which is a relative path wrt. current directory
|
||||
dir_path = cur_path;
|
||||
}
|
||||
}
|
||||
|
||||
// For UNC names, the path must also include a trailing slash.
|
||||
path::string_type str = dir_path.native();
|
||||
if (str.size() >= 2u && detail::is_directory_separator(str[0]) && detail::is_directory_separator(str[1]) && !detail::is_directory_separator(*(str.end() - 1)))
|
||||
str.push_back(path::preferred_separator);
|
||||
|
||||
ULARGE_INTEGER avail, total, free;
|
||||
if (!error(::GetDiskFreeSpaceExW(str.c_str(), &avail, &total, &free) == 0,
|
||||
p, ec, "boost::filesystem::space"))
|
||||
{
|
||||
info.capacity
|
||||
= (static_cast<boost::uintmax_t>(total.HighPart)<< 32)
|
||||
+ total.LowPart;
|
||||
info.free
|
||||
= (static_cast<boost::uintmax_t>(free.HighPart)<< 32)
|
||||
+ free.LowPart;
|
||||
info.available
|
||||
= (static_cast<boost::uintmax_t>(avail.HighPart)<< 32)
|
||||
+ avail.LowPart;
|
||||
info.capacity = static_cast<boost::uintmax_t>(total.QuadPart);
|
||||
info.free = static_cast<boost::uintmax_t>(free.QuadPart);
|
||||
info.available = static_cast<boost::uintmax_t>(avail.QuadPart);
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
else
|
||||
{
|
||||
info.capacity = info.free = info.available = 0;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
|
@ -1920,6 +1920,10 @@ namespace
|
||||
cout << " free = " << spi.free << '\n';
|
||||
cout << " available = " << spi.available << '\n';
|
||||
# endif
|
||||
|
||||
// Test that we can specify path to file
|
||||
fs::space_info spi_file(fs::space(f0));
|
||||
BOOST_TEST_EQ(spi_file.capacity, spi.capacity);
|
||||
}
|
||||
|
||||
// equivalent_tests ----------------------------------------------------------------//
|
||||
|
Loading…
x
Reference in New Issue
Block a user