gulrak / filesystem

An implementation of C++17 std::filesystem for C++11 /C++14/C++17/C++20 on Windows, macOS, Linux and FreeBSD.
MIT License
1.34k stars 173 forks source link

ghc::filesystem::remove_all fails if symlink target is pointing to a read only filesystem #132

Closed CedricDC closed 2 years ago

CedricDC commented 3 years ago

Hi!

The call to ghc::filesystem::remove_all(path) (same with the version with the std::error_code) appears to fail when "path" is a symlink on a read-write filesystem that points to a non-empty directory on a read-only filesystem. It works correctly when the symlink target is a file or if the target directory is empty. The call returns an error with the "Read-only file system" message.

Tested on Ubuntu 18.04 with gcc 9.2.0 with filesystem 1.0.8 as well as current master. Using std::filesystem instead, the symlink is deleted as expected.

Test procedure:

  1. Create virtual filesystem as described here : https://www.thegeekdiary.com/how-to-create-virtual-block-device-loop-device-filesystem-in-linux/ (or use real one, whatever is available)
  2. Create directory _testdir with a file in it
  3. Remount filesystem as read-only.
  4. Create symlink (called _sym_testdir in the example below) to _testdir from a different, read-write filesystem and try to delete that symlink via remove_all

Sample executable:

#include <iostream>
#include <string>

#include "ghc_filesystem.hpp"

namespace fs = ghc::filesystem;

void removeSomething(const std::string& name) {
  std::error_code ec_remove;
  fs::remove_all(name, ec_remove);
  if (ec_remove.value() != 0) {
    std::string msg = ec_remove.message();
    std::cout << "Could not remove " << name << ": " << msg << std::endl;
  } else {
    std::cout << "Happily removed " << name << std::endl;
  }
}

int main() {

  std::string symlink_path = "sym_test_dir";

  // try to remove non-empty dir --> fails with "Read-only file system"
  removeSomething(symlink_dir);

  return 0;
}

Thanks!

gulrak commented 3 years ago

Thank you for the detailed report, I'll look into it.

phprus commented 3 years ago

@CedricDC Please replace line https://github.com/gulrak/filesystem/blob/7bc5c17305fe70518ca72162e244af1d12455a91/include/ghc/filesystem.hpp#L4743

to

auto fs = symlink_status(p, tec);

and run your test.

gulrak commented 3 years ago

This is indeed be fixed by #135 and I want to thank @phprus for his repeated supportive work.

gulrak commented 2 years ago

Fix is part of v1.5.10.