// Class filesystem::directory_entry etc. -*- C++ -*-

// Copyright (C) 2014-2023 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.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

#ifndef _GLIBCXX_USE_CXX11_ABI
# define _GLIBCXX_USE_CXX11_ABI 1
#endif

#include <bits/largefile-config.h>
#include <filesystem>
#include <utility>
#include <stack>
#include <string.h>
#include <errno.h>
#define _GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM namespace filesystem {
#define _GLIBCXX_END_NAMESPACE_FILESYSTEM }
#include "../filesystem/dir-common.h"

namespace fs = std::filesystem;
namespace posix = std::filesystem::__gnu_posix;

template class std::__shared_ptr<fs::_Dir>;
template class std::__shared_ptr<fs::recursive_directory_iterator::_Dir_stack>;

struct fs::_Dir : _Dir_base
{
  _Dir(const fs::path& p, bool skip_permission_denied, bool nofollow,
       [[maybe_unused]] bool filename_only, error_code& ec)
  : _Dir_base(p.c_str(), skip_permission_denied, nofollow, ec)
  {
#if _GLIBCXX_HAVE_DIRFD && _GLIBCXX_HAVE_OPENAT && _GLIBCXX_HAVE_UNLINKAT
    if (filename_only)
      return; // Do not store path p when we aren't going to use it.
#endif

    if (!ec)
      path = p;
  }

  _Dir(_Dir_base&& d, const path& p) : _Dir_base(std::move(d)), path(p) { }

  _Dir(_Dir&&) = default;

  // Returns false when the end of the directory entries is reached.
  // Reports errors by setting ec.
  bool advance(bool skip_permission_denied, error_code& ec) noexcept
  {
    if (const auto entp = _Dir_base::advance(skip_permission_denied, ec))
      {
	auto name = path;
	name /= entp->d_name;
	file_type type = file_type::none;
#ifdef _GLIBCXX_HAVE_STRUCT_DIRENT_D_TYPE
	// Even if the OS supports dirent::d_type the filesystem might not:
	if (entp->d_type != DT_UNKNOWN)
	  type = get_file_type(*entp);
#endif
	entry = fs::directory_entry{std::move(name), type};
	return true;
      }
    else if (!ec)
      {
	// reached the end
	entry = {};
      }
    return false;
  }

  bool advance(error_code& ec) noexcept { return advance(false, ec); }

  // Returns false when the end of the directory entries is reached.
  // Reports errors by throwing.
  bool advance(bool skip_permission_denied = false)
  {
    error_code ec;
    const bool ok = advance(skip_permission_denied, ec);
    if (ec)
      _GLIBCXX_THROW_OR_ABORT(filesystem_error(
	      "directory iterator cannot advance", ec));
    return ok;
  }

  bool should_recurse(bool follow_symlink, error_code& ec) const
  {
    file_type type = entry._M_type;
    if (type == file_type::none)
    {
      type = entry.symlink_status(ec).type();
      if (ec)
	return false;
    }

    if (type == file_type::directory)
      return true;
    if (type == file_type::symlink)
      return follow_symlink && is_directory(entry.status(ec));
    return false;
  }

  // Return a pathname for the current directory entry, as an _At_path.
  _Dir_base::_At_path
  current() const noexcept
  {
    const fs::path& p = entry.path();
#if _GLIBCXX_HAVE_DIRFD
    if (!p.empty()) [[__likely__]]
      {
	auto len = std::prev(p.end())->native().size();
	return {::dirfd(this->dirp), p.c_str(), p.native().size() - len};
      }
#endif
    return p.c_str();
  }

  // Create a new _Dir for the directory this->entry.path().
  _Dir
  open_subdir(bool skip_permission_denied, bool nofollow,
	      error_code& ec) const noexcept
  {
    _Dir_base d(current(), skip_permission_denied, nofollow, ec);
    // If this->path is empty, the new _Dir should have an empty path too.
    const fs::path& p = this->path.empty() ? this->path : this->entry.path();
    return _Dir(std::move(d), p);
  }

  bool
  do_unlink(bool is_directory, error_code& ec) const noexcept
  {
#if _GLIBCXX_HAVE_UNLINKAT
    const auto atp = current();
    if (::unlinkat(atp.dir(), atp.path_at_dir(),
		   is_directory ? AT_REMOVEDIR : 0) == -1)
      {
	ec.assign(errno, std::generic_category());
	return false;
      }
    else
      {
	ec.clear();
	return true;
      }
#else
    return fs::remove(entry.path(), ec);
#endif
  }

  // Remove the non-directory that this->entry refers to.
  bool
  unlink(error_code& ec) const noexcept
  { return do_unlink(/* is_directory*/ false, ec); }

  // Remove the directory that this->entry refers to.
  bool
  rmdir(error_code& ec) const noexcept
  { return do_unlink(/* is_directory*/ true, ec); }

  fs::path		path; // Empty if only using unlinkat with file descr.
  directory_entry	entry;
};

namespace
{
  template<typename Bitmask>
    inline bool
    is_set(Bitmask obj, Bitmask bits)
    {
      return (obj & bits) != Bitmask::none;
    }

// Non-standard directory option flags, currently only for internal use:
//
// Do not allow directory iterator to open a symlink.
// This might seem redundant given directory_options::follow_directory_symlink
// but that is only checked for recursing into sub-directories, and we need
// something that controls the initial opendir() call in the constructor.
constexpr fs::directory_options __directory_iterator_nofollow{64};
// Do not store full paths in std::filesystem::recursive_directory_iterator.
// When fs::remove_all uses recursive_directory_iterator::__erase and unlinkat
// is available in libc, we do not need the parent directory's path, only the
// filenames of the directory entries (and a file descriptor for the parent).
// This flag avoids allocating memory for full paths that won't be needed.
constexpr fs::directory_options __directory_iterator_filename_only{128};
}

fs::directory_iterator::
directory_iterator(const path& p, directory_options options, error_code* ecptr)
{
  // Do not report an error for permission denied errors.
  const bool skip_permission_denied
    = is_set(options, directory_options::skip_permission_denied);
  // Do not allow opening a symlink.
  const bool nofollow = is_set(options, __directory_iterator_nofollow);

  error_code ec;
  _Dir dir(p, skip_permission_denied, nofollow, /*filename only*/false, ec);

  if (dir.dirp)
    {
      auto sp = std::__make_shared<fs::_Dir>(std::move(dir));
      if (sp->advance(skip_permission_denied, ec))
	_M_dir.swap(sp);
    }
  if (ecptr)
    *ecptr = ec;
  else if (ec)
    _GLIBCXX_THROW_OR_ABORT(fs::filesystem_error(
	  "directory iterator cannot open directory", p, ec));
}

const fs::directory_entry&
fs::directory_iterator::operator*() const noexcept
{
  return _M_dir->entry;
}

fs::directory_iterator&
fs::directory_iterator::operator++()
{
  if (!_M_dir)
    _GLIBCXX_THROW_OR_ABORT(filesystem_error(
	  "cannot advance non-dereferenceable directory iterator",
	  std::make_error_code(errc::invalid_argument)));
  if (!_M_dir->advance())
    _M_dir.reset();
  return *this;
}

fs::directory_iterator&
fs::directory_iterator::increment(error_code& ec)
{
  if (!_M_dir)
    {
      ec = std::make_error_code(errc::invalid_argument);
      return *this;
    }
  if (!_M_dir->advance(ec))
    _M_dir.reset();
  return *this;
}

struct fs::recursive_directory_iterator::_Dir_stack : std::stack<_Dir>
{
  _Dir_stack(directory_options opts, _Dir&& dir)
  : options(opts), pending(true)
  {
    this->push(std::move(dir));
  }

  path::string_type orig;
  const directory_options options;
  bool pending;

  void clear() { c.clear(); }

  path current_path() const
  {
    path p;
    if (top().path.empty())
      {
	// Reconstruct path that failed from dir stack.
	p = orig;
	for (auto& d : this->c)
	  p /= d.entry.path();
      }
    else
      p = top().entry.path();
    return p;
  }
};

fs::recursive_directory_iterator::
recursive_directory_iterator(const path& p, directory_options options,
                             error_code* ecptr)
{
  // Do not report an error for permission denied errors.
  const bool skip_permission_denied
    = is_set(options, directory_options::skip_permission_denied);
  // Do not allow opening a symlink as the starting directory.
  const bool nofollow = is_set(options, __directory_iterator_nofollow);
  // Prefer to store only filenames (not full paths) in directory_entry values.
  const bool filename_only
     = is_set(options, __directory_iterator_filename_only);

  error_code ec;
  _Dir dir(p, skip_permission_denied, nofollow, filename_only, ec);

  if (dir.dirp)
    {
      auto sp = std::__make_shared<_Dir_stack>(options, std::move(dir));
      if (ecptr ? sp->top().advance(skip_permission_denied, *ecptr)
		: sp->top().advance(skip_permission_denied))
	{
	  _M_dirs.swap(sp);
	  if (filename_only) // Need to save original path for error reporting.
	    _M_dirs->orig = p.native();
	}
    }
  else if (ecptr)
    *ecptr = ec;
  else if (ec)
    _GLIBCXX_THROW_OR_ABORT(fs::filesystem_error(
	  "recursive directory iterator cannot open directory", p, ec));
}

fs::recursive_directory_iterator::~recursive_directory_iterator() = default;

fs::directory_options
fs::recursive_directory_iterator::options() const noexcept
{
  return _M_dirs->options;
}

int
fs::recursive_directory_iterator::depth() const noexcept
{
  return int(_M_dirs->size()) - 1;
}

bool
fs::recursive_directory_iterator::recursion_pending() const noexcept
{
  return _M_dirs->pending;
}

const fs::directory_entry&
fs::recursive_directory_iterator::operator*() const noexcept
{
  return _M_dirs->top().entry;
}

fs::recursive_directory_iterator&
fs::recursive_directory_iterator::
operator=(const recursive_directory_iterator& other) noexcept = default;

fs::recursive_directory_iterator&
fs::recursive_directory_iterator::
operator=(recursive_directory_iterator&& other) noexcept = default;

fs::recursive_directory_iterator&
fs::recursive_directory_iterator::operator++()
{
  error_code ec;
  increment(ec);
  if (ec)
    _GLIBCXX_THROW_OR_ABORT(filesystem_error(
	  "cannot increment recursive directory iterator", ec));
  return *this;
}

fs::recursive_directory_iterator&
fs::recursive_directory_iterator::increment(error_code& ec)
{
  if (!_M_dirs)
    {
      ec = std::make_error_code(errc::invalid_argument);
      return *this;
    }

  const bool follow
    = is_set(_M_dirs->options, directory_options::follow_directory_symlink);
  const bool skip_permission_denied
    = is_set(_M_dirs->options, directory_options::skip_permission_denied);

  auto& top = _M_dirs->top();

  if (std::exchange(_M_dirs->pending, true) && top.should_recurse(follow, ec))
    {
      _Dir dir = top.open_subdir(skip_permission_denied, !follow, ec);
      if (ec)
	{
	  _M_dirs.reset();
	  return *this;
	}
      if (dir.dirp)
	_M_dirs->push(std::move(dir));
    }

  while (!_M_dirs->top().advance(skip_permission_denied, ec) && !ec)
    {
      _M_dirs->pop();
      if (_M_dirs->empty())
	{
	  _M_dirs.reset();
	  return *this;
	}
    }

  if (ec)
    _M_dirs.reset();

  return *this;
}

void
fs::recursive_directory_iterator::pop(error_code& ec)
{
  if (!_M_dirs)
    {
      ec = std::make_error_code(errc::invalid_argument);
      return;
    }

  const bool skip_permission_denied
    = is_set(_M_dirs->options, directory_options::skip_permission_denied);

  do {
    _M_dirs->pop();
    if (_M_dirs->empty())
      {
	_M_dirs.reset();
	ec.clear();
	return;
      }
  } while (!_M_dirs->top().advance(skip_permission_denied, ec) && !ec);

  if (ec)
    _M_dirs.reset();
}

void
fs::recursive_directory_iterator::pop()
{
  [[maybe_unused]] const bool dereferenceable = _M_dirs != nullptr;
  error_code ec;
  pop(ec);
  if (ec)
    _GLIBCXX_THROW_OR_ABORT(filesystem_error(dereferenceable
	  ? "recursive directory iterator cannot pop"
	  : "non-dereferenceable recursive directory iterator cannot pop",
	  ec));
}

void
fs::recursive_directory_iterator::disable_recursion_pending() noexcept
{
  _M_dirs->pending = false;
}

// Used to implement filesystem::remove_all.
fs::recursive_directory_iterator&
fs::recursive_directory_iterator::__erase(error_code* ecptr)
{
  error_code ec;
  if (!_M_dirs)
    {
      ec = std::make_error_code(errc::invalid_argument);
      return *this;
    }

  // We never want to skip permission denied when removing files.
  const bool skip_permission_denied = false;
  // We never want to follow directory symlinks when removing files.
  const bool nofollow = true;

  // Loop until we find something we can remove.
  while (!ec)
    {
      auto& top = _M_dirs->top();

#if _GLIBCXX_FILESYSTEM_IS_WINDOWS
      // _Dir::unlink uses fs::remove which uses std::system_category() for
      // Windows errror codes, so we can't just check for EPERM and EISDIR.
      // Use directory_entry::refresh() here to check if we have a directory.
      // This can be a TOCTTOU race, but we don't have openat or unlinkat to
      // solve that on Windows, and generally don't support symlinks anyway.
      if (top.entry._M_type == file_type::none)
	top.entry.refresh();
#endif

      if (top.entry._M_type == file_type::directory)
	{
	  _Dir dir = top.open_subdir(skip_permission_denied, nofollow, ec);
	  if (!ec)
	    {
	      __glibcxx_assert(dir.dirp != nullptr);
	      if (dir.advance(skip_permission_denied, ec))
		{
		  // Non-empty directory, recurse into it.
		  _M_dirs->push(std::move(dir));
		  continue;
		}
	      if (!ec)
		{
		  // Directory is empty so we can remove it.
		  if (top.rmdir(ec))
		    break; // Success
		}
	    }
	}
      else if (top.unlink(ec))
	break; // Success
#if ! _GLIBCXX_FILESYSTEM_IS_WINDOWS
      else if (top.entry._M_type == file_type::none)
	{
	  // We did not have a cached type, so it's possible that top.entry
	  // is actually a directory, and that's why the unlink above failed.
#ifdef EPERM
	  // POSIX.1-2017 says unlink on a directory returns EPERM,
	  // but LSB allows EISDIR too. Some targets don't even define EPERM.
	  if (ec.value() == EPERM || ec.value() == EISDIR)
#else
	  if (ec.value() == EISDIR)
#endif
	    {
	      // Retry, treating it as a directory.
	      top.entry._M_type = file_type::directory;
	      ec.clear();
	      continue;
	    }
	}
#endif
    }

  if (!ec)
    {
      // We successfully removed the current entry, so advance to the next one.
      if (_M_dirs->top().advance(skip_permission_denied, ec))
	return *this;
      else if (!ec)
	{
	  // Reached the end of the current directory.
	  _M_dirs->pop();
	  if (_M_dirs->empty())
	    _M_dirs.reset();
	  return *this;
	}
    }

  // Reset _M_dirs to empty.
  auto dirs = std::move(_M_dirs);

  // Need to report an error
  if (ecptr)
    *ecptr = ec;
  else
    _GLIBCXX_THROW_OR_ABORT(fs::filesystem_error("cannot remove all",
						 dirs->orig,
						 dirs->current_path(),
						 ec));

  return *this;
}
