Apache Mesos
fs.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_WINDOWS_FS_HPP__
14 #define __STOUT_WINDOWS_FS_HPP__
15 
16 #include <string>
17 
18 #include <stout/bytes.hpp>
19 #include <stout/error.hpp>
20 #include <stout/nothing.hpp>
21 #include <stout/try.hpp>
22 #include <stout/windows.hpp>
23 
24 #include <stout/os/realpath.hpp>
25 
28 
29 namespace fs {
30 
31 // Returns the total disk size in bytes.
32 inline Try<Bytes> size(const std::string& path = "/")
33 {
34  Result<std::string> real_path = os::realpath(path);
35  if (!real_path.isSome()) {
36  return Error(
37  "Failed to get realpath for '" + path+ "': " +
38  (real_path.isError() ? real_path.error() : "No such directory"));
39  }
40 
41  ULARGE_INTEGER free_bytes, total_bytes, total_free_bytes;
42  if (::GetDiskFreeSpaceExW(
43  internal::windows::longpath(real_path.get()).data(),
44  &free_bytes,
45  &total_bytes,
46  &total_free_bytes) == 0) {
47  return WindowsError(
48  "Error invoking 'GetDiskFreeSpaceEx' on '" + path + "'");
49  }
50 
51  return Bytes(total_bytes.QuadPart);
52 }
53 
54 
55 // Returns relative disk usage of the file system that the given path
56 // is mounted at.
57 inline Try<double> usage(const std::string& path = "/")
58 {
59  Result<std::string> real_path = os::realpath(path);
60  if (!real_path.isSome()) {
61  return Error(
62  "Failed to get realpath for '" + path + "': " +
63  (real_path.isError() ? real_path.error() : "No such directory"));
64  }
65 
66  ULARGE_INTEGER free_bytes, total_bytes, total_free_bytes;
67  if (::GetDiskFreeSpaceExW(
68  internal::windows::longpath(real_path.get()).data(),
69  &free_bytes,
70  &total_bytes,
71  &total_free_bytes) == 0) {
72  return WindowsError(
73  "Error invoking 'GetDiskFreeSpaceEx' on '" + path + "'");
74  }
75 
76  double used = static_cast<double>(total_bytes.QuadPart - free_bytes.QuadPart);
77  return used / total_bytes.QuadPart;
78 }
79 
80 
81 inline Try<Nothing> symlink(
82  const std::string& original,
83  const std::string& link)
84 {
85  return internal::windows::create_symbolic_link(original, link);
86 }
87 
88 
89 // Returns a list of all files matching the given pattern. This is meant to
90 // be a lightweight alternative to glob() - the only supported wildcards are
91 // `?` and `*`, and only when they appear at the tail end of `pattern` (e.g.
92 // `/root/dir/subdir/*.txt` or `/root/dir/subdir/file?.txt`.
93 inline Try<std::list<std::string>> list(const std::string& pattern)
94 {
95  std::list<std::string> found_files;
96  WIN32_FIND_DATAW found;
97  const SharedHandle search_handle(
98  ::FindFirstFileW(wide_stringify(pattern).data(), &found),
99  ::FindClose);
100 
101  if (search_handle.get() == INVALID_HANDLE_VALUE) {
102  // For compliance with the POSIX implementation (which uses `::glob`),
103  // return an empty list instead of an error when the path does not exist.
104  int error = ::GetLastError();
105  if (error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND) {
106  return found_files;
107  }
108 
109  return WindowsError(
110  "'fs::list' failed when searching for files with pattern '" +
111  pattern + "'");
112  }
113 
114  do {
115  const std::wstring current_file(found.cFileName);
116 
117  // Ignore `.` and `..` entries.
118  if (current_file.compare(L".") != 0 && current_file.compare(L"..") != 0) {
119  found_files.push_back(stringify(current_file));
120  }
121  } while (::FindNextFileW(search_handle.get(), &found));
122 
123  const DWORD error = ::GetLastError();
124  if (error != ERROR_NO_MORE_FILES) {
125  return WindowsError(
126  error,
127  "'fs::list': 'FindNextFile' failed when searching for files with "
128  "'pattern '" + pattern + "'");
129  }
130 
131  return found_files;
132 }
133 
134 } // namespace fs {
135 
136 #endif // __STOUT_WINDOWS_FS_HPP__
Definition: errorbase.hpp:35
Definition: windows.hpp:78
Definition: try.hpp:34
Result< std::string > realpath(const std::string &path)
Definition: realpath.hpp:24
static Result< T > error(const std::string &message)
Definition: result.hpp:53
Try< Nothing > symlink(const std::string &original, const std::string &link)
Definition: fs.hpp:54
Definition: error.hpp:106
Definition: result.hpp:40
Try< Bytes > size(const std::string &path="/")
Definition: fs.hpp:32
Try< std::list< std::string > > list(const std::string &pattern)
Definition: fs.hpp:75
Try< double > usage(const std::string &path="/")
Definition: fs.hpp:44
const T & get() const
Definition: result.hpp:115
std::string error(const std::string &msg, uint32_t code)
bool isSome() const
Definition: result.hpp:111
bool isError() const
Definition: result.hpp:113
std::wstring longpath(const std::string &path)
Definition: longpath.hpp:38
Definition: bytes.hpp:30
std::string stringify(int flags)
Try< Nothing > create_symbolic_link(const std::string &target, const std::string &reparse_point)
Definition: reparsepoint.hpp:315