]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/core/impl/file_posix.ipp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / beast / core / impl / file_posix.ipp
1 //
2 // Copyright (c) 2015-2016 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 #if ! defined(BOOST_BEAST_NO_POSIX_FADVISE)
14 # if defined(__APPLE__) || (defined(ANDROID) && (__ANDROID_API__ < 21))
15 # define BOOST_BEAST_NO_POSIX_FADVISE
16 # endif
17 #endif
18
19 #if ! defined(BOOST_BEAST_USE_POSIX_FADVISE)
20 # if ! defined(BOOST_BEAST_NO_POSIX_FADVISE)
21 # define BOOST_BEAST_USE_POSIX_FADVISE 1
22 # else
23 # define BOOST_BEAST_USE_POSIX_FADVISE 0
24 # endif
25 #endif
26
27 #include <limits>
28 #include <fcntl.h>
29 #include <sys/types.h>
30 #include <sys/uio.h>
31 #include <sys/stat.h>
32 #include <unistd.h>
33 #include <limits.h>
34
35 namespace boost {
36 namespace beast {
37
38 namespace detail {
39
40 inline
41 int
42 file_posix_close(int fd)
43 {
44 for(;;)
45 {
46 if(! ::close(fd))
47 break;
48 int const ev = errno;
49 if(errno != EINTR)
50 return ev;
51 }
52 return 0;
53 }
54
55 } // detail
56
57 inline
58 file_posix::
59 ~file_posix()
60 {
61 if(fd_ != -1)
62 detail::file_posix_close(fd_);
63 }
64
65 inline
66 file_posix::
67 file_posix(file_posix&& other)
68 : fd_(other.fd_)
69 {
70 other.fd_ = -1;
71 }
72
73 inline
74 file_posix&
75 file_posix::
76 operator=(file_posix&& other)
77 {
78 if(&other == this)
79 return *this;
80 if(fd_ != -1)
81 detail::file_posix_close(fd_);
82 fd_ = other.fd_;
83 other.fd_ = -1;
84 return *this;
85 }
86
87 inline
88 void
89 file_posix::
90 native_handle(native_handle_type fd)
91 {
92 if(fd_ != -1)
93 detail::file_posix_close(fd_);
94 fd_ = fd;
95 }
96
97 inline
98 void
99 file_posix::
100 close(error_code& ec)
101 {
102 if(fd_ != -1)
103 {
104 auto const ev =
105 detail::file_posix_close(fd_);
106 if(ev)
107 ec.assign(ev, generic_category());
108 else
109 ec.assign(0, ec.category());
110 fd_ = -1;
111 }
112 else
113 {
114 ec.assign(0, ec.category());
115 }
116 }
117
118 inline
119 void
120 file_posix::
121 open(char const* path, file_mode mode, error_code& ec)
122 {
123 if(fd_ != -1)
124 {
125 auto const ev =
126 detail::file_posix_close(fd_);
127 if(ev)
128 ec.assign(ev, generic_category());
129 else
130 ec.assign(0, ec.category());
131 fd_ = -1;
132 }
133 int f = 0;
134 #if BOOST_BEAST_USE_POSIX_FADVISE
135 int advise = 0;
136 #endif
137 switch(mode)
138 {
139 default:
140 case file_mode::read:
141 f = O_RDONLY;
142 #if BOOST_BEAST_USE_POSIX_FADVISE
143 advise = POSIX_FADV_RANDOM;
144 #endif
145 break;
146 case file_mode::scan:
147 f = O_RDONLY;
148 #if BOOST_BEAST_USE_POSIX_FADVISE
149 advise = POSIX_FADV_SEQUENTIAL;
150 #endif
151 break;
152
153 case file_mode::write:
154 f = O_RDWR | O_CREAT | O_TRUNC;
155 #if BOOST_BEAST_USE_POSIX_FADVISE
156 advise = POSIX_FADV_RANDOM;
157 #endif
158 break;
159
160 case file_mode::write_new:
161 f = O_RDWR | O_CREAT | O_EXCL;
162 #if BOOST_BEAST_USE_POSIX_FADVISE
163 advise = POSIX_FADV_RANDOM;
164 #endif
165 break;
166
167 case file_mode::write_existing:
168 f = O_RDWR | O_EXCL;
169 #if BOOST_BEAST_USE_POSIX_FADVISE
170 advise = POSIX_FADV_RANDOM;
171 #endif
172 break;
173
174 case file_mode::append:
175 f = O_RDWR | O_CREAT | O_TRUNC;
176 #if BOOST_BEAST_USE_POSIX_FADVISE
177 advise = POSIX_FADV_SEQUENTIAL;
178 #endif
179 break;
180
181 case file_mode::append_new:
182 f = O_RDWR | O_CREAT | O_EXCL;
183 #if BOOST_BEAST_USE_POSIX_FADVISE
184 advise = POSIX_FADV_SEQUENTIAL;
185 #endif
186 break;
187
188 case file_mode::append_existing:
189 f = O_RDWR | O_EXCL;
190 #if BOOST_BEAST_USE_POSIX_FADVISE
191 advise = POSIX_FADV_SEQUENTIAL;
192 #endif
193 break;
194 }
195 for(;;)
196 {
197 fd_ = ::open(path, f, 0644);
198 if(fd_ != -1)
199 break;
200 auto const ev = errno;
201 if(ev != EINTR)
202 {
203 ec.assign(ev, generic_category());
204 return;
205 }
206 }
207 #if BOOST_BEAST_USE_POSIX_FADVISE
208 if(::posix_fadvise(fd_, 0, 0, advise))
209 {
210 auto const ev = errno;
211 detail::file_posix_close(fd_);
212 fd_ = -1;
213 ec.assign(ev, generic_category());
214 return;
215 }
216 #endif
217 ec.assign(0, ec.category());
218 }
219
220 inline
221 std::uint64_t
222 file_posix::
223 size(error_code& ec) const
224 {
225 if(fd_ == -1)
226 {
227 ec.assign(errc::invalid_argument, generic_category());
228 return 0;
229 }
230 struct stat st;
231 if(::fstat(fd_, &st) != 0)
232 {
233 ec.assign(errno, generic_category());
234 return 0;
235 }
236 ec.assign(0, ec.category());
237 return st.st_size;
238 }
239
240 inline
241 std::uint64_t
242 file_posix::
243 pos(error_code& ec) const
244 {
245 if(fd_ == -1)
246 {
247 ec.assign(errc::invalid_argument, generic_category());
248 return 0;
249 }
250 auto const result = ::lseek(fd_, 0, SEEK_CUR);
251 if(result == (off_t)-1)
252 {
253 ec.assign(errno, generic_category());
254 return 0;
255 }
256 ec.assign(0, ec.category());
257 return result;
258 }
259
260 inline
261 void
262 file_posix::
263 seek(std::uint64_t offset, error_code& ec)
264 {
265 if(fd_ == -1)
266 {
267 ec.assign(errc::invalid_argument, generic_category());
268 return;
269 }
270 auto const result = ::lseek(fd_, offset, SEEK_SET);
271 if(result == static_cast<off_t>(-1))
272 {
273 ec.assign(errno, generic_category());
274 return;
275 }
276 ec.assign(0, ec.category());
277 }
278
279 inline
280 std::size_t
281 file_posix::
282 read(void* buffer, std::size_t n, error_code& ec) const
283 {
284 if(fd_ == -1)
285 {
286 ec.assign(errc::invalid_argument, generic_category());
287 return 0;
288 }
289 std::size_t nread = 0;
290 while(n > 0)
291 {
292 auto const amount = static_cast<ssize_t>((std::min)(
293 n, static_cast<std::size_t>(SSIZE_MAX)));
294 auto const result = ::read(fd_, buffer, amount);
295 if(result == -1)
296 {
297 auto const ev = errno;
298 if(ev == EINTR)
299 continue;
300 ec.assign(ev, generic_category());
301 return nread;
302 }
303 if(result == 0)
304 {
305 // short read
306 return nread;
307 }
308 n -= result;
309 nread += result;
310 buffer = reinterpret_cast<char*>(buffer) + result;
311 }
312 return nread;
313 }
314
315 inline
316 std::size_t
317 file_posix::
318 write(void const* buffer, std::size_t n, error_code& ec)
319 {
320 if(fd_ == -1)
321 {
322 ec.assign(errc::invalid_argument, generic_category());
323 return 0;
324 }
325 std::size_t nwritten = 0;
326 while(n > 0)
327 {
328 auto const amount = static_cast<ssize_t>((std::min)(
329 n, static_cast<std::size_t>(SSIZE_MAX)));
330 auto const result = ::write(fd_, buffer, amount);
331 if(result == -1)
332 {
333 auto const ev = errno;
334 if(ev == EINTR)
335 continue;
336 ec.assign(ev, generic_category());
337 return nwritten;
338 }
339 n -= result;
340 nwritten += result;
341 buffer = reinterpret_cast<char const*>(buffer) + result;
342 }
343 return nwritten;
344 }
345
346 } // beast
347 } // boost
348
349 #endif