]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/core/impl/file_posix.ipp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / beast / core / impl / file_posix.ipp
1 //
2 // Copyright (c) 2015-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9
10 #ifndef BOOST_BEAST_CORE_IMPL_FILE_POSIX_IPP
11 #define BOOST_BEAST_CORE_IMPL_FILE_POSIX_IPP
12
13 #include <boost/beast/core/file_posix.hpp>
14
15 #if BOOST_BEAST_USE_POSIX_FILE
16
17 #include <boost/core/exchange.hpp>
18 #include <limits>
19 #include <fcntl.h>
20 #include <sys/types.h>
21 #include <sys/uio.h>
22 #include <sys/stat.h>
23 #include <unistd.h>
24 #include <limits.h>
25
26 #if ! defined(BOOST_BEAST_NO_POSIX_FADVISE)
27 # if defined(__APPLE__) || (defined(__ANDROID__) && (__ANDROID_API__ < 21))
28 # define BOOST_BEAST_NO_POSIX_FADVISE
29 # endif
30 #endif
31
32 #if ! defined(BOOST_BEAST_USE_POSIX_FADVISE)
33 # if ! defined(BOOST_BEAST_NO_POSIX_FADVISE)
34 # define BOOST_BEAST_USE_POSIX_FADVISE 1
35 # else
36 # define BOOST_BEAST_USE_POSIX_FADVISE 0
37 # endif
38 #endif
39
40 namespace boost {
41 namespace beast {
42
43 int
44 file_posix::
45 native_close(native_handle_type& fd)
46 {
47 /* https://github.com/boostorg/beast/issues/1445
48
49 This function is tuned for Linux / Mac OS:
50
51 * only calls close() once
52 * returns the error directly to the caller
53 * does not loop on EINTR
54
55 If this is incorrect for the platform, then the
56 caller will need to implement their own type
57 meeting the File requirements and use the correct
58 behavior.
59
60 See:
61 http://man7.org/linux/man-pages/man2/close.2.html
62 */
63 int ev = 0;
64 if(fd != -1)
65 {
66 if(::close(fd) != 0)
67 ev = errno;
68 fd = -1;
69 }
70 return ev;
71 }
72
73 file_posix::
74 ~file_posix()
75 {
76 native_close(fd_);
77 }
78
79 file_posix::
80 file_posix(file_posix&& other)
81 : fd_(boost::exchange(other.fd_, -1))
82 {
83 }
84
85 file_posix&
86 file_posix::
87 operator=(file_posix&& other)
88 {
89 if(&other == this)
90 return *this;
91 native_close(fd_);
92 fd_ = other.fd_;
93 other.fd_ = -1;
94 return *this;
95 }
96
97 void
98 file_posix::
99 native_handle(native_handle_type fd)
100 {
101 native_close(fd_);
102 fd_ = fd;
103 }
104
105 void
106 file_posix::
107 close(error_code& ec)
108 {
109 auto const ev = native_close(fd_);
110 if(ev)
111 ec.assign(ev, system_category());
112 else
113 ec = {};
114 }
115
116 void
117 file_posix::
118 open(char const* path, file_mode mode, error_code& ec)
119 {
120 auto const ev = native_close(fd_);
121 if(ev)
122 ec.assign(ev, system_category());
123 else
124 ec = {};
125
126 int f = 0;
127 #if BOOST_BEAST_USE_POSIX_FADVISE
128 int advise = 0;
129 #endif
130 switch(mode)
131 {
132 default:
133 case file_mode::read:
134 f = O_RDONLY;
135 #if BOOST_BEAST_USE_POSIX_FADVISE
136 advise = POSIX_FADV_RANDOM;
137 #endif
138 break;
139 case file_mode::scan:
140 f = O_RDONLY;
141 #if BOOST_BEAST_USE_POSIX_FADVISE
142 advise = POSIX_FADV_SEQUENTIAL;
143 #endif
144 break;
145
146 case file_mode::write:
147 f = O_RDWR | O_CREAT | O_TRUNC;
148 #if BOOST_BEAST_USE_POSIX_FADVISE
149 advise = POSIX_FADV_RANDOM;
150 #endif
151 break;
152
153 case file_mode::write_new:
154 f = O_RDWR | O_CREAT | O_EXCL;
155 #if BOOST_BEAST_USE_POSIX_FADVISE
156 advise = POSIX_FADV_RANDOM;
157 #endif
158 break;
159
160 case file_mode::write_existing:
161 f = O_RDWR | O_EXCL;
162 #if BOOST_BEAST_USE_POSIX_FADVISE
163 advise = POSIX_FADV_RANDOM;
164 #endif
165 break;
166
167 case file_mode::append:
168 f = O_WRONLY | O_CREAT | O_APPEND;
169 #if BOOST_BEAST_USE_POSIX_FADVISE
170 advise = POSIX_FADV_SEQUENTIAL;
171 #endif
172 break;
173
174 case file_mode::append_existing:
175 f = O_WRONLY | O_APPEND;
176 #if BOOST_BEAST_USE_POSIX_FADVISE
177 advise = POSIX_FADV_SEQUENTIAL;
178 #endif
179 break;
180 }
181 for(;;)
182 {
183 fd_ = ::open(path, f, 0644);
184 if(fd_ != -1)
185 break;
186 auto const ev = errno;
187 if(ev != EINTR)
188 {
189 ec.assign(ev, system_category());
190 return;
191 }
192 }
193 #if BOOST_BEAST_USE_POSIX_FADVISE
194 if(::posix_fadvise(fd_, 0, 0, advise))
195 {
196 auto const ev = errno;
197 native_close(fd_);
198 ec.assign(ev, system_category());
199 return;
200 }
201 #endif
202 ec = {};
203 }
204
205 std::uint64_t
206 file_posix::
207 size(error_code& ec) const
208 {
209 if(fd_ == -1)
210 {
211 ec = make_error_code(errc::bad_file_descriptor);
212 return 0;
213 }
214 struct stat st;
215 if(::fstat(fd_, &st) != 0)
216 {
217 ec.assign(errno, system_category());
218 return 0;
219 }
220 ec = {};
221 return st.st_size;
222 }
223
224 std::uint64_t
225 file_posix::
226 pos(error_code& ec) const
227 {
228 if(fd_ == -1)
229 {
230 ec = make_error_code(errc::bad_file_descriptor);
231 return 0;
232 }
233 auto const result = ::lseek(fd_, 0, SEEK_CUR);
234 if(result == (off_t)-1)
235 {
236 ec.assign(errno, system_category());
237 return 0;
238 }
239 ec = {};
240 return result;
241 }
242
243 void
244 file_posix::
245 seek(std::uint64_t offset, error_code& ec)
246 {
247 if(fd_ == -1)
248 {
249 ec = make_error_code(errc::bad_file_descriptor);
250 return;
251 }
252 auto const result = ::lseek(fd_, offset, SEEK_SET);
253 if(result == static_cast<off_t>(-1))
254 {
255 ec.assign(errno, system_category());
256 return;
257 }
258 ec = {};
259 }
260
261 std::size_t
262 file_posix::
263 read(void* buffer, std::size_t n, error_code& ec) const
264 {
265 if(fd_ == -1)
266 {
267 ec = make_error_code(errc::bad_file_descriptor);
268 return 0;
269 }
270 std::size_t nread = 0;
271 while(n > 0)
272 {
273 // <limits> not required to define SSIZE_MAX so we avoid it
274 constexpr auto ssmax =
275 static_cast<std::size_t>((std::numeric_limits<
276 decltype(::read(fd_, buffer, n))>::max)());
277 auto const amount = (std::min)(
278 n, ssmax);
279 auto const result = ::read(fd_, buffer, amount);
280 if(result == -1)
281 {
282 auto const ev = errno;
283 if(ev == EINTR)
284 continue;
285 ec.assign(ev, system_category());
286 return nread;
287 }
288 if(result == 0)
289 {
290 // short read
291 return nread;
292 }
293 n -= result;
294 nread += result;
295 buffer = static_cast<char*>(buffer) + result;
296 }
297 return nread;
298 }
299
300 std::size_t
301 file_posix::
302 write(void const* buffer, std::size_t n, error_code& ec)
303 {
304 if(fd_ == -1)
305 {
306 ec = make_error_code(errc::bad_file_descriptor);
307 return 0;
308 }
309 std::size_t nwritten = 0;
310 while(n > 0)
311 {
312 // <limits> not required to define SSIZE_MAX so we avoid it
313 constexpr auto ssmax =
314 static_cast<std::size_t>((std::numeric_limits<
315 decltype(::write(fd_, buffer, n))>::max)());
316 auto const amount = (std::min)(
317 n, ssmax);
318 auto const result = ::write(fd_, buffer, amount);
319 if(result == -1)
320 {
321 auto const ev = errno;
322 if(ev == EINTR)
323 continue;
324 ec.assign(ev, system_category());
325 return nwritten;
326 }
327 n -= result;
328 nwritten += result;
329 buffer = static_cast<char const*>(buffer) + result;
330 }
331 return nwritten;
332 }
333
334 } // beast
335 } // boost
336
337 #endif
338
339 #endif