Something went wrong. Try again.
Monorepo for PackTools - tooling for Minecraft Modpacks!
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107// The file system, as packutils needs it: links never followed unless asked, every failure as a// `FileSystem` failure naming its cause and path, and paths as UTF-8 throughout (wide only inside// the Windows half). `fs_posix.cpp` and `fs_windows.cpp` implement it; each compiles to nothing// on the other platform. AI-authored (Claude).#pragma once
#include "failure.hpp"
#include <cstddef>#include <cstdint>#include <optional>#include <string>#include <string_view>#include <vector>
namespace packutils::fs {
#ifdef _WIN32inline constexpr char separator = '\\';#elseinline constexpr char separator = '/';#endif
/// What is at a path, without following a link.enum class State : std::uint8_t { missing, link, directory, file, other };
/// A file's size and modification time, which say whether its source changed since a copy.struct Stamp { std::uint64_t size = 0; std::int64_t mtime_ns = 0;
bool operator==(const Stamp &) const = default;};
struct Entry { std::string name; State kind = State::other;};
/// `a` joined with `b` by the platform's separator, as Zig's `std.fs.path.join` joins two parts.[[nodiscard]] std::string join(std::string_view a, std::string_view b);
[[nodiscard]] Result<State> state(const std::string &path);/// The file's bytes, or nothing when it does not exist. Larger than `limit` fails.[[nodiscard]] Result<std::optional<std::string>> read(const std::string &path, std::size_t limit);/// Replaces `path` through a flushed temp file beside it, creating the directory first.[[nodiscard]] Result<void> write_atomic(const std::string &path, std::string_view bytes);[[nodiscard]] Result<void> make_path(const std::string &path);/// One directory; an existing one fails with cause `PathAlreadyExists`.[[nodiscard]] Result<void> make_dir(const std::string &path);[[nodiscard]] Result<void> remove_file(const std::string &path);/// An empty directory, or (Windows) a junction itself.[[nodiscard]] Result<void> remove_dir(const std::string &path);[[nodiscard]] Result<void> rename(const std::string &from, const std::string &to);/// Replaces `to` with a copy of `from`.[[nodiscard]] Result<void> copy_file(const std::string &from, const std::string &to);/// The real full path; a missing path fails.[[nodiscard]] Result<std::string> real_path(const std::string &path);/// The entries of a directory, `.` and `..` left out. The directory itself is followed when it is/// a link only if `follow` says so.[[nodiscard]] Result<std::vector<Entry>> list(const std::string &path, bool follow);[[nodiscard]] Result<Stamp> stamp(const std::string &path);/// Whether `path` is a directory, not a link, with nothing in it.[[nodiscard]] bool is_empty_directory(const std::string &path);/// Where the link at `path` points, or nothing when it is not a link.[[nodiscard]] std::optional<std::string> read_link(const std::string &path);/// Whether two link targets name the same place: on Windows without regard to separators or/// ASCII case, as the file system resolves them.[[nodiscard]] bool same_path(std::string_view a, std::string_view b);
/// A directory link at `link` (which must not exist) to the directory `target`: a symlink, or on/// Windows a junction. False when the file system takes none; a refusal is never an error.[[nodiscard]] bool link_directory(const std::string &link, const std::string &target);
/// An exclusive lock on a file, released when this goes away.class FileLock { public: FileLock() = default; FileLock(const FileLock &) = delete; FileLock &operator=(const FileLock &) = delete; FileLock(FileLock &&other) noexcept; FileLock &operator=(FileLock &&other) noexcept; ~FileLock();
/// The lock on `path` (created when missing), or nothing while another process holds it. [[nodiscard]] static Result<std::optional<FileLock>> try_acquire(const std::string &path);
private:#ifdef _WIN32 void *handle_ = nullptr;#else int fd_ = -1;#endif void release() noexcept;};
/// Sleeps for `milliseconds`.void pause(std::uint32_t milliseconds);
/// A junction's reparse data (`REPARSE_DATA_BUFFER`, mount point variant): the substitute name/// (`\??\C:\...`) and the print name (`C:\...`), each followed by a NUL. Nothing when the names do/// not fit the 16-bit lengths. Pure, so it is tested on every platform.[[nodiscard]] std::optional<std::vector<std::uint8_t>>junction_buffer(const std::u16string &substitute, const std::u16string &print);
} // namespace packutils::fs