Apache Mesos
sendfile.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_POSIX_SENDFILE_HPP__
14 #define __STOUT_OS_POSIX_SENDFILE_HPP__
15 
16 #include <errno.h>
17 
18 #if defined(__linux__) || defined(__sun)
19 #include <sys/sendfile.h>
20 #endif
21 #if defined(__APPLE__) || defined(__FreeBSD__)
22 #include <sys/socket.h>
23 #include <sys/types.h>
24 #include <sys/uio.h>
25 #endif // __APPLE__ || __FreeBSD__
26 
27 #include <stout/os/signals.hpp>
28 #include <stout/unreachable.hpp>
29 
30 #include <stout/error.hpp>
31 #include <stout/try.hpp>
32 
33 namespace os {
34 
35 // Returns the amount of bytes written from the input file
36 // descriptor to the output socket. On error,
37 // `Try<ssize_t, SocketError>` contains the error.
38 // NOTE: The following limitations exist because of the OS X
39 // implementation of sendfile:
40 // 1. s must be a stream oriented socket descriptor.
41 // 2. fd must be a regular file descriptor.
43  int s, int fd, off_t offset, size_t length)
44 {
45 #if defined(__linux__) || defined(__sun)
46  SUPPRESS (SIGPIPE) {
47  // This will set errno to EPIPE if a SIGPIPE occurs.
48  ssize_t sent = ::sendfile(s, fd, &offset, length);
49  if (sent < 0) {
50  return SocketError();
51  }
52 
53  return sent;
54  }
55  UNREACHABLE();
56 #elif defined __APPLE__
57  // On OS X, sendfile does not need to have SIGPIPE suppressed.
58  off_t _length = static_cast<off_t>(length);
59 
60  if (::sendfile(fd, s, offset, &_length, nullptr, 0) < 0) {
61  if (errno == EAGAIN && _length > 0) {
62  return _length;
63  }
64  return SocketError();
65  }
66 
67  return _length;
68 #elif defined __FreeBSD__
69  off_t _length = 0;
70 
71  SUPPRESS (SIGPIPE) {
72  if (::sendfile(fd, s, offset, length, nullptr, &_length, 0) < 0) {
73  if (errno == EAGAIN && length > 0) {
74  return _length;
75  }
76  return SocketError();
77  }
78  }
79 
80  return _length;
81 #endif
82 }
83 
84 } // namespace os {
85 
86 #endif // __STOUT_OS_POSIX_SENDFILE_HPP__
SSIZE_T ssize_t
Definition: windows.hpp:192
Definition: try.hpp:34
ErrnoError SocketError
Definition: error.hpp:33
#define SUPPRESS(signal)
Definition: signals.hpp:26
#define UNREACHABLE()
Definition: unreachable.hpp:22
Try< ssize_t, SocketError > sendfile(int s, int fd, off_t offset, size_t length)
Definition: sendfile.hpp:42
#define SIGPIPE
Definition: windows.hpp:365