LWG2720 implement filesystem::perms::symlink_nofollow
* include/experimental/bits/fs_fwd.h (perms::resolve_symlinks): Replace with symlink_nofollow (LWG 2720). * src/filesystem/ops.cc (permissions(const path&, perms, error_code&)): Handle symlink_nofollow. * testsuite/experimental/filesystem/operations/create_symlink.cc: New test. * testsuite/experimental/filesystem/operations/permissions.cc: Test overload taking error_code. From-SVN: r241418
This commit is contained in:
parent
2be9212713
commit
d17f7088fb
@ -1,5 +1,14 @@
|
||||
2016-10-21 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* include/experimental/bits/fs_fwd.h (perms::resolve_symlinks):
|
||||
Replace with symlink_nofollow (LWG 2720).
|
||||
* src/filesystem/ops.cc (permissions(const path&, perms, error_code&)):
|
||||
Handle symlink_nofollow.
|
||||
* testsuite/experimental/filesystem/operations/create_symlink.cc: New
|
||||
test.
|
||||
* testsuite/experimental/filesystem/operations/permissions.cc: Test
|
||||
overload taking error_code.
|
||||
|
||||
* include/experimental/bits/fs_ops.h
|
||||
(exists(const path&, error_code&)): Clear error if status is known
|
||||
(LWG 2725).
|
||||
|
@ -162,7 +162,7 @@ _GLIBCXX_END_NAMESPACE_CXX11
|
||||
unknown = 0xFFFF,
|
||||
add_perms = 0x10000,
|
||||
remove_perms = 0x20000,
|
||||
resolve_symlinks = 0x40000
|
||||
symlink_nofollow = 0x40000
|
||||
};
|
||||
|
||||
constexpr perms
|
||||
|
@ -1101,6 +1101,7 @@ void fs::permissions(const path& p, perms prms, error_code& ec) noexcept
|
||||
{
|
||||
const bool add = is_set(prms, perms::add_perms);
|
||||
const bool remove = is_set(prms, perms::remove_perms);
|
||||
const bool nofollow = is_set(prms, perms::symlink_nofollow);
|
||||
if (add && remove)
|
||||
{
|
||||
ec = std::make_error_code(std::errc::invalid_argument);
|
||||
@ -1111,7 +1112,7 @@ void fs::permissions(const path& p, perms prms, error_code& ec) noexcept
|
||||
|
||||
if (add || remove)
|
||||
{
|
||||
auto st = status(p, ec);
|
||||
auto st = nofollow ? symlink_status(p, ec) : status(p, ec);
|
||||
if (ec)
|
||||
return;
|
||||
auto curr = st.permissions();
|
||||
@ -1122,9 +1123,12 @@ void fs::permissions(const path& p, perms prms, error_code& ec) noexcept
|
||||
}
|
||||
|
||||
#if _GLIBCXX_USE_FCHMODAT
|
||||
if (::fchmodat(AT_FDCWD, p.c_str(), static_cast<mode_t>(prms), 0))
|
||||
const int flag = nofollow ? AT_SYMLINK_NOFOLLOW : 0;
|
||||
if (::fchmodat(AT_FDCWD, p.c_str(), static_cast<mode_t>(prms), flag))
|
||||
#else
|
||||
if (::chmod(p.c_str(), static_cast<mode_t>(prms)))
|
||||
if (nofollow)
|
||||
ec = std::make_error_code(std::errc::operation_not_supported);
|
||||
else if (::chmod(p.c_str(), static_cast<mode_t>(prms)))
|
||||
#endif
|
||||
ec.assign(errno, std::generic_category());
|
||||
else
|
||||
|
@ -0,0 +1,93 @@
|
||||
// Copyright (C) 2016 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-lstdc++fs" }
|
||||
// { dg-do run { target c++11 } }
|
||||
// { dg-require-filesystem-ts "" }
|
||||
|
||||
#include <experimental/filesystem>
|
||||
#include <testsuite_hooks.h>
|
||||
#include <testsuite_fs.h>
|
||||
|
||||
namespace fs = std::experimental::filesystem;
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
std::error_code ec, ec2;
|
||||
__gnu_test::scoped_file f;
|
||||
auto tgt = f.path;
|
||||
|
||||
// Test empty path.
|
||||
fs::path p;
|
||||
create_symlink(tgt, p, ec );
|
||||
VERIFY( ec );
|
||||
try
|
||||
{
|
||||
create_symlink(tgt, p);
|
||||
}
|
||||
catch (const std::experimental::filesystem::filesystem_error& ex)
|
||||
{
|
||||
ec2 = ex.code();
|
||||
VERIFY( ex.path1() == tgt );
|
||||
VERIFY( ex.path2() == p );
|
||||
}
|
||||
VERIFY( ec2 == ec );
|
||||
}
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
std::error_code ec, ec2;
|
||||
__gnu_test::scoped_file f;
|
||||
auto tgt = f.path;
|
||||
|
||||
// Test non-existent path
|
||||
auto p = __gnu_test::nonexistent_path();
|
||||
VERIFY( !exists(p) );
|
||||
|
||||
create_symlink(tgt, p, ec); // create the symlink once
|
||||
VERIFY( !ec );
|
||||
VERIFY( exists(p) );
|
||||
VERIFY( is_symlink(p) );
|
||||
remove(p);
|
||||
create_symlink(tgt, p); // create the symlink again
|
||||
VERIFY( exists(p) );
|
||||
VERIFY( is_symlink(p) );
|
||||
|
||||
create_symlink(tgt, p, ec); // Try to create existing symlink
|
||||
VERIFY( ec );
|
||||
try
|
||||
{
|
||||
create_symlink(tgt, p);
|
||||
}
|
||||
catch (const std::experimental::filesystem::filesystem_error& ex)
|
||||
{
|
||||
ec2 = ex.code();
|
||||
VERIFY( ex.path1() == tgt );
|
||||
VERIFY( ex.path2() == p );
|
||||
}
|
||||
VERIFY( ec2 == ec );
|
||||
|
||||
remove(p);
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
}
|
@ -22,7 +22,6 @@
|
||||
// 15.26 Permissions [fs.op.permissions]
|
||||
|
||||
#include <experimental/filesystem>
|
||||
#include <fstream>
|
||||
#include <testsuite_fs.h>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
@ -32,7 +31,8 @@ test01()
|
||||
using perms = std::experimental::filesystem::perms;
|
||||
|
||||
auto p = __gnu_test::nonexistent_path();
|
||||
std::ofstream{p.native()};
|
||||
|
||||
__gnu_test::scoped_file f(p);
|
||||
VERIFY( exists(p) );
|
||||
permissions(p, perms::owner_all);
|
||||
VERIFY( status(p).permissions() == perms::owner_all );
|
||||
@ -40,6 +40,83 @@ test01()
|
||||
VERIFY( status(p).permissions() == (perms::owner_all | perms::group_read) );
|
||||
permissions(p, perms::group_read | perms::remove_perms);
|
||||
VERIFY( status(p).permissions() == perms::owner_all );
|
||||
}
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
using perms = std::experimental::filesystem::perms;
|
||||
|
||||
auto p = __gnu_test::nonexistent_path();
|
||||
|
||||
std::error_code ec;
|
||||
permissions(p, perms::owner_all, ec);
|
||||
VERIFY( ec );
|
||||
|
||||
__gnu_test::scoped_file f(p);
|
||||
VERIFY( exists(p) );
|
||||
|
||||
ec = std::make_error_code(std::errc::invalid_argument);
|
||||
permissions(p, perms::owner_all, ec);
|
||||
VERIFY( !ec );
|
||||
VERIFY( status(p).permissions() == perms::owner_all );
|
||||
permissions(p, perms::group_read | perms::add_perms, ec);
|
||||
VERIFY( !ec );
|
||||
VERIFY( status(p).permissions() == (perms::owner_all | perms::group_read) );
|
||||
permissions(p, perms::group_read | perms::remove_perms, ec);
|
||||
VERIFY( !ec );
|
||||
VERIFY( status(p).permissions() == perms::owner_all );
|
||||
}
|
||||
|
||||
void
|
||||
test03()
|
||||
{
|
||||
using perms = std::experimental::filesystem::perms;
|
||||
|
||||
__gnu_test::scoped_file f;
|
||||
VERIFY( exists(f.path) );
|
||||
|
||||
auto p = __gnu_test::nonexistent_path();
|
||||
create_symlink(f.path, p);
|
||||
|
||||
std::error_code ec, ec2;
|
||||
permissions(p, perms::owner_all | perms::symlink_nofollow, ec);
|
||||
try
|
||||
{
|
||||
permissions(p, perms::owner_all | perms::symlink_nofollow);
|
||||
}
|
||||
catch (const std::experimental::filesystem::filesystem_error& ex)
|
||||
{
|
||||
ec2 = ex.code();
|
||||
VERIFY( ex.path1() == p );
|
||||
}
|
||||
// Both calls should succeed, or both should fail with same error:
|
||||
VERIFY( ec == ec2 );
|
||||
|
||||
remove(p);
|
||||
}
|
||||
|
||||
void
|
||||
test04()
|
||||
{
|
||||
using perms = std::experimental::filesystem::perms;
|
||||
|
||||
auto p = __gnu_test::nonexistent_path();
|
||||
create_symlink(__gnu_test::nonexistent_path(), p);
|
||||
|
||||
std::error_code ec, ec2;
|
||||
permissions(p, perms::owner_all, ec);
|
||||
VERIFY( ec );
|
||||
try
|
||||
{
|
||||
permissions(p, perms::owner_all);
|
||||
}
|
||||
catch (const std::experimental::filesystem::filesystem_error& ex)
|
||||
{
|
||||
ec2 = ex.code();
|
||||
VERIFY( ex.path1() == p );
|
||||
}
|
||||
VERIFY( ec == ec2 );
|
||||
|
||||
remove(p);
|
||||
}
|
||||
@ -48,4 +125,7 @@ int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
test02();
|
||||
test03();
|
||||
test04();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user