aboutsummaryrefslogtreecommitdiffstats
path: root/recv.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2019-11-01 22:06:40 +0100
committerMattias Andrée <maandree@kth.se>2019-11-01 22:06:40 +0100
commitc57844b08bced71778f38f2346464c3e0836287c (patch)
treee3733b4c99818ee6c77ed3d4d37becf30f92268f /recv.c
parentUse installed liberror (diff)
downloadliberror-libc-c57844b08bced71778f38f2346464c3e0836287c.tar.gz
liberror-libc-c57844b08bced71778f38f2346464c3e0836287c.tar.bz2
liberror-libc-c57844b08bced71778f38f2346464c3e0836287c.tar.xz
Add some functions and add functions with _failed suffix
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'recv.c')
-rw-r--r--recv.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/recv.c b/recv.c
new file mode 100644
index 0000000..03985ba
--- /dev/null
+++ b/recv.c
@@ -0,0 +1,124 @@
+/* See LICENSE file for copyright and license details. */
+#include "internal.h"
+
+
+void
+liberror_recv_failed(int fd, void *buf, size_t n, int flags, const char *fname)
+{
+ const char *desc;
+ int saved_errno, val;
+ struct timeval tv;
+ switch (errno) {
+#if defined(EAGAIN)
+ case EAGAIN:
+#endif
+#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || EAGAIN != EWOULDBLOCK)
+ case EWOULDBLOCK:
+#endif
+#if defined(EAGAIN) || defined(EWOULDBLOCK)
+ saved_errno = errno;
+ if (flags & MSG_OOB) {
+ desc = "Attempting to receive in nonblocking mode but the operation would block, "
+ "attempting to receive with time out and the operation timed out "
+ "or the socket does not support blocking to await out-of-band data";
+ if (flags & MSG_DONTWAIT) {
+ msg_oob_nonblocking:
+ desc = "Attempting to receive in nonblocking mode but the operation would block or"
+ " the socket does not support blocking to await out-of-band data";
+ } else if ((val = fcntl(fd, F_GETFL)) < 0) {
+ /* Do nothing */
+ } else if (val & O_NONBLOCK) {
+ goto msg_oob_nonblocking;
+ } else if (getsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, &(socklen_t){(socklen_t)sizeof(tv)}) ||
+ tv.tv_sec || tv.tv_usec) {
+ desc = "Attempting to receive with time out and the operation timed out or"
+ " the socket does not support blocking to await out-of-band data";
+ } else {
+ desc = "The socket does not support blocking to await out-of-band data";
+ }
+ } else {
+ desc = "Attempting to receive in nonblocking mode but the operation would block "
+ "or attempting to receive with time out and the operation timed out";
+ if (flags & MSG_DONTWAIT) {
+ no_msg_oob_nonblocking:
+ desc = "Attempting to receive in nonblocking mode but the operation would block";
+ } else if ((val = fcntl(fd, F_GETFL)) < 0) {
+ /* Do nothing */
+ } else if (val & O_NONBLOCK) {
+ goto no_msg_oob_nonblocking;
+ } else if (!getsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, &(socklen_t){(socklen_t)sizeof(tv)}) &&
+ !tv.tv_sec && !tv.tv_usec) {
+ desc = "Attempting to receive with time out and the operation timed out";
+ }
+ }
+ errno = saved_errno;
+ break;
+#endif
+ case EBADF:
+ if (fd < 0)
+ desc = "Negative file descriptor number specified";
+ else
+ desc = "Unassigned file descriptor number specified";
+ break;
+ case ECONNREFUSED:
+ desc = "The remote host refused to allow the network connection";
+ break;
+ case ECONNRESET:
+ desc = "The connection was forcibly closed by a peer";
+ break;
+ case EFAULT:
+ desc = "Invalid user space address specified in the second argument";
+ break;
+ case EINTR:
+ desc = "System call was interrupted by a signal or machine suspension";
+ break;
+ case EINVAL:
+ if (fd < 0)
+ desc = "Negative file descriptor number specified";
+ else if ((flags & ~(MSG_PEEK | MSG_WAITALL)) == MSG_OOB)
+ desc = "No out-of-band data is available";
+ else if (flags & MSG_OOB)
+ desc = "No out-of-band data is available or non-existing flag is specified";
+ else
+ desc = "Non-existing flag is specified";
+ break;
+ case EIO:
+ desc = "An I/O error occurred while reading from or writing to the file system";
+ break;
+ case ENOBUFS:
+ desc = "Insufficient resource available in the system to perform the operation";
+ break;
+ case ENOMEM:
+ desc = "Out of memory";
+ break;
+ case ENOTCONN:
+ desc = "The socket is not connected";
+ break;
+ case ENOTSOCK:
+ desc = "The file descriptor refer to a non-socket file";
+ break;
+ case EOPNOTSUPP:
+ desc = "A flag that is not supported for the socket protocol is specified";
+ break;
+ case ETIMEDOUT:
+ desc = "The connection timed out during connection establishment, "
+ "or due to a transmission timeout on active connection";
+ break;
+ default:
+ desc = "";
+ break;
+ }
+ liberror_libc_set_error_one_file(desc, "recv", "Socket file", fd, fname);
+}
+
+
+ssize_t
+liberror_recv(int fd, void *buf, size_t n, int flags, const char *fname)
+{
+ ssize_t r = recv(fd, buf, n, flags);
+ if (r >= 0)
+ return r;
+ liberror_save_backtrace(NULL);
+ liberror_recv_failed(fd, buf, n, flags, fname);
+ return -1;
+}