* net.cc (free_char_list): Delete.

(dup_addr_list): Delete.
(dup_char_list): Delete.
(free_hostent_ptr): Delete.
(free_protoent_ptr): Delete.
(free_servent_ptr): Delete.
(DWORD_round): New function.
(strlen_round): New function.  Returns strlen rounded up to word size.
(dup_ent): New, generic function to duplicate a {host,proto,serv}ent structure.
(gen_ent): New macro.  Generates a generic dup_{host,proto,serv}ent_ptr
function.
(cygwin_getservbyname): Remove call to free_servent_ptr, pass servent_buf to
dup_servent_ptr.
(cygwin_getservbyport): Ditto.
(cygwin_gethostbyname): Ditto for hostent.
(cygwin_gethostbyaddr): Ditto.
(cygwin_getprotobyname): Ditto for protoent.
(cygwin_getprotobynumber): Ditto.
This commit is contained in:
Christopher Faylor 2003-08-31 22:02:15 +00:00
parent f8e2f358c4
commit edf16a29fc
3 changed files with 226 additions and 204 deletions

View File

@ -1,3 +1,25 @@
2003-08-31 Christopher Faylor <cgf@redhat.com>
* net.cc (free_char_list): Delete.
(dup_addr_list): Delete.
(dup_char_list): Delete.
(free_hostent_ptr): Delete.
(free_protoent_ptr): Delete.
(free_servent_ptr): Delete.
(DWORD_round): New function.
(strlen_round): New function. Returns strlen rounded up to word size.
(dup_ent): New, generic function to duplicate a {host,proto,serv}ent
structure.
(gen_ent): New macro. Generates a generic dup_{host,proto,serv}ent_ptr
function.
(cygwin_getservbyname): Remove call to free_servent_ptr, pass
servent_buf to dup_servent_ptr.
(cygwin_getservbyport): Ditto.
(cygwin_gethostbyname): Ditto for hostent.
(cygwin_gethostbyaddr): Ditto.
(cygwin_getprotobyname): Ditto for protoent.
(cygwin_getprotobynumber): Ditto.
2003-08-31 Christopher Faylor <cgf@redhat.com>
* Makefile.in (MALLOC_OFILES): Always fill in with correct malloc

View File

@ -139,7 +139,6 @@ sbrk (int n)
/* Couldn't allocate memory. Maybe we can reserve some more.
Reserve either the maximum of the standard cygwin_shared->heap_chunk_size ()
or the requested amount. Then attempt to actually allocate it. */
if ((newbrksize = cygheap->user_heap.chunk) < commitbytes)
newbrksize = commitbytes;
@ -147,7 +146,7 @@ sbrk (int n)
|| VirtualAlloc (cygheap->user_heap.top, newbrksize = commitbytes, MEM_RESERVE, PAGE_NOACCESS))
&& VirtualAlloc (cygheap->user_heap.top, commitbytes, MEM_COMMIT, PAGE_READWRITE) != NULL)
{
(char *) cygheap->user_heap.max += newbrksize;
(char *) cygheap->user_heap.max += pround (newbrksize);
goto good;
}

View File

@ -25,6 +25,7 @@ details. */
#include <netdb.h>
#define USE_SYS_TYPES_FD_SET
#include <winsock2.h>
#include <assert.h>
#include "cygerrno.h"
#include "security.h"
#include "fhandler.h"
@ -381,96 +382,211 @@ set_host_errno ()
h_errno = NETDB_INTERNAL;
}
static void
free_char_list (char **clist)
inline int
DWORD_round (int n)
{
if (clist)
return sizeof (DWORD) * (((n + sizeof (DWORD) - 1)) / sizeof (DWORD));
}
inline int
strlen_round (const char *s)
{
if (!s)
return 0;
return DWORD_round (strlen (s) + 1);
}
enum struct_type
{
is_protoent, is_servent, is_hostent
};
#pragma pack(push,2)
struct pservent
{
char *s_name;
char **s_aliases;
short s_port;
char *s_proto;
};
#pragma pack(pop)
struct unionent
{
char *name;
char **list;
short port_proto_addrtype;
short h_len;
union
{
char *s_proto;
char **h_addr_list;
};
};
/* Generic "dup a {host,proto,serv}ent structure" function.
This is complicated because we need to be able to free the
structure at any point and we can't rely on the pointer contents
being untouched by callers. So, we allocate a chunk of memory
large enough to hold the structure and all of the stuff it points
to then we copy the source into this new block of memory.
The 'unionent' struct is a union of all of the currently used
*ent structure. */
#ifdef DEBUGGING
static void *
#else
static inline void *
#endif
dup_ent (void *src0, struct_type type)
{
unionent *src = (unionent *) src0;
/* Find the size of the raw structure minus any character strings, etc. */
int sz, struct_sz;
switch (type)
{
for (char **cl = clist; *cl; ++cl)
free (*cl);
free (clist);
case is_protoent:
struct_sz = sizeof (protoent);
break;
case is_servent:
struct_sz = sizeof (servent);
break;
case is_hostent:
struct_sz = sizeof (hostent);
break;
default:
api_fatal ("called with invalid value %d", type);
break;
}
}
static char **
dup_char_list (char **src)
{
char **dst;
int cnt = 0;
/* Every *ent begins with a name. Calculate it's length. */
int namelen = strlen_round (src->name);
sz = struct_sz + namelen;
for (char **cl = src; *cl; ++cl)
++cnt;
if (!(dst = (char **) calloc (cnt + 1, sizeof *dst)))
return NULL;
while (cnt-- > 0)
if (!(dst[cnt] = strdup (src[cnt])))
return NULL;
return dst;
}
#define free_addr_list(addr_list) free_char_list (addr_list)
static char **
dup_addr_list (char **src, unsigned int size)
{
char **dst;
int cnt = 0;
for (char **cl = src; *cl; ++cl)
++cnt;
if (!(dst = (char **) calloc (cnt + 1, sizeof *dst)))
return NULL;
while (cnt-- > 0)
char **av;
/* The next field in every *ent is an argv list of "something".
Calculate the number of components and how much space the
character strings will take. */
int list_len = 0;
for (av = src->list; av && *av; av++)
{
if (!(dst[cnt] = (char *) malloc (size)))
return NULL;
memcpy (dst[cnt], src[cnt], size);
list_len++;
sz += sizeof (char **) + strlen_round (*av);
}
/* NULL terminate if there actually was a list */
if (av)
{
sz += sizeof (char **);
list_len++;
}
/* Do servent/hostent specific processing */
int protolen = 0;
int addr_list_len = 0;
if (type == is_servent)
sz += (protolen = strlen_round (src->s_proto));
else if (type == is_hostent)
{
/* Calculate the length and storage used for h_addr_list */
for (av = src->h_addr_list; av && *av; av++)
{
addr_list_len++;
sz += sizeof (char **) + DWORD_round (src->h_len);
}
if (av)
{
sz += sizeof (char **);
addr_list_len++;
}
}
/* Allocate the storage needed */
unionent *dst = (unionent *) calloc (1, sz);
/* Hopefully, this worked. */
if (dst)
{
/* This field is common to all *ent structures but named differently
in each, of course. */
dst->port_proto_addrtype = src->port_proto_addrtype;
/* Copy the name field to dst, using space just beyond the end of
the dst structure. */
char *dp = ((char *) dst) + struct_sz;
strcpy (dst->name = dp, src->name);
dp += namelen;
/* Copy the 'list' type to dst, using space beyond end of structure
+ storage for name. */
if (src->list)
{
char **dav = dst->list = (char **) dp;
dp += sizeof (char **) * list_len;
for (av = src->list; av && *av; av++)
{
int len = strlen (*av) + 1;
memcpy (*dav++ = dp, *av, len);
dp += DWORD_round (len);
}
}
/* Do servent/hostent specific processing. */
if (type == is_servent)
{
if (src->s_proto)
{
char *s_proto;
/* Windows 95 idiocy. Structure is misaligned on Windows 95.
Kludge around this by trying a different pointer alignment. */
if (IsBadReadPtr (src->s_proto, sizeof (src->s_proto))
&& !IsBadReadPtr (((pservent *) src)->s_proto, sizeof (src->s_proto)))
s_proto = ((pservent *) src)->s_proto;
else
s_proto = src->s_proto;
strcpy (dst->s_proto = dp, s_proto);
dp += protolen;
}
}
else if (type == is_hostent)
{
/* Transfer h_len and duplicate contents of h_addr_list, using
memory after 'list' allocation. */
dst->h_len = src->h_len;
char **dav = dst->h_addr_list = (char **) dp;
dp += sizeof (char **) * addr_list_len;
for (av = src->h_addr_list; av && *av; av++)
{
memcpy (*dav++ = dp, *av, src->h_len);
dp += DWORD_round (src->h_len);
}
}
/* Sanity check that we did our bookkeeping correctly. */
assert ((dp - (char *) dst) == sz);
}
return dst;
}
static void
free_protoent_ptr (struct protoent *&p)
{
if (p)
{
debug_printf ("protoent: %s", p->p_name);
/* Generic macro to build a dup_{host,proto,serv}ent_ptr function.
The *ent buffers are allocated by dup_ent as contiguous storage.
Frees any previously exiting `old' storage, as well. */
#define gen_ent(x, p) \
static x * \
dup_##x##_ptr (x *old, x *src) \
{ \
if (old) \
{ \
debug_printf ("freeing %s", old->p##_name); \
free (old); \
} \
debug_printf ("%s", src ? "<null!>" : src->p##_name); \
x *dst = (x *) dup_ent (src, is_##x); \
debug_printf ("copied %s", dst ? "<null!>" : dst->p##_name); \
return dst; \
} \
if (p->p_name)
free (p->p_name);
free_char_list (p->p_aliases);
free ((void *) p);
p = NULL;
}
}
static struct protoent *
dup_protoent_ptr (struct protoent *src)
{
if (!src)
return NULL;
struct protoent *dst = (struct protoent *) calloc (1, sizeof *dst);
if (!dst)
return NULL;
debug_printf ("protoent: %s", src->p_name);
dst->p_proto = src->p_proto;
if (src->p_name && !(dst->p_name = strdup (src->p_name)))
goto out;
if (src->p_aliases && !(dst->p_aliases = dup_char_list (src->p_aliases)))
goto out;
debug_printf ("protoent: copied %s", dst->p_name);
return dst;
out:
free_protoent_ptr (dst);
return NULL;
}
gen_ent (protoent, p)
#ifdef _MT_SAFE
#define protoent_buf _reent_winsup ()->_protoent_buf
@ -484,8 +600,7 @@ cygwin_getprotobyname (const char *p)
{
if (check_null_str_errno (p))
return NULL;
free_protoent_ptr (protoent_buf);
protoent_buf = dup_protoent_ptr (getprotobyname (p));
protoent_buf = dup_protoent_ptr (protoent_buf, getprotobyname (p));
if (!protoent_buf)
set_winsock_errno ();
@ -497,8 +612,7 @@ cygwin_getprotobyname (const char *p)
extern "C" struct protoent *
cygwin_getprotobynumber (int number)
{
free_protoent_ptr (protoent_buf);
protoent_buf = dup_protoent_ptr (getprotobynumber (number));
protoent_buf = dup_protoent_ptr (protoent_buf, getprotobynumber (number));
if (!protoent_buf)
set_winsock_errno ();
@ -828,70 +942,7 @@ cygwin_connect (int fd, const struct sockaddr *name, int namelen)
return res;
}
static void
free_servent_ptr (struct servent *&p)
{
if (p)
{
debug_printf ("servent: %s", p->s_name);
if (p->s_name)
free (p->s_name);
if (p->s_proto)
free (p->s_proto);
free_char_list (p->s_aliases);
free ((void *) p);
p = NULL;
}
}
#pragma pack(push,2)
struct pservent
{
char *s_name;
char **s_aliases;
short s_port;
char *s_proto;
};
#pragma pack(pop)
static struct servent *
dup_servent_ptr (struct servent *src)
{
if (!src)
return NULL;
struct servent *dst = (struct servent *) calloc (1, sizeof *dst);
if (!dst)
return NULL;
debug_printf ("servent: %s", src->s_name);
dst->s_port = src->s_port;
if (src->s_name && !(dst->s_name = strdup (src->s_name)))
goto out;
if (src->s_aliases && !(dst->s_aliases = dup_char_list (src->s_aliases)))
goto out;
char *s_proto;
if (IsBadReadPtr (src->s_proto, sizeof (src->s_proto))
&& !IsBadReadPtr (((pservent *) src)->s_proto, sizeof (src->s_proto)))
s_proto = ((pservent *) src)->s_proto;
else
s_proto = src->s_proto;
if (s_proto && !(dst->s_proto = strdup (s_proto)))
goto out;
debug_printf ("servent: copied %s", dst->s_name);
return dst;
out:
free_servent_ptr (dst);
return NULL;
}
gen_ent (servent, s)
#ifdef _MT_SAFE
#define servent_buf _reent_winsup ()->_servent_buf
@ -909,8 +960,7 @@ cygwin_getservbyname (const char *name, const char *proto)
|| (proto != NULL && check_null_str_errno (proto)))
return NULL;
free_servent_ptr (servent_buf);
servent_buf = dup_servent_ptr (getservbyname (name, proto));
servent_buf = dup_servent_ptr (servent_buf, getservbyname (name, proto));
if (!servent_buf)
set_winsock_errno ();
@ -927,8 +977,7 @@ cygwin_getservbyport (int port, const char *proto)
if (proto != NULL && check_null_str_errno (proto))
return NULL;
free_servent_ptr (servent_buf);
servent_buf = dup_servent_ptr (getservbyport (port, proto));
servent_buf = dup_servent_ptr (servent_buf, getservbyport (port, proto));
if (!servent_buf)
set_winsock_errno ();
@ -959,53 +1008,7 @@ cygwin_gethostname (char *name, size_t len)
return 0;
}
static void
free_hostent_ptr (struct hostent *&p)
{
if (p)
{
debug_printf ("hostent: %s", p->h_name);
if (p->h_name)
free ((void *) p->h_name);
free_char_list (p->h_aliases);
free_addr_list (p->h_addr_list);
free ((void *) p);
p = NULL;
}
}
static struct hostent *
dup_hostent_ptr (struct hostent *src)
{
if (!src)
return NULL;
struct hostent *dst = (struct hostent *) calloc (1, sizeof *dst);
if (!dst)
return NULL;
debug_printf ("hostent: %s", src->h_name);
dst->h_addrtype = src->h_addrtype;
dst->h_length = src->h_length;
if (src->h_name && !(dst->h_name = strdup (src->h_name)))
goto out;
if (src->h_aliases && !(dst->h_aliases = dup_char_list (src->h_aliases)))
goto out;
if (src->h_addr_list
&& !(dst->h_addr_list = dup_addr_list (src->h_addr_list, src->h_length)))
goto out;
debug_printf ("hostent: copied %s", dst->h_name);
return dst;
out:
free_hostent_ptr (dst);
return NULL;
}
gen_ent (hostent, h)
#ifdef _MT_SAFE
#define hostent_buf _reent_winsup ()->_hostent_buf
@ -1045,8 +1048,7 @@ cygwin_gethostbyname (const char *name)
return &tmp;
}
free_hostent_ptr (hostent_buf);
hostent_buf = dup_hostent_ptr (gethostbyname (name));
hostent_buf = dup_hostent_ptr (hostent_buf, gethostbyname (name));
if (!hostent_buf)
{
set_winsock_errno ();
@ -1069,8 +1071,7 @@ cygwin_gethostbyaddr (const char *addr, int len, int type)
if (__check_invalid_read_ptr_errno (addr, len))
return NULL;
free_hostent_ptr (hostent_buf);
hostent_buf = dup_hostent_ptr (gethostbyaddr (addr, len, type));
hostent_buf = dup_hostent_ptr (hostent_buf, gethostbyaddr (addr, len, type));
if (!hostent_buf)
{
set_winsock_errno ();