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 <stdlib.h>
21 
22 #include <random>
23 #include <string>
24 
25 #include <stout/error.hpp>
26 #include <stout/nothing.hpp>
27 #include <stout/path.hpp>
28 #include <stout/strings.hpp>
29 #include <stout/try.hpp>
30 
31 #include <stout/os/mkdir.hpp>
32 #include <stout/os/temp.hpp>
33 
34 
35 namespace os {
36 
37 // Creates a temporary directory using the specified path
38 // template. The template may be any path with _6_ `Xs' appended to
39 // it, for example /tmp/temp.XXXXXX. The trailing `Xs' are replaced
40 // with a unique alphanumeric combination.
42  const std::string& path = path::join(os::temp(), "XXXXXX"))
43 {
44  // NOTE: We'd like to avoid reallocating `postfixTemplate` and `alphabet`,
45  // and to avoid recomputing their sizes on each call to `mkdtemp`, so we
46  // make them `static const` and use the slightly awkward `sizeof` trick to
47  // compute their sizes once instead of calling `strlen` for each call.
48  static const char postfixTemplate[] = "XXXXXX";
49  static const size_t postfixSize = sizeof(postfixTemplate) - 1;
50 
51  if (!strings::endsWith(path, postfixTemplate)) {
52  return Error(
53  "Invalid template passed to `os::mkdtemp`: template '" + path +
54  "' should end with 6 'X' characters");
55  }
56 
57  static const char alphabet[] =
58  "0123456789"
59  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
60  "abcdefghijklmnopqrstuvwxyz";
61 
62  // NOTE: The maximum addressable index in a string is the total length of the
63  // string minus 1; but C strings have an extra null character at the end, so
64  // the size of the array is actually one more than the length of the string,
65  // which is why we're subtracting 2 here.
66  static const size_t maxAlphabetIndex = sizeof(alphabet) - 2;
67 
68  std::string postfix(postfixTemplate);
69  static thread_local std::mt19937 generator((std::random_device())());
70 
71  for (int i = 0; i < postfixSize; ++i) {
72  int index = generator() % maxAlphabetIndex;
73  postfix[i] = alphabet[index];
74  }
75 
76  // Replace template, make directory.
77  std::string tempPath = path
78  .substr(0, path.length() - postfixSize)
79  .append(postfix);
80 
81  Try<Nothing> mkdir = os::mkdir(tempPath, false);
82 
83  if (mkdir.isError()) {
84  return Error(mkdir.error());
85  }
86 
87  return tempPath;
88 }
89 
90 } // namespace os {
91 
92 
93 #endif // __STOUT_OS_WINDOWS_MKDTEMP_HPP__
bool endsWith(const std::string &s, const std::string &suffix)
Definition: strings.hpp:393
Definition: path.hpp:26
Definition: errorbase.hpp:35
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:135
Try< std::string > mkdtemp(const std::string &path=path::join(os::temp(),"XXXXXX"))
Definition: mkdtemp.hpp:38