// 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();
}