diff options
Diffstat (limited to 'source4/heimdal/lib/roken')
-rw-r--r-- | source4/heimdal/lib/roken/base64.c | 2 | ||||
-rw-r--r-- | source4/heimdal/lib/roken/getarg.c | 5 | ||||
-rw-r--r-- | source4/heimdal/lib/roken/getarg.h | 2 | ||||
-rw-r--r-- | source4/heimdal/lib/roken/inet_ntop.c | 21 | ||||
-rw-r--r-- | source4/heimdal/lib/roken/inet_pton.c | 13 | ||||
-rw-r--r-- | source4/heimdal/lib/roken/net_read.c | 20 | ||||
-rw-r--r-- | source4/heimdal/lib/roken/net_write.c | 19 | ||||
-rw-r--r-- | source4/heimdal/lib/roken/resolve.c | 218 | ||||
-rw-r--r-- | source4/heimdal/lib/roken/resolve.h | 4 | ||||
-rw-r--r-- | source4/heimdal/lib/roken/roken.h.in | 89 | ||||
-rw-r--r-- | source4/heimdal/lib/roken/roken_gethostby.c | 9 | ||||
-rw-r--r-- | source4/heimdal/lib/roken/socket.c | 13 | ||||
-rw-r--r-- | source4/heimdal/lib/roken/strerror_r.c | 2 |
13 files changed, 375 insertions, 42 deletions
diff --git a/source4/heimdal/lib/roken/base64.c b/source4/heimdal/lib/roken/base64.c index 4c06bd2d1f..394e9841c7 100644 --- a/source4/heimdal/lib/roken/base64.c +++ b/source4/heimdal/lib/roken/base64.c @@ -93,7 +93,7 @@ base64_encode(const void *data, int size, char **str) } *p = 0; *str = s; - return strlen(s); + return (int) strlen(s); } #define DECODE_ERROR 0xffffffff diff --git a/source4/heimdal/lib/roken/getarg.c b/source4/heimdal/lib/roken/getarg.c index d182f0019e..e7dc74b7bc 100644 --- a/source4/heimdal/lib/roken/getarg.c +++ b/source4/heimdal/lib/roken/getarg.c @@ -223,7 +223,7 @@ arg_printusage_i18n (struct getargs *args, const char *usage, const char *progname, const char *extra_string, - char *(i18n)(const char *)) + char *(*i18n)(const char *)) { size_t i, max_len = 0; char buf[128]; @@ -475,9 +475,6 @@ arg_match_long(struct getargs *args, size_t num_args, abort (); UNREACHABLE(return 0); } - - /* not reached */ - return ARG_ERR_NO_MATCH; } static int diff --git a/source4/heimdal/lib/roken/getarg.h b/source4/heimdal/lib/roken/getarg.h index 79573a0ea4..1065c7c661 100644 --- a/source4/heimdal/lib/roken/getarg.h +++ b/source4/heimdal/lib/roken/getarg.h @@ -104,7 +104,7 @@ arg_printusage_i18n (struct getargs *args, const char *usage, const char *progname, const char *extra_string, - char *(i18n)(const char *)); + char *(*i18n)(const char *)); ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL free_getarg_strings (getarg_strings *); diff --git a/source4/heimdal/lib/roken/inet_ntop.c b/source4/heimdal/lib/roken/inet_ntop.c index 0c72b27fc6..b3c327cc3e 100644 --- a/source4/heimdal/lib/roken/inet_ntop.c +++ b/source4/heimdal/lib/roken/inet_ntop.c @@ -83,6 +83,7 @@ inet_ntop_v6 (const void *src, char *dst, size_t size) const struct in6_addr *addr = (struct in6_addr *)src; const u_char *ptr = addr->s6_addr; const char *orig_dst = dst; + int compressed = 0; if (size < INET6_ADDRSTRLEN) { errno = ENOSPC; @@ -91,6 +92,26 @@ inet_ntop_v6 (const void *src, char *dst, size_t size) for (i = 0; i < 8; ++i) { int non_zerop = 0; + if (compressed == 0 && + ptr[0] == 0 && ptr[1] == 0 && + i <= 5 && + ptr[2] == 0 && ptr[3] == 0 && + ptr[4] == 0 && ptr[5] == 0) { + + compressed = 1; + + if (i == 0) + *dst++ = ':'; + *dst++ = ':'; + + for (ptr += 6, i += 3; + i < 8 && ptr[0] == 0 && ptr[1] == 0; + ++i, ptr += 2); + + if (i >= 8) + break; + } + if (non_zerop || (ptr[0] >> 4)) { *dst++ = xdigits[ptr[0] >> 4]; non_zerop = 1; diff --git a/source4/heimdal/lib/roken/inet_pton.c b/source4/heimdal/lib/roken/inet_pton.c index 3db1f49f22..e44fb1925a 100644 --- a/source4/heimdal/lib/roken/inet_pton.c +++ b/source4/heimdal/lib/roken/inet_pton.c @@ -38,8 +38,15 @@ #ifdef HAVE_WINSOCK ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL -inet_pton(int af, const char *src, void *dst) +inet_pton(int af, const char *csrc, void *dst) { + char * src; + + if (csrc == NULL || (src = strdup(csrc)) == NULL) { + _set_errno( ENOMEM ); + return 0; + } + switch (af) { case AF_INET: { @@ -49,6 +56,8 @@ inet_pton(int af, const char *src, void *dst) si4.sin_family = AF_INET; r = WSAStringToAddress(src, AF_INET, NULL, (LPSOCKADDR) &si4, &s); + free(src); + src = NULL; if (r == 0) { memcpy(dst, &si4.sin_addr, sizeof(si4.sin_addr)); @@ -65,6 +74,8 @@ inet_pton(int af, const char *src, void *dst) si6.sin6_family = AF_INET6; r = WSAStringToAddress(src, AF_INET6, NULL, (LPSOCKADDR) &si6, &s); + free(src); + src = NULL; if (r == 0) { memcpy(dst, &si6.sin6_addr, sizeof(si6.sin6_addr)); diff --git a/source4/heimdal/lib/roken/net_read.c b/source4/heimdal/lib/roken/net_read.c index b57dda3dda..df1ac53def 100644 --- a/source4/heimdal/lib/roken/net_read.c +++ b/source4/heimdal/lib/roken/net_read.c @@ -73,8 +73,28 @@ net_read(rk_socket_t sock, void *buf, size_t nbytes) ssize_t count; size_t rem = nbytes; +#ifdef SOCKET_IS_NOT_AN_FD + int use_read = 0; +#endif + while (rem > 0) { +#ifdef SOCKET_IS_NOT_AN_FD + if (use_read) + count = _read (sock, cbuf, rem); + else + count = recv (sock, cbuf, rem, 0); + + if (use_read == 0 && + rk_IS_SOCKET_ERROR(count) && + (rk_SOCK_ERRNO == WSANOTINITIALISED || + rk_SOCK_ERRNO == WSAENOTSOCK)) { + use_read = 1; + + count = _read (sock, cbuf, rem); + } +#else count = recv (sock, cbuf, rem, 0); +#endif if (count < 0) { /* With WinSock, the error EINTR (WSAEINTR), is used to diff --git a/source4/heimdal/lib/roken/net_write.c b/source4/heimdal/lib/roken/net_write.c index 94c9df1c38..e1cfa99074 100644 --- a/source4/heimdal/lib/roken/net_write.c +++ b/source4/heimdal/lib/roken/net_write.c @@ -70,9 +70,28 @@ net_write(rk_socket_t sock, const void *buf, size_t nbytes) const char *cbuf = (const char *)buf; ssize_t count; size_t rem = nbytes; +#ifdef SOCKET_IS_NOT_AN_FD + int use_write = 0; +#endif while (rem > 0) { +#ifdef SOCKET_IS_NOT_AN_FD + if (use_write) + count = _write (sock, cbuf, rem); + else + count = send (sock, cbuf, rem, 0); + + if (use_write == 0 && + rk_IS_SOCKET_ERROR(count) && + (rk_SOCK_ERRNO == WSANOTINITIALISED || + rk_SOCK_ERRNO == WSAENOTSOCK)) { + use_write = 1; + + count = _write (sock, cbuf, rem); + } +#else count = send (sock, cbuf, rem, 0); +#endif if (count < 0) { if (errno == EINTR) continue; diff --git a/source4/heimdal/lib/roken/resolve.c b/source4/heimdal/lib/roken/resolve.c index e112274a68..97edda471b 100644 --- a/source4/heimdal/lib/roken/resolve.c +++ b/source4/heimdal/lib/roken/resolve.c @@ -98,7 +98,7 @@ rk_dns_type_to_string(int type) return NULL; } -#if (defined(HAVE_RES_SEARCH) || defined(HAVE_RES_NSEARCH)) && defined(HAVE_DN_EXPAND) +#if ((defined(HAVE_RES_SEARCH) || defined(HAVE_RES_NSEARCH)) && defined(HAVE_DN_EXPAND)) || defined(HAVE_WINDNS) static void dns_free_rr(struct rk_resource_record *rr) @@ -124,6 +124,8 @@ rk_dns_free_data(struct rk_dns_reply *r) free (r); } +#ifndef HAVE_WINDNS + static int parse_record(const unsigned char *data, const unsigned char *end_data, const unsigned char **pp, struct rk_resource_record **ret_rr) @@ -605,6 +607,8 @@ rk_dns_lookup(const char *domain, const char *type_name) return dns_lookup_int(domain, rk_ns_c_in, type); } +#endif /* !HAVE_WINDNS */ + static int compare_srv(const void *a, const void *b) { @@ -708,6 +712,218 @@ rk_dns_srv_order(struct rk_dns_reply *r) return; } +#ifdef HAVE_WINDNS + +#include <WinDNS.h> + +static struct rk_resource_record * +parse_dns_record(PDNS_RECORD pRec) +{ + struct rk_resource_record * rr; + + if (pRec == NULL) + return NULL; + + rr = calloc(1, sizeof(*rr)); + + rr->domain = strdup(pRec->pName); + rr->type = pRec->wType; + rr->class = 0; + rr->ttl = pRec->dwTtl; + rr->size = 0; + + switch (rr->type) { + case rk_ns_t_ns: + case rk_ns_t_cname: + case rk_ns_t_ptr: + rr->u.txt = strdup(pRec->Data.NS.pNameHost); + if(rr->u.txt == NULL) { + dns_free_rr(rr); + return NULL; + } + break; + + case rk_ns_t_mx: + case rk_ns_t_afsdb:{ + size_t hostlen = strnlen(pRec->Data.MX.pNameExchange, DNS_MAX_NAME_LENGTH); + + rr->u.mx = (struct mx_record *)malloc(sizeof(struct mx_record) + + hostlen); + if (rr->u.mx == NULL) { + dns_free_rr(rr); + return NULL; + } + + strcpy_s(rr->u.mx->domain, hostlen + 1, pRec->Data.MX.pNameExchange); + rr->u.mx->preference = pRec->Data.MX.wPreference; + break; + } + + case rk_ns_t_srv:{ + size_t hostlen = strnlen(pRec->Data.SRV.pNameTarget, DNS_MAX_NAME_LENGTH); + + rr->u.srv = + (struct srv_record*)malloc(sizeof(struct srv_record) + + hostlen); + if(rr->u.srv == NULL) { + dns_free_rr(rr); + return NULL; + } + + rr->u.srv->priority = pRec->Data.SRV.wPriority; + rr->u.srv->weight = pRec->Data.SRV.wWeight; + rr->u.srv->port = pRec->Data.SRV.wPort; + strcpy_s(rr->u.srv->target, hostlen + 1, pRec->Data.SRV.pNameTarget); + + break; + } + + case rk_ns_t_txt:{ + size_t len; + + if (pRec->Data.TXT.dwStringCount == 0) { + rr->u.txt = strdup(""); + break; + } + + len = strnlen(pRec->Data.TXT.pStringArray[0], DNS_MAX_TEXT_STRING_LENGTH); + + rr->u.txt = (char *)malloc(len + 1); + strcpy_s(rr->u.txt, len + 1, pRec->Data.TXT.pStringArray[0]); + + break; + } + + case rk_ns_t_key : { + size_t key_len; + + if (pRec->wDataLength < 4) { + dns_free_rr(rr); + return NULL; + } + + key_len = pRec->wDataLength - 4; + rr->u.key = malloc (sizeof(*rr->u.key) + key_len - 1); + if (rr->u.key == NULL) { + dns_free_rr(rr); + return NULL; + } + + rr->u.key->flags = pRec->Data.KEY.wFlags; + rr->u.key->protocol = pRec->Data.KEY.chProtocol; + rr->u.key->algorithm = pRec->Data.KEY.chAlgorithm; + rr->u.key->key_len = key_len; + memcpy_s (rr->u.key->key_data, key_len, + pRec->Data.KEY.Key, key_len); + break; + } + + case rk_ns_t_sig : { + size_t sig_len, hostlen; + + if(pRec->wDataLength <= 18) { + dns_free_rr(rr); + return NULL; + } + + sig_len = pRec->wDataLength; + + hostlen = strnlen(pRec->Data.SIG.pNameSigner, DNS_MAX_NAME_LENGTH); + + rr->u.sig = malloc(sizeof(*rr->u.sig) + + hostlen + sig_len); + if (rr->u.sig == NULL) { + dns_free_rr(rr); + return NULL; + } + rr->u.sig->type = pRec->Data.SIG.wTypeCovered; + rr->u.sig->algorithm = pRec->Data.SIG.chAlgorithm; + rr->u.sig->labels = pRec->Data.SIG.chLabelCount; + rr->u.sig->orig_ttl = pRec->Data.SIG.dwOriginalTtl; + rr->u.sig->sig_expiration = pRec->Data.SIG.dwExpiration; + rr->u.sig->sig_inception = pRec->Data.SIG.dwTimeSigned; + rr->u.sig->key_tag = pRec->Data.SIG.wKeyTag; + rr->u.sig->sig_len = sig_len; + memcpy_s (rr->u.sig->sig_data, sig_len, + pRec->Data.SIG.Signature, sig_len); + rr->u.sig->signer = &rr->u.sig->sig_data[sig_len]; + strcpy_s(rr->u.sig->signer, hostlen + 1, pRec->Data.SIG.pNameSigner); + break; + } + +#ifdef DNS_TYPE_DS + case rk_ns_t_ds: { + rr->u.ds = malloc (sizeof(*rr->u.ds) + pRec->Data.DS.wDigestLength - 1); + if (rr->u.ds == NULL) { + dns_free_rr(rr); + return NULL; + } + + rr->u.ds->key_tag = pRec->Data.DS.wKeyTag; + rr->u.ds->algorithm = pRec->Data.DS.chAlgorithm; + rr->u.ds->digest_type = pRec->Data.DS.chDigestType; + rr->u.ds->digest_len = pRec->Data.DS.wDigestLength; + memcpy_s (rr->u.ds->digest_data, pRec->Data.DS.wDigestLength, + pRec->Data.DS.Digest, pRec->Data.DS.wDigestLength); + break; + } +#endif + + default: + dns_free_rr(rr); + return NULL; + } + + rr->next = parse_dns_record(pRec->pNext); + return rr; +} + +ROKEN_LIB_FUNCTION struct rk_dns_reply * ROKEN_LIB_CALL +rk_dns_lookup(const char *domain, const char *type_name) +{ + DNS_STATUS status; + int type; + PDNS_RECORD pRec = NULL; + struct rk_dns_reply * r = NULL; + + __try { + + type = rk_dns_string_to_type(type_name); + if(type == -1) { + if(_resolve_debug) + fprintf(stderr, "dns_lookup: unknown resource type: `%s'\n", + type_name); + return NULL; + } + + status = DnsQuery_UTF8(domain, type, DNS_QUERY_STANDARD, NULL, + &pRec, NULL); + if (status != ERROR_SUCCESS) + return NULL; + + r = calloc(1, sizeof(*r)); + r->q.domain = strdup(domain); + r->q.type = type; + r->q.class = 0; + + r->head = parse_dns_record(pRec); + + if (r->head == NULL) { + rk_dns_free_data(r); + return NULL; + } else { + return r; + } + + } __finally { + + if (pRec) + DnsRecordListFree(pRec, DnsFreeRecordList); + + } +} +#endif /* HAVE_WINDNS */ + #else /* NOT defined(HAVE_RES_SEARCH) && defined(HAVE_DN_EXPAND) */ ROKEN_LIB_FUNCTION struct rk_dns_reply * ROKEN_LIB_CALL diff --git a/source4/heimdal/lib/roken/resolve.h b/source4/heimdal/lib/roken/resolve.h index adec8084b8..fc1e97fc63 100644 --- a/source4/heimdal/lib/roken/resolve.h +++ b/source4/heimdal/lib/roken/resolve.h @@ -153,7 +153,7 @@ struct rk_sig_record { unsigned sig_inception; unsigned key_tag; char *signer; - unsigned sig_len; + size_t sig_len; char sig_data[1]; /* also includes signer */ }; @@ -176,7 +176,7 @@ struct rk_ds_record { unsigned key_tag; unsigned algorithm; unsigned digest_type; - unsigned digest_len; + size_t digest_len; u_char digest_data[1]; }; diff --git a/source4/heimdal/lib/roken/roken.h.in b/source4/heimdal/lib/roken/roken.h.in index 76b083c797..d6e9024bd0 100644 --- a/source4/heimdal/lib/roken/roken.h.in +++ b/source4/heimdal/lib/roken/roken.h.in @@ -68,7 +68,8 @@ typedef SOCKET rk_socket_t; #define rk_IS_BAD_SOCKET(s) ((s) == INVALID_SOCKET) #define rk_IS_SOCKET_ERROR(rv) ((rv) == SOCKET_ERROR) #define rk_SOCK_ERRNO WSAGetLastError() -#define rk_SOCK_IOCTL(s,c,a) ioctlsocket((s),(c),(a)) + +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL rk_SOCK_IOCTL(SOCKET s, long cmd, int * argp); #define ETIMEDOUT WSAETIMEDOUT #define EWOULDBLOCK WSAEWOULDBLOCK @@ -124,6 +125,32 @@ typedef uint64_t u_int64_t; #define UNREACHABLE(x) x #define UNUSED_ARGUMENT(x) ((void) x) +#define RETSIGTYPE void + +#define VOID_RETSIGTYPE 1 + +#ifdef VOID_RETSIGTYPE +#define SIGRETURN(x) return +#else +#define SIGRETURN(x) return (RETSIGTYPE)(x) +#endif + +#ifndef CPP_ONLY + +typedef int pid_t; + +typedef unsigned int gid_t; + +typedef unsigned int uid_t; + +typedef unsigned short mode_t; + +#endif + +#ifndef __cplusplus +#define inline __inline +#endif + #else #define UNREACHABLE(x) @@ -315,6 +342,32 @@ rk_vsnprintf (char *str, size_t sz, const char *format, va_list args); #endif /* _MSC_VER */ +#ifdef HAVE_WINSOCK + +/* While we are at it, define WinSock specific scatter gather socket + I/O. */ + +#define iovec _WSABUF +#define iov_base buf +#define iov_len len + +struct msghdr { + void *msg_name; + socklen_t msg_namelen; + struct iovec *msg_iov; + size_t msg_iovlen; + void *msg_control; + socklen_t msg_controllen; + int msg_flags; +}; + +#define sendmsg sendmsg_w32 + +ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL +sendmsg_w32(rk_socket_t s, const struct msghdr * msg, int flags); + +#endif /* HAVE_WINSOCK */ + #ifndef HAVE_PUTENV #define putenv rk_putenv ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL putenv(const char *); @@ -563,6 +616,12 @@ ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL initgroups(const char *, gid_t); ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL fchown(int, uid_t, gid_t); #endif +#ifdef RENAME_DOES_NOT_UNLINK +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL rk_rename(const char *, const char *); +#else +#define rk_rename(__rk_rn_from,__rk_rn_to) rename(__rk_rn_from,__rk_rn_to) +#endif + #if !defined(HAVE_DAEMON) || defined(NEED_DAEMON_PROTO) #ifndef HAVE_DAEMON #define daemon rk_daemon @@ -824,32 +883,6 @@ ROKEN_LIB_FUNCTION const char * ROKEN_LIB_CALL gai_strerror(int); #endif -#ifdef HAVE_WINSOCK - -/* While we are at it, define WinSock specific scatter gather socket - I/O. */ - -#define iovec _WSABUF -#define iov_base buf -#define iov_len len - -struct msghdr { - void *msg_name; - socklen_t msg_namelen; - struct iovec *msg_iov; - size_t msg_iovlen; - void *msg_control; - socklen_t msg_controllen; - int msg_flags; -}; - -#define sendmsg sendmsg_w32 - -ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL -sendmsg_w32(rk_socket_t s, const struct msghdr * msg, int flags); - -#endif - #ifdef NO_SLEEP ROKEN_LIB_FUNCTION unsigned int ROKEN_LIB_CALL @@ -1039,7 +1072,7 @@ void rk_qsort(void *, size_t, size_t, int (*)(const void *, const void *)); #endif -#if defined(__linux__) && SOCK_CLOEXEC && !defined(SOCKET_WRAPPER_REPLACE) +#if defined(__linux__) && defined(SOCK_CLOEXEC) && !defined(SOCKET_WRAPPER_REPLACE) #undef socket #define socket(_fam,_type,_prot) rk_socket(_fam,_type,_prot) int ROKEN_LIB_FUNCTION rk_socket(int, int, int); diff --git a/source4/heimdal/lib/roken/roken_gethostby.c b/source4/heimdal/lib/roken/roken_gethostby.c index c99596c536..1d6c8ffe8a 100644 --- a/source4/heimdal/lib/roken/roken_gethostby.c +++ b/source4/heimdal/lib/roken/roken_gethostby.c @@ -66,11 +66,13 @@ setup_int(const char *proxy_host, short proxy_port, memset(&dns_addr, 0, sizeof(dns_addr)); if(dns_req) free(dns_req); + dns_req = NULL; if(proxy_host) { if(make_address(proxy_host, &dns_addr.sin_addr) != 0) return -1; dns_addr.sin_port = htons(proxy_port); - asprintf(&dns_req, "http://%s:%d%s", dns_host, dns_port, dns_path); + if (asprintf(&dns_req, "http://%s:%d%s", dns_host, dns_port, dns_path) < 0) + return -1; } else { if(make_address(dns_host, &dns_addr.sin_addr) != 0) return -1; @@ -135,7 +137,7 @@ roken_gethostby(const char *hostname) { int s; struct sockaddr_in addr; - char *request; + char *request = NULL; char buf[1024]; int offset = 0; int n; @@ -144,7 +146,8 @@ roken_gethostby(const char *hostname) if(dns_addr.sin_family == 0) return NULL; /* no configured host */ addr = dns_addr; - asprintf(&request, "GET %s?%s HTTP/1.0\r\n\r\n", dns_req, hostname); + if (asprintf(&request, "GET %s?%s HTTP/1.0\r\n\r\n", dns_req, hostname) < 0) + return NULL; if(request == NULL) return NULL; s = socket(AF_INET, SOCK_STREAM, 0); diff --git a/source4/heimdal/lib/roken/socket.c b/source4/heimdal/lib/roken/socket.c index bd800ac5a1..ef594ffd0d 100644 --- a/source4/heimdal/lib/roken/socket.c +++ b/source4/heimdal/lib/roken/socket.c @@ -316,6 +316,19 @@ socket_to_fd(rk_socket_t sock, int flags) #endif } +#ifdef HAVE_WINSOCK +ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL +rk_SOCK_IOCTL(SOCKET s, long cmd, int * argp) { + u_long ul = (argp)? *argp : 0; + int rv; + + rv = ioctlsocket(s, cmd, &ul); + if (argp) + *argp = (int) ul; + return rv; +} +#endif + #ifndef HEIMDAL_SMALLER #undef socket diff --git a/source4/heimdal/lib/roken/strerror_r.c b/source4/heimdal/lib/roken/strerror_r.c index 5155c28cb5..85271ecaf5 100644 --- a/source4/heimdal/lib/roken/strerror_r.c +++ b/source4/heimdal/lib/roken/strerror_r.c @@ -72,7 +72,7 @@ rk_strerror_r(int eno, char *strerrbuf, size_t buflen) return 0; #else int ret; - ret = strlcpy(strerrbuf, buflen, strerror(eno)); + ret = strlcpy(strerrbuf, strerror(eno), buflen); if (ret > buflen) return ERANGE; return 0; |