Apache Mesos
mkdtemp.hpp
Go to the documentation of this file.
1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements. See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership. The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License. You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 
17 #ifndef __STOUT_OS_WINDOWS_MKDTEMP_HPP__
18 #define __STOUT_OS_WINDOWS_MKDTEMP_HPP__
19 
20 #include <random>
21 #include <string>
22 
23 #include <stout/error.hpp>
24 #include <stout/nothing.hpp>
25 #include <stout/path.hpp>
26 #include <stout/strings.hpp>
27 #include <stout/try.hpp>
28 
29 #include <stout/os/mkdir.hpp>
30 #include <stout/os/temp.hpp>
31 
32 
33 namespace os {
34 
35 // Creates a temporary directory using the specified path
36 // template. The template may be any path with _6_ `Xs' appended to
37 // it, for example /tmp/temp.XXXXXX. The trailing `Xs' are replaced
38 // with a unique alphanumeric combination.
40  const std::string& path = path::join(os::temp(), "XXXXXX"))
41 {
42  // NOTE: We'd like to avoid reallocating `postfixTemplate` and `alphabet`,
43  // and to avoid recomputing their sizes on each call to `mkdtemp`, so we
44  // make them `static const` and use the slightly awkward `sizeof` trick to
45  // compute their sizes once instead of calling `strlen` for each call.
46  static const char postfixTemplate[] = "XXXXXX";
47  static const size_t postfixSize = sizeof(postfixTemplate) - 1;
48 
49  if (!strings::endsWith(path, postfixTemplate)) {
50  return Error(
51  "Invalid template passed to `os::mkdtemp`: template '" + path +
52  "' should end with 6 'X' characters");
53  }
54 
55  static const char alphabet[] =
56  "0123456789"
57  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
58  "abcdefghijklmnopqrstuvwxyz";
59 
60  // NOTE: The maximum addressable index in a string is the total length of the
61  // string minus 1; but C strings have an extra null character at the end, so
62  // the size of the array is actually one more than the length of the string,
63  // which is why we're subtracting 2 here.
64  static const size_t maxAlphabetIndex = sizeof(alphabet) - 2;
65 
66  std::string postfix(postfixTemplate);
67  static thread_local std::mt19937 generator((std::random_device())());
68 
69  for (int i = 0; i < postfixSize; ++i) {
70  int index = generator() % maxAlphabetIndex;
71  postfix[i] = alphabet[index];
72  }
73 
74  // Replace template, make directory.
75  std::string tempPath = path
76  .substr(0, path.length() - postfixSize)
77  .append(postfix);
78 
79  Try<Nothing> mkdir = os::mkdir(tempPath, false);
80 
81  if (mkdir.isError()) {
82  return Error(mkdir.error());
83  }
84 
85  return tempPath;
86 }
87 
88 } // namespace os {
89 
90 
91 #endif // __STOUT_OS_WINDOWS_MKDTEMP_HPP__
bool endsWith(const std::string &s, const std::string &suffix)
Definition: strings.hpp:402
Definition: path.hpp:26
Definition: errorbase.hpp:36
Definition: check.hpp:33
Definition: posix_signalhandler.hpp:23
std::string join(const std::string &path1, const std::string &path2, const char _separator=os::PATH_SEPARATOR)
Definition: path.hpp:56
Try< Nothing > mkdir(const std::string &directory, bool recursive=true)
Definition: mkdir.hpp:31
static Try error(const E &e)
Definition: try.hpp:42
bool isError() const
Definition: try.hpp:71
std::string temp()
Definition: temp.hpp:27
Try< Nothing > append(const std::string &path, const google::protobuf::Message &message)
Definition: protobuf.hpp:158
Try< std::string > mkdtemp(const std::string &path=path::join(os::temp(),"XXXXXX"))
Definition: mkdtemp.hpp:38