
Core::Directory represents an existing directory on the system, and it holds an actual file descriptor so that the user can be sure the directory stays in existence.
100 lines
2.5 KiB
C++
100 lines
2.5 KiB
C++
/*
|
|
* Copyright (c) 2022, kleines Filmröllchen <filmroellchen@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include "Directory.h"
|
|
#include "DirIterator.h"
|
|
#include "System.h"
|
|
#include <dirent.h>
|
|
|
|
namespace Core {
|
|
|
|
// We assume that the fd is a valid directory.
|
|
Directory::Directory(int fd, Optional<LexicalPath> path)
|
|
: m_path(move(path))
|
|
, m_directory_fd(fd)
|
|
{
|
|
}
|
|
|
|
Directory::Directory(Directory&& other)
|
|
: m_path(move(other.m_path))
|
|
, m_directory_fd(other.m_directory_fd)
|
|
{
|
|
other.m_directory_fd = -1;
|
|
}
|
|
|
|
Directory::~Directory()
|
|
{
|
|
if (m_directory_fd != -1)
|
|
MUST(System::close(m_directory_fd));
|
|
}
|
|
|
|
ErrorOr<bool> Directory::is_valid_directory(int fd)
|
|
{
|
|
auto stat = TRY(System::fstat(fd));
|
|
return stat.st_mode & S_IFDIR;
|
|
}
|
|
|
|
ErrorOr<Directory> Directory::adopt_fd(int fd, Optional<LexicalPath> path)
|
|
{
|
|
// This will also fail if the fd is invalid in the first place.
|
|
if (!TRY(Directory::is_valid_directory(fd)))
|
|
return Error::from_errno(ENOTDIR);
|
|
return Directory { fd, move(path) };
|
|
}
|
|
|
|
ErrorOr<Directory> Directory::create(String path, CreateDirectories create_directories)
|
|
{
|
|
return create(LexicalPath { move(path) }, create_directories);
|
|
}
|
|
|
|
ErrorOr<Directory> Directory::create(LexicalPath path, CreateDirectories create_directories)
|
|
{
|
|
if (create_directories == CreateDirectories::Yes)
|
|
TRY(ensure_directory(path));
|
|
// FIXME: doesn't work on Linux probably
|
|
auto fd = TRY(System::open(path.string(), O_CLOEXEC));
|
|
return adopt_fd(fd, move(path));
|
|
}
|
|
|
|
ErrorOr<void> Directory::ensure_directory(LexicalPath const& path)
|
|
{
|
|
if (path.basename() == "/")
|
|
return {};
|
|
|
|
TRY(ensure_directory(path.parent()));
|
|
|
|
auto return_value = System::mkdir(path.string(), 0755);
|
|
// We don't care if the directory already exists.
|
|
if (return_value.is_error() && return_value.error().code() != EEXIST)
|
|
return return_value;
|
|
|
|
return {};
|
|
}
|
|
|
|
ErrorOr<LexicalPath> Directory::path() const
|
|
{
|
|
if (!m_path.has_value())
|
|
return Error::from_string_literal("Directory wasn't created with a path");
|
|
return m_path.value();
|
|
}
|
|
|
|
ErrorOr<NonnullOwnPtr<Stream::File>> Directory::open(StringView filename, Stream::OpenMode mode) const
|
|
{
|
|
auto fd = TRY(System::openat(m_directory_fd, filename, Stream::File::open_mode_to_options(mode)));
|
|
return Stream::File::adopt_fd(fd, mode);
|
|
}
|
|
|
|
ErrorOr<struct stat> Directory::stat() const
|
|
{
|
|
return System::fstat(m_directory_fd);
|
|
}
|
|
|
|
ErrorOr<DirIterator> Directory::create_iterator() const
|
|
{
|
|
return DirIterator { TRY(path()).string() };
|
|
}
|
|
|
|
}
|