diff options
-rw-r--r-- | libstdc++-v3/ChangeLog | 7 | ||||
-rw-r--r-- | libstdc++-v3/src/filesystem/ops.cc | 21 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/experimental/filesystem/operations/permissions.cc | 21 |
3 files changed, 42 insertions, 7 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index fd79dec..abe1efc 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,10 @@ +2016-10-22 Jonathan Wakely <jwakely@redhat.com> + + * src/filesystem/ops.cc (permissions(const path&, perms, error_code&)): + Ignore symlink_nofollow flag if file is not a symlink. + * testsuite/experimental/filesystem/operations/permissions.cc: Test + symlink_nofollow on non-symlinks. + 2016-10-21 Jonathan Wakely <jwakely@redhat.com> * include/experimental/bits/fs_fwd.h (perms::resolve_symlinks): diff --git a/libstdc++-v3/src/filesystem/ops.cc b/libstdc++-v3/src/filesystem/ops.cc index 68343a9..2286e22 100644 --- a/libstdc++-v3/src/filesystem/ops.cc +++ b/libstdc++-v3/src/filesystem/ops.cc @@ -1097,7 +1097,8 @@ fs::permissions(const path& p, perms prms) _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot set permissions", p, ec)); } -void fs::permissions(const path& p, perms prms, error_code& ec) noexcept +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); @@ -1110,27 +1111,33 @@ void fs::permissions(const path& p, perms prms, error_code& ec) noexcept prms &= perms::mask; - if (add || remove) + file_status st; + if (add || remove || nofollow) { - auto st = nofollow ? symlink_status(p, ec) : status(p, ec); + st = nofollow ? symlink_status(p, ec) : status(p, ec); if (ec) return; auto curr = st.permissions(); if (add) prms |= curr; - else + else if (remove) prms = curr & ~prms; } + int err = 0; #if _GLIBCXX_USE_FCHMODAT - const int flag = nofollow ? AT_SYMLINK_NOFOLLOW : 0; + const int flag = (nofollow && is_symlink(st)) ? AT_SYMLINK_NOFOLLOW : 0; if (::fchmodat(AT_FDCWD, p.c_str(), static_cast<mode_t>(prms), flag)) + err = errno; #else - if (nofollow) + if (nofollow && is_symlink(st)) ec = std::make_error_code(std::errc::operation_not_supported); else if (::chmod(p.c_str(), static_cast<mode_t>(prms))) + err = errno; #endif - ec.assign(errno, std::generic_category()); + + if (err) + ec.assign(err, std::generic_category()); else ec.clear(); } diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/permissions.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/permissions.cc index 839cfef..61471a3 100644 --- a/libstdc++-v3/testsuite/experimental/filesystem/operations/permissions.cc +++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/permissions.cc @@ -121,6 +121,26 @@ test04() remove(p); } +void +test05() +{ + using perms = std::experimental::filesystem::perms; + std::error_code ec; + + __gnu_test::scoped_file f; + auto p = perms::owner_write; + + // symlink_nofollow should not give an error for non-symlinks + permissions(f.path, p|perms::symlink_nofollow, ec); + VERIFY( !ec ); + auto st = status(f.path); + VERIFY( st.permissions() == p ); + p |= perms::owner_read; + permissions(f.path, p|perms::symlink_nofollow, ec); + st = status(f.path); + VERIFY( st.permissions() == p ); +} + int main() { @@ -128,4 +148,5 @@ main() test02(); test03(); test04(); + test05(); } |