| /* |
| * 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 <sys/stat.h> |
| #include <cerrno> |
| #include <cstdint> |
| #include <limits> |
| #include <system_error> |
| |
| // 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<uintmax_t>::max(); |
| } |
| if (!is_regular_file(stat)) { |
| ec.assign(ENOTSUP, std::generic_category()); |
| return std::numeric_limits<uintmax_t>::max(); |
| } |
| ec.clear(); |
| return stat.st_size; |
| } |
| } |