diff options
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | abs.c | 14 | ||||
-rw-r--r-- | calloc.c | 24 | ||||
-rw-r--r-- | chdir.c | 54 | ||||
-rw-r--r-- | imaxabs.c | 14 | ||||
-rw-r--r-- | internal.h | 3 | ||||
-rw-r--r-- | labs.c | 14 | ||||
-rw-r--r-- | liberror-libc.h | 28 | ||||
-rw-r--r-- | llabs.c | 14 | ||||
-rw-r--r-- | malloc.c | 23 | ||||
-rw-r--r-- | pipe.c | 28 | ||||
-rw-r--r-- | putenv.c | 20 | ||||
-rw-r--r-- | raise.c | 24 | ||||
-rw-r--r-- | realloc.c | 24 | ||||
-rw-r--r-- | recv.c | 124 | ||||
-rw-r--r-- | send.c | 157 | ||||
-rw-r--r-- | shutdown.c | 30 | ||||
-rw-r--r-- | sockatmark.c | 37 | ||||
-rw-r--r-- | unsetenv.c | 27 |
19 files changed, 622 insertions, 45 deletions
@@ -19,14 +19,22 @@ HDR =\ OBJ =\ abs.o\ + calloc.o\ + chdir.o\ imaxabs.o\ labs.o\ llabs.o\ + malloc.o\ pipe.o\ putenv.o\ + raise.o\ + realloc.o\ + recv.o\ + send.o\ set_error_one_file.o\ setenv.o\ shutdown.o\ + sockatmark.o\ unsetenv.o LOBJ = $(OBJ:.o=.lo) @@ -2,6 +2,16 @@ #include "internal.h" +void +liberror_abs_failed(int i) +{ + liberror_set_error_errno("The absolute value of largest negative integer " + "cannot be represented as a signed integer", + "abs", EOVERFLOW); + (void) i; +} + + int liberror_abs(int i) { @@ -11,9 +21,7 @@ liberror_abs(int i) if (i != INT_MIN) return abs(i); liberror_save_backtrace(NULL); - liberror_set_error_errno("The absolute value of largest negative integer " - "cannot be represented as a signed integer", - "abs", EOVERFLOW); + liberror_abs_failed(i); return i; #endif } diff --git a/calloc.c b/calloc.c new file mode 100644 index 0000000..86a939c --- /dev/null +++ b/calloc.c @@ -0,0 +1,24 @@ +/* See LICENSE file for copyright and license details. */ +#include "internal.h" + + +void +liberror_calloc_failed(size_t n, size_t m) +{ + liberror_set_error_errno("Out of memory", "calloc", ENOMEM); + errno = ENOMEM; + (void) n; + (void) m; +} + + +void * +liberror_calloc(size_t n, size_t m) +{ + void *ret = calloc(n, m); + if (ret || !n || !m) + return ret; + liberror_save_backtrace(NULL); + liberror_calloc_failed(n, m); + return NULL; +} @@ -0,0 +1,54 @@ +/* See LICENSE file for copyright and license details. */ +#include "internal.h" + + +void +liberror_chdir_failed(const char *path) +{ + const char *desc; + switch (errno) { + case EFAULT: + if (!path) + desc = "Path parameter is NULL"; + else + desc = "Path parameter is an invalid pointer"; + break; + case EACCES: + desc = "Search permission is denied for any component of the path"; + break; + case ELOOP: + desc = "A symbolic link chain in the path too long or circular"; + break; + case ENAMETOOLONG: + desc = "The canonical path or intermediate result in pathname resolution is too long"; + break; + case ENOENT: + if (!*path) + desc = "Path parameter is the empty string"; + else + desc = "A component of path does not name an existing directory"; + break; + case ENOTDIR: + desc = "A component of path is not a directory"; + break; + case ENOMEM: + desc = "Insufficient kernel memory was available"; + break; + case EIO: + default: + desc = ""; + break; + } + liberror_libc_set_error_one_file(desc, "chdir", "Directory file", -1, path); +} + + +int +liberror_chdir(const char *path) +{ + if (!chdir(path)) + return 0; + liberror_save_backtrace(NULL); + liberror_chdir_failed(path); + return -1; +} @@ -2,6 +2,16 @@ #include "internal.h" +void +liberror_imaxabs_failed(intmax_t i) +{ + liberror_set_error_errno("The absolute value of largest negative integer " + "cannot be represented as a signed integer", + "imaxabs", EOVERFLOW); + (void) i; +} + + intmax_t liberror_imaxabs(intmax_t i) { @@ -11,9 +21,7 @@ liberror_imaxabs(intmax_t i) if (i != INTMAX_MIN) return imaxabs(i); liberror_save_backtrace(NULL); - liberror_set_error_errno("The absolute value of largest negative integer " - "cannot be represented as a signed integer", - "imaxabs", EOVERFLOW); + liberror_imaxabs_failed(i); return i; #endif } @@ -1,9 +1,12 @@ /* See LICENSE file for copyright and license details. */ #include "liberror-libc.h" +#include <netinet/in.h> #include <sys/socket.h> #include <errno.h> +#include <fcntl.h> #include <inttypes.h> +#include <signal.h> #include <stdlib.h> #include <string.h> #include <unistd.h> @@ -2,6 +2,16 @@ #include "internal.h" +void +liberror_labs_failed(long int i) +{ + liberror_set_error_errno("The absolute value of largest negative integer " + "cannot be represented as a signed integer", + "labs", EOVERFLOW); + (void) i; +} + + long int liberror_labs(long int i) { @@ -11,9 +21,7 @@ liberror_labs(long int i) if (i != LONG_MIN) return labs(i); liberror_save_backtrace(NULL); - liberror_set_error_errno("The absolute value of largest negative integer " - "cannot be represented as a signed integer", - "labs", EOVERFLOW); + liberror_labs_failed(i); return i; #endif } diff --git a/liberror-libc.h b/liberror-libc.h index fd67f3b..9a67245 100644 --- a/liberror-libc.h +++ b/liberror-libc.h @@ -2,18 +2,46 @@ #ifndef LIBERROR_LIBC_H #define LIBERROR_LIBC_H +#include <stddef.h> #include <stdint.h> +#include <unistd.h> int liberror_abs(int); +void liberror_abs_failed(int); +/* void *liberror_aligned_alloc(size_t, size_t); TODO */ +void *liberror_calloc(size_t, size_t); +void liberror_calloc_failed(size_t, size_t); +int liberror_chdir(const char *); +void liberror_chdir_failed(const char *); intmax_t liberror_imaxabs(intmax_t); +void liberror_imaxabs_failed(intmax_t); long int liberror_labs(long int); +void liberror_labs_failed(long int); long long int liberror_llabs(long long int); +void liberror_llabs_failed(long long int); +void *liberror_malloc(size_t); +void liberror_malloc_failed(size_t); int liberror_pipe(int[2]); +void liberror_pipe_failed(int[2]); int liberror_putenv(char *); +void liberror_putenv_failed(char *); +int liberror_raise(int); +void liberror_raise_failed(int); +void *liberror_realloc(void *, size_t); +void liberror_realloc_failed(void *, size_t); +ssize_t liberror_recv(int, void *, size_t, int, const char *); +void liberror_recv_failed(int, void *, size_t, int, const char *); +/* void *liberror_posix_memalign(void **, size_t, size_t); TODO */ +ssize_t liberror_send(int, const void *, size_t, int, const char *); +void liberror_send_failed(int, const void *, size_t, int, const char *); int liberror_setenv(const char *, const char *, int); int liberror_shutdown(int, int, const char *); +void liberror_shutdown_failed(int, int, const char *); +int liberror_sockatmark(int, const char *); +void liberror_sockatmark_failed(int, const char *); int liberror_unsetenv(const char *); +void liberror_unsetenv_failed(const char *); #endif @@ -2,6 +2,16 @@ #include "internal.h" +void +liberror_llabs_failed(long long int i) +{ + liberror_set_error_errno("The absolute value of largest negative integer " + "cannot be represented as a signed integer", + "llabs", EOVERFLOW); + (void) i; +} + + long long int liberror_llabs(long long int i) { @@ -11,9 +21,7 @@ liberror_llabs(long long int i) if (i != LLONG_MIN) return llabs(i); liberror_save_backtrace(NULL); - liberror_set_error_errno("The absolute value of largest negative integer " - "cannot be represented as a signed integer", - "llabs", EOVERFLOW); + liberror_llabs(i); return i; #endif } diff --git a/malloc.c b/malloc.c new file mode 100644 index 0000000..4d40572 --- /dev/null +++ b/malloc.c @@ -0,0 +1,23 @@ +/* See LICENSE file for copyright and license details. */ +#include "internal.h" + + +void +liberror_malloc_failed(size_t n) +{ + liberror_set_error_errno("Out of memory", "malloc", ENOMEM); + errno = ENOMEM; + (void) n; +} + + +void * +liberror_malloc(size_t n) +{ + void *ret = malloc(n); + if (ret || !n) + return ret; + liberror_save_backtrace(NULL); + liberror_malloc_failed(n); + return NULL; +} @@ -2,19 +2,16 @@ #include "internal.h" -int -liberror_pipe(int fds[2]) +void +liberror_pipe_failed(int fds[2]) { const char *desc; - if (!fds) { - desc = "Output parameter is NULL"; - goto error; - } - if (!pipe(fds)) - return 0; switch (errno) { case EFAULT: - desc = "Output parameter is an invalid pointer"; + if (!fds) + desc = "Output parameter is NULL"; + else + desc = "Output parameter is an invalid pointer"; break; case EMFILE: desc = "The process have too many file descriptors open"; @@ -26,8 +23,17 @@ liberror_pipe(int fds[2]) desc = ""; break; } -error: - liberror_save_backtrace(NULL); liberror_set_error_errno(desc, "pipe", errno); + (void) fds; +} + + +int +liberror_pipe(int fds[2]) +{ + if (!pipe(fds)) + return 0; + liberror_save_backtrace(NULL); + liberror_pipe_failed(fds); return -1; } @@ -2,6 +2,26 @@ #include "internal.h" +void +liberror_putenv_failed(char *string) +{ + const char *desc; + if (!string) { + errno = EINVAL; + desc = "Environment string is NULL"; + } else if (*string == '=') { + errno = EINVAL; + desc = "Environment variable name is the empty string"; + } else if (!strchr(string, '=')) { + errno = EINVAL; + desc = "Environment does not contain an '=' symbol"; + } else { + desc = ""; + } + liberror_set_error_errno(desc, "putenv", errno); +} + + int liberror_putenv(char *string) { @@ -0,0 +1,24 @@ +/* See LICENSE file for copyright and license details. */ +#include "internal.h" + + +void +liberror_raise_failed(int sig) +{ + const char *desc = ""; + if (errno == EINVAL) + desc = "Invalid signal number"; + liberror_set_error_errno(desc, "raise", errno); + (void) sig; +} + + +int +liberror_raise(int sig) +{ + if (!raise(sig)) + return 0; + liberror_save_backtrace(NULL); + liberror_raise_failed(sig); + return -1; +} diff --git a/realloc.c b/realloc.c new file mode 100644 index 0000000..a029221 --- /dev/null +++ b/realloc.c @@ -0,0 +1,24 @@ +/* See LICENSE file for copyright and license details. */ +#include "internal.h" + + +void +liberror_realloc_failed(void *ptr, size_t n) +{ + liberror_set_error_errno("Out of memory", "realloc", ENOMEM); + errno = ENOMEM; + (void) ptr; + (void) n; +} + + +void * +liberror_realloc(void *ptr, size_t n) +{ + void *ret = realloc(ptr, n); + if (ret || !n) + return ret; + liberror_save_backtrace(NULL); + liberror_realloc_failed(ptr, n); + return NULL; +} @@ -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; +} @@ -0,0 +1,157 @@ +/* See LICENSE file for copyright and license details. */ +#include "internal.h" + + +void +liberror_send_failed(int fd, const void *buf, size_t n, int flags, const char *fname) +{ + const char *desc; + int saved_errno, val; + struct sockaddr_storage addr; + socklen_t len = 0; + switch (errno) { + case EACCES: + desc = "The calling process does not have appropriate privileges"; + saved_errno = errno; + if (getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &val, &(socklen_t){(socklen_t)sizeof(val)})) { + /* Do nothing */ + } else if (val == PF_LOCAL) { + desc = "Write or search permission to the destination socket file is denied"; + } else if (val != PF_INET && val != PF_INET6) { + /* Do nothing */ + } else if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &val, &(socklen_t){(socklen_t)sizeof(val)})) { + /* Do nothing */ + } else if (val != SOCK_DGRAM) { + /* Do nothing */ + } else if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &val, &(socklen_t){(socklen_t)sizeof(val)})) { + /* Do nothing */ + } else if (val == IPPROTO_UDP) { + desc = "An attempt was made to send to a network/broadcast address as though it was a unicast address"; + } + errno = saved_errno; + break; +#if defined(EAGAIN) + case EAGAIN: +#endif +#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || EAGAIN != EWOULDBLOCK) + case EWOULDBLOCK: +#endif +#if defined(EAGAIN) || defined(EWOULDBLOCK) + desc = "Attempting to send in nonblocking mode but the operation would block " + "or the socket is unbound and all ephemeral ports are currently in used"; +# if defined(EAGAIN) +# if defined(EWOULDBLOCK) && (EAGAIN != EWOULDBLOCK) + if (errno == EAGAIN) { +# endif + saved_errno = errno; + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &val, &(socklen_t){(socklen_t)sizeof(val)})) { + /* Do nothing */ + } else if (val != SOCK_DGRAM) { + goto first_case_in_eagain; + } else if (getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &val, &(socklen_t){(socklen_t)sizeof(val)})) { + /* Do nothing */ + } else if (val != PF_INET && val != PF_INET6) { + goto first_case_in_eagain; + } else if (len = 0, getsockname(fd, (void *)&addr, &len)) { + /* Do nothing */ + } else if ((len && addr.ss_family == AF_INET && ((struct sockaddr_in *)&addr)->sin_port) || + (len && addr.ss_family == AF_INET6 && ((struct sockaddr_in6 *)&addr)->sin6_port)) { + first_case_in_eagain: + desc = "Attempting to send in nonblocking mode but the operation would block"; + } + errno = saved_errno; +# if defined(EWOULDBLOCK) && (EAGAIN != EWOULDBLOCK) + } else { + goto first_case_in_eagain: + } +# endif +# endif + break; +#endif + case EALREADY: + desc = "Another Fast Open is already in progress"; + break; + case EBADF: + if (fd < 0) + desc = "Negative file descriptor number specified"; + else + desc = "Unassigned file descriptor number specified"; + break; + case ECONNRESET: + desc = "The peer has closed the connection without reading all received messages"; + break; + case EDESTADDRREQ: + desc = "The no peer address is set"; + 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 + 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 EISCONN: + desc = "The recipient is specified but the socket is already connected"; + break; + case EMSGSIZE: + desc = "Message is to large to be sent atomically as required by the socket type"; + break; + case ENETDOWN: + desc = "All local network interfaces that can be used to reach the destination are down"; + break; + case ENETUNREACH: + desc = "No route to the network it present"; + 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 EPIPE: + desc = "The socket is shut down for writing or is no longer connected"; + saved_errno = errno; + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &val, &(socklen_t){(socklen_t)sizeof(val)})) { + /* Do nothing */ + } else if (val == SOCK_DGRAM) { + desc = "The socket is shut down"; + } else if (getpeername(fd, (void *)&addr, &len) && errno == ENOTCONN) { + desc = "The socket is no longer connected"; + } + errno = saved_errno; + break; + default: + desc = ""; + break; + } + liberror_libc_set_error_one_file(desc, "send", "Socket file", fd, fname); +} + + +ssize_t +liberror_send(int fd, const void *buf, size_t n, int flags, const char *fname) +{ + ssize_t r = send(fd, buf, n, flags); + if (r >= 0) + return r; + liberror_save_backtrace(NULL); + liberror_send_failed(fd, buf, n, flags, fname); + return -1; +} @@ -2,33 +2,43 @@ #include "internal.h" -int -liberror_shutdown(int fd, int how, const char *fname) +void +liberror_shutdown_failed(int fd, int how, const char *fname) { const char *desc; - if (!shutdown(fd, how)) - return 0; switch (errno) { case EBADF: - desc = fd < 0 ? "Negative file descriptor number specified" : "Unassigned file descriptor number specified"; + if (fd < 0) + desc = "Negative file descriptor number specified"; + else + desc = "Unassigned file descriptor number specified"; break; case EINVAL: desc = "Invalid value of second parameter"; break; + case ENOBUFS: + desc = "Insufficient resource available in the system to perform the operation"; + break; case ENOTCONN: desc = "The socket is not connected"; break; case ENOTSOCK: - desc = "The specified file is not a socket"; - break; - case ENOBUFS: - desc = "Insufficient resource available in the system to perform the operation"; + desc = "The file descriptor refer to a non-socket file"; break; default: desc = ""; break; } - liberror_save_backtrace(NULL); liberror_libc_set_error_one_file(desc, "shutdown", "Socket file", fd, fname); +} + + +int +liberror_shutdown(int fd, int how, const char *fname) +{ + if (!shutdown(fd, how)) + return 0; + liberror_save_backtrace(NULL); + liberror_shutdown_failed(fd, how, fname); return -1; } diff --git a/sockatmark.c b/sockatmark.c new file mode 100644 index 0000000..aa5a20e --- /dev/null +++ b/sockatmark.c @@ -0,0 +1,37 @@ +/* See LICENSE file for copyright and license details. */ +#include "internal.h" + + +void +liberror_sockatmark_failed(int fd, const char *fname) +{ + const char *desc; + switch (errno) { + case EBADF: + if (fd < 0) + desc = "Negative file descriptor number specified"; + else + desc = "Unassigned file descriptor number specified"; + break; + case ENOTSOCK: + case ENOTTY: + case EINVAL: + desc = "Operation not supported by specified file"; + break; + default: + desc = ""; + break; + } + liberror_libc_set_error_one_file(desc, "sockatmark", "Socket file", fd, fname); +} + + +int +liberror_sockatmark(int fd, const char *fname) +{ + if (!sockatmark(fd)) + return 0; + liberror_save_backtrace(NULL); + liberror_sockatmark_failed(fd, fname); + return -1; +} @@ -2,23 +2,26 @@ #include "internal.h" -int -liberror_unsetenv(const char *name) +void +liberror_unsetenv_failed(const char *name) { const char *desc = ""; - if (!name) { - errno = EINVAL; + if (!name) desc = "Environment variable name is NULL"; - goto error; - } else if (!unsetenv(name)) { - return 0; - } else if (!*name) { + else if (!*name) desc = "Environment variable name is the empty string"; - } else if (errno == EINVAL) { + else if (errno == EINVAL) desc = "Environment variable name contains the '=' character"; - } -error: - liberror_save_backtrace(NULL); liberror_set_error_errno(desc, "setenv", errno); +} + + +int +liberror_unsetenv(const char *name) +{ + if (!unsetenv(name)) + return 0; + liberror_save_backtrace(NULL); + liberror_unsetenv_failed(name); return -1; } |