https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71313

            Bug ID: 71313
           Summary: [Filesystem TS] remove_all fails to remove directory
                    contents recursively
           Product: gcc
           Version: 6.1.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: felix.morgner at gmail dot com
  Target Milestone: ---

Created attachment 38583
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=38583&action=edit
Sample code to reproduce the problem

According to the Filesystem TS [fs.op.remove_all], remove_all should
recursively remove the contents of the given file.

From the final draft:

...
    Recursively deletes the contents of p if it exists, then deletes file p
itself, as if by POSIX remove().
...

The current implementation in libstdc++-v3 (libstdc++fs) fails to do so.

The following code:

    #include <experimental/filesystem>

    #include <fstream>
    #include <iostream>

    namespace fs = std::experimental::filesystem;

    int main() try
      {
      auto const kDirectory = fs::path("dtop");
      create_directory(kDirectory);
      create_directory(kDirectory / "dsub");
      std::ofstream out{kDirectory / "dsub" / "file"};
      out.close();
      fs::remove_all(kDirectory);
      }
    catch(fs::filesystem_error const & e)
      {
      std::cout << "Error: " << e.what() << '\n';
      }

produces the following output:

    Error: filesystem error: cannot remove all: Directory not empty [dtop]

I assume that the bug is caused by 4 missing characters in 'filesystem/ops.cc'.
From the current HEAD:

    std::uintmax_t
    fs::remove_all(const path& p, error_code& ec) noexcept
    {
      auto fs = symlink_status(p, ec);
      uintmax_t count = 0;
      if (ec.value() == 0 && fs.type() == file_type::directory)
        for (directory_iterator d(p, ec), end; ec.value() == 0 && d != end;
++d)
          count += fs::remove(d->path(), ec);
      if (ec.value())
        return -1;
      return fs::remove(p, ec) ? ++count : -1;  // fs:remove() calls ec.clear()
    }

I believe that the line

    count += fs::remove(d->path(), ec);

should really be

    count += fs::remove_all(d->path(), ec);

Reply via email to