Apache Mesos
stat.hpp
Go to the documentation of this file.
1 // Licensed under the Apache License, Version 2.0 (the "License");
2 // you may not use this file except in compliance with the License.
3 // You may obtain a copy of the License at
4 //
5 // http://www.apache.org/licenses/LICENSE-2.0
6 //
7 // Unless required by applicable law or agreed to in writing, software
8 // distributed under the License is distributed on an "AS IS" BASIS,
9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 // See the License for the specific language governing permissions and
11 // limitations under the License.
12 
13 #ifndef __STOUT_OS_WINDOWS_STAT_HPP__
14 #define __STOUT_OS_WINDOWS_STAT_HPP__
15 
16 #include <string>
17 
18 #include <stout/bytes.hpp>
19 #include <stout/try.hpp>
20 #include <stout/unreachable.hpp>
21 #include <stout/windows.hpp>
22 
27 
28 #ifdef _USE_32BIT_TIME_T
29 #error "Implementation of `os::stat::mtime` assumes 64-bit `time_t`."
30 #endif // _USE_32BIT_TIME_T
31 
32 
33 namespace os {
34 namespace stat {
35 
36 // Forward declaration.
37 inline bool islink(const std::string& path);
38 
39 inline bool isdir(
40  const std::string& path,
42 {
43  // A symlink itself is not a directory.
44  // If it's not a link, we ignore `follow`.
45  if (follow == FollowSymlink::DO_NOT_FOLLOW_SYMLINK && islink(path)) {
46  return false;
47  }
48 
51 
52  if (attributes.isError()) {
53  return false;
54  }
55 
56  return attributes.get() & FILE_ATTRIBUTE_DIRECTORY;
57 }
58 
59 
60 inline bool isfile(
61  const std::string& path,
63 {
64  // A symlink itself is a file, but not a regular file.
65  // On POSIX, this check is done with `S_IFREG`, which
66  // returns false for symbolic links.
67  // If it's not a link, we ignore `follow`.
68  if (follow == FollowSymlink::DO_NOT_FOLLOW_SYMLINK && islink(path)) {
69  return false;
70  }
71 
74 
75  if (attributes.isError()) {
76  return false;
77  }
78 
79  // NOTE: Windows files attributes do not define a flag for "regular"
80  // files. Instead, this call will only return successfully iff the
81  // given file or directory exists. Checking against the directory
82  // flag determines if the path is a file or directory.
83  return !(attributes.get() & FILE_ATTRIBUTE_DIRECTORY);
84 }
85 
86 
87 inline bool islink(const std::string& path)
88 {
91 
92  return symlink.isSome();
93 }
94 
95 
96 // Returns the size in Bytes of a given file system entry. When applied to a
97 // symbolic link with `follow` set to `DO_NOT_FOLLOW_SYMLINK`, this will return
98 // zero because that's what Windows says.
99 inline Try<Bytes> size(
100  const std::string& path,
102 {
103  const Try<SharedHandle> handle = (follow == FollowSymlink::FOLLOW_SYMLINK)
106  if (handle.isError()) {
107  return Error("Error obtaining handle to file: " + handle.error());
108  }
109 
110  LARGE_INTEGER file_size;
111 
112  if (::GetFileSizeEx(handle->get_handle(), &file_size) == 0) {
113  return WindowsError();
114  }
115 
116  return Bytes(file_size.QuadPart);
117 }
118 
119 
120 // TODO(andschwa): Replace `::_stat`. See MESOS-8275.
121 inline Try<long> mtime(
122  const std::string& path,
124 {
125  if (follow == FollowSymlink::DO_NOT_FOLLOW_SYMLINK) {
128 
129  if (symlink.isSome()) {
130  return Error(
131  "Requested mtime for '" + path +
132  "', but symbolic links don't have an mtime on Windows");
133  }
134  }
135 
136  struct _stat s;
137 
138  if (::_stat(path.c_str(), &s) < 0) {
139  return ErrnoError("Error invoking stat for '" + path + "'");
140  }
141 
142  // To be safe, we assert that `st_mtime` is represented as `__int64`. To
143  // conform to the POSIX, we also cast `st_mtime` to `long`; we choose to make
144  // this conversion explicit because we expect the truncation to not cause
145  // information loss.
146  static_assert(
147  std::is_same<__int64, __time64_t>::value,
148  "Mesos assumes `__time64_t` is represented as `__int64`");
149  return static_cast<long>(s.st_mtime);
150 }
151 
152 
153 // TODO(andschwa): Replace `::_stat`. See MESOS-8275.
154 inline Try<mode_t> mode(
155  const std::string& path,
157 {
158  struct _stat s;
159 
160  if (follow == FollowSymlink::DO_NOT_FOLLOW_SYMLINK && islink(path)) {
161  return Error("lstat not supported for symlink '" + path + "'");
162  }
163 
164  if (::_stat(path.c_str(), &s) < 0) {
165  return ErrnoError("Error invoking stat for '" + path + "'");
166  }
167 
168  return s.st_mode;
169 }
170 
171 
172 // TODO(andschwa): Replace `::_stat`. See MESOS-8275.
173 inline Try<dev_t> dev(
174  const std::string& path,
176 {
177  struct _stat s;
178 
179  if (follow == FollowSymlink::DO_NOT_FOLLOW_SYMLINK && islink(path)) {
180  return Error("lstat not supported for symlink '" + path + "'");
181  }
182 
183  if (::_stat(path.c_str(), &s) < 0) {
184  return ErrnoError("Error invoking stat for '" + path + "'");
185  }
186 
187  return s.st_dev;
188 }
189 
190 
191 // TODO(andschwa): Replace `::_stat`. See MESOS-8275.
192 inline Try<ino_t> inode(
193  const std::string& path,
195 {
196  struct _stat s;
197 
198  if (follow == FollowSymlink::DO_NOT_FOLLOW_SYMLINK) {
199  return Error("Non-following stat not supported for '" + path + "'");
200  }
201 
202  if (::_stat(path.c_str(), &s) < 0) {
203  return ErrnoError("Error invoking stat for '" + path + "'");
204  }
205 
206  return s.st_ino;
207 }
208 
209 } // namespace stat {
210 } // namespace os {
211 
212 #endif // __STOUT_OS_WINDOWS_STAT_HPP__
Try< SharedHandle > get_handle_no_follow(const std::string &absolute_path)
Definition: reparsepoint.hpp:212
bool isfile(const std::string &path, const FollowSymlink follow=FollowSymlink::FOLLOW_SYMLINK)
Definition: stat.hpp:87
Definition: errorbase.hpp:35
Try< Bytes > size(const std::string &path, const FollowSymlink follow=FollowSymlink::FOLLOW_SYMLINK)
Definition: stat.hpp:100
HANDLE get_handle() const
Definition: windows.hpp:96
bool islink(const std::string &path)
Definition: stat.hpp:67
Definition: try.hpp:34
Try< DWORD > get_file_attributes(const std::wstring &path)
Definition: attributes.hpp:27
Try< Nothing > symlink(const std::string &original, const std::string &link)
Definition: fs.hpp:54
Definition: error.hpp:106
Definition: errorbase.hpp:49
Try< long > mtime(const std::string &path, const FollowSymlink follow=FollowSymlink::FOLLOW_SYMLINK)
Definition: stat.hpp:113
Try< ino_t > inode(const std::string &path, const FollowSymlink follow=FollowSymlink::FOLLOW_SYMLINK)
Definition: stat.hpp:169
FollowSymlink
Definition: reparsepoint.hpp:35
Try< SymbolicLink > query_symbolic_link_data(const std::string &path)
Definition: symlink.hpp:79
Try< dev_t > dev(const std::string &path, const FollowSymlink follow=FollowSymlink::FOLLOW_SYMLINK)
Definition: stat.hpp:139
bool isSome() const
Definition: try.hpp:70
Try< hashmap< std::string, uint64_t > > stat(const std::string &hierarchy, const std::string &cgroup, const std::string &file)
static Try error(const E &e)
Definition: try.hpp:42
Try< SharedHandle > get_handle_follow(const std::string &absolute_path)
Definition: reparsepoint.hpp:155
bool isError() const
Definition: try.hpp:71
bool isdir(const std::string &path, const FollowSymlink follow=FollowSymlink::FOLLOW_SYMLINK)
Definition: stat.hpp:78
Try< mode_t > mode(const std::string &path, const FollowSymlink follow=FollowSymlink::FOLLOW_SYMLINK)
Definition: stat.hpp:126
std::wstring longpath(const std::string &path)
Definition: longpath.hpp:38
Definition: bytes.hpp:30
const T & get() const
Definition: try.hpp:73