97 lines
2.7 KiB
C
97 lines
2.7 KiB
C
|
/*
|
||
|
* 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;
|
||
|
}
|
||
|
}
|