/* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). */ #pragma once #include "utils/Portability.h" #include "utils/Range.h" #include #include #include #include #include // A small subset of `std::filesystem`. // `std::filesystem` should be a drop in replacement. // See https://en.cppreference.com/w/cpp/filesystem for documentation. namespace pzstd { // using file_status = ... causes gcc to emit a false positive warning #if defined(_MSC_VER) typedef struct ::_stat64 file_status; #else typedef struct ::stat file_status; #endif /// https://en.cppreference.com/w/cpp/filesystem/status inline file_status status(StringPiece path, std::error_code& ec) noexcept { file_status status; #if defined(_MSC_VER) const auto error = ::_stat64(path.data(), &status); #else const auto error = ::stat(path.data(), &status); #endif if (error) { ec.assign(errno, std::generic_category()); } else { ec.clear(); } return status; } /// https://en.cppreference.com/w/cpp/filesystem/is_regular_file inline bool is_regular_file(file_status status) noexcept { #if defined(S_ISREG) return S_ISREG(status.st_mode); #elif !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG) return (status.st_mode & S_IFMT) == S_IFREG; #else static_assert(false, "No POSIX stat() support."); #endif } /// https://en.cppreference.com/w/cpp/filesystem/is_regular_file inline bool is_regular_file(StringPiece path, std::error_code& ec) noexcept { return is_regular_file(status(path, ec)); } /// https://en.cppreference.com/w/cpp/filesystem/is_directory inline bool is_directory(file_status status) noexcept { #if defined(S_ISDIR) return S_ISDIR(status.st_mode); #elif !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR) return (status.st_mode & S_IFMT) == S_IFDIR; #else static_assert(false, "NO POSIX stat() support."); #endif } /// https://en.cppreference.com/w/cpp/filesystem/is_directory inline bool is_directory(StringPiece path, std::error_code& ec) noexcept { return is_directory(status(path, ec)); } /// https://en.cppreference.com/w/cpp/filesystem/file_size inline std::uintmax_t file_size( StringPiece path, std::error_code& ec) noexcept { auto stat = status(path, ec); if (ec) { return std::numeric_limits::max(); } if (!is_regular_file(stat)) { ec.assign(ENOTSUP, std::generic_category()); return std::numeric_limits::max(); } ec.clear(); return stat.st_size; } }