summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2013-02-02 02:07:38 -0500
committerRich Felker <dalias@aerifal.cx>2013-02-02 02:07:38 -0500
commita47ad3ebce8e20a5d72535996a0d0d5458241213 (patch)
treea165841faf258c2283bf7135424c3beb2d95bdee
parentc0193550a022cb75d1cddb0254e98029b3b56420 (diff)
downloadmusl-a47ad3ebce8e20a5d72535996a0d0d5458241213.tar.gz
dynamically allocate storage for gethostby* buffers
this change shaves ~1k off libc.so bss size, and also avoids hard errors in the case where the static buffer was not large enough to hold the result. this whole framework is really ugly and might should be replaced or at least heavily overhauled when some changes/factorizations are made to getaddrinfo internals in the future.
-rw-r--r--src/network/gethostbyaddr.c21
-rw-r--r--src/network/gethostbyname2.c21
2 files changed, 32 insertions, 10 deletions
diff --git a/src/network/gethostbyaddr.c b/src/network/gethostbyaddr.c
index 51e1c569..c9b6388a 100644
--- a/src/network/gethostbyaddr.c
+++ b/src/network/gethostbyaddr.c
@@ -3,13 +3,24 @@
#include <netdb.h>
#include <string.h>
#include <netinet/in.h>
+#include <errno.h>
+#include <stdlib.h>
struct hostent *gethostbyaddr(const void *a, socklen_t l, int af)
{
- static struct hostent h;
- static long buf[512/sizeof(long)];
+ static struct hostent *h;
+ size_t size = 63;
struct hostent *res;
- if (gethostbyaddr_r(a, l, af, &h,
- (void *)buf, sizeof buf, &res, &h_errno)) return 0;
- return &h;
+ int err;
+ do {
+ free(h);
+ h = malloc(size+=size+1);
+ if (!h) {
+ h_errno = NO_RECOVERY;
+ return 0;
+ }
+ err = gethostbyaddr_r(a, l, af, h,
+ (void *)(h+1), size-sizeof *h, &res, &h_errno);
+ } while (err == ERANGE);
+ return err ? 0 : h;
}
diff --git a/src/network/gethostbyname2.c b/src/network/gethostbyname2.c
index 9fbe2647..c9f90da2 100644
--- a/src/network/gethostbyname2.c
+++ b/src/network/gethostbyname2.c
@@ -4,13 +4,24 @@
#include <netdb.h>
#include <string.h>
#include <netinet/in.h>
+#include <errno.h>
+#include <stdlib.h>
struct hostent *gethostbyname2(const char *name, int af)
{
- static struct hostent h;
- static long buf[512/sizeof(long)];
+ static struct hostent *h;
+ size_t size = 63;
struct hostent *res;
- if (gethostbyname2_r(name, af, &h,
- (void *)buf, sizeof buf, &res, &h_errno)) return 0;
- return &h;
+ int err;
+ do {
+ free(h);
+ h = malloc(size+=size+1);
+ if (!h) {
+ h_errno = NO_RECOVERY;
+ return 0;
+ }
+ err = gethostbyname2_r(name, af, h,
+ (void *)(h+1), size-sizeof *h, &res, &h_errno);
+ } while (err == ERANGE);
+ return err ? 0 : h;
}