summaryrefslogtreecommitdiff
path: root/nss/nss_files
diff options
context:
space:
mode:
Diffstat (limited to 'nss/nss_files')
-rw-r--r--nss/nss_files/files-XXX.c158
-rw-r--r--nss/nss_files/files-alias.c37
-rw-r--r--nss/nss_files/files-ethers.c2
-rw-r--r--nss/nss_files/files-grp.c2
-rw-r--r--nss/nss_files/files-have_o_cloexec.c23
-rw-r--r--nss/nss_files/files-hosts.c410
-rw-r--r--nss/nss_files/files-init.c2
-rw-r--r--nss/nss_files/files-initgroups.c34
-rw-r--r--nss/nss_files/files-key.c2
-rw-r--r--nss/nss_files/files-netgrp.c2
-rw-r--r--nss/nss_files/files-network.c2
-rw-r--r--nss/nss_files/files-parse.c2
-rw-r--r--nss/nss_files/files-proto.c2
-rw-r--r--nss/nss_files/files-pwd.c2
-rw-r--r--nss/nss_files/files-rpc.c2
-rw-r--r--nss/nss_files/files-service.c2
-rw-r--r--nss/nss_files/files-sgrp.c2
-rw-r--r--nss/nss_files/files-spwd.c2
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