Apache Mesos
write.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_WRITE_HPP__
14 #define __STOUT_OS_WRITE_HPP__
15 
16 #include <cstring>
17 
18 #include <stout/error.hpp>
19 #include <stout/nothing.hpp>
20 #include <stout/try.hpp>
21 
22 #include <stout/os/close.hpp>
23 #include <stout/os/int_fd.hpp>
24 #include <stout/os/open.hpp>
25 #include <stout/os/socket.hpp>
26 
27 #ifdef __WINDOWS__
29 #else
30 #include <stout/os/posix/write.hpp>
31 #endif // __WINDOWS__
32 
33 
34 namespace os {
35 
36 namespace signal_safe {
37 
38 inline ssize_t write_impl(int_fd fd, const char* buffer, size_t count)
39 {
40  size_t offset = 0;
41 
42  while (offset < count) {
43  ssize_t length = os::write(fd, buffer + offset, count - offset);
44 
45  if (length < 0) {
46 #ifdef __WINDOWS__
47  // NOTE: There is no actual difference between `WSAGetLastError` and
48  // `GetLastError`, the former is an alias for the latter. So we can
49  // simply use the former here for both `HANDLE` and `SOCKET` types of
50  // `int_fd`. See MESOS-8764.
51  int error = ::GetLastError();
52 #else
53  int error = errno;
54 #endif // __WINDOWS__
55 
56  // TODO(benh): Handle a non-blocking fd? (EAGAIN, EWOULDBLOCK).
57  if (net::is_restartable_error(error)) {
58  continue;
59  }
60  return -1;
61  }
62 
63  offset += length;
64  }
65 
66  return offset;
67 }
68 
69 
70 inline ssize_t write(int_fd fd, const char* message)
71 {
72  // `strlen` declared as async-signal safe in POSIX.1-2016 standard.
73  return write_impl(fd, message, std::strlen(message));
74 }
75 
76 
77 inline ssize_t write(int_fd fd, const std::string& message)
78 {
79  return write_impl(fd, message.data(), message.length());
80 }
81 
82 
83 template <typename T, typename... Args>
84 inline ssize_t write(int_fd fd, const T& message, Args... args)
85 {
86  ssize_t result = write(fd, message);
87  if (result < 0) {
88  return result;
89  }
90 
91  return write(fd, args...);
92 }
93 
94 } // namespace signal_safe {
95 
96 
97 // Write out the string to the file at the current fd position.
98 inline Try<Nothing> write(int_fd fd, const std::string& message)
99 {
100  ssize_t result = signal_safe::write(fd, message);
101  if (result < 0) {
102 #ifdef __WINDOWS__
103  return WindowsError();
104 #else
105  return ErrnoError();
106 #endif // __WINDOWS__
107  }
108 
109  return Nothing();
110 }
111 
112 
113 // A wrapper function that wraps the above write() with
114 // open and closing the file.
115 inline Try<Nothing> write(const std::string& path, const std::string& message)
116 {
117  Try<int_fd> fd = os::open(
118  path,
119  O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC,
121 
122  if (fd.isError()) {
123  return Error(fd.error());
124  }
125 
126  Try<Nothing> result = write(fd.get(), message);
127 
128  // We ignore the return value of close(). This is because users
129  // calling this function are interested in the return value of
130  // write(). Also an unsuccessful close() doesn't affect the write.
131  os::close(fd.get());
132 
133  return result;
134 }
135 
136 
137 // NOTE: This overload is necessary to disambiguate between arguments
138 // of type `HANDLE` (`typedef void*`) and `char*` on Windows.
139 inline Try<Nothing> write(const char* path, const std::string& message)
140 {
141  return write(std::string(path), message);
142 }
143 
144 } // namespace os {
145 
146 
147 #endif // __STOUT_OS_WRITE_HPP__
SSIZE_T ssize_t
Definition: windows.hpp:186
Definition: path.hpp:26
Definition: nothing.hpp:16
Definition: errorbase.hpp:36
const mode_t S_IRGRP
Definition: windows.hpp:313
T & get()&
Definition: try.hpp:73
ssize_t write(const int_fd &fd, const void *data, size_t size)
Definition: write.hpp:72
Definition: check.hpp:33
const mode_t S_IWUSR
Definition: windows.hpp:306
Try< int_fd > open(const std::string &path, int oflag, mode_t mode=0)
Definition: open.hpp:35
Definition: error.hpp:108
Definition: errorbase.hpp:50
Definition: posix_signalhandler.hpp:23
const mode_t S_IRUSR
Definition: windows.hpp:305
bool is_restartable_error(int error)
Definition: socket.hpp:56
constexpr int O_CLOEXEC
Definition: open.hpp:41
Try< Nothing > close(int fd)
Definition: close.hpp:24
static Try error(const E &e)
Definition: try.hpp:42
ssize_t write_impl(int_fd fd, const char *buffer, size_t count)
Definition: write.hpp:38
bool isError() const
Definition: try.hpp:71
std::string error(const std::string &msg, uint32_t code)
int int_fd
Definition: int_fd.hpp:35
const mode_t S_IROTH
Definition: windows.hpp:321
ssize_t write(int_fd fd, const char *message)
Definition: write.hpp:70