diff options
Diffstat (limited to 'nss/nss_files')
-rw-r--r-- | nss/nss_files/files-XXX.c | 158 | ||||
-rw-r--r-- | nss/nss_files/files-alias.c | 37 | ||||
-rw-r--r-- | nss/nss_files/files-ethers.c | 2 | ||||
-rw-r--r-- | nss/nss_files/files-grp.c | 2 | ||||
-rw-r--r-- | nss/nss_files/files-have_o_cloexec.c | 23 | ||||
-rw-r--r-- | nss/nss_files/files-hosts.c | 410 | ||||
-rw-r--r-- | nss/nss_files/files-init.c | 2 | ||||
-rw-r--r-- | nss/nss_files/files-initgroups.c | 34 | ||||
-rw-r--r-- | nss/nss_files/files-key.c | 2 | ||||
-rw-r--r-- | nss/nss_files/files-netgrp.c | 2 | ||||
-rw-r--r-- | nss/nss_files/files-network.c | 2 | ||||
-rw-r--r-- | nss/nss_files/files-parse.c | 2 | ||||
-rw-r--r-- | nss/nss_files/files-proto.c | 2 | ||||
-rw-r--r-- | nss/nss_files/files-pwd.c | 2 | ||||
-rw-r--r-- | nss/nss_files/files-rpc.c | 2 | ||||
-rw-r--r-- | nss/nss_files/files-service.c | 2 | ||||
-rw-r--r-- | nss/nss_files/files-sgrp.c | 2 | ||||
-rw-r--r-- | nss/nss_files/files-spwd.c | 2 |
18 files changed, 293 insertions, 395 deletions
diff --git a/nss/nss_files/files-XXX.c b/nss/nss_files/files-XXX.c index 3215393ff1..60d1544a96 100644 --- a/nss/nss_files/files-XXX.c +++ b/nss/nss_files/files-XXX.c @@ -1,5 +1,5 @@ /* Common code for file-based databases in nss_files module. - Copyright (C) 1996-2016 Free Software Foundation, Inc. + Copyright (C) 1996-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -78,41 +78,6 @@ internal_setent (FILE **stream) if (*stream == NULL) status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; - else - { -#if !defined O_CLOEXEC || !defined __ASSUME_O_CLOEXEC -# ifdef O_CLOEXEC - if (__have_o_cloexec <= 0) -# endif - { - /* We have to make sure the file is `closed on exec'. */ - int result; - int flags; - - result = flags = fcntl (fileno (*stream), F_GETFD, 0); - if (result >= 0) - { -# ifdef O_CLOEXEC - if (__have_o_cloexec == 0) - __have_o_cloexec = (flags & FD_CLOEXEC) == 0 ? -1 : 1; - if (__have_o_cloexec < 0) -# endif - { - flags |= FD_CLOEXEC; - result = fcntl (fileno (*stream), F_SETFD, flags); - } - } - if (result < 0) - { - /* Something went wrong. Close the stream and return a - failure. */ - fclose (*stream); - *stream = NULL; - status = NSS_STATUS_UNAVAIL; - } - } -#endif - } } else rewind (*stream); @@ -163,51 +128,6 @@ CONCAT(_nss_files_end,ENTNAME) (void) } -typedef enum -{ - gcr_ok = 0, - gcr_error = -1, - gcr_overflow = -2 -} get_contents_ret; - -/* Hack around the fact that fgets only accepts int sizes. */ -static get_contents_ret -get_contents (char *linebuf, size_t len, FILE *stream) -{ - size_t remaining_len = len; - char *curbuf = linebuf; - - do - { - int curlen = ((remaining_len > (size_t) INT_MAX) ? INT_MAX - : remaining_len); - - /* Terminate the line so that we can test for overflow. */ - ((unsigned char *) curbuf)[curlen - 1] = 0xff; - - char *p = fgets_unlocked (curbuf, curlen, stream); - - /* EOF or read error. */ - if (p == NULL) - return gcr_error; - - /* Done reading in the line. */ - if (((unsigned char *) curbuf)[curlen - 1] == 0xff) - return gcr_ok; - - /* Drop the terminating '\0'. */ - remaining_len -= curlen - 1; - curbuf += curlen - 1; - } - /* fgets copies one less than the input length. Our last iteration is of - REMAINING_LEN and once that is done, REMAINING_LEN is decremented by - REMAINING_LEN - 1, leaving the result as 1. */ - while (remaining_len > 1); - - /* This means that the current buffer was not large enough. */ - return gcr_overflow; -} - /* Parsing the database file into `struct STRUCTURE' data structures. */ static enum nss_status internal_getent (FILE *stream, struct STRUCTURE *result, @@ -226,45 +146,69 @@ internal_getent (FILE *stream, struct STRUCTURE *result, return NSS_STATUS_TRYAGAIN; } - do + while (true) { - get_contents_ret r = get_contents (data->linebuffer, linebuflen, stream); - - if (r == gcr_error) + ssize_t r = __libc_readline_unlocked + (stream, data->linebuffer, linebuflen); + if (r < 0) { - /* End of file or read error. */ + *errnop = errno; + H_ERRNO_SET (NETDB_INTERNAL); + if (*errnop == ERANGE) + /* Request larger buffer. */ + return NSS_STATUS_TRYAGAIN; + else + /* Other read failure. */ + return NSS_STATUS_UNAVAIL; + } + else if (r == 0) + { + /* End of file. */ H_ERRNO_SET (HOST_NOT_FOUND); return NSS_STATUS_NOTFOUND; } - if (r == gcr_overflow) + /* Everything OK. Now skip leading blanks. */ + p = data->linebuffer; + while (isspace (*p)) + ++p; + + /* Ignore empty and comment lines. */ + if (*p == '\0' || *p == '#') + continue; + + /* Parse the line. */ + *errnop = EINVAL; + parse_result = parse_line (p, result, data, buflen, errnop EXTRA_ARGS); + + if (parse_result == -1) { - /* The line is too long. Give the user the opportunity to - enlarge the buffer. */ - *errnop = ERANGE; + if (*errnop == ERANGE) + { + /* Return to the original file position at the beginning + of the line, so that the next call can read it again + if necessary. */ + if (__fseeko64 (stream, -r, SEEK_CUR) != 0) + { + if (errno == ERANGE) + *errnop = EINVAL; + else + *errnop = errno; + H_ERRNO_SET (NETDB_INTERNAL); + return NSS_STATUS_UNAVAIL; + } + } H_ERRNO_SET (NETDB_INTERNAL); return NSS_STATUS_TRYAGAIN; } - /* Everything OK. Now skip leading blanks. */ - p = data->linebuffer; - while (isspace (*p)) - ++p; - } - while (*p == '\0' || *p == '#' /* Ignore empty and comment lines. */ - /* Parse the line. If it is invalid, loop to get the next - line of the file to parse. */ - || ! (parse_result = parse_line (p, result, data, buflen, errnop - EXTRA_ARGS))); + /* Return the data if parsed successfully. */ + if (parse_result != 0) + return NSS_STATUS_SUCCESS; - if (__glibc_unlikely (parse_result == -1)) - { - H_ERRNO_SET (NETDB_INTERNAL); - return NSS_STATUS_TRYAGAIN; + /* If it is invalid, loop to get the next line of the file to + parse. */ } - - /* Filled in RESULT with the next entry from the database file. */ - return NSS_STATUS_SUCCESS; } diff --git a/nss/nss_files/files-alias.c b/nss/nss_files/files-alias.c index 94872b7569..cfd34b66b9 100644 --- a/nss/nss_files/files-alias.c +++ b/nss/nss_files/files-alias.c @@ -1,5 +1,5 @@ /* Mail alias file parser in nss_files module. - Copyright (C) 1996-2016 Free Software Foundation, Inc. + Copyright (C) 1996-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. @@ -51,41 +51,6 @@ internal_setent (FILE **stream) if (*stream == NULL) status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; - else - { -#if !defined O_CLOEXEC || !defined __ASSUME_O_CLOEXEC -# ifdef O_CLOEXEC - if (__have_o_cloexec <= 0) -# endif - { - /* We have to make sure the file is `closed on exec'. */ - int result; - int flags; - - result = flags = fcntl (fileno (*stream), F_GETFD, 0); - if (result >= 0) - { -# ifdef O_CLOEXEC - if (__have_o_cloexec == 0) - __have_o_cloexec = (flags & FD_CLOEXEC) == 0 ? -1 : 1; - if (__have_o_cloexec < 0) -# endif - { - flags |= FD_CLOEXEC; - result = fcntl (fileno (*stream), F_SETFD, flags); - } - } - if (result < 0) - { - /* Something went wrong. Close the stream and return a - failure. */ - fclose (*stream); - stream = NULL; - status = NSS_STATUS_UNAVAIL; - } - } -#endif - } } else rewind (*stream); diff --git a/nss/nss_files/files-ethers.c b/nss/nss_files/files-ethers.c index 57104f07c8..2fdbc37649 100644 --- a/nss/nss_files/files-ethers.c +++ b/nss/nss_files/files-ethers.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-2016 Free Software Foundation, Inc. +/* Copyright (C) 1996-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or diff --git a/nss/nss_files/files-grp.c b/nss/nss_files/files-grp.c index 29d1e5e40a..9a20b15495 100644 --- a/nss/nss_files/files-grp.c +++ b/nss/nss_files/files-grp.c @@ -1,5 +1,5 @@ /* Group file parser in nss_files module. - Copyright (C) 1996-2016 Free Software Foundation, Inc. + Copyright (C) 1996-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or diff --git a/nss/nss_files/files-have_o_cloexec.c b/nss/nss_files/files-have_o_cloexec.c deleted file mode 100644 index 30f79ac40c..0000000000 --- a/nss/nss_files/files-have_o_cloexec.c +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (C) 2007-2016 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <fcntl.h> -#include <kernel-features.h> - -#if defined O_CLOEXEC && !defined __ASSUME_O_CLOEXEC -int __have_o_cloexec; -#endif diff --git a/nss/nss_files/files-hosts.c b/nss/nss_files/files-hosts.c index 2a4a665d7e..87c0af8cfe 100644 --- a/nss/nss_files/files-hosts.c +++ b/nss/nss_files/files-hosts.c @@ -1,5 +1,5 @@ /* Hosts file parser in nss_files module. - Copyright (C) 1996-2016 Free Software Foundation, Inc. + Copyright (C) 1996-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -21,7 +21,9 @@ #include <arpa/inet.h> #include <arpa/nameser.h> #include <netdb.h> -#include <resolv.h> +#include <resolv/resolv-internal.h> +#include <scratch_buffer.h> +#include <alloc_buffer.h> /* Get implementation for some internal functions. */ @@ -98,8 +100,8 @@ LINE_PARSER }) #define EXTRA_ARGS_VALUE \ - , ((_res.options & RES_USE_INET6) ? AF_INET6 : AF_INET), \ - ((_res.options & RES_USE_INET6) ? AI_V4MAPPED : 0) + , (res_use_inet6 () ? AF_INET6 : AF_INET), \ + (res_use_inet6 () ? AI_V4MAPPED : 0) #include "files-XXX.c" #undef EXTRA_ARGS_VALUE @@ -115,228 +117,250 @@ DB_LOOKUP (hostbyaddr, ,,, }, const void *addr, socklen_t len, int af) #undef EXTRA_ARGS_VALUE -enum nss_status -_nss_files_gethostbyname3_r (const char *name, int af, struct hostent *result, - char *buffer, size_t buflen, int *errnop, - int *herrnop, int32_t *ttlp, char **canonp) -{ - FILE *stream = NULL; - uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct hostent_data); - buffer += pad; - buflen = buflen > pad ? buflen - pad : 0; +/* Type of the address and alias arrays. */ +#define DYNARRAY_STRUCT array +#define DYNARRAY_ELEMENT char * +#define DYNARRAY_PREFIX array_ +#include <malloc/dynarray-skeleton.c> - /* Open file. */ - enum nss_status status = internal_setent (&stream); +static enum nss_status +gethostbyname3_multi (FILE * stream, const char *name, int af, + struct hostent *result, char *buffer, size_t buflen, + int *errnop, int *herrnop, int flags) +{ + assert (af == AF_INET || af == AF_INET6); + + /* We have to get all host entries from the file. */ + struct scratch_buffer tmp_buffer; + scratch_buffer_init (&tmp_buffer); + struct hostent tmp_result_buf; + struct array addresses; + array_init (&addresses); + struct array aliases; + array_init (&aliases); + enum nss_status status; + + /* Preserve the addresses and aliases encountered so far. */ + for (size_t i = 0; result->h_addr_list[i] != NULL; ++i) + array_add (&addresses, result->h_addr_list[i]); + for (size_t i = 0; result->h_aliases[i] != NULL; ++i) + array_add (&aliases, result->h_aliases[i]); + + /* The output buffer re-uses now-unused space at the end of the + buffer, starting with the aliases array. It comes last in the + data produced by internal_getent. (The alias names themselves + are still located in the line read in internal_getent, which is + stored at the beginning of the buffer.) */ + struct alloc_buffer outbuf; + { + char *bufferend = (char *) result->h_aliases; + outbuf = alloc_buffer_create (bufferend, buffer + buflen - bufferend); + } - if (status == NSS_STATUS_SUCCESS) + while (true) { - /* XXX Is using _res to determine whether we want to convert IPv4 - addresses to IPv6 addresses really the right thing to do? */ - int flags = ((_res.options & RES_USE_INET6) ? AI_V4MAPPED : 0); - - while ((status = internal_getent (stream, result, buffer, buflen, errnop, - herrnop, af, flags)) - == NSS_STATUS_SUCCESS) + status = internal_getent (stream, &tmp_result_buf, tmp_buffer.data, + tmp_buffer.length, errnop, herrnop, af, + flags); + /* Enlarge the buffer if necessary. */ + if (status == NSS_STATUS_TRYAGAIN && *herrnop == NETDB_INTERNAL + && *errnop == ERANGE) { - LOOKUP_NAME_CASE (h_name, h_aliases) + if (!scratch_buffer_grow (&tmp_buffer)) + { + *errnop = ENOMEM; + /* *herrnop and status already have the right value. */ + break; + } + /* Loop around and retry with a larger buffer. */ } - - if (status == NSS_STATUS_SUCCESS - && _res_hconf.flags & HCONF_FLAG_MULTI) + else if (status == NSS_STATUS_SUCCESS) { - /* We have to get all host entries from the file. */ - size_t tmp_buflen = MIN (buflen, 4096); - char tmp_buffer_stack[tmp_buflen] - __attribute__ ((__aligned__ (__alignof__ (struct hostent_data)))); - char *tmp_buffer = tmp_buffer_stack; - struct hostent tmp_result_buf; - int naddrs = 1; - int naliases = 0; - char *bufferend; - bool tmp_buffer_malloced = false; - - while (result->h_aliases[naliases] != NULL) - ++naliases; - - bufferend = (char *) &result->h_aliases[naliases + 1]; - - again: - while ((status = internal_getent (stream, &tmp_result_buf, tmp_buffer, - tmp_buflen, errnop, herrnop, af, - flags)) - == NSS_STATUS_SUCCESS) + /* A line was read. Check that it matches the search + criteria. */ + + int matches = 1; + struct hostent *old_result = result; + result = &tmp_result_buf; + /* The following piece is a bit clumsy but we want to use + the `LOOKUP_NAME_CASE' value. The optimizer should do + its job. */ + do { - int matches = 1; - struct hostent *old_result = result; - result = &tmp_result_buf; - /* The following piece is a bit clumsy but we want to use the - `LOOKUP_NAME_CASE' value. The optimizer should do its - job. */ - do - { - LOOKUP_NAME_CASE (h_name, h_aliases) - result = old_result; - } - while ((matches = 0)); + LOOKUP_NAME_CASE (h_name, h_aliases) + result = old_result; + } + while ((matches = 0)); - if (matches) + /* If the line matches, we need to copy the addresses and + aliases, so that we can reuse tmp_buffer for the next + line. */ + if (matches) + { + /* Record the addresses. */ + for (size_t i = 0; tmp_result_buf.h_addr_list[i] != NULL; ++i) { - /* We could be very clever and try to recycle a few bytes - in the buffer instead of generating new arrays. But - we are not doing this here since it's more work than - it's worth. Simply let the user provide a bit bigger - buffer. */ - char **new_h_addr_list; - char **new_h_aliases; - int newaliases = 0; - size_t newstrlen = 0; - int cnt; - - /* Count the new aliases and the length of the strings. */ - while (tmp_result_buf.h_aliases[newaliases] != NULL) + /* Allocate the target space in the output buffer, + depending on the address family. */ + void *target; + if (af == AF_INET) { - char *cp = tmp_result_buf.h_aliases[newaliases]; - ++newaliases; - newstrlen += strlen (cp) + 1; + assert (tmp_result_buf.h_length == 4); + target = alloc_buffer_alloc (&outbuf, struct in_addr); } - /* If the real name is different add it also to the - aliases. This means that there is a duplication - in the alias list but this is really the user's - problem. */ - if (strcmp (old_result->h_name, - tmp_result_buf.h_name) != 0) + else if (af == AF_INET6) { - ++newaliases; - newstrlen += strlen (tmp_result_buf.h_name) + 1; + assert (tmp_result_buf.h_length == 16); + target = alloc_buffer_alloc (&outbuf, struct in6_addr); } + else + __builtin_unreachable (); - /* Make sure bufferend is aligned. */ - assert ((bufferend - (char *) 0) % sizeof (char *) == 0); - - /* Now we can check whether the buffer is large enough. - 16 is the maximal size of the IP address. */ - if (bufferend + 16 + (naddrs + 2) * sizeof (char *) - + roundup (newstrlen, sizeof (char *)) - + (naliases + newaliases + 1) * sizeof (char *) - >= buffer + buflen) + if (target == NULL) { + /* Request a larger output buffer. */ *errnop = ERANGE; *herrnop = NETDB_INTERNAL; status = NSS_STATUS_TRYAGAIN; - goto out; + break; } + memcpy (target, tmp_result_buf.h_addr_list[i], + tmp_result_buf.h_length); + array_add (&addresses, target); + } - new_h_addr_list = - (char **) (bufferend - + roundup (newstrlen, sizeof (char *)) - + 16); - new_h_aliases = - (char **) ((char *) new_h_addr_list - + (naddrs + 2) * sizeof (char *)); + /* Record the aliases. */ + for (size_t i = 0; tmp_result_buf.h_aliases[i] != NULL; ++i) + { + char *alias = tmp_result_buf.h_aliases[i]; + array_add (&aliases, + alloc_buffer_copy_string (&outbuf, alias)); + } - /* Copy the old data in the new arrays. */ - for (cnt = 0; cnt < naddrs; ++cnt) - new_h_addr_list[cnt] = old_result->h_addr_list[cnt]; + /* If the real name is different add, it also to the + aliases. This means that there is a duplication in + the alias list but this is really the user's + problem. */ + { + char *new_name = tmp_result_buf.h_name; + if (strcmp (old_result->h_name, new_name) != 0) + array_add (&aliases, + alloc_buffer_copy_string (&outbuf, new_name)); + } + + /* Report memory allocation failures during the + expansion of the temporary arrays. */ + if (array_has_failed (&addresses) || array_has_failed (&aliases)) + { + *errnop = ENOMEM; + *herrnop = NETDB_INTERNAL; + status = NSS_STATUS_UNAVAIL; + break; + } - for (cnt = 0; cnt < naliases; ++cnt) - new_h_aliases[cnt] = old_result->h_aliases[cnt]; + /* Request a larger output buffer if we ran out of room. */ + if (alloc_buffer_has_failed (&outbuf)) + { + *errnop = ERANGE; + *herrnop = NETDB_INTERNAL; + status = NSS_STATUS_TRYAGAIN; + break; + } - /* Store the new strings. */ - cnt = 0; - while (tmp_result_buf.h_aliases[cnt] != NULL) - { - new_h_aliases[naliases++] = bufferend; - bufferend = (__stpcpy (bufferend, - tmp_result_buf.h_aliases[cnt]) - + 1); - ++cnt; - } + result = old_result; + } /* If match was found. */ - if (cnt < newaliases) - { - new_h_aliases[naliases++] = bufferend; - bufferend = __stpcpy (bufferend, - tmp_result_buf.h_name) + 1; - } + /* If no match is found, loop around and fetch another + line. */ - /* Final NULL pointer. */ - new_h_aliases[naliases] = NULL; + } /* status == NSS_STATUS_SUCCESS. */ + else + /* internal_getent returned an error. */ + break; + } /* while (true) */ - /* Round up the buffer end address. */ - bufferend += (sizeof (char *) - - ((bufferend - (char *) 0) - % sizeof (char *))) % sizeof (char *); + /* Propagate the NSS_STATUS_TRYAGAIN error to the caller. It means + that we may not have loaded the complete result. + NSS_STATUS_NOTFOUND, however, means that we reached the end of + the file successfully. */ + if (status != NSS_STATUS_TRYAGAIN) + status = NSS_STATUS_SUCCESS; - /* Now the new address. */ - new_h_addr_list[naddrs++] = - memcpy (bufferend, tmp_result_buf.h_addr, - tmp_result_buf.h_length); + if (status == NSS_STATUS_SUCCESS) + { + /* Copy the address and alias arrays into the output buffer and + add NULL terminators. The pointed-to elements were directly + written into the output buffer above and do not need to be + copied again. */ + size_t addresses_count = array_size (&addresses); + size_t aliases_count = array_size (&aliases); + char **out_addresses = alloc_buffer_alloc_array + (&outbuf, char *, addresses_count + 1); + char **out_aliases = alloc_buffer_alloc_array + (&outbuf, char *, aliases_count + 1); + if (out_addresses == NULL || out_aliases == NULL) + { + /* The output buffer is not large enough. */ + *errnop = ERANGE; + *herrnop = NETDB_INTERNAL; + status = NSS_STATUS_TRYAGAIN; + /* Fall through to function exit. */ + } + else + { + /* Everything is allocated in place. Make the copies and + adjust the array pointers. */ + memcpy (out_addresses, array_begin (&addresses), + addresses_count * sizeof (char *)); + out_addresses[addresses_count] = NULL; + memcpy (out_aliases, array_begin (&aliases), + aliases_count * sizeof (char *)); + out_aliases[aliases_count] = NULL; + + result->h_addr_list = out_addresses; + result->h_aliases = out_aliases; - /* Also here a final NULL pointer. */ - new_h_addr_list[naddrs] = NULL; + status = NSS_STATUS_SUCCESS; + } + } - /* Store the new array pointers. */ - old_result->h_aliases = new_h_aliases; - old_result->h_addr_list = new_h_addr_list; + scratch_buffer_free (&tmp_buffer); + array_free (&addresses); + array_free (&aliases); + return status; +} - /* Compute the new buffer end. */ - bufferend = (char *) &new_h_aliases[naliases + 1]; - assert (bufferend <= buffer + buflen); +enum nss_status +_nss_files_gethostbyname3_r (const char *name, int af, struct hostent *result, + char *buffer, size_t buflen, int *errnop, + int *herrnop, int32_t *ttlp, char **canonp) +{ + FILE *stream = NULL; + uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct hostent_data); + buffer += pad; + buflen = buflen > pad ? buflen - pad : 0; - result = old_result; - } - } + /* Open file. */ + enum nss_status status = internal_setent (&stream); - if (status == NSS_STATUS_TRYAGAIN) - { - size_t newsize = 2 * tmp_buflen; - if (tmp_buffer_malloced) - { - char *newp = realloc (tmp_buffer, newsize); - if (newp != NULL) - { - assert ((((uintptr_t) newp) - & (__alignof__ (struct hostent_data) - 1)) - == 0); - tmp_buffer = newp; - tmp_buflen = newsize; - goto again; - } - } - else if (!__libc_use_alloca (buflen + newsize)) - { - tmp_buffer = malloc (newsize); - if (tmp_buffer != NULL) - { - assert ((((uintptr_t) tmp_buffer) - & (__alignof__ (struct hostent_data) - 1)) - == 0); - tmp_buffer_malloced = true; - tmp_buflen = newsize; - goto again; - } - } - else - { - tmp_buffer - = extend_alloca (tmp_buffer, tmp_buflen, - newsize - + __alignof__ (struct hostent_data)); - tmp_buffer = (char *) (((uintptr_t) tmp_buffer - + __alignof__ (struct hostent_data) - - 1) - & ~(__alignof__ (struct hostent_data) - - 1)); - goto again; - } - } - else - status = NSS_STATUS_SUCCESS; - out: - if (tmp_buffer_malloced) - free (tmp_buffer); + if (status == NSS_STATUS_SUCCESS) + { + /* XXX Is using _res to determine whether we want to convert IPv4 + addresses to IPv6 addresses really the right thing to do? */ + int flags = (res_use_inet6 () ? AI_V4MAPPED : 0); + + while ((status = internal_getent (stream, result, buffer, buflen, errnop, + herrnop, af, flags)) + == NSS_STATUS_SUCCESS) + { + LOOKUP_NAME_CASE (h_name, h_aliases) } + if (status == NSS_STATUS_SUCCESS + && _res_hconf.flags & HCONF_FLAG_MULTI) + status = gethostbyname3_multi + (stream, name, af, result, buffer, buflen, errnop, herrnop, flags); + internal_endent (&stream); } @@ -351,7 +375,7 @@ _nss_files_gethostbyname_r (const char *name, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *herrnop) { - int af = ((_res.options & RES_USE_INET6) ? AF_INET6 : AF_INET); + int af = (res_use_inet6 () ? AF_INET6 : AF_INET); return _nss_files_gethostbyname3_r (name, af, result, buffer, buflen, errnop, herrnop, NULL, NULL); diff --git a/nss/nss_files/files-init.c b/nss/nss_files/files-init.c index 9d465292ae..3efe26ab66 100644 --- a/nss/nss_files/files-init.c +++ b/nss/nss_files/files-init.c @@ -1,5 +1,5 @@ /* Initialization in nss_files module. - Copyright (C) 2011-2016 Free Software Foundation, Inc. + Copyright (C) 2011-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or diff --git a/nss/nss_files/files-initgroups.c b/nss/nss_files/files-initgroups.c index 6e0d8258da..b441d8345f 100644 --- a/nss/nss_files/files-initgroups.c +++ b/nss/nss_files/files-initgroups.c @@ -1,5 +1,5 @@ /* Initgroups handling in nss_files module. - Copyright (C) 2011-2016 Free Software Foundation, Inc. + Copyright (C) 2011-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -16,7 +16,6 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ -#include <alloca.h> #include <errno.h> #include <grp.h> #include <nss.h> @@ -25,6 +24,7 @@ #include <sys/param.h> #include <stdbool.h> #include <stdlib.h> +#include <scratch_buffer.h> enum nss_status _nss_files_initgroups_dyn (const char *user, gid_t group, long int *start, @@ -46,9 +46,8 @@ _nss_files_initgroups_dyn (const char *user, gid_t group, long int *start, enum nss_status status = NSS_STATUS_SUCCESS; bool any = false; - size_t buflen = 1024; - void *buffer = alloca (buflen); - bool buffer_use_malloc = false; + struct scratch_buffer tmpbuf; + scratch_buffer_init (&tmpbuf); gid_t *groups = *groupsp; @@ -67,26 +66,16 @@ _nss_files_initgroups_dyn (const char *user, gid_t group, long int *start, } struct group grp; - int res = _nss_files_parse_grent (line, &grp, buffer, buflen, errnop); + int res = _nss_files_parse_grent (line, &grp, + tmpbuf.data, tmpbuf.length, errnop); if (res == -1) { - size_t newbuflen = 2 * buflen; - if (buffer_use_malloc || ! __libc_use_alloca (buflen + newbuflen)) + if (!scratch_buffer_grow (&tmpbuf)) { - void *newbuf = realloc (buffer_use_malloc ? buffer : NULL, - newbuflen); - if (newbuf == NULL) - { - *errnop = ENOMEM; - status = NSS_STATUS_TRYAGAIN; - goto out; - } - buffer = newbuf; - buflen = newbuflen; - buffer_use_malloc = true; + *errnop = ENOMEM; + status = NSS_STATUS_TRYAGAIN; + goto out; } - else - buffer = extend_alloca (buffer, buflen, newbuflen); /* Reread current line, the parser has clobbered it. */ fsetpos (stream, &pos); continue; @@ -132,8 +121,7 @@ _nss_files_initgroups_dyn (const char *user, gid_t group, long int *start, out: /* Free memory. */ - if (buffer_use_malloc) - free (buffer); + scratch_buffer_free (&tmpbuf); free (line); fclose (stream); diff --git a/nss/nss_files/files-key.c b/nss/nss_files/files-key.c index 5af7ea2dd0..44d4348a80 100644 --- a/nss/nss_files/files-key.c +++ b/nss/nss_files/files-key.c @@ -1,5 +1,5 @@ /* Public key file parser in nss_files module. - Copyright (C) 1996-2016 Free Software Foundation, Inc. + Copyright (C) 1996-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or diff --git a/nss/nss_files/files-netgrp.c b/nss/nss_files/files-netgrp.c index a1c46b3ca9..f910ba2f8d 100644 --- a/nss/nss_files/files-netgrp.c +++ b/nss/nss_files/files-netgrp.c @@ -1,5 +1,5 @@ /* Netgroup file parser in nss_files modules. - Copyright (C) 1996-2016 Free Software Foundation, Inc. + Copyright (C) 1996-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. diff --git a/nss/nss_files/files-network.c b/nss/nss_files/files-network.c index 8c95ed5286..2a8605eb5b 100644 --- a/nss/nss_files/files-network.c +++ b/nss/nss_files/files-network.c @@ -1,5 +1,5 @@ /* Networks file parser in nss_files module. - Copyright (C) 1996-2016 Free Software Foundation, Inc. + Copyright (C) 1996-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or diff --git a/nss/nss_files/files-parse.c b/nss/nss_files/files-parse.c index 36487541f1..97f5167d83 100644 --- a/nss/nss_files/files-parse.c +++ b/nss/nss_files/files-parse.c @@ -1,5 +1,5 @@ /* Common code for file-based database parsers in nss_files module. - Copyright (C) 1996-2016 Free Software Foundation, Inc. + Copyright (C) 1996-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or diff --git a/nss/nss_files/files-proto.c b/nss/nss_files/files-proto.c index 90a85f07c4..19316a0418 100644 --- a/nss/nss_files/files-proto.c +++ b/nss/nss_files/files-proto.c @@ -1,5 +1,5 @@ /* Protocols file parser in nss_files module. - Copyright (C) 1996-2016 Free Software Foundation, Inc. + Copyright (C) 1996-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or diff --git a/nss/nss_files/files-pwd.c b/nss/nss_files/files-pwd.c index 823e58ad06..1648fc04d9 100644 --- a/nss/nss_files/files-pwd.c +++ b/nss/nss_files/files-pwd.c @@ -1,5 +1,5 @@ /* User file parser in nss_files module. - Copyright (C) 1996-2016 Free Software Foundation, Inc. + Copyright (C) 1996-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or diff --git a/nss/nss_files/files-rpc.c b/nss/nss_files/files-rpc.c index 5b9a91f058..f162d469f1 100644 --- a/nss/nss_files/files-rpc.c +++ b/nss/nss_files/files-rpc.c @@ -1,5 +1,5 @@ /* SunRPC program number file parser in nss_files module. - Copyright (C) 1996-2016 Free Software Foundation, Inc. + Copyright (C) 1996-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or diff --git a/nss/nss_files/files-service.c b/nss/nss_files/files-service.c index 7a6e2266d1..5ec79a2770 100644 --- a/nss/nss_files/files-service.c +++ b/nss/nss_files/files-service.c @@ -1,5 +1,5 @@ /* Services file parser in nss_files module. - Copyright (C) 1996-2016 Free Software Foundation, Inc. + Copyright (C) 1996-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or diff --git a/nss/nss_files/files-sgrp.c b/nss/nss_files/files-sgrp.c index 15dc65964c..c4af2bd2fa 100644 --- a/nss/nss_files/files-sgrp.c +++ b/nss/nss_files/files-sgrp.c @@ -1,5 +1,5 @@ /* User file parser in nss_files module. - Copyright (C) 2009-2016 Free Software Foundation, Inc. + Copyright (C) 2009-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or diff --git a/nss/nss_files/files-spwd.c b/nss/nss_files/files-spwd.c index 652dc1394a..5012cd969e 100644 --- a/nss/nss_files/files-spwd.c +++ b/nss/nss_files/files-spwd.c @@ -1,5 +1,5 @@ /* User file parser in nss_files module. - Copyright (C) 1996-2016 Free Software Foundation, Inc. + Copyright (C) 1996-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or |