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 #include <type_traits>
18 
19 #include <stout/bytes.hpp>
20 #include <stout/try.hpp>
21 #include <stout/unreachable.hpp>
22 #include <stout/windows.hpp>
23 
24 #include <stout/os/int_fd.hpp>
25 
26 #include <stout/windows/os.hpp>
27 
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 // TODO(andschwa): Refactor `GetFileInformationByHandle` into its own function.
61 inline bool isdir(const int_fd& fd)
62 {
63  BY_HANDLE_FILE_INFORMATION info;
64  const BOOL result = ::GetFileInformationByHandle(fd, &info);
65  if (result == FALSE) {
66  return false;
67  }
68 
69  return info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
70 }
71 
72 
73 inline bool isfile(
74  const std::string& path,
76 {
77  // A symlink itself is a file, but not a regular file.
78  // On POSIX, this check is done with `S_IFREG`, which
79  // returns false for symbolic links.
80  // If it's not a link, we ignore `follow`.
81  if (follow == FollowSymlink::DO_NOT_FOLLOW_SYMLINK && islink(path)) {
82  return false;
83  }
84 
87 
88  if (attributes.isError()) {
89  return false;
90  }
91 
92  // NOTE: Windows files attributes do not define a flag for "regular"
93  // files. Instead, this call will only return successfully iff the
94  // given file or directory exists. Checking against the directory
95  // flag determines if the path is a file or directory.
96  return !(attributes.get() & FILE_ATTRIBUTE_DIRECTORY);
97 }
98 
99 
100 inline bool islink(const std::string& path)
101 {
104 
105  return symlink.isSome();
106 }
107 
108 
109 // Returns the size in Bytes of a given file system entry. When applied to a
110 // symbolic link with `follow` set to `DO_NOT_FOLLOW_SYMLINK`, this will return
111 // zero because that's what Windows says.
112 inline Try<Bytes> size(
113  const std::string& path,
115 {
116  const Try<SharedHandle> handle = (follow == FollowSymlink::FOLLOW_SYMLINK)
119  if (handle.isError()) {
120  return Error("Error obtaining handle to file: " + handle.error());
121  }
122 
123  LARGE_INTEGER file_size;
124 
125  if (::GetFileSizeEx(handle->get_handle(), &file_size) == 0) {
126  return WindowsError();
127  }
128 
129  return Bytes(file_size.QuadPart);
130 }
131 
132 
133 inline Try<Bytes> size(const int_fd& fd)
134 {
135  LARGE_INTEGER file_size;
136 
137  if (::GetFileSizeEx(fd, &file_size) == 0) {
138  return WindowsError();
139  }
140 
141  return Bytes(file_size.QuadPart);
142 }
143 
144 
145 inline Try<long> mtime(
146  const std::string& path,
148 {
149  if (follow == FollowSymlink::DO_NOT_FOLLOW_SYMLINK && islink(path)) {
150  return Error(
151  "Requested mtime for '" + path +
152  "', but symbolic links don't have an mtime on Windows");
153  }
154 
155  Try<SharedHandle> handle =
159  if (handle.isError()) {
160  return Error(handle.error());
161  }
162 
163  FILETIME filetime;
164  // The last argument is file write time, AKA modification time.
165  const BOOL result =
166  ::GetFileTime(handle->get_handle(), nullptr, nullptr, &filetime);
167  if (result == FALSE) {
168  return WindowsError();
169  }
170 
171  const uint64_t unixtime = os::internal::windows_to_unix_epoch(filetime);
172 
173  // We choose to make this conversion explicit because we expect the
174  // truncation to not cause information loss.
175  return static_cast<long>(unixtime);
176 }
177 
178 
179 // NOTE: The following are deleted because implementing them would use
180 // the CRT API `_stat`, which we want to avoid, and they're not
181 // currently used on Windows.
182 inline Try<mode_t> mode(
183  const std::string& path,
184  const FollowSymlink follow) = delete;
185 
186 
187 inline Try<dev_t> dev(
188  const std::string& path,
189  const FollowSymlink follow) = delete;
190 
191 
192 inline Try<ino_t> inode(
193  const std::string& path,
194  const FollowSymlink follow) = delete;
195 
196 } // namespace stat {
197 } // namespace os {
198 
199 #endif // __STOUT_OS_WINDOWS_STAT_HPP__
Definition: path.hpp:26
Try< SharedHandle > get_handle_no_follow(const std::string &absolute_path)
Definition: reparsepoint.hpp:215
bool isfile(const std::string &path, const FollowSymlink follow=FollowSymlink::FOLLOW_SYMLINK)
Definition: stat.hpp:108
Definition: errorbase.hpp:36
Try< Bytes > size(const std::string &path, const FollowSymlink follow=FollowSymlink::FOLLOW_SYMLINK)
Definition: stat.hpp:121
T & get()&
Definition: try.hpp:73
HANDLE get_handle() const
Definition: windows.hpp:90
bool islink(const std::string &path)
Definition: stat.hpp:80
Definition: check.hpp:33
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:65
Definition: error.hpp:108
Try< long > mtime(const std::string &path, const FollowSymlink follow=FollowSymlink::FOLLOW_SYMLINK)
Definition: stat.hpp:146
Definition: posix_signalhandler.hpp:23
Try< ino_t > inode(const std::string &path, const FollowSymlink follow=FollowSymlink::FOLLOW_SYMLINK)
Definition: stat.hpp:202
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:172
double windows_to_unix_epoch(const FILETIME &filetime)
Definition: os.hpp:87
bool isSome() const
Definition: try.hpp:70
Try< struct::stat > stat(const int_fd fd)
Definition: stat.hpp:68
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:91
Try< mode_t > mode(const std::string &path, const FollowSymlink follow=FollowSymlink::FOLLOW_SYMLINK)
Definition: stat.hpp:159
std::wstring longpath(const std::string &path)
Definition: longpath.hpp:38
Definition: bytes.hpp:30
int int_fd
Definition: int_fd.hpp:35