Apache Mesos
open.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_OPEN_HPP__
14 #define __STOUT_OS_WINDOWS_OPEN_HPP__
15 
16 #include <fcntl.h> // For file access flags like `_O_CREAT`.
17 
18 #include <string>
19 
20 #include <stout/error.hpp>
21 #include <stout/try.hpp>
22 #include <stout/windows.hpp> // For `mode_t`.
23 
24 #include <stout/os/int_fd.hpp>
25 
27 
28 // TODO(andschwa): Windows does not support the Linux extension
29 // O_NONBLOCK, as asynchronous I/O is done through other mechanisms.
30 // Overlapped I/O will be implemented later.
31 constexpr int O_NONBLOCK = 0;
32 
33 // Windows does not support the Linux extension O_SYNC, as buffering
34 // is done differently.
35 // TODO(andschwa): This could be equivalent to
36 // `FILE_FLAG_WRITE_THROUGH`, but we don't seem to need it.
37 constexpr int O_SYNC = 0;
38 
39 // Windows does not support the Linux extension O_CLOEXEC. Instead, by
40 // default we set all handles to be non-inheritable.
41 constexpr int O_CLOEXEC = 0;
42 
43 namespace os {
44 
45 // TODO(andschwa): Handle specified creation permissions in `mode_t mode`. See
46 // MESOS-3176.
47 //
48 // NOTE: This function always opens files in non-overlapped mode, because
49 // we only support overlapped pipes and sockets through the `os::pipe`
50 // and `os::socket` functions.
51 inline Try<int_fd> open(const std::string& path, int oflag, mode_t mode = 0)
52 {
53  std::wstring longpath = ::internal::windows::longpath(path);
54 
55  // Map the POSIX `oflag` access flags.
56 
57  // O_APPEND: Write only appends.
58  //
59  // NOTE: We choose a `write` flag here because emulating `O_APPEND`
60  // requires granting the `FILE_APPEND_DATA` access right, but not
61  // the `FILE_WRITE_DATA` access right, which `GENERIC_WRITE` would
62  // otherwise grant.
63  const DWORD write = (oflag & O_APPEND) ? FILE_APPEND_DATA : GENERIC_WRITE;
64 
65  DWORD access;
66  switch (oflag & (O_RDONLY | O_WRONLY | O_RDWR)) {
67  case O_RDONLY: {
68  access = GENERIC_READ;
69  break;
70  }
71  case O_WRONLY: {
72  access = write;
73  break;
74  }
75  case O_RDWR: {
76  access = GENERIC_READ | write;
77  break;
78  }
79  default: {
80  return Error("Access mode not specified.");
81  }
82  }
83 
84  // Map the POSIX `oflag` creation flags.
85  DWORD create;
86  switch (oflag & (O_CREAT | O_EXCL | O_TRUNC)) {
87  case O_CREAT: {
88  // Create a new file or open an existing file.
89  create = OPEN_ALWAYS;
90  break;
91  }
92  case O_CREAT | O_EXCL:
93  case O_CREAT | O_EXCL | O_TRUNC: {
94  // Create a new file, but fail if it already exists.
95  // Ignore `O_TRUNC` with `O_CREAT | O_EXCL`
96  create = CREATE_NEW;
97  break;
98  }
99  case O_CREAT | O_TRUNC: {
100  // Truncate file if it already exists.
101  create = CREATE_ALWAYS;
102  break;
103  }
104  case O_EXCL:
105  case O_EXCL | O_TRUNC: {
106  return Error("`O_EXCL` is undefined without `O_CREAT`.");
107  }
108  case O_TRUNC: {
109  // Truncate file if it exists, otherwise fail.
110  create = TRUNCATE_EXISTING;
111  break;
112  }
113  default: {
114  // Open file if it exists, otherwise fail.
115  create = OPEN_EXISTING;
116  break;
117  }
118  }
119 
120  const HANDLE handle = ::CreateFileW(
121  longpath.data(),
122  access,
123  // Share all access so we don't lock the file.
124  FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
125  // Disable inheritance by default.
126  nullptr,
127  create,
128  FILE_ATTRIBUTE_NORMAL,
129  // No template file.
130  nullptr);
131 
132  if (handle == INVALID_HANDLE_VALUE) {
133  return WindowsError();
134  }
135 
136  return handle;
137 }
138 
139 } // namespace os {
140 
141 #endif // __STOUT_OS_WINDOWS_OPEN_HPP__
Definition: path.hpp:29
constexpr int O_NONBLOCK
Definition: open.hpp:31
Definition: errorbase.hpp:36
ssize_t write(const int_fd &fd, const void *data, size_t size)
Definition: write.hpp:72
Definition: check.hpp:33
constexpr int O_SYNC
Definition: open.hpp:37
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
Try< bool > access(const std::string &path, int how)
Definition: access.hpp:28
int mode_t
Definition: windows.hpp:177
constexpr int O_CLOEXEC
Definition: open.hpp:41
constexpr Handle HANDLE
Definition: ingress.hpp:37
Try< mode_t > mode(const std::string &path, const FollowSymlink follow=FollowSymlink::FOLLOW_SYMLINK)
Definition: stat.hpp:168
std::wstring longpath(const std::string &path)
Definition: longpath.hpp:38
Try< Nothing > create(const std::string &hierarchy, const std::string &cgroup, bool recursive=false)