Apache Mesos
mktemp.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_MKTEMP_HPP__
14 #define __STOUT_OS_WINDOWS_MKTEMP_HPP__
15 
16 #include <string>
17 #include <vector>
18 
19 #include <stout/error.hpp>
20 #include <stout/path.hpp>
21 #include <stout/stringify.hpp>
22 #include <stout/try.hpp>
23 #include <stout/windows.hpp>
24 
25 #include <stout/os/close.hpp>
26 #include <stout/os/int_fd.hpp>
27 #include <stout/os/open.hpp>
28 #include <stout/os/temp.hpp>
29 
31 
32 
33 namespace os {
34 
35 // Creates a temporary file using the specified path template. The
36 // template may be any path with _6_ `Xs' appended to it, for example
37 // /tmp/temp.XXXXXX. The trailing `Xs' are replaced with a unique
38 // alphanumeric combination.
40  const std::string& path = path::join(os::temp(), "XXXXXX"))
41 {
42  const std::wstring longpath = ::internal::windows::longpath(path);
43  std::vector<wchar_t> buffer(longpath.begin(), longpath.end());
44 
45  // The range does not include the null terminator, needed to reconstruct
46  // the next string.
47  buffer.push_back(L'\0');
48 
49  // NOTE: in the POSIX spec, `mkstemp` will generate a random filename from
50  // the `path` template, `open` that filename, and return the resulting file
51  // descriptor. On Windows, `_mktemp_s` will actually only generate the path,
52  // so here we actually have to call `open` ourselves to get a file descriptor
53  // we can return as a result.
54  if (::_wmktemp_s(buffer.data(), buffer.size()) != 0) {
55  return WindowsError();
56  }
57 
58  const std::string temp_file = stringify(std::wstring(buffer.data()));
59 
60  // NOTE: We open the file with read/write access for the given user, an
61  // attempt to match POSIX's specification of `mkstemp`. We use `_S_IREAD` and
62  // `_S_IWRITE` here instead of the POSIX equivalents. On Windows the file is
63  // is not present, we use `_O_CREAT` option when opening the file.
64  Try<int_fd> fd =
65  os::open(temp_file, O_RDWR | O_CREAT | O_EXCL, _S_IREAD | _S_IWRITE);
66  if (fd.isError()) {
67  return Error(fd.error());
68  }
69 
70  // We ignore the return value of close(). This is because users
71  // calling this function are interested in the return value of
72  // mkstemp(). Also an unsuccessful close() doesn't affect the file.
73  os::close(fd.get());
74 
75  return strings::remove(temp_file, os::LONGPATH_PREFIX, strings::Mode::PREFIX);
76 }
77 
78 } // namespace os {
79 
80 #endif // __STOUT_OS_WINDOWS_MKTEMP_HPP__
Definition: path.hpp:29
Definition: errorbase.hpp:36
T & get()&
Definition: try.hpp:80
Definition: check.hpp:33
Try< std::string > mktemp(const std::string &path=path::join(os::temp(),"XXXXXX"))
Definition: mktemp.hpp:36
Try< int_fd > open(const std::string &path, int oflag, mode_t mode=0)
Definition: open.hpp:35
Definition: error.hpp:108
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:116
std::string remove(const std::string &from, const std::string &substring, Mode mode=ANY)
Definition: strings.hpp:41
Try< Nothing > close(int fd)
Definition: close.hpp:24
static Try error(const E &e)
Definition: try.hpp:43
bool isError() const
Definition: try.hpp:78
std::string temp()
Definition: temp.hpp:27
std::wstring longpath(const std::string &path)
Definition: longpath.hpp:38
std::string stringify(int flags)