// Copyright (C) 2021 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 // . // { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } // { dg-require-filesystem-ts "" } #include #include #include namespace fs = std::filesystem; void test01() { std::error_code ec; const std::error_code bad_ec = make_error_code(std::errc::invalid_argument); auto p1 = __gnu_test::nonexistent_path(); auto p2 = __gnu_test::nonexistent_path(); fs::rename(p1, p2, ec); VERIFY( ec ); ec.clear(); fs::rename(p1, "", ec); VERIFY( ec ); ec.clear(); fs::rename("", p1, ec); VERIFY( ec ); ec = bad_ec; std::ofstream{p1}; // create file fs::rename(p1, p1, ec); // no-op VERIFY( !ec ); VERIFY( is_regular_file(p1) ); ec.clear(); rename(p2, p1, ec); VERIFY( ec ); VERIFY( ec.value() == ENOENT ); VERIFY( is_regular_file(p1) ); ec = bad_ec; fs::rename(p1, p2, ec); VERIFY( !ec ); VERIFY( !exists(p1) ); VERIFY( is_regular_file(p2) ); ec = bad_ec; std::ofstream{p1}; // create file fs::rename(p1, p2, ec); VERIFY( !ec ); VERIFY( !exists(p1) ); VERIFY( is_regular_file(p2) ); fs::remove(p2, ec); } void test_symlinks() { #if defined(__MINGW32__) || defined(__MINGW64__) // No symlink support #else std::error_code ec; const std::error_code bad_ec = make_error_code(std::errc::invalid_argument); const auto dir = __gnu_test::nonexistent_path(); fs::create_directory(dir); create_symlink(dir/"nonesuch", dir/"link"); // dangling symlink ec = bad_ec; fs::rename(dir/"link", dir/"newlink", ec); VERIFY( !ec ); VERIFY( !exists(symlink_status(dir/"link")) ); VERIFY( is_symlink(dir/"newlink") ); __gnu_test::scoped_file f(dir/"file"); create_symlink(dir/"file", dir/"link"); ec = bad_ec; fs::rename(dir/"link", dir/"newerlink", ec); VERIFY( !ec ); VERIFY( !exists(symlink_status(dir/"link")) ); VERIFY( is_symlink(dir/"newerlink") ); VERIFY( is_regular_file(dir/"file") ); fs::remove_all(dir, ec); f.path.clear(); #endif } void test_directories() { std::error_code ec; const std::error_code bad_ec = make_error_code(std::errc::invalid_argument); const auto dir = __gnu_test::nonexistent_path(); fs::create_directory(dir); __gnu_test::scoped_file f(dir/"file"); fs::create_directory(dir/"subdir"); // Rename directory. ec = bad_ec; fs::rename(dir/"subdir", dir/"subdir2", ec); VERIFY( !ec ); VERIFY( is_directory(dir/"subdir2") ); VERIFY( !exists(dir/"subdir") ); // Cannot rename a directory to a sub-directory of itself. fs::rename(dir/"subdir2", dir/"subdir2/subsubdir", ec); VERIFY( ec ); VERIFY( is_directory(dir/"subdir2") ); VERIFY( !exists(dir/"subdir2"/"subsubdir") ); // Cannot rename a file to the name of an existing directory. ec.clear(); fs::rename(dir/"file", dir/"subdir2", ec); VERIFY( ec ); VERIFY( is_directory(dir/"subdir2") ); VERIFY( is_regular_file(dir/"file") ); // Cannot rename a directory to the name of an existing non-directory ec.clear(); fs::rename(dir/"subdir2", dir/"file", ec); VERIFY( ec ); VERIFY( is_regular_file(dir/"file") ); VERIFY( is_directory(dir/"subdir2") ); // Cannot rename directory to the name of a non-empty directory. ec.clear(); __gnu_test::scoped_file f2(dir/"subdir2/file"); fs::create_directory(dir/"subdir"); fs::rename(dir/"subdir", dir/"subdir2", ec); VERIFY( ec ); VERIFY( is_directory(dir/"subdir") ); VERIFY( is_directory(dir/"subdir2") ); VERIFY( is_regular_file(dir/"subdir2/file") ); #if defined(__MINGW32__) || defined(__MINGW64__) // Cannot rename a directory to an existing directory #else // Can rename a non-empty directory to the name of an empty directory. ec = bad_ec; fs::rename(dir/"subdir2", dir/"subdir", ec); VERIFY( !ec ); VERIFY( is_directory(dir/"subdir") ); VERIFY( !exists(dir/"subdir2") ); VERIFY( is_regular_file(dir/"subdir/file") ); #endif f2.path.clear(); f.path.clear(); fs::remove_all(dir, ec); } int main() { test01(); test_symlinks(); test_directories(); }