dynamically allocate storage for gethostby* buffers
authorRich Felker <dalias@aerifal.cx>
Sat, 2 Feb 2013 07:07:38 +0000 (02:07 -0500)
committerRich Felker <dalias@aerifal.cx>
Sat, 2 Feb 2013 07:07:38 +0000 (02:07 -0500)
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.

src/network/gethostbyaddr.c
src/network/gethostbyname2.c

index 51e1c5699856be573a3e45e288af2689772e07be..c9b6388a415b5c5aa78c449003cf8ce3519b84b6 100644 (file)
@@ -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;
 }
index 9fbe2647b4daa6638e34c4151992adda3e0930fa..c9f90da2d3d6fb387cdba87cbbbb011fd02b84d6 100644 (file)
@@ -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;
 }