Apache Mesos
mkdir.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_POSIX_MKDIR_HPP__
14 #define __STOUT_OS_POSIX_MKDIR_HPP__
15 
16 #include <sys/stat.h>
17 
18 #include <string>
19 #include <vector>
20 
21 #include <stout/error.hpp>
22 #include <stout/foreach.hpp>
23 #include <stout/nothing.hpp>
24 #include <stout/strings.hpp>
25 #include <stout/path.hpp>
26 #include <stout/try.hpp>
27 
28 #include <stout/os/constants.hpp>
29 #include <stout/os/fsync.hpp>
30 
31 namespace os {
32 
33 // Make a directory.
34 //
35 // If `recursive` is set to true, all intermediate directories will be created
36 // as required. If `sync` is set to true, `fsync()` will be called on the parent
37 // of each created directory to ensure that the result is committed to its
38 // filesystem.
39 //
40 // NOTE: This function doesn't ensure that any existing directory is committed
41 // to its filesystem, and it does not perform any cleanup in case of a failure.
43  const std::string& directory,
44  bool recursive = true,
45  bool sync = false)
46 {
47  if (!recursive) {
48  if (::mkdir(directory.c_str(), 0755) < 0) {
49  return ErrnoError();
50  }
51 
52  if (sync) {
53  const std::string parent = Path(directory).dirname();
54  Try<Nothing> fsync = os::fsync(parent);
55  if (fsync.isError()) {
56  return Error(
57  "Failed to fsync directory '" + parent + "': " + fsync.error());
58  }
59  }
60  } else {
61  std::vector<std::string> tokens =
63 
64  std::string path;
65 
66  // We got an absolute path, so keep the leading slash.
67  if (directory.find_first_of(stringify(os::PATH_SEPARATOR)) == 0) {
68  path = os::PATH_SEPARATOR;
69  }
70 
71  foreach (const std::string& token, tokens) {
72  path += token;
73  if (::mkdir(path.c_str(), 0755) < 0) {
74  if (errno != EEXIST) {
75  return ErrnoError();
76  }
77  } else if (sync) {
78  const std::string parent = Path(path).dirname();
79  Try<Nothing> fsync = os::fsync(parent);
80  if (fsync.isError()) {
81  return Error(
82  "Failed to fsync directory '" + parent + "': " + fsync.error());
83  }
84  }
85 
86  path += os::PATH_SEPARATOR;
87  }
88  }
89 
90  return Nothing();
91 }
92 
93 } // namespace os {
94 
95 #endif // __STOUT_OS_POSIX_MKDIR_HPP__
Definition: path.hpp:29
Definition: nothing.hpp:16
Definition: errorbase.hpp:36
Definition: check.hpp:33
Definition: errorbase.hpp:50
Definition: posix_signalhandler.hpp:23
std::vector< std::string > tokenize(const std::string &s, const std::string &delims, const Option< size_t > &maxTokens=None())
Definition: strings.hpp:139
Try< Nothing > mkdir(const std::string &directory, bool recursive=true, bool sync=false)
Definition: mkdir.hpp:42
Represents a POSIX or Windows file system path and offers common path manipulations.
Definition: path.hpp:212
static Try error(const E &e)
Definition: try.hpp:43
std::string dirname() const
Extracts the component up to, but not including, the final &#39;/&#39;.
Definition: path.hpp:308
Try< Nothing > fsync(int fd)
Definition: fsync.hpp:29
bool isError() const
Definition: try.hpp:78
std::string stringify(int flags)
constexpr char PATH_SEPARATOR
Definition: constants.hpp:24