1 // Copyright 2018 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_INTERNAL_FILESYSTEM_H
16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_INTERNAL_FILESYSTEM_H
17
18 #include "google/cloud/version.h"
19 #include <cinttypes>
20 #include <system_error>
21
22 namespace google {
23 namespace cloud {
24 inline namespace GOOGLE_CLOUD_CPP_NS {
25 namespace internal {
26
27 enum class file_type {
28 none = 0, // NOLINT(readability-identifier-naming)
29 not_found, // NOLINT(readability-identifier-naming)
30 regular, // NOLINT(readability-identifier-naming)
31 directory, // NOLINT(readability-identifier-naming)
32 symlink, // NOLINT(readability-identifier-naming)
33 block, // NOLINT(readability-identifier-naming)
34 character, // NOLINT(readability-identifier-naming)
35 fifo, // NOLINT(readability-identifier-naming)
36 socket, // NOLINT(readability-identifier-naming)
37 unknown, // NOLINT(readability-identifier-naming)
38 };
39
40 enum class perms {
41 none = 0, // NOLINT(readability-identifier-naming)
42 owner_read = 0400, // NOLINT(readability-identifier-naming)
43 owner_write = 0200, // NOLINT(readability-identifier-naming)
44 owner_exec = 0100, // NOLINT(readability-identifier-naming)
45 owner_all = 0700, // NOLINT(readability-identifier-naming)
46 group_read = 0040, // NOLINT(readability-identifier-naming)
47 group_write = 0020, // NOLINT(readability-identifier-naming)
48 group_exec = 0010, // NOLINT(readability-identifier-naming)
49 group_all = 0070, // NOLINT(readability-identifier-naming)
50 others_read = 0004, // NOLINT(readability-identifier-naming)
51 others_write = 0002, // NOLINT(readability-identifier-naming)
52 others_exec = 0001, // NOLINT(readability-identifier-naming)
53 others_all = 0007, // NOLINT(readability-identifier-naming)
54 all = 0777, // NOLINT(readability-identifier-naming)
55 set_uid = 04000, // NOLINT(readability-identifier-naming)
56 set_gid = 02000, // NOLINT(readability-identifier-naming)
57 sticky_bit = 01000, // NOLINT(readability-identifier-naming)
58 mask = 07777, // NOLINT(readability-identifier-naming)
59
60 unknown = 0xFFFF, // NOLINT(readability-identifier-naming)
61 };
62
63 inline perms operator&(perms lhs, perms rhs) {
64 return static_cast<perms>(static_cast<unsigned>(lhs) &
65 static_cast<unsigned>(rhs));
66 }
67
68 inline perms operator|(perms lhs, perms rhs) {
69 return static_cast<perms>(static_cast<unsigned>(lhs) |
70 static_cast<unsigned>(rhs));
71 }
72
73 inline perms operator^(perms lhs, perms rhs) {
74 return static_cast<perms>(static_cast<unsigned>(lhs) ^
75 static_cast<unsigned>(rhs));
76 }
77
78 inline perms operator~(perms lhs) {
79 return static_cast<perms>(static_cast<unsigned>(perms::mask) &
80 ~static_cast<unsigned>(lhs));
81 }
82
83 inline perms& operator&=(perms& lhs, perms rhs) {
84 lhs = lhs & rhs;
85 return lhs;
86 }
87
88 inline perms operator|=(perms& lhs, perms rhs) {
89 lhs = lhs | rhs;
90 return lhs;
91 }
92
93 inline perms operator^=(perms& lhs, perms rhs) {
94 lhs = lhs ^ rhs;
95 return lhs;
96 }
97
98 /**
99 * A drop-in replacement for `std::filesystem::file_status`.
100 *
101 * Implement the C++17 `std::filesystem::file_status` class.
102 */
103 class file_status { // NOLINT(readability-identifier-naming)
104 public:
file_status()105 file_status() noexcept : file_status(file_type::none) {}
106 explicit file_status(file_type type, perms permissions = perms::unknown)
type_(type)107 : type_(type), permissions_(permissions) {}
108 file_status(file_status const&) noexcept = default;
109 file_status(file_status&&) noexcept = default;
110 file_status& operator=(file_status const&) noexcept = default;
111 file_status& operator=(file_status&&) noexcept = default;
112
type()113 file_type type() const noexcept { return type_; }
type(file_type type)114 void type(file_type type) noexcept { type_ = type; }
permissions()115 perms permissions() const noexcept { return permissions_; }
permissions(perms permissions)116 void permissions(perms permissions) noexcept { permissions_ = permissions; }
117
118 private:
119 file_type type_;
120 perms permissions_;
121 };
122
123 file_status status(std::string const& path);
124 file_status status(std::string const& path, std::error_code& ec) noexcept;
125
status_known(file_status s)126 inline bool status_known(file_status s) noexcept {
127 return s.type() != file_type::none;
128 }
129
is_block_file(file_status s)130 inline bool is_block_file(file_status s) noexcept {
131 return s.type() == file_type::block;
132 }
133
is_character_file(file_status s)134 inline bool is_character_file(file_status s) noexcept {
135 return s.type() == file_type::character;
136 }
137
is_directory(file_status s)138 inline bool is_directory(file_status s) noexcept {
139 return s.type() == file_type::directory;
140 }
141
is_fifo(file_status s)142 inline bool is_fifo(file_status s) noexcept {
143 return s.type() == file_type::fifo;
144 }
145
is_regular(file_status s)146 inline bool is_regular(file_status s) noexcept {
147 return s.type() == file_type::regular;
148 }
149
is_socket(file_status s)150 inline bool is_socket(file_status s) noexcept {
151 return s.type() == file_type::socket;
152 }
153
is_symlink(file_status s)154 inline bool is_symlink(file_status s) noexcept {
155 return s.type() == file_type::symlink;
156 }
157
exists(file_status s)158 inline bool exists(file_status s) noexcept {
159 return status_known(s) && s.type() != file_type::not_found;
160 }
161
is_other(file_status s)162 inline bool is_other(file_status s) noexcept {
163 return exists(s) && !is_regular(s) && !is_directory(s) && !is_symlink(s);
164 }
165
166 std::uintmax_t file_size(std::string const& path);
167 std::uintmax_t file_size(std::string const& path, std::error_code& ec) noexcept;
168
169 } // namespace internal
170 } // namespace GOOGLE_CLOUD_CPP_NS
171 } // namespace cloud
172 } // namespace google
173
174 #endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_INTERNAL_FILESYSTEM_H
175