xref: /aosp_15_r20/external/zstd/contrib/pzstd/utils/FileSystem.h (revision 01826a4963a0d8a59bc3812d29bdf0fb76416722)
1  /*
2   * Copyright (c) Meta Platforms, Inc. and affiliates.
3   * All rights reserved.
4   *
5   * This source code is licensed under both the BSD-style license (found in the
6   * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7   * in the COPYING file in the root directory of this source tree).
8   */
9  #pragma once
10  
11  #include "utils/Portability.h"
12  #include "utils/Range.h"
13  
14  #include <sys/stat.h>
15  #include <cerrno>
16  #include <cstdint>
17  #include <limits>
18  #include <system_error>
19  
20  // A small subset of `std::filesystem`.
21  // `std::filesystem` should be a drop in replacement.
22  // See https://en.cppreference.com/w/cpp/filesystem for documentation.
23  
24  namespace pzstd {
25  
26  // using file_status = ... causes gcc to emit a false positive warning
27  #if defined(_MSC_VER)
28  typedef struct ::_stat64 file_status;
29  #else
30  typedef struct ::stat file_status;
31  #endif
32  
33  /// https://en.cppreference.com/w/cpp/filesystem/status
status(StringPiece path,std::error_code & ec)34  inline file_status status(StringPiece path, std::error_code& ec) noexcept {
35    file_status status;
36  #if defined(_MSC_VER)
37    const auto error = ::_stat64(path.data(), &status);
38  #else
39    const auto error = ::stat(path.data(), &status);
40  #endif
41    if (error) {
42      ec.assign(errno, std::generic_category());
43    } else {
44      ec.clear();
45    }
46    return status;
47  }
48  
49  /// https://en.cppreference.com/w/cpp/filesystem/is_regular_file
is_regular_file(file_status status)50  inline bool is_regular_file(file_status status) noexcept {
51  #if defined(S_ISREG)
52    return S_ISREG(status.st_mode);
53  #elif !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG)
54    return (status.st_mode & S_IFMT) == S_IFREG;
55  #else
56    static_assert(false, "No POSIX stat() support.");
57  #endif
58  }
59  
60  /// https://en.cppreference.com/w/cpp/filesystem/is_regular_file
is_regular_file(StringPiece path,std::error_code & ec)61  inline bool is_regular_file(StringPiece path, std::error_code& ec) noexcept {
62    return is_regular_file(status(path, ec));
63  }
64  
65  /// https://en.cppreference.com/w/cpp/filesystem/is_directory
is_directory(file_status status)66  inline bool is_directory(file_status status) noexcept {
67  #if defined(S_ISDIR)
68    return S_ISDIR(status.st_mode);
69  #elif !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR)
70    return (status.st_mode & S_IFMT) == S_IFDIR;
71  #else
72    static_assert(false, "NO POSIX stat() support.");
73  #endif
74  }
75  
76  /// https://en.cppreference.com/w/cpp/filesystem/is_directory
is_directory(StringPiece path,std::error_code & ec)77  inline bool is_directory(StringPiece path, std::error_code& ec) noexcept {
78    return is_directory(status(path, ec));
79  }
80  
81  /// https://en.cppreference.com/w/cpp/filesystem/file_size
file_size(StringPiece path,std::error_code & ec)82  inline std::uintmax_t file_size(
83      StringPiece path,
84      std::error_code& ec) noexcept {
85    auto stat = status(path, ec);
86    if (ec) {
87      return std::numeric_limits<uintmax_t>::max();
88    }
89    if (!is_regular_file(stat)) {
90      ec.assign(ENOTSUP, std::generic_category());
91      return std::numeric_limits<uintmax_t>::max();
92    }
93    ec.clear();
94    return stat.st_size;
95  }
96  }
97