diff options
Diffstat (limited to 'sysdeps/posix')
92 files changed, 1071 insertions, 1180 deletions
diff --git a/sysdeps/posix/alarm.c b/sysdeps/posix/alarm.c index 47b7477e6d..91543cef18 100644 --- a/sysdeps/posix/alarm.c +++ b/sysdeps/posix/alarm.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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/sysdeps/posix/clock.c b/sysdeps/posix/clock.c index 04ac806410..52382b72c1 100644 --- a/sysdeps/posix/clock.c +++ b/sysdeps/posix/clock.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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/sysdeps/posix/clock_getres.c b/sysdeps/posix/clock_getres.c index fb328d78a9..e7924e0891 100644 --- a/sysdeps/posix/clock_getres.c +++ b/sysdeps/posix/clock_getres.c @@ -1,5 +1,5 @@ /* clock_getres -- Get the resolution of a POSIX clockid_t. - Copyright (C) 1999-2016 Free Software Foundation, Inc. + Copyright (C) 1999-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 @@ -58,7 +58,7 @@ hp_timing_getres (struct timespec *res) static inline int realtime_getres (struct timespec *res) { - long int clk_tck = sysconf (_SC_CLK_TCK); + long int clk_tck = __sysconf (_SC_CLK_TCK); if (__glibc_likely (clk_tck != -1)) { diff --git a/sysdeps/posix/closedir.c b/sysdeps/posix/closedir.c index 960cdec8d3..9b1e698762 100644 --- a/sysdeps/posix/closedir.c +++ b/sysdeps/posix/closedir.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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 @@ -49,6 +49,6 @@ __closedir (DIR *dirp) free ((void *) dirp); - return close_not_cancel (fd); + return __close_nocancel (fd); } weak_alias (__closedir, closedir) diff --git a/sysdeps/posix/ctermid.c b/sysdeps/posix/ctermid.c index 5efdab6a39..767743b4e8 100644 --- a/sysdeps/posix/ctermid.c +++ b/sysdeps/posix/ctermid.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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/sysdeps/posix/cuserid.c b/sysdeps/posix/cuserid.c index 5f5ea3a8f7..721c645608 100644 --- a/sysdeps/posix/cuserid.c +++ b/sysdeps/posix/cuserid.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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/sysdeps/posix/dirfd.c b/sysdeps/posix/dirfd.c index f47aafd83a..5afc9f37e7 100644 --- a/sysdeps/posix/dirfd.c +++ b/sysdeps/posix/dirfd.c @@ -1,5 +1,5 @@ /* Return the file descriptor used by a DIR stream. Unix version. - Copyright (C) 1995-2016 Free Software Foundation, Inc. + Copyright (C) 1995-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 @@ -22,7 +22,10 @@ #undef dirfd int -dirfd (DIR *dirp) +__dirfd (DIR *dirp) { return dirp->fd; } + +weak_alias (__dirfd, dirfd) +libc_hidden_def (dirfd) diff --git a/sysdeps/posix/dirstream.h b/sysdeps/posix/dirstream.h index 87a930d7fe..ae6faf65f5 100644 --- a/sysdeps/posix/dirstream.h +++ b/sysdeps/posix/dirstream.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1993-2016 Free Software Foundation, Inc. +/* Copyright (C) 1993-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/sysdeps/posix/dl-fileid.h b/sysdeps/posix/dl-fileid.h index c56e324e65..26bef2f9dc 100644 --- a/sysdeps/posix/dl-fileid.h +++ b/sysdeps/posix/dl-fileid.h @@ -1,5 +1,5 @@ /* File identity for the dynamic linker. Generic POSIX.1 version. - Copyright (C) 2015-2016 Free Software Foundation, Inc. + Copyright (C) 2015-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/sysdeps/posix/dup.c b/sysdeps/posix/dup.c index 9525e76749..be6ec4b2bf 100644 --- a/sysdeps/posix/dup.c +++ b/sysdeps/posix/dup.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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 @@ -24,7 +24,7 @@ int __dup (int fd) { - return fcntl (fd, F_DUPFD, 0); + return __fcntl (fd, F_DUPFD, 0); } - +libc_hidden_def (__dup) weak_alias (__dup, dup) diff --git a/sysdeps/posix/dup2.c b/sysdeps/posix/dup2.c index 9fc65029a8..6e050f5fad 100644 --- a/sysdeps/posix/dup2.c +++ b/sysdeps/posix/dup2.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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/sysdeps/posix/euidaccess.c b/sysdeps/posix/euidaccess.c index d8878aa28f..ec44b0f696 100644 --- a/sysdeps/posix/euidaccess.c +++ b/sysdeps/posix/euidaccess.c @@ -1,5 +1,5 @@ /* Check if effective user id can access file - Copyright (C) 1990-2016 Free Software Foundation, Inc. + Copyright (C) 1990-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/sysdeps/posix/fdopendir.c b/sysdeps/posix/fdopendir.c index 227174ec54..b72eecc66b 100644 --- a/sysdeps/posix/fdopendir.c +++ b/sysdeps/posix/fdopendir.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005-2016 Free Software Foundation, Inc. +/* Copyright (C) 2005-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 @@ -38,7 +38,7 @@ __fdopendir (int fd) } /* Make sure the descriptor allows for reading. */ - int flags = __fcntl (fd, F_GETFL); + int flags = __fcntl64_nocancel (fd, F_GETFL); if (__glibc_unlikely (flags == -1)) return NULL; if (__glibc_unlikely ((flags & O_ACCMODE) == O_WRONLY)) diff --git a/sysdeps/posix/flock.c b/sysdeps/posix/flock.c index c621a5b03e..998bc84866 100644 --- a/sysdeps/posix/flock.c +++ b/sysdeps/posix/flock.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1992-2016 Free Software Foundation, Inc. +/* Copyright (C) 1992-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/sysdeps/posix/fpathconf.c b/sysdeps/posix/fpathconf.c index 4aaded14be..a9d164564e 100644 --- a/sysdeps/posix/fpathconf.c +++ b/sysdeps/posix/fpathconf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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 @@ -103,25 +103,22 @@ __fpathconf (int fd, int name) #endif case _PC_CHOWN_RESTRICTED: -#ifdef _POSIX_CHOWN_RESTRICTED - return _POSIX_CHOWN_RESTRICTED; -#else - return -1; +#if _POSIX_CHOWN_RESTRICTED == -1 +# error "Invalid value for _POSIX_CHOWN_RESTRICTED" #endif + return _POSIX_CHOWN_RESTRICTED; case _PC_NO_TRUNC: -#ifdef _POSIX_NO_TRUNC - return _POSIX_NO_TRUNC; -#else - return -1; +#if _POSIX_NO_TRUNC == -1 +# error "Invalid value for _POSIX_NO_TRUNC" #endif + return _POSIX_NO_TRUNC; case _PC_VDISABLE: -#ifdef _POSIX_VDISABLE - return _POSIX_VDISABLE; -#else - return -1; +#if _POSIX_VDISABLE == -1 +# error "Invalid value for _POSIX_VDISABLE" #endif + return _POSIX_VDISABLE; case _PC_SYNC_IO: #ifdef _POSIX_SYNC_IO diff --git a/sysdeps/posix/gai_strerror.c b/sysdeps/posix/gai_strerror.c index 151ee08c29..6c2b66bf9f 100644 --- a/sysdeps/posix/gai_strerror.c +++ b/sysdeps/posix/gai_strerror.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1997-2016 Free Software Foundation, Inc. +/* Copyright (C) 1997-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Philip Blundell <pjb27@cam.ac.uk>, 1997. diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c index 1ef3f20d98..553833d1f2 100644 --- a/sysdeps/posix/getaddrinfo.c +++ b/sysdeps/posix/getaddrinfo.c @@ -1,3 +1,21 @@ +/* Host and service name lookups using Name Service Switch modules. + 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 + 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/>. */ + /* The Inner Net License, Version 2.00 The author(s) grant permission for redistribution and use in source and @@ -41,7 +59,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <ifaddrs.h> #include <netdb.h> #include <nss.h> -#include <resolv.h> +#include <resolv/resolv-internal.h> +#include <resolv/resolv_context.h> +#include <resolv/res_use_inet6.h> #include <stdbool.h> #include <stdio.h> #include <stdio_ext.h> @@ -62,13 +82,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <not-cancel.h> #include <nscd/nscd-client.h> #include <nscd/nscd_proto.h> -#include <resolv/res_hconf.h> +#include <scratch_buffer.h> +#include <inet/net-internal.h> + +/* Former AI_IDN_ALLOW_UNASSIGNED and AI_IDN_USE_STD3_ASCII_RULES + flags, now ignored. */ +#define DEPRECATED_AI_IDN 0x300 -#ifdef HAVE_LIBIDN -extern int __idna_to_ascii_lz (const char *input, char **output, int flags); -extern int __idna_to_unicode_lzlz (const char *input, char **output, - int flags); -# include <libidn/idna.h> +#if IS_IN (libc) +# define feof_unlocked(fp) __feof_unlocked (fp) #endif struct gaih_service @@ -135,24 +157,24 @@ static const struct addrinfo default_hints = static int gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp, - const struct addrinfo *req, struct gaih_servtuple *st) + const struct addrinfo *req, struct gaih_servtuple *st, + struct scratch_buffer *tmpbuf) { struct servent *s; - size_t tmpbuflen = 1024; struct servent ts; - char *tmpbuf; int r; do { - tmpbuf = __alloca (tmpbuflen); - - r = __getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen, - &s); + r = __getservbyname_r (servicename, tp->name, &ts, + tmpbuf->data, tmpbuf->length, &s); if (r != 0 || s == NULL) { if (r == ERANGE) - tmpbuflen *= 2; + { + if (!scratch_buffer_grow (tmpbuf)) + return -EAI_MEMORY; + } else return -EAI_SERVICE; } @@ -168,87 +190,114 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp, return 0; } +/* Convert struct hostent to a list of struct gaih_addrtuple objects. + h_name is not copied, and the struct hostent object must not be + deallocated prematurely. *RESULT must be NULL or a pointer to a + linked-list. The new addresses are appended at the end. */ +static bool +convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, + int family, + struct hostent *h, + struct gaih_addrtuple **result) +{ + while (*result) + result = &(*result)->next; + + /* Count the number of addresses in h->h_addr_list. */ + size_t count = 0; + for (char **p = h->h_addr_list; *p != NULL; ++p) + ++count; + + /* Report no data if no addresses are available, or if the incoming + address size is larger than what we can store. */ + if (count == 0 || h->h_length > sizeof (((struct gaih_addrtuple) {}).addr)) + return true; + + struct gaih_addrtuple *array = calloc (count, sizeof (*array)); + if (array == NULL) + return false; + + for (size_t i = 0; i < count; ++i) + { + if (family == AF_INET && req->ai_family == AF_INET6) + { + /* Perform address mapping. */ + array[i].family = AF_INET6; + memcpy(array[i].addr + 3, h->h_addr_list[i], sizeof (uint32_t)); + array[i].addr[2] = htonl (0xffff); + } + else + { + array[i].family = family; + memcpy (array[i].addr, h->h_addr_list[i], h->h_length); + } + array[i].next = array + i + 1; + } + array[0].name = h->h_name; + array[count - 1].next = NULL; + + *result = array; + return true; +} + #define gethosts(_family, _type) \ { \ - int i; \ - int herrno; \ struct hostent th; \ - struct hostent *h; \ char *localcanon = NULL; \ no_data = 0; \ - while (1) { \ - rc = 0; \ - status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen, \ - &rc, &herrno, NULL, &localcanon)); \ - if (rc != ERANGE || herrno != NETDB_INTERNAL) \ - break; \ - if (!malloc_tmpbuf && __libc_use_alloca (alloca_used + 2 * tmpbuflen)) \ - tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen, 2 * tmpbuflen, \ - alloca_used); \ - else \ - { \ - char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL, \ - 2 * tmpbuflen); \ - if (newp == NULL) \ - { \ - result = -EAI_MEMORY; \ - goto free_and_return; \ - } \ - tmpbuf = newp; \ - malloc_tmpbuf = true; \ - tmpbuflen = 2 * tmpbuflen; \ - } \ - } \ - if (status == NSS_STATUS_SUCCESS && rc == 0) \ - h = &th; \ - else \ - h = NULL; \ - if (rc != 0) \ + while (1) \ + { \ + status = DL_CALL_FCT (fct, (name, _family, &th, \ + tmpbuf->data, tmpbuf->length, \ + &errno, &h_errno, NULL, &localcanon)); \ + if (status != NSS_STATUS_TRYAGAIN || h_errno != NETDB_INTERNAL \ + || errno != ERANGE) \ + break; \ + if (!scratch_buffer_grow (tmpbuf)) \ + { \ + __resolv_context_enable_inet6 (res_ctx, res_enable_inet6); \ + __resolv_context_put (res_ctx); \ + result = -EAI_MEMORY; \ + goto free_and_return; \ + } \ + } \ + if (status == NSS_STATUS_NOTFOUND \ + || status == NSS_STATUS_TRYAGAIN || status == NSS_STATUS_UNAVAIL) \ { \ - if (herrno == NETDB_INTERNAL) \ + if (h_errno == NETDB_INTERNAL) \ { \ - __set_h_errno (herrno); \ - _res.options |= old_res_options & RES_USE_INET6; \ + __resolv_context_enable_inet6 (res_ctx, res_enable_inet6); \ + __resolv_context_put (res_ctx); \ result = -EAI_SYSTEM; \ goto free_and_return; \ } \ - if (herrno == TRY_AGAIN) \ + if (h_errno == TRY_AGAIN) \ no_data = EAI_AGAIN; \ else \ - no_data = herrno == NO_DATA; \ + no_data = h_errno == NO_DATA; \ } \ - else if (h != NULL) \ + else if (status == NSS_STATUS_SUCCESS) \ { \ - for (i = 0; h->h_addr_list[i]; i++) \ + if (!convert_hostent_to_gaih_addrtuple (req, _family, &th, &addrmem)) \ { \ - if (*pat == NULL) \ - { \ - *pat = __alloca (sizeof (struct gaih_addrtuple)); \ - (*pat)->scopeid = 0; \ - } \ - uint32_t *addr = (*pat)->addr; \ - (*pat)->next = NULL; \ - (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL; \ - if (_family == AF_INET && req->ai_family == AF_INET6) \ - { \ - (*pat)->family = AF_INET6; \ - addr[3] = *(uint32_t *) h->h_addr_list[i]; \ - addr[2] = htonl (0xffff); \ - addr[1] = 0; \ - addr[0] = 0; \ - } \ - else \ + __resolv_context_enable_inet6 (res_ctx, res_enable_inet6); \ + __resolv_context_put (res_ctx); \ + result = -EAI_SYSTEM; \ + goto free_and_return; \ + } \ + *pat = addrmem; \ + \ + if (localcanon != NULL && canon == NULL) \ + { \ + canonbuf = __strdup (localcanon); \ + if (canonbuf == NULL) \ { \ - (*pat)->family = _family; \ - memcpy (addr, h->h_addr_list[i], sizeof(_type)); \ + result = -EAI_SYSTEM; \ + goto free_and_return; \ } \ - pat = &((*pat)->next); \ + canon = canonbuf; \ } \ - \ - if (localcanon != NULL && canon == NULL) \ - canon = strdupa (localcanon); \ - \ - if (_family == AF_INET6 && i > 0) \ + if (_family == AF_INET6 && *pat != NULL) \ got_ipv6 = true; \ } \ } @@ -265,22 +314,45 @@ typedef enum nss_status (*nss_gethostbyname3_r) typedef enum nss_status (*nss_getcanonname_r) (const char *name, char *buffer, size_t buflen, char **result, int *errnop, int *h_errnop); -extern service_user *__nss_hosts_database attribute_hidden; +/* This function is called if a canonical name is requested, but if + the service function did not provide it. It tries to obtain the + name using getcanonname_r from the same service NIP. If the name + cannot be canonicalized, return a copy of NAME. Return NULL on + memory allocation failure. The returned string is allocated on the + heap; the caller has to free it. */ +static char * +getcanonname (service_user *nip, struct gaih_addrtuple *at, const char *name) +{ + nss_getcanonname_r cfct = __nss_lookup_function (nip, "getcanonname_r"); + char *s = (char *) name; + if (cfct != NULL) + { + char buf[256]; + if (DL_CALL_FCT (cfct, (at->name ?: name, buf, sizeof (buf), + &s, &errno, &h_errno)) != NSS_STATUS_SUCCESS) + /* If the canonical name cannot be determined, use the passed + string. */ + s = (char *) name; + } + return __strdup (name); +} static int gaih_inet (const char *name, const struct gaih_service *service, const struct addrinfo *req, struct addrinfo **pai, - unsigned int *naddrs) + unsigned int *naddrs, struct scratch_buffer *tmpbuf) { const struct gaih_typeproto *tp = gaih_inet_typeproto; struct gaih_servtuple *st = (struct gaih_servtuple *) &nullserv; struct gaih_addrtuple *at = NULL; - int rc; bool got_ipv6 = false; const char *canon = NULL; const char *orig_name = name; - size_t alloca_used = 0; + + /* Reserve stack memory for the scratch buffer in the getaddrinfo + function. */ + size_t alloca_used = sizeof (struct scratch_buffer); if (req->ai_protocol || req->ai_socktype) { @@ -315,7 +387,8 @@ gaih_inet (const char *name, const struct gaih_service *service, st = (struct gaih_servtuple *) alloca_account (sizeof (struct gaih_servtuple), alloca_used); - if ((rc = gaih_inet_serv (service->name, tp, req, st))) + int rc = gaih_inet_serv (service->name, tp, req, st, tmpbuf); + if (__glibc_unlikely (rc != 0)) return rc; } else @@ -340,12 +413,9 @@ gaih_inet (const char *name, const struct gaih_service *service, alloca_account (sizeof (struct gaih_servtuple), alloca_used); - if ((rc = gaih_inet_serv (service->name, tp, req, newp))) - { - if (rc) - continue; - return rc; - } + if (gaih_inet_serv (service->name, + tp, req, newp, tmpbuf) != 0) + continue; *pst = newp; pst = &(newp->next); @@ -397,13 +467,10 @@ gaih_inet (const char *name, const struct gaih_service *service, } bool malloc_name = false; - bool malloc_addrmem = false; struct gaih_addrtuple *addrmem = NULL; - bool malloc_canonbuf = false; char *canonbuf = NULL; - bool malloc_tmpbuf = false; - char *tmpbuf = NULL; int result = 0; + if (name != NULL) { at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used); @@ -411,35 +478,15 @@ gaih_inet (const char *name, const struct gaih_service *service, at->scopeid = 0; at->next = NULL; -#ifdef HAVE_LIBIDN if (req->ai_flags & AI_IDN) { - int idn_flags = 0; - if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED) - idn_flags |= IDNA_ALLOW_UNASSIGNED; - if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES) - idn_flags |= IDNA_USE_STD3_ASCII_RULES; - - char *p = NULL; - rc = __idna_to_ascii_lz (name, &p, idn_flags); - if (rc != IDNA_SUCCESS) - { - /* No need to jump to free_and_return here. */ - if (rc == IDNA_MALLOC_ERROR) - return -EAI_MEMORY; - if (rc == IDNA_DLOPEN_ERROR) - return -EAI_SYSTEM; - return -EAI_IDN_ENCODE; - } - /* In case the output string is the same as the input string - no new string has been allocated. */ - if (p != name) - { - name = p; - malloc_name = true; - } + char *out; + result = __idna_to_dns_encoding (name, &out); + if (result != 0) + return -result; + name = out; + malloc_name = true; } -#endif if (__inet_aton (name, (struct in_addr *) at->addr) != 0) { @@ -466,46 +513,11 @@ gaih_inet (const char *name, const struct gaih_service *service, { char *scope_delim = strchr (name, SCOPE_DELIMITER); int e; - - { - bool malloc_namebuf = false; - char *namebuf = (char *) name; - - if (__glibc_unlikely (scope_delim != NULL)) - { - if (malloc_name) - *scope_delim = '\0'; - else - { - if (__libc_use_alloca (alloca_used - + scope_delim - name + 1)) - { - namebuf = alloca_account (scope_delim - name + 1, - alloca_used); - *((char *) __mempcpy (namebuf, name, - scope_delim - name)) = '\0'; - } - else - { - namebuf = strndup (name, scope_delim - name); - if (namebuf == NULL) - { - assert (!malloc_name); - return -EAI_MEMORY; - } - malloc_namebuf = true; - } - } - } - - e = inet_pton (AF_INET6, namebuf, at->addr); - - if (malloc_namebuf) - free (namebuf); - else if (scope_delim != NULL && malloc_name) - /* Undo what we did above. */ - *scope_delim = SCOPE_DELIMITER; - } + if (scope_delim == NULL) + e = inet_pton (AF_INET6, name, at->addr); + else + e = __inet_pton_length (AF_INET6, name, scope_delim - name, + at->addr); if (e > 0) { if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6) @@ -522,31 +534,13 @@ gaih_inet (const char *name, const struct gaih_service *service, goto free_and_return; } - if (scope_delim != NULL) + if (scope_delim != NULL + && __inet6_scopeid_pton ((struct in6_addr *) at->addr, + scope_delim + 1, + &at->scopeid) != 0) { - int try_numericscope = 0; - if (IN6_IS_ADDR_LINKLOCAL (at->addr) - || IN6_IS_ADDR_MC_LINKLOCAL (at->addr)) - { - at->scopeid = if_nametoindex (scope_delim + 1); - if (at->scopeid == 0) - try_numericscope = 1; - } - else - try_numericscope = 1; - - if (try_numericscope != 0) - { - char *end; - assert (sizeof (uint32_t) <= sizeof (unsigned long)); - at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end, - 10); - if (*end != '\0') - { - result = -EAI_NONAME; - goto free_and_return; - } - } + result = -EAI_NONAME; + goto free_and_return; } if (req->ai_flags & AI_CANONNAME) @@ -563,7 +557,8 @@ gaih_inet (const char *name, const struct gaih_service *service, enum nss_status inet6_status = NSS_STATUS_UNAVAIL; enum nss_status status = NSS_STATUS_UNAVAIL; int no_more; - int old_res_options; + struct resolv_context *res_ctx = NULL; + bool res_enable_inet6 = false; /* If we do not have to look for IPv6 addresses or the canonical name, use the simple, old functions, which do not support @@ -571,40 +566,21 @@ gaih_inet (const char *name, const struct gaih_service *service, if (req->ai_family == AF_INET && (req->ai_flags & AI_CANONNAME) == 0) { - /* Allocate additional room for struct host_data. */ - size_t tmpbuflen = (512 + MAX_NR_ALIASES * sizeof(char*) - + 16 * sizeof(char)); - assert (tmpbuf == NULL); - tmpbuf = alloca_account (tmpbuflen, alloca_used); int rc; struct hostent th; struct hostent *h; - int herrno; while (1) { - rc = __gethostbyname2_r (name, AF_INET, &th, tmpbuf, - tmpbuflen, &h, &herrno); - if (rc != ERANGE || herrno != NETDB_INTERNAL) + rc = __gethostbyname2_r (name, AF_INET, &th, + tmpbuf->data, tmpbuf->length, + &h, &h_errno); + if (rc != ERANGE || h_errno != NETDB_INTERNAL) break; - - if (!malloc_tmpbuf - && __libc_use_alloca (alloca_used + 2 * tmpbuflen)) - tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen, - 2 * tmpbuflen, - alloca_used); - else + if (!scratch_buffer_grow (tmpbuf)) { - char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL, - 2 * tmpbuflen); - if (newp == NULL) - { - result = -EAI_MEMORY; - goto free_and_return; - } - tmpbuf = newp; - malloc_tmpbuf = true; - tmpbuflen = 2 * tmpbuflen; + result = -EAI_MEMORY; + goto free_and_return; } } @@ -612,54 +588,29 @@ gaih_inet (const char *name, const struct gaih_service *service, { if (h != NULL) { - int i; - /* We found data, count the number of addresses. */ - for (i = 0; h->h_addr_list[i]; ++i) - ; - if (i > 0 && *pat != NULL) - --i; - - if (__libc_use_alloca (alloca_used - + i * sizeof (struct gaih_addrtuple))) - addrmem = alloca_account (i * sizeof (struct gaih_addrtuple), - alloca_used); - else - { - addrmem = malloc (i - * sizeof (struct gaih_addrtuple)); - if (addrmem == NULL) - { - result = -EAI_MEMORY; - goto free_and_return; - } - malloc_addrmem = true; - } - - /* Now convert it into the list. */ - struct gaih_addrtuple *addrfree = addrmem; - for (i = 0; h->h_addr_list[i]; ++i) + /* We found data, convert it. */ + if (!convert_hostent_to_gaih_addrtuple + (req, AF_INET, h, &addrmem)) { - if (*pat == NULL) - { - *pat = addrfree++; - (*pat)->scopeid = 0; - } - (*pat)->next = NULL; - (*pat)->family = AF_INET; - memcpy ((*pat)->addr, h->h_addr_list[i], - h->h_length); - pat = &((*pat)->next); + result = -EAI_MEMORY; + goto free_and_return; } + *pat = addrmem; + } + else + { + if (h_errno == NO_DATA) + result = -EAI_NODATA; + else + result = -EAI_NONAME; + goto free_and_return; } } else { - if (herrno == NETDB_INTERNAL) - { - __set_h_errno (herrno); - result = -EAI_SYSTEM; - } - else if (herrno == TRY_AGAIN) + if (h_errno == NETDB_INTERNAL) + result = -EAI_SYSTEM; + else if (h_errno == TRY_AGAIN) result = -EAI_AGAIN; else /* We made requests but they turned out no data. @@ -682,29 +633,18 @@ gaih_inet (const char *name, const struct gaih_service *service, { /* Try to use nscd. */ struct nscd_ai_result *air = NULL; - int herrno; - int err = __nscd_getai (name, &air, &herrno); + int err = __nscd_getai (name, &air, &h_errno); if (air != NULL) { /* Transform into gaih_addrtuple list. */ bool added_canon = (req->ai_flags & AI_CANONNAME) == 0; char *addrs = air->addrs; - if (__libc_use_alloca (alloca_used - + air->naddrs * sizeof (struct gaih_addrtuple))) - addrmem = alloca_account (air->naddrs - * sizeof (struct gaih_addrtuple), - alloca_used); - else + addrmem = calloc (air->naddrs, sizeof (*addrmem)); + if (addrmem == NULL) { - addrmem = malloc (air->naddrs - * sizeof (struct gaih_addrtuple)); - if (addrmem == NULL) - { - result = -EAI_MEMORY; - goto free_and_return; - } - malloc_addrmem = true; + result = -EAI_MEMORY; + goto free_and_return; } struct gaih_addrtuple *addrfree = addrmem; @@ -735,22 +675,13 @@ gaih_inet (const char *name, const struct gaih_service *service, (*pat)->name = NULL; else if (canonbuf == NULL) { - size_t canonlen = strlen (air->canon) + 1; - if ((req->ai_flags & AI_CANONIDN) != 0 - && __libc_use_alloca (alloca_used + canonlen)) - canonbuf = alloca_account (canonlen, alloca_used); - else + canonbuf = __strdup (air->canon); + if (canonbuf == NULL) { - canonbuf = malloc (canonlen); - if (canonbuf == NULL) - { - result = -EAI_MEMORY; - goto free_and_return; - } - malloc_canonbuf = true; + result = -EAI_MEMORY; + goto free_and_return; } - canon = (*pat)->name = memcpy (canonbuf, air->canon, - canonlen); + canon = (*pat)->name = canonbuf; } if (air->family[i] == AF_INET @@ -793,9 +724,9 @@ gaih_inet (const char *name, const struct gaih_service *service, goto free_and_return; else if (__nss_not_use_nscd_hosts == 0) { - if (herrno == NETDB_INTERNAL && errno == ENOMEM) + if (h_errno == NETDB_INTERNAL && errno == ENOMEM) result = -EAI_MEMORY; - else if (herrno == TRY_AGAIN) + else if (h_errno == TRY_AGAIN) result = -EAI_AGAIN; else result = -EAI_SYSTEM; @@ -813,34 +744,14 @@ gaih_inet (const char *name, const struct gaih_service *service, no_more = 0; nip = __nss_hosts_database; - /* Initialize configurations. */ - if (__glibc_unlikely (!_res_hconf.initialized)) - _res_hconf_init (); - if (__res_maybe_init (&_res, 0) == -1) - no_more = 1; - /* If we are looking for both IPv4 and IPv6 address we don't want the lookup functions to automatically promote IPv4 - addresses to IPv6 addresses. Currently this is decided - by setting the RES_USE_INET6 bit in _res.options. */ - old_res_options = _res.options; - _res.options &= ~RES_USE_INET6; - - size_t tmpbuflen = 1024 + sizeof(struct gaih_addrtuple); - malloc_tmpbuf = !__libc_use_alloca (alloca_used + tmpbuflen); - assert (tmpbuf == NULL); - if (!malloc_tmpbuf) - tmpbuf = alloca_account (tmpbuflen, alloca_used); - else - { - tmpbuf = malloc (tmpbuflen); - if (tmpbuf == NULL) - { - _res.options |= old_res_options & RES_USE_INET6; - result = -EAI_MEMORY; - goto free_and_return; - } - } + addresses to IPv6 addresses, so we use the no_inet6 + function variant. */ + res_ctx = __resolv_context_get (); + res_enable_inet6 = __resolv_context_disable_inet6 (res_ctx); + if (res_ctx == NULL) + no_more = 1; while (!no_more) { @@ -854,44 +765,31 @@ gaih_inet (const char *name, const struct gaih_service *service, if (fct4 != NULL) { - int herrno; - while (1) { - rc = 0; - status = DL_CALL_FCT (fct4, (name, pat, tmpbuf, - tmpbuflen, &rc, &herrno, + status = DL_CALL_FCT (fct4, (name, pat, + tmpbuf->data, tmpbuf->length, + &errno, &h_errno, NULL)); if (status == NSS_STATUS_SUCCESS) break; if (status != NSS_STATUS_TRYAGAIN - || rc != ERANGE || herrno != NETDB_INTERNAL) + || errno != ERANGE || h_errno != NETDB_INTERNAL) { - if (herrno == TRY_AGAIN) + if (h_errno == TRY_AGAIN) no_data = EAI_AGAIN; else - no_data = herrno == NO_DATA; + no_data = h_errno == NO_DATA; break; } - if (!malloc_tmpbuf - && __libc_use_alloca (alloca_used + 2 * tmpbuflen)) - tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen, - 2 * tmpbuflen, - alloca_used); - else + if (!scratch_buffer_grow (tmpbuf)) { - char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL, - 2 * tmpbuflen); - if (newp == NULL) - { - _res.options |= old_res_options & RES_USE_INET6; - result = -EAI_MEMORY; - goto free_and_return; - } - tmpbuf = newp; - malloc_tmpbuf = true; - tmpbuflen = 2 * tmpbuflen; + __resolv_context_enable_inet6 + (res_ctx, res_enable_inet6); + __resolv_context_put (res_ctx); + result = -EAI_MEMORY; + goto free_and_return; } } @@ -985,54 +883,16 @@ gaih_inet (const char *name, const struct gaih_service *service, if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL) { - /* If we need the canonical name, get it - from the same service as the result. */ - nss_getcanonname_r cfct; - int herrno; - - cfct = __nss_lookup_function (nip, - "getcanonname_r"); - if (cfct != NULL) + canonbuf = getcanonname (nip, at, name); + if (canonbuf == NULL) { - const size_t max_fqdn_len = 256; - if ((req->ai_flags & AI_CANONIDN) != 0 - && __libc_use_alloca (alloca_used - + max_fqdn_len)) - canonbuf = alloca_account (max_fqdn_len, - alloca_used); - else - { - canonbuf = malloc (max_fqdn_len); - if (canonbuf == NULL) - { - _res.options - |= old_res_options & RES_USE_INET6; - result = -EAI_MEMORY; - goto free_and_return; - } - malloc_canonbuf = true; - } - char *s; - - if (DL_CALL_FCT (cfct, (at->name ?: name, - canonbuf, - max_fqdn_len, - &s, &rc, &herrno)) - == NSS_STATUS_SUCCESS) - canon = s; - else - { - /* If the canonical name cannot be - determined, use the passed in - string. */ - if (malloc_canonbuf) - { - free (canonbuf); - malloc_canonbuf = false; - } - canon = name; - } + __resolv_context_enable_inet6 + (res_ctx, res_enable_inet6); + __resolv_context_put (res_ctx); + result = -EAI_MEMORY; + goto free_and_return; } + canon = canonbuf; } status = NSS_STATUS_SUCCESS; } @@ -1049,13 +909,17 @@ gaih_inet (const char *name, const struct gaih_service *service, } else { + /* Could not locate any of the lookup functions. + The NSS lookup code does not consistently set + errno, so we need to supply our own error + code here. The root cause could either be a + resource allocation failure, or a missing + service function in the DSO (so it should not + be listed in /etc/nsswitch.conf). Assume the + former, and return EBUSY. */ status = NSS_STATUS_UNAVAIL; - /* Could not load any of the lookup functions. Indicate - an internal error if the failure was due to a system - error other than the file not being found. We use the - errno from the last failed callback. */ - if (errno != 0 && errno != ENOENT) - __set_h_errno (NETDB_INTERNAL); + __set_h_errno (NETDB_INTERNAL); + __set_errno (EBUSY); } } @@ -1068,9 +932,13 @@ gaih_inet (const char *name, const struct gaih_service *service, nip = nip->next; } - _res.options |= old_res_options & RES_USE_INET6; + __resolv_context_enable_inet6 (res_ctx, res_enable_inet6); + __resolv_context_put (res_ctx); - if (h_errno == NETDB_INTERNAL) + /* If we have a failure which sets errno, report it using + EAI_SYSTEM. */ + if ((status == NSS_STATUS_TRYAGAIN || status == NSS_STATUS_UNAVAIL) + && h_errno == NETDB_INTERNAL) { result = -EAI_SYSTEM; goto free_and_return; @@ -1144,46 +1012,31 @@ gaih_inet (const char *name, const struct gaih_service *service, the passed in string. */ canon = orig_name; -#ifdef HAVE_LIBIDN - if (req->ai_flags & AI_CANONIDN) + bool do_idn = req->ai_flags & AI_CANONIDN; + if (do_idn) { - int idn_flags = 0; - if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED) - idn_flags |= IDNA_ALLOW_UNASSIGNED; - if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES) - idn_flags |= IDNA_USE_STD3_ASCII_RULES; - char *out; - int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags); - if (rc != IDNA_SUCCESS) + int rc = __idna_from_dns_encoding (canon, &out); + if (rc == 0) + canon = out; + else if (rc == EAI_IDN_ENCODE) + /* Use the punycode name as a fallback. */ + do_idn = false; + else { - if (rc == IDNA_MALLOC_ERROR) - result = -EAI_MEMORY; - else if (rc == IDNA_DLOPEN_ERROR) - result = -EAI_SYSTEM; - else - result = -EAI_IDN_ENCODE; + result = -rc; goto free_and_return; } - /* In case the output string is the same as the input - string no new string has been allocated and we - make a copy. */ - if (out == canon) - goto make_copy; - canon = out; } - else -#endif + if (!do_idn) { -#ifdef HAVE_LIBIDN - make_copy: -#endif - if (malloc_canonbuf) - /* We already allocated the string using malloc. */ - malloc_canonbuf = false; + if (canonbuf != NULL) + /* We already allocated the string using malloc, but + the buffer is now owned by canon. */ + canonbuf = NULL; else { - canon = strdup (canon); + canon = __strdup (canon); if (canon == NULL) { result = -EAI_MEMORY; @@ -1274,12 +1127,8 @@ gaih_inet (const char *name, const struct gaih_service *service, free_and_return: if (malloc_name) free ((char *) name); - if (malloc_addrmem) - free (addrmem); - if (malloc_canonbuf) - free (canonbuf); - if (malloc_tmpbuf) - free (tmpbuf); + free (addrmem); + free (canonbuf); return result; } @@ -2341,10 +2190,7 @@ getaddrinfo (const char *name, const char *service, if (hints->ai_flags & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|AI_ADDRCONFIG|AI_V4MAPPED -#ifdef HAVE_LIBIDN - |AI_IDN|AI_CANONIDN|AI_IDN_ALLOW_UNASSIGNED - |AI_IDN_USE_STD3_ASCII_RULES -#endif + |AI_IDN|AI_CANONIDN|DEPRECATED_AI_IDN |AI_NUMERICSERV|AI_ALL)) return EAI_BADFLAGS; @@ -2414,7 +2260,11 @@ getaddrinfo (const char *name, const char *service, if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET || hints->ai_family == AF_INET6) { - last_i = gaih_inet (name, pservice, hints, end, &naddrs); + struct scratch_buffer tmpbuf; + scratch_buffer_init (&tmpbuf); + last_i = gaih_inet (name, pservice, hints, end, &naddrs, &tmpbuf); + scratch_buffer_free (&tmpbuf); + if (last_i != 0) { freeaddrinfo (p); @@ -2510,9 +2360,9 @@ getaddrinfo (const char *name, const char *service, { if (fd != -1) close_retry: - close_not_cancel_no_status (fd); + __close_nocancel_nostatus (fd); af = q->ai_family; - fd = __socket (af, SOCK_DGRAM, IPPROTO_IP); + fd = __socket (af, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_IP); } else { @@ -2613,7 +2463,7 @@ getaddrinfo (const char *name, const char *service, } if (fd != -1) - close_not_cancel_no_status (fd); + __close_nocancel_nostatus (fd); /* We got all the source addresses we can get, now sort using the information. */ diff --git a/sysdeps/posix/getcwd.c b/sysdeps/posix/getcwd.c index 38cf4e7fc8..b53433a2dc 100644 --- a/sysdeps/posix/getcwd.c +++ b/sysdeps/posix/getcwd.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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 @@ -175,8 +175,8 @@ extern char *alloca (); # include <not-cancel.h> # include <kernel-features.h> #else -# define openat64_not_cancel_3(dfd, name, mode) openat64 (dfd, name, mode) -# define close_not_cancel_no_status(fd) close (fd) +# define __openat64_nocancel(dfd, name, mode) openat64 (dfd, name, mode) +# define __close_nocancel_nostatus(fd) close (fd) #endif #ifndef PATH_MAX @@ -281,13 +281,7 @@ __getcwd (char *buf, size_t size) while (!(thisdev == rootdev && thisino == rootino)) { if (__have_atfcts >= 0) - { - int mode = O_RDONLY; -#ifdef O_CLOEXEC - mode |= O_CLOEXEC; -#endif - fd = openat64_not_cancel_3 (fd, "..", mode); - } + fd = __openat64_nocancel (fd, "..", O_RDONLY | O_CLOEXEC); else fd = -1; if (fd >= 0) @@ -324,7 +318,7 @@ __getcwd (char *buf, size_t size) } else { - new = realloc ((__ptr_t) dotlist, dotsize * 2 + 1); + new = realloc ((void *) dotlist, dotsize * 2 + 1); if (new == NULL) goto lose; dotp = &new[dotsize]; @@ -498,7 +492,7 @@ __getcwd (char *buf, size_t size) #ifndef __ASSUME_ATFCTS if (dotlist != dots) - free ((__ptr_t) dotlist); + free ((void *) dotlist); #endif size_t used = path + allocated - pathp; @@ -522,12 +516,12 @@ __getcwd (char *buf, size_t size) int save_errno = errno; #ifndef __ASSUME_ATFCTS if (dotlist != dots) - free ((__ptr_t) dotlist); + free ((void *) dotlist); #endif if (dirstream != NULL) __closedir (dirstream); if (fd_needs_closing) - close_not_cancel_no_status (fd); + __close_nocancel_nostatus (fd); #ifndef NO_ALLOCATION if (buf == NULL) free (path); diff --git a/sysdeps/posix/getdtsz.c b/sysdeps/posix/getdtsz.c index ea1c66ca0b..0da5081575 100644 --- a/sysdeps/posix/getdtsz.c +++ b/sysdeps/posix/getdtsz.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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/sysdeps/posix/gethostname.c b/sysdeps/posix/gethostname.c index 6ce54e933b..0e29e18617 100644 --- a/sysdeps/posix/gethostname.c +++ b/sysdeps/posix/gethostname.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1992-2016 Free Software Foundation, Inc. +/* Copyright (C) 1992-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 @@ -29,7 +29,7 @@ __gethostname (char *name, size_t len) struct utsname buf; size_t node_len; - if (uname (&buf)) + if (__uname (&buf)) return -1; node_len = strlen (buf.nodename) + 1; diff --git a/sysdeps/posix/getpagesize.c b/sysdeps/posix/getpagesize.c index 11963ac7a6..6f37dba644 100644 --- a/sysdeps/posix/getpagesize.c +++ b/sysdeps/posix/getpagesize.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993-2016 Free Software Foundation, Inc. +/* Copyright (C) 1993-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Brendan Kehoe (brendan@cygnus.com). diff --git a/sysdeps/posix/gettimeofday.c b/sysdeps/posix/gettimeofday.c index e6e343c23d..ea00cd387d 100644 --- a/sysdeps/posix/gettimeofday.c +++ b/sysdeps/posix/gettimeofday.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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/sysdeps/posix/isatty.c b/sysdeps/posix/isatty.c index aaed61af74..a06e7ecad5 100644 --- a/sysdeps/posix/isatty.c +++ b/sysdeps/posix/isatty.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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/sysdeps/posix/isfdtype.c b/sysdeps/posix/isfdtype.c index e3779b4530..38e7fd4210 100644 --- a/sysdeps/posix/isfdtype.c +++ b/sysdeps/posix/isfdtype.c @@ -1,5 +1,5 @@ /* Determine whether descriptor has given property. - 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/sysdeps/posix/killpg.c b/sysdeps/posix/killpg.c index dc3a7f1433..533d2f1722 100644 --- a/sysdeps/posix/killpg.c +++ b/sysdeps/posix/killpg.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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/sysdeps/posix/libc_fatal.c b/sysdeps/posix/libc_fatal.c index 3c820dab11..89a20080e1 100644 --- a/sysdeps/posix/libc_fatal.c +++ b/sysdeps/posix/libc_fatal.c @@ -1,5 +1,5 @@ /* Catastrophic failure reports. Generic POSIX.1 version. - Copyright (C) 1993-2016 Free Software Foundation, Inc. + Copyright (C) 1993-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 @@ -64,7 +64,7 @@ struct str_list /* Abort with an error message. */ void -__libc_message (int do_abort, const char *fmt, ...) +__libc_message (enum __libc_message_action action, const char *fmt, ...) { va_list ap; int fd = -1; @@ -75,11 +75,16 @@ __libc_message (int do_abort, const char *fmt, ...) FATAL_PREPARE; #endif - /* Open a descriptor for /dev/tty unless the user explicitly - requests errors on standard error. */ - const char *on_2 = __libc_secure_getenv ("LIBC_FATAL_STDERR_"); - if (on_2 == NULL || *on_2 == '\0') - fd = open_not_cancel_2 (_PATH_TTY, O_RDWR | O_NOCTTY | O_NDELAY); + /* Don't call __libc_secure_getenv if we aren't doing backtrace, which + may access the corrupted stack. */ + if ((action & do_backtrace)) + { + /* Open a descriptor for /dev/tty unless the user explicitly + requests errors on standard error. */ + const char *on_2 = __libc_secure_getenv ("LIBC_FATAL_STDERR_"); + if (on_2 == NULL || *on_2 == '\0') + fd = __open_nocancel (_PATH_TTY, O_RDWR | O_NOCTTY | O_NDELAY); + } if (fd == -1) fd = STDERR_FILENO; @@ -140,7 +145,7 @@ __libc_message (int do_abort, const char *fmt, ...) written = WRITEV_FOR_FATAL (fd, iov, nlist, total); - if (do_abort) + if ((action & do_abort)) { total = ((total + 1 + GLRO(dl_pagesize) - 1) & ~(GLRO(dl_pagesize) - 1)); @@ -167,9 +172,10 @@ __libc_message (int do_abort, const char *fmt, ...) va_end (ap); - if (do_abort) + if ((action & do_abort)) { - BEFORE_ABORT (do_abort, written, fd); + if ((action & do_backtrace)) + BEFORE_ABORT (do_abort, written, fd); /* Kill the application. */ abort (); @@ -182,6 +188,6 @@ __libc_fatal (const char *message) { /* The loop is added only to keep gcc happy. */ while (1) - __libc_message (1, "%s", message); + __libc_message (do_abort | do_backtrace, "%s", message); } libc_hidden_def (__libc_fatal) diff --git a/sysdeps/posix/mkfifo.c b/sysdeps/posix/mkfifo.c index 7eea6572ca..eedbf9e28c 100644 --- a/sysdeps/posix/mkfifo.c +++ b/sysdeps/posix/mkfifo.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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/sysdeps/posix/mkfifoat.c b/sysdeps/posix/mkfifoat.c index 0f910d7441..c54383eab9 100644 --- a/sysdeps/posix/mkfifoat.c +++ b/sysdeps/posix/mkfifoat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005-2016 Free Software Foundation, Inc. +/* Copyright (C) 2005-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/sysdeps/posix/nice.c b/sysdeps/posix/nice.c index ae82618767..2d907e80e4 100644 --- a/sysdeps/posix/nice.c +++ b/sysdeps/posix/nice.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1992-2016 Free Software Foundation, Inc. +/* Copyright (C) 1992-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/sysdeps/posix/open64.c b/sysdeps/posix/open64.c index dc0387b44a..c4209c8cdb 100644 --- a/sysdeps/posix/open64.c +++ b/sysdeps/posix/open64.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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/sysdeps/posix/opendir.c b/sysdeps/posix/opendir.c index 3e09deb805..bb6bd7cc85 100644 --- a/sysdeps/posix/opendir.c +++ b/sysdeps/posix/opendir.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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 @@ -15,24 +15,13 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ -#include <assert.h> -#include <errno.h> -#include <limits.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdlib.h> #include <dirent.h> #include <fcntl.h> -#include <sys/param.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <stdio.h> -#include <string.h> +#include <errno.h> +#include <stdio.h> /* For BUFSIZ. */ +#include <sys/param.h> /* For MIN and MAX. */ -#include <dirstream.h> #include <not-cancel.h> -#include <kernel-features.h> /* The st_blksize value of the directory is used as a hint for the size of the buffer which receives struct dirent values from the @@ -40,47 +29,9 @@ file system provides a bogus value. */ #define MAX_DIR_BUFFER_SIZE 1048576U -/* opendir() must not accidentally open something other than a directory. - Some OS's have kernel support for that, some don't. In the worst - case we have to stat() before the open() AND fstat() after. - - We have to test at runtime for kernel support since libc may have - been compiled with different headers to the kernel it's running on. - This test can't be done reliably in the general case. We'll use - /dev/null, which if it's not a device lots of stuff will break, as - a guinea pig. It may be missing in chroot environments, so we - make sure to fail safe. */ -#ifdef O_DIRECTORY -# ifdef O_DIRECTORY_WORKS -# define o_directory_works 1 -# define tryopen_o_directory() while (1) /* This must not be called. */ -# else -static int o_directory_works; - -static void -tryopen_o_directory (void) -{ - int serrno = errno; - int x = open_not_cancel_2 ("/dev/null", O_RDONLY|O_NDELAY|O_DIRECTORY); - - if (x >= 0) - { - close_not_cancel_no_status (x); - o_directory_works = -1; - } - else if (errno != ENOTDIR) - o_directory_works = -1; - else - o_directory_works = 1; - - __set_errno (serrno); -} -# endif -# define EXTRA_FLAGS O_DIRECTORY -#else -# define EXTRA_FLAGS 0 -#endif - +enum { + opendir_oflags = O_RDONLY|O_NDELAY|O_DIRECTORY|O_LARGEFILE|O_CLOEXEC +}; static bool invalid_name (const char *name) @@ -95,33 +46,6 @@ invalid_name (const char *name) return false; } - -static bool -need_isdir_precheck (void) -{ -#ifdef O_DIRECTORY - /* Test whether O_DIRECTORY works. */ - if (o_directory_works == 0) - tryopen_o_directory (); - - /* We can skip the expensive `stat' call if O_DIRECTORY works. */ - return o_directory_works < 0; -#endif - return true; -} - - -static int -opendir_oflags (void) -{ - int flags = O_RDONLY|O_NDELAY|EXTRA_FLAGS|O_LARGEFILE; -#ifdef O_CLOEXEC - flags |= O_CLOEXEC; -#endif - return flags; -} - - static DIR * opendir_tail (int fd) { @@ -138,7 +62,7 @@ opendir_tail (int fd) { __set_errno (ENOTDIR); lose: - close_not_cancel_no_status (fd); + __close_nocancel_nostatus (fd); return NULL; } @@ -148,29 +72,12 @@ opendir_tail (int fd) #if IS_IN (libc) DIR * -internal_function __opendirat (int dfd, const char *name) { if (__glibc_unlikely (invalid_name (name))) return NULL; - if (need_isdir_precheck ()) - { - /* We first have to check whether the name is for a directory. We - cannot do this after the open() call since the open/close operation - performed on, say, a tape device might have undesirable effects. */ - struct stat64 statbuf; - if (__glibc_unlikely (__fxstatat64 (_STAT_VER, dfd, name, - &statbuf, 0) < 0)) - return NULL; - if (__glibc_unlikely (! S_ISDIR (statbuf.st_mode))) - { - __set_errno (ENOTDIR); - return NULL; - } - } - - return opendir_tail (openat_not_cancel_3 (dfd, name, opendir_oflags ())); + return opendir_tail (__openat_nocancel (dfd, name, opendir_oflags)); } #endif @@ -182,54 +89,18 @@ __opendir (const char *name) if (__glibc_unlikely (invalid_name (name))) return NULL; - if (need_isdir_precheck ()) - { - /* We first have to check whether the name is for a directory. We - cannot do this after the open() call since the open/close operation - performed on, say, a tape device might have undesirable effects. */ - struct stat64 statbuf; - if (__glibc_unlikely (__xstat64 (_STAT_VER, name, &statbuf) < 0)) - return NULL; - if (__glibc_unlikely (! S_ISDIR (statbuf.st_mode))) - { - __set_errno (ENOTDIR); - return NULL; - } - } - - return opendir_tail (open_not_cancel_2 (name, opendir_oflags ())); + return opendir_tail (__open_nocancel (name, opendir_oflags)); } weak_alias (__opendir, opendir) - -#ifdef __ASSUME_O_CLOEXEC -# define check_have_o_cloexec(fd) 1 -#else -static int -check_have_o_cloexec (int fd) -{ - if (__have_o_cloexec == 0) - __have_o_cloexec = (__fcntl (fd, F_GETFD, 0) & FD_CLOEXEC) == 0 ? -1 : 1; - return __have_o_cloexec > 0; -} -#endif - - DIR * -internal_function __alloc_dir (int fd, bool close_fd, int flags, const struct stat64 *statp) { - /* We always have to set the close-on-exit flag if the user provided - the file descriptor. Otherwise only if we have no working - O_CLOEXEC support. */ -#ifdef O_CLOEXEC - if ((! close_fd && (flags & O_CLOEXEC) == 0) - || ! check_have_o_cloexec (fd)) -#endif - { - if (__builtin_expect (__fcntl (fd, F_SETFD, FD_CLOEXEC), 0) < 0) + /* We have to set the close-on-exit flag if the user provided the + file descriptor. */ + if (!close_fd + && __glibc_unlikely (__fcntl64_nocancel (fd, F_SETFD, FD_CLOEXEC) < 0)) goto lose; - } const size_t default_allocation = (4 * BUFSIZ < sizeof (struct dirent64) ? sizeof (struct dirent64) : 4 * BUFSIZ); @@ -256,7 +127,7 @@ __alloc_dir (int fd, bool close_fd, int flags, const struct stat64 *statp) if (close_fd) { int save_errno = errno; - close_not_cancel_no_status (fd); + __close_nocancel_nostatus (fd); __set_errno (save_errno); } return NULL; diff --git a/sysdeps/posix/pathconf.c b/sysdeps/posix/pathconf.c index f65d5018ea..0f893ec1ba 100644 --- a/sysdeps/posix/pathconf.c +++ b/sysdeps/posix/pathconf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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 @@ -101,25 +101,22 @@ __pathconf (const char *path, int name) #endif case _PC_CHOWN_RESTRICTED: -#ifdef _POSIX_CHOWN_RESTRICTED - return _POSIX_CHOWN_RESTRICTED; -#else - return -1; +#if _POSIX_CHOWN_RESTRICTED == -1 +# error "Invalid value for _POSIX_CHOWN_RESTRICTED" #endif + return _POSIX_CHOWN_RESTRICTED; case _PC_NO_TRUNC: -#ifdef _POSIX_NO_TRUNC - return _POSIX_NO_TRUNC; -#else - return -1; +#if _POSIX_NO_TRUNC == -1 +# error "Invalid value for _POSIX_NO_TRUNC" #endif + return _POSIX_NO_TRUNC; case _PC_VDISABLE: -#ifdef _POSIX_VDISABLE - return _POSIX_VDISABLE; -#else - return -1; +#if _POSIX_VDISABLE == -1 +# error "Invalid value for _POSIX_VDISABLE" #endif + return _POSIX_VDISABLE; case _PC_SYNC_IO: #ifdef _POSIX_SYNC_IO diff --git a/sysdeps/posix/pause.c b/sysdeps/posix/pause.c index f1ecc4f98b..2b9eca2192 100644 --- a/sysdeps/posix/pause.c +++ b/sysdeps/posix/pause.c @@ -1,5 +1,5 @@ /* pause -- suspend the process until a signal arrives. POSIX.1 version. - Copyright (C) 2003-2016 Free Software Foundation, Inc. + Copyright (C) 2003-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 @@ -19,6 +19,7 @@ #include <signal.h> #include <unistd.h> #include <sysdep-cancel.h> +#include <sigsetops.h> /* Suspend the process until a signal arrives. This always returns -1 and sets errno to EINTR. */ @@ -39,18 +40,3 @@ __libc_pause (void) weak_alias (__libc_pause, pause) LIBC_CANCEL_HANDLED (); /* sigsuspend handles our cancellation. */ - -#ifndef NO_CANCELLATION -# include <not-cancel.h> - -int -__pause_nocancel (void) -{ - sigset_t set; - - __sigemptyset (&set); - __sigprocmask (SIG_BLOCK, NULL, &set); - - return sigsuspend_not_cancel (&set); -} -#endif diff --git a/sysdeps/posix/posix_fallocate.c b/sysdeps/posix/posix_fallocate.c index 970e7d80e8..f3c2182486 100644 --- a/sysdeps/posix/posix_fallocate.c +++ b/sysdeps/posix/posix_fallocate.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2016 Free Software Foundation, Inc. +/* Copyright (C) 2000-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/sysdeps/posix/posix_fallocate64.c b/sysdeps/posix/posix_fallocate64.c index 0c094ff9b8..2eaeab2a6f 100644 --- a/sysdeps/posix/posix_fallocate64.c +++ b/sysdeps/posix/posix_fallocate64.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2016 Free Software Foundation, Inc. +/* Copyright (C) 2000-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/sysdeps/posix/pread.c b/sysdeps/posix/pread.c index aa8e8901fd..aa0a56cf98 100644 --- a/sysdeps/posix/pread.c +++ b/sysdeps/posix/pread.c @@ -1,6 +1,6 @@ /* Read block from given position in file without changing file pointer. POSIX version. - Copyright (C) 1997-2016 Free Software Foundation, Inc. + Copyright (C) 1997-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. diff --git a/sysdeps/posix/pread64.c b/sysdeps/posix/pread64.c index b7a2808c07..04146239a8 100644 --- a/sysdeps/posix/pread64.c +++ b/sysdeps/posix/pread64.c @@ -1,6 +1,6 @@ /* Read block from given position in file without changing file pointer. POSIX version. - Copyright (C) 1997-2016 Free Software Foundation, Inc. + Copyright (C) 1997-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -58,5 +58,6 @@ __libc_pread64 (int fd, void *buf, size_t nbyte, off64_t offset) #ifndef __libc_pread64 weak_alias (__libc_pread64, __pread64) +libc_hidden_weak (__pread64) weak_alias (__libc_pread64, pread64) #endif diff --git a/sysdeps/posix/preadv.c b/sysdeps/posix/preadv.c index fb7586c0a6..f944ec746e 100644 --- a/sysdeps/posix/preadv.c +++ b/sysdeps/posix/preadv.c @@ -1,4 +1,5 @@ -/* Copyright (C) 2009-2016 Free Software Foundation, Inc. +/* Read data into multiple buffers. Generic version. + 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 @@ -15,93 +16,15 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ -#include <errno.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <limits.h> -#include <stdbool.h> -#include <sys/param.h> -#if __WORDSIZE == 64 && !defined PREADV -/* Hide the preadv64 declaration. */ -# define preadv64 __redirect_preadv64 -#endif -#include <sys/uio.h> -#include <bits/wordsize.h> +#include <sys/types.h> + +#ifndef __OFF_T_MATCHES_OFF64_T -#ifndef PREADV # define PREADV preadv # define PREAD __pread # define OFF_T off_t -#endif - - -static void -ifree (char **ptrp) -{ - free (*ptrp); -} - - -/* Read data from file descriptor FD at the given position OFFSET - without change the file pointer, and put the result in the buffers - described by VECTOR, which is a vector of COUNT 'struct iovec's. - The buffers are filled in the order specified. Operates just like - 'pread' (see <unistd.h>) except that data are put in VECTOR instead - of a contiguous buffer. */ -ssize_t -PREADV (int fd, const struct iovec *vector, int count, OFF_T offset) -{ - /* Find the total number of bytes to be read. */ - size_t bytes = 0; - for (int i = 0; i < count; ++i) - { - /* Check for ssize_t overflow. */ - if (SSIZE_MAX - bytes < vector[i].iov_len) - { - __set_errno (EINVAL); - return -1; - } - bytes += vector[i].iov_len; - } - - /* Allocate a temporary buffer to hold the data. We should normally - use alloca since it's faster and does not require synchronization - with other threads. But we cannot if the amount of memory - required is too large. */ - char *buffer; - char *malloced_buffer __attribute__ ((__cleanup__ (ifree))) = NULL; - if (__libc_use_alloca (bytes)) - buffer = (char *) __alloca (bytes); - else - { - malloced_buffer = buffer = (char *) malloc (bytes); - if (buffer == NULL) - return -1; - } - - /* Read the data. */ - ssize_t bytes_read = PREAD (fd, buffer, bytes, offset); - if (bytes_read < 0) - return -1; - - /* Copy the data from BUFFER into the memory specified by VECTOR. */ - bytes = bytes_read; - for (int i = 0; i < count; ++i) - { - size_t copy = MIN (vector[i].iov_len, bytes); - - (void) memcpy ((void *) vector[i].iov_base, (void *) buffer, copy); +# include <sysdeps/posix/preadv_common.c> - buffer += copy; - bytes -= copy; - if (bytes == 0) - break; - } +libc_hidden_def (preadv) - return bytes_read; -} -#if __WORDSIZE == 64 && defined preadv64 -# undef preadv64 -strong_alias (preadv, preadv64) #endif diff --git a/sysdeps/posix/preadv2.c b/sysdeps/posix/preadv2.c new file mode 100644 index 0000000000..4f8557ac83 --- /dev/null +++ b/sysdeps/posix/preadv2.c @@ -0,0 +1,42 @@ +/* Generic version of preadv2. + Copyright (C) 2017-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 + 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 <errno.h> +#include <unistd.h> +#include <sys/uio.h> + +#ifndef __OFF_T_MATCHES_OFF64_T + +/* Since we define no flags for preadv2 just route to preadv. */ +ssize_t +preadv2 (int fd, const struct iovec *vector, int count, off_t offset, + int flags) +{ + if (flags != 0) + { + __set_errno (ENOTSUP); + return -1; + } + + if (offset == -1) + return __readv (fd, vector, count); + else + return preadv (fd, vector, count, offset); +} + +#endif diff --git a/sysdeps/posix/preadv64.c b/sysdeps/posix/preadv64.c index 198622353a..d0ee6dae4a 100644 --- a/sysdeps/posix/preadv64.c +++ b/sysdeps/posix/preadv64.c @@ -1,9 +1,28 @@ -#include <bits/wordsize.h> +/* Read data into multiple buffers. Generic LFS version. + Copyright (C) 2009-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. -#if __WORDSIZE == 32 -# define PREADV preadv64 -# define PREAD __pread64 -# define OFF_T off64_t + 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. -# include "preadv.c" + 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/>. */ + +#define PREADV preadv64 +#define PREAD __pread64 +#define OFF_T off64_t +#include <sysdeps/posix/preadv_common.c> + +libc_hidden_def (preadv64) +#ifdef __OFF_T_MATCHES_OFF64_T +strong_alias (preadv64, preadv) +libc_hidden_def (preadv) #endif diff --git a/sysdeps/posix/preadv64v2.c b/sysdeps/posix/preadv64v2.c new file mode 100644 index 0000000000..f89ad08c54 --- /dev/null +++ b/sysdeps/posix/preadv64v2.c @@ -0,0 +1,41 @@ +/* Generic version of preadv2. + Copyright (C) 2017-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 + 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 <errno.h> +#include <unistd.h> +#include <sys/uio.h> + +ssize_t +preadv64v2 (int fd, const struct iovec *vector, int count, off64_t offset, + int flags) +{ + if (flags != 0) + { + __set_errno (ENOTSUP); + return -1; + } + + if (offset == -1) + return __readv (fd, vector, count); + else + return preadv64 (fd, vector, count, offset); +} + +#ifdef __OFF_T_MATCHES_OFF64_T +strong_alias (preadv64v2, preadv2) +#endif diff --git a/sysdeps/posix/preadv_common.c b/sysdeps/posix/preadv_common.c new file mode 100644 index 0000000000..14fd4cea2a --- /dev/null +++ b/sysdeps/posix/preadv_common.c @@ -0,0 +1,85 @@ +/* Read data into multiple buffers. Base implementation for preadv + and preadv64. + Copyright (C) 2017-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 + 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 <unistd.h> +#include <sys/uio.h> +#include <sys/param.h> +#include <errno.h> +#include <malloc.h> + +#include <ldsodefs.h> +#include <libc-pointer-arith.h> + +/* Read data from file descriptor FD at the given position OFFSET + without change the file pointer, and put the result in the buffers + described by VECTOR, which is a vector of COUNT 'struct iovec's. + The buffers are filled in the order specified. Operates just like + 'pread' (see <unistd.h>) except that data are put in VECTOR instead + of a contiguous buffer. */ +ssize_t +PREADV (int fd, const struct iovec *vector, int count, OFF_T offset) +{ + /* Find the total number of bytes to be read. */ + size_t bytes = 0; + for (int i = 0; i < count; ++i) + { + /* Check for ssize_t overflow. */ + if (SSIZE_MAX - bytes < vector[i].iov_len) + { + __set_errno (EINVAL); + return -1; + } + bytes += vector[i].iov_len; + } + + /* Allocate a temporary buffer to hold the data. It could be done with a + stack allocation, but due limitations on some system (Linux with + O_DIRECT) it aligns the buffer to pagesize. A possible optimization + would be querying if the syscall would impose any alignment constraint, + but 1. it is system specific (not meant in generic implementation), and + 2. it would make the implementation more complex, and 3. it will require + another syscall (fcntl). */ + void *buffer = __mmap (NULL, bytes, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (__glibc_unlikely (buffer == MAP_FAILED)) + return -1; + + ssize_t bytes_read = PREAD (fd, buffer, bytes, offset); + if (bytes_read < 0) + goto end; + + /* Copy the data from BUFFER into the memory specified by VECTOR. */ + bytes = bytes_read; + void *buf = buffer; + for (int i = 0; i < count; ++i) + { + size_t copy = MIN (vector[i].iov_len, bytes); + + memcpy (vector[i].iov_base, buf, copy); + + buf += copy; + bytes -= copy; + if (bytes == 0) + break; + } + +end: + __munmap (buffer, bytes); + return bytes_read; +} diff --git a/sysdeps/posix/profil.c b/sysdeps/posix/profil.c index 23e601c6c2..ae0a663533 100644 --- a/sysdeps/posix/profil.c +++ b/sysdeps/posix/profil.c @@ -1,5 +1,5 @@ /* Low-level statistical profiling support function. Mostly POSIX.1 version. - 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 @@ -22,6 +22,7 @@ #include <signal.h> #include <sys/time.h> #include <libc-internal.h> +#include <sigsetops.h> #ifndef SIGPROF diff --git a/sysdeps/posix/pwrite.c b/sysdeps/posix/pwrite.c index c3aa7c084a..0455a806d0 100644 --- a/sysdeps/posix/pwrite.c +++ b/sysdeps/posix/pwrite.c @@ -1,6 +1,6 @@ /* Write block to given position in file without changing file pointer. POSIX version. - Copyright (C) 1997-2016 Free Software Foundation, Inc. + Copyright (C) 1997-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. diff --git a/sysdeps/posix/pwrite64.c b/sysdeps/posix/pwrite64.c index 721c733c3f..38c1903958 100644 --- a/sysdeps/posix/pwrite64.c +++ b/sysdeps/posix/pwrite64.c @@ -1,6 +1,6 @@ /* Write block to given position in file without changing file pointer. POSIX version. - Copyright (C) 1997-2016 Free Software Foundation, Inc. + Copyright (C) 1997-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. diff --git a/sysdeps/posix/pwritev.c b/sysdeps/posix/pwritev.c index 8c483f1b47..3a8b1b2081 100644 --- a/sysdeps/posix/pwritev.c +++ b/sysdeps/posix/pwritev.c @@ -1,4 +1,5 @@ -/* Copyright (C) 2009-2016 Free Software Foundation, Inc. +/* Write data into multiple buffers. Generic version. + 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 @@ -15,81 +16,15 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ -#include <errno.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <limits.h> -#include <stdbool.h> -#include <sys/param.h> -#if __WORDSIZE == 64 && !defined PWRITEV -/* Hide the pwritev64 declaration. */ -# define pwritev64 __redirect_pwritev64 -#endif -#include <sys/uio.h> -#include <bits/wordsize.h> +#include <sys/types.h> + +#ifndef __OFF_T_MATCHES_OFF64_T -#ifndef PWRITEV # define PWRITEV pwritev # define PWRITE __pwrite # define OFF_T off_t -#endif - - -static void -ifree (char **ptrp) -{ - free (*ptrp); -} - - -/* Write data pointed by the buffers described by IOVEC, which is a - vector of COUNT 'struct iovec's, to file descriptor FD at the given - position OFFSET without change the file pointer. The data is - written in the order specified. Operates just like 'write' (see - <unistd.h>) except that the data are taken from IOVEC instead of a - contiguous buffer. */ -ssize_t -PWRITEV (int fd, const struct iovec *vector, int count, OFF_T offset) -{ - /* Find the total number of bytes to be read. */ - size_t bytes = 0; - for (int i = 0; i < count; ++i) - { - /* Check for ssize_t overflow. */ - if (SSIZE_MAX - bytes < vector[i].iov_len) - { - __set_errno (EINVAL); - return -1; - } - bytes += vector[i].iov_len; - } - - /* Allocate a temporary buffer to hold the data. We should normally - use alloca since it's faster and does not require synchronization - with other threads. But we cannot if the amount of memory - required is too large. */ - char *buffer; - char *malloced_buffer __attribute__ ((__cleanup__ (ifree))) = NULL; - if (__libc_use_alloca (bytes)) - buffer = (char *) __alloca (bytes); - else - { - malloced_buffer = buffer = (char *) malloc (bytes); - if (buffer == NULL) - return -1; - } +# include <sysdeps/posix/pwritev_common.c> - /* Copy the data from BUFFER into the memory specified by VECTOR. */ - char *ptr = buffer; - for (int i = 0; i < count; ++i) - ptr = __mempcpy ((void *) ptr, (void *) vector[i].iov_base, - vector[i].iov_len); +libc_hidden_def (pwritev) - /* Write the data. */ - return PWRITE (fd, buffer, bytes, offset); -} -#if __WORDSIZE == 64 && defined pwritev64 -# undef pwritev64 -strong_alias (pwritev, pwritev64) #endif diff --git a/sysdeps/posix/pwritev2.c b/sysdeps/posix/pwritev2.c new file mode 100644 index 0000000000..a39304d9d9 --- /dev/null +++ b/sysdeps/posix/pwritev2.c @@ -0,0 +1,42 @@ +/* Generic version of pwritev2. + Copyright (C) 2017-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 + 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 <errno.h> +#include <unistd.h> +#include <sys/uio.h> + +#ifndef __OFF_T_MATCHES_OFF64_T + +/* Since we define no flags for pwritev2 just route to pwritev. */ +ssize_t +pwritev2 (int fd, const struct iovec *vector, int count, off_t offset, + int flags) +{ + if (flags != 0) + { + __set_errno (ENOTSUP); + return -1; + } + + if (offset == -1) + return __writev (fd, vector, count); + else + return pwritev (fd, vector, count, offset); +} + +#endif diff --git a/sysdeps/posix/pwritev64.c b/sysdeps/posix/pwritev64.c index 4948d2efee..f16b1c1b8e 100644 --- a/sysdeps/posix/pwritev64.c +++ b/sysdeps/posix/pwritev64.c @@ -1,9 +1,28 @@ -#include <bits/wordsize.h> +/* Write data into multiple buffers. Generic LFS version. + Copyright (C) 2009-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. -#if __WORDSIZE == 32 -# define PWRITEV pwritev64 -# define PWRITE __pwrite64 -# define OFF_T off64_t + 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. -# include "pwritev.c" + 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/>. */ + +#define PWRITEV pwritev64 +#define PWRITE __pwrite64 +#define OFF_T off64_t +#include <sysdeps/posix/pwritev_common.c> + +libc_hidden_def (pwritev64) +#ifdef __OFF_T_MATCHES_OFF64_T +strong_alias (pwritev64, pwritev) +libc_hidden_def (pwritev) #endif diff --git a/sysdeps/posix/pwritev64v2.c b/sysdeps/posix/pwritev64v2.c new file mode 100644 index 0000000000..7a3a3239d7 --- /dev/null +++ b/sysdeps/posix/pwritev64v2.c @@ -0,0 +1,42 @@ +/* Generic version of pwritev2. + Copyright (C) 2017-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 + 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 <errno.h> +#include <unistd.h> +#include <sys/uio.h> + +/* Since we define no flags for pwritev2 just route to pwritev. */ +ssize_t +pwritev64v2 (int fd, const struct iovec *vector, int count, off64_t offset, + int flags) +{ + if (flags != 0) + { + __set_errno (ENOTSUP); + return -1; + } + + if (offset == -1) + return __writev (fd, vector, count); + else + return pwritev64 (fd, vector, count, offset); +} + +#ifdef __OFF_T_MATCHES_OFF64_T +strong_alias (pwritev64v2, pwritev2) +#endif diff --git a/sysdeps/posix/pwritev_common.c b/sysdeps/posix/pwritev_common.c new file mode 100644 index 0000000000..344ab4d61b --- /dev/null +++ b/sysdeps/posix/pwritev_common.c @@ -0,0 +1,74 @@ +/* Write data into multiple buffers. Base implementation for pwritev + and pwritev64. + Copyright (C) 2017-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 + 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 <unistd.h> +#include <sys/uio.h> +#include <sys/param.h> +#include <errno.h> +#include <malloc.h> + +#include <ldsodefs.h> +#include <libc-pointer-arith.h> + +/* Write data pointed by the buffers described by IOVEC, which is a + vector of COUNT 'struct iovec's, to file descriptor FD at the given + position OFFSET without change the file pointer. The data is + written in the order specified. Operates just like 'write' (see + <unistd.h>) except that the data are taken from IOVEC instead of a + contiguous buffer. */ +ssize_t +PWRITEV (int fd, const struct iovec *vector, int count, OFF_T offset) +{ + /* Find the total number of bytes to be read. */ + size_t bytes = 0; + for (int i = 0; i < count; ++i) + { + /* Check for ssize_t overflow. */ + if (SSIZE_MAX - bytes < vector[i].iov_len) + { + __set_errno (EINVAL); + return -1; + } + bytes += vector[i].iov_len; + } + + /* Allocate a temporary buffer to hold the data. It could be done with a + stack allocation, but due limitations on some system (Linux with + O_DIRECT) it aligns the buffer to pagesize. A possible optimization + would be querying if the syscall would impose any alignment constraint, + but 1. it is system specific (not meant in generic implementation), and + 2. it would make the implementation more complex, and 3. it will require + another syscall (fcntl). */ + void *buffer = __mmap (NULL, bytes, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (__glibc_unlikely (buffer == MAP_FAILED)) + return -1; + + /* Copy the data from BUFFER into the memory specified by VECTOR. */ + char *ptr = buffer; + for (int i = 0; i < count; ++i) + ptr = __mempcpy ((void *) ptr, (void *) vector[i].iov_base, + vector[i].iov_len); + + ssize_t ret = PWRITE (fd, buffer, bytes, offset); + + __munmap (buffer, bytes); + + return ret; +} diff --git a/sysdeps/posix/raise.c b/sysdeps/posix/raise.c index d438fcb87e..1f02b201e1 100644 --- a/sysdeps/posix/raise.c +++ b/sysdeps/posix/raise.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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/sysdeps/posix/readdir.c b/sysdeps/posix/readdir.c index e1e63f6157..a6ecc0fe5b 100644 --- a/sysdeps/posix/readdir.c +++ b/sysdeps/posix/readdir.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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 @@ -120,3 +120,8 @@ __READDIR (DIR *dirp) #ifdef __READDIR_ALIAS weak_alias (__readdir, readdir) #endif + +#undef __READDIR +#undef __GETDENTS +#undef DIRENT_TYPE +#undef __READDIR_ALIAS diff --git a/sysdeps/posix/readdir_r.c b/sysdeps/posix/readdir_r.c index 4c7b3701fe..2d691e7242 100644 --- a/sysdeps/posix/readdir_r.c +++ b/sysdeps/posix/readdir_r.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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 @@ -152,3 +152,8 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result) #ifdef __READDIR_R_ALIAS weak_alias (__readdir_r, readdir_r) #endif + +#undef __READDIR_R +#undef __GETDENTS +#undef DIRENT_TYPE +#undef __READDIR_R_ALIAS diff --git a/sysdeps/posix/readv.c b/sysdeps/posix/readv.c index 17a864d2fa..4fe6218454 100644 --- a/sysdeps/posix/readv.c +++ b/sysdeps/posix/readv.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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 @@ -88,4 +88,5 @@ __readv (int fd, const struct iovec *vector, int count) return bytes_read; } +libc_hidden_def (__readv) weak_alias (__readv, readv) diff --git a/sysdeps/posix/remove.c b/sysdeps/posix/remove.c index 8d331fa171..1ddf9ebc1b 100644 --- a/sysdeps/posix/remove.c +++ b/sysdeps/posix/remove.c @@ -1,5 +1,5 @@ /* ANSI C `remove' function to delete a file or directory. POSIX.1 version. - Copyright (C) 1995-2016 Free Software Foundation, Inc. + Copyright (C) 1995-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/sysdeps/posix/rename.c b/sysdeps/posix/rename.c index df34f0949d..15c7f56e65 100644 --- a/sysdeps/posix/rename.c +++ b/sysdeps/posix/rename.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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/sysdeps/posix/rewinddir.c b/sysdeps/posix/rewinddir.c index 1fa4c94a04..5c5d8f1514 100644 --- a/sysdeps/posix/rewinddir.c +++ b/sysdeps/posix/rewinddir.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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/sysdeps/posix/seekdir.c b/sysdeps/posix/seekdir.c index 5e774a16e8..bcf2405e16 100644 --- a/sysdeps/posix/seekdir.c +++ b/sysdeps/posix/seekdir.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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/sysdeps/posix/shm-directory.c b/sysdeps/posix/shm-directory.c index 953085b7ce..4e2285ff24 100644 --- a/sysdeps/posix/shm-directory.c +++ b/sysdeps/posix/shm-directory.c @@ -1,5 +1,5 @@ /* Determine directory for shm/sem files. Generic POSIX version. - Copyright (C) 2014-2016 Free Software Foundation, Inc. + Copyright (C) 2014-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/sysdeps/posix/shm-directory.h b/sysdeps/posix/shm-directory.h index 76c528d8be..55ded84efa 100644 --- a/sysdeps/posix/shm-directory.h +++ b/sysdeps/posix/shm-directory.h @@ -1,5 +1,5 @@ /* Header for directory for shm/sem files. - Copyright (C) 2014-2016 Free Software Foundation, Inc. + Copyright (C) 2014-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/sysdeps/posix/shm_open.c b/sysdeps/posix/shm_open.c index f2961620b4..b9b473ceed 100644 --- a/sysdeps/posix/shm_open.c +++ b/sysdeps/posix/shm_open.c @@ -1,5 +1,5 @@ /* shm_open -- open a POSIX shared memory object. Generic POSIX file version. - Copyright (C) 2001-2016 Free Software Foundation, Inc. + Copyright (C) 2001-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 @@ -25,6 +25,7 @@ #else # include <fcntl.h> +# include <pthread.h> # include <shm-directory.h> @@ -34,12 +35,12 @@ shm_open (const char *name, int oflag, mode_t mode) { SHM_GET_NAME (EINVAL, -1, ""); -# ifdef O_NOFOLLOW - oflag |= O_NOFOLLOW; -# endif -# ifdef O_CLOEXEC - oflag |= O_CLOEXEC; -# endif + oflag |= O_NOFOLLOW | O_CLOEXEC; + + /* Disable asynchronous cancellation. */ + int state; + pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &state); + int fd = open (shm_name, oflag, mode); if (fd == -1 && __glibc_unlikely (errno == EISDIR)) /* It might be better to fold this error with EINVAL since @@ -47,28 +48,7 @@ shm_open (const char *name, int oflag, mode_t mode) object names and the standard does not mention EISDIR. */ __set_errno (EINVAL); -# ifndef O_CLOEXEC - if (fd != -1) - { - /* We got a descriptor. Now set the FD_CLOEXEC bit. */ - int flags = fcntl (fd, F_GETFD, 0); - - if (__glibc_likely (flags != -1)) - { - flags |= FD_CLOEXEC; - flags = fcntl (fd, F_SETFD, flags); - } - - if (flags == -1) - { - /* Something went wrong. We cannot return the descriptor. */ - int save_errno = errno; - close (fd); - fd = -1; - __set_errno (save_errno); - } - } -# endif + pthread_setcancelstate (state, NULL); return fd; } diff --git a/sysdeps/posix/shm_unlink.c b/sysdeps/posix/shm_unlink.c index ae742d3fcb..de8466f4c1 100644 --- a/sysdeps/posix/shm_unlink.c +++ b/sysdeps/posix/shm_unlink.c @@ -1,5 +1,5 @@ /* shm_unlink -- remove a POSIX shared memory object. Generic POSIX version. - Copyright (C) 2001-2016 Free Software Foundation, Inc. + Copyright (C) 2001-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/sysdeps/posix/sigblock.c b/sysdeps/posix/sigblock.c index c28b819376..9d8f4db47d 100644 --- a/sysdeps/posix/sigblock.c +++ b/sysdeps/posix/sigblock.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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 @@ -35,4 +35,5 @@ __sigblock (int mask) return sigset_get_old_mask (&oset); } +libc_hidden_def (__sigblock) weak_alias (__sigblock, sigblock) diff --git a/sysdeps/posix/sigignore.c b/sysdeps/posix/sigignore.c index 28d3eeb706..120d06cef1 100644 --- a/sysdeps/posix/sigignore.c +++ b/sysdeps/posix/sigignore.c @@ -1,5 +1,5 @@ /* Set the disposition of SIG to SIG_IGN. - Copyright (C) 1998-2016 Free Software Foundation, Inc. + Copyright (C) 1998-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. @@ -22,7 +22,7 @@ #include <stddef.h> #include <signal.h> #include <string.h> /* For the real memset prototype. */ - +#include <sigsetops.h> int sigignore (int sig) @@ -30,8 +30,7 @@ sigignore (int sig) struct sigaction act; act.sa_handler = SIG_IGN; - if (__sigemptyset (&act.sa_mask) < 0) - return -1; + __sigemptyset (&act.sa_mask); act.sa_flags = 0; return __sigaction (sig, &act, NULL); diff --git a/sysdeps/posix/sigintr.c b/sysdeps/posix/sigintr.c index bce75b7cf9..435fc75f3e 100644 --- a/sysdeps/posix/sigintr.c +++ b/sysdeps/posix/sigintr.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1992-2016 Free Software Foundation, Inc. +/* Copyright (C) 1992-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 @@ -18,6 +18,7 @@ #include <stddef.h> #include <signal.h> #include <errno.h> +#include <sigsetops.h> /* If INTERRUPT is nonzero, make signal SIG interrupt system calls (causing them to fail with EINTR); if INTERRUPT is zero, make system diff --git a/sysdeps/posix/signal.c b/sysdeps/posix/signal.c index 6884fc742d..8a135c7b0e 100644 --- a/sysdeps/posix/signal.c +++ b/sysdeps/posix/signal.c @@ -1,5 +1,5 @@ /* BSD-like signal function. - Copyright (C) 1991-2016 Free Software Foundation, Inc. + Copyright (C) 1991-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 @@ -18,8 +18,8 @@ #include <errno.h> #include <signal.h> -#include <string.h> /* For the real memset prototype. */ - +#include <sigsetops.h> +#include <internal-signals.h> sigset_t _sigintr attribute_hidden; /* Set by siginterrupt. */ @@ -31,16 +31,16 @@ __bsd_signal (int sig, __sighandler_t handler) struct sigaction act, oact; /* Check signal extents to protect __sigismember. */ - if (handler == SIG_ERR || sig < 1 || sig >= NSIG) + if (handler == SIG_ERR || sig < 1 || sig >= NSIG + || __is_internal_signal (sig)) { __set_errno (EINVAL); return SIG_ERR; } act.sa_handler = handler; - if (__sigemptyset (&act.sa_mask) < 0 - || __sigaddset (&act.sa_mask, sig) < 0) - return SIG_ERR; + __sigemptyset (&act.sa_mask); + __sigaddset (&act.sa_mask, sig); act.sa_flags = __sigismember (&_sigintr, sig) ? 0 : SA_RESTART; if (__sigaction (sig, &act, &oact) < 0) return SIG_ERR; diff --git a/sysdeps/posix/sigpause.c b/sysdeps/posix/sigpause.c index bbe8bde324..db9df8eb6e 100644 --- a/sysdeps/posix/sigpause.c +++ b/sysdeps/posix/sigpause.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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 @@ -19,15 +19,13 @@ #include <errno.h> #include <signal.h> #include <stddef.h> /* For NULL. */ -#include <sysdep-cancel.h> #undef sigpause #include <sigset-cvt-mask.h> +#include <sysdep-cancel.h> -/* Set the mask of blocked signals to MASK, - wait for a signal to arrive, and then restore the mask. */ -static int -do_sigpause (int sig_or_mask, int is_sig) +int +__sigpause (int sig_or_mask, int is_sig) { sigset_t set; @@ -46,21 +44,6 @@ do_sigpause (int sig_or_mask, int is_sig) to do anything here. */ return __sigsuspend (&set); } - -int -__sigpause (int sig_or_mask, int is_sig) -{ - if (SINGLE_THREAD_P) - return do_sigpause (sig_or_mask, is_sig); - - int oldtype = LIBC_CANCEL_ASYNC (); - - int result = do_sigpause (sig_or_mask, is_sig); - - LIBC_CANCEL_RESET (oldtype); - - return result; -} libc_hidden_def (__sigpause) /* We have to provide a default version of this function since the @@ -87,3 +70,6 @@ __xpg_sigpause (int sig) return __sigpause (sig, 1); } strong_alias (__xpg_sigpause, __libc___xpg_sigpause) + +/* __sigsuspend handles cancellation. */ +LIBC_CANCEL_HANDLED (); diff --git a/sysdeps/posix/sigset.c b/sysdeps/posix/sigset.c index 765fe637f1..6ab4a48767 100644 --- a/sysdeps/posix/sigset.c +++ b/sysdeps/posix/sigset.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998-2016 Free Software Foundation, Inc. +/* Copyright (C) 1998-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 @@ -8,7 +8,7 @@ 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 + 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 @@ -20,7 +20,7 @@ #include <stddef.h> #include <signal.h> #include <string.h> /* For the real memset prototype. */ - +#include <sigsetops.h> /* Set the disposition for SIG. */ __sighandler_t @@ -31,19 +31,13 @@ sigset (int sig, __sighandler_t disp) sigset_t set; sigset_t oset; -#ifdef SIG_HOLD - /* Handle SIG_HOLD first. */ + __sigemptyset (&set); + if (sigaddset (&set, sig) < 0) + return SIG_ERR; + if (disp == SIG_HOLD) { - /* Create an empty signal set. */ - if (__sigemptyset (&set) < 0) - return SIG_ERR; - - /* Add the specified signal. */ - if (__sigaddset (&set, sig) < 0) - return SIG_ERR; - - /* Add the signal set to the current signal mask. */ + /* Add the signal to the current signal mask. */ if (__sigprocmask (SIG_BLOCK, &set, &oset) < 0) return SIG_ERR; @@ -57,34 +51,19 @@ sigset (int sig, __sighandler_t disp) return oact.sa_handler; } -#endif /* SIG_HOLD */ - - /* Check signal extents to protect __sigismember. */ - if (disp == SIG_ERR || sig < 1 || sig >= NSIG) + else { - __set_errno (EINVAL); - return SIG_ERR; - } - - act.sa_handler = disp; - if (__sigemptyset (&act.sa_mask) < 0) - return SIG_ERR; - act.sa_flags = 0; - if (__sigaction (sig, &act, &oact) < 0) - return SIG_ERR; - - /* Create an empty signal set. */ - if (__sigemptyset (&set) < 0) - return SIG_ERR; - - /* Add the specified signal. */ - if (__sigaddset (&set, sig) < 0) - return SIG_ERR; + act.sa_handler = disp; + __sigemptyset (&act.sa_mask); + act.sa_flags = 0; + if (__sigaction (sig, &act, &oact) < 0) + return SIG_ERR; - /* Remove the signal set from the current signal mask. */ - if (__sigprocmask (SIG_UNBLOCK, &set, &oset) < 0) - return SIG_ERR; + /* Remove the signal from the current signal mask. */ + if (__sigprocmask (SIG_UNBLOCK, &set, &oset) < 0) + return SIG_ERR; - /* If the signal was already blocked return SIG_HOLD. */ - return __sigismember (&oset, sig) ? SIG_HOLD : oact.sa_handler; + /* If the signal was already blocked return SIG_HOLD. */ + return __sigismember (&oset, sig) ? SIG_HOLD : oact.sa_handler; + } } diff --git a/sysdeps/posix/sigsetmask.c b/sysdeps/posix/sigsetmask.c index bb16262ece..9895848937 100644 --- a/sysdeps/posix/sigsetmask.c +++ b/sysdeps/posix/sigsetmask.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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/sysdeps/posix/sigsuspend.c b/sysdeps/posix/sigsuspend.c index 090edc208c..50953fc818 100644 --- a/sysdeps/posix/sigsuspend.c +++ b/sysdeps/posix/sigsuspend.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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/sysdeps/posix/sigwait.c b/sysdeps/posix/sigwait.c index b9b328176d..4ff9d847d4 100644 --- a/sysdeps/posix/sigwait.c +++ b/sysdeps/posix/sigwait.c @@ -1,5 +1,5 @@ /* Implementation of sigwait function from POSIX.1c. - 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/sysdeps/posix/sleep.c b/sysdeps/posix/sleep.c index f15028bd1a..7de748fe44 100644 --- a/sysdeps/posix/sleep.c +++ b/sysdeps/posix/sleep.c @@ -1,5 +1,5 @@ /* Sleep for a given number of seconds. POSIX.1 version. - Copyright (C) 1991-2016 Free Software Foundation, Inc. + Copyright (C) 1991-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/sysdeps/posix/spawni.c b/sysdeps/posix/spawni.c index 043266dcd3..b138ab4393 100644 --- a/sysdeps/posix/spawni.c +++ b/sysdeps/posix/spawni.c @@ -1,5 +1,5 @@ /* Guts of POSIX spawn interface. Generic POSIX.1 version. - Copyright (C) 2000-2016 Free Software Foundation, Inc. + Copyright (C) 2000-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,20 +16,23 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ -#include <errno.h> +#include <spawn.h> +#include <assert.h> #include <fcntl.h> #include <paths.h> -#include <spawn.h> -#include <stdbool.h> -#include <stdlib.h> #include <string.h> -#include <unistd.h> -#include <signal.h> #include <sys/resource.h> -#include "spawn_int.h" +#include <sys/wait.h> +#include <sys/param.h> +#include <sys/mman.h> #include <not-cancel.h> #include <local-setxid.h> #include <shlib-compat.h> +#include <nptl/pthreadP.h> +#include <dl-sysdep.h> +#include <libc-pointer-arith.h> +#include <ldsodefs.h> +#include "spawn_int.h" /* The Unix standard contains a long explanation of the way to signal @@ -39,93 +42,59 @@ normal program exit with the exit code 127. */ #define SPAWN_ERROR 127 - -/* The file is accessible but it is not an executable file. Invoke - the shell to interpret it as a script. */ -static void -internal_function -script_execute (const char *file, char *const argv[], char *const envp[]) +struct posix_spawn_args { - /* Count the arguments. */ - int argc = 0; - while (argv[argc++]) - ; - - /* Construct an argument list for the shell. */ - { - char *new_argv[argc + 1]; - new_argv[0] = (char *) _PATH_BSHELL; - new_argv[1] = (char *) file; - while (argc > 1) - { - new_argv[argc] = argv[argc - 1]; - --argc; - } - - /* Execute the shell. */ - __execve (new_argv[0], new_argv, envp); - } -} - -static inline void -maybe_script_execute (const char *file, char *const argv[], char *const envp[], - int xflags) + sigset_t oldmask; + const char *file; + int (*exec) (const char *, char *const *, char *const *); + const posix_spawn_file_actions_t *fa; + const posix_spawnattr_t *restrict attr; + char *const *argv; + ptrdiff_t argc; + char *const *envp; + int xflags; + int pipe[2]; +}; + +/* Older version requires that shell script without shebang definition + to be called explicitly using /bin/sh (_PATH_BSHELL). */ +static void +maybe_script_execute (struct posix_spawn_args *args) { if (SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_15) - && (xflags & SPAWN_XFLAGS_TRY_SHELL) - && errno == ENOEXEC) - script_execute (file, argv, envp); -} - -/* Spawn a new process executing PATH with the attributes describes in *ATTRP. - Before running the process perform the actions described in FILE-ACTIONS. */ -int -__spawni (pid_t *pid, const char *file, - const posix_spawn_file_actions_t *file_actions, - const posix_spawnattr_t *attrp, char *const argv[], - char *const envp[], int xflags) -{ - pid_t new_pid; - char *path, *p, *name; - size_t len; - size_t pathlen; - - /* Do this once. */ - short int flags = attrp == NULL ? 0 : attrp->__flags; - - /* Generate the new process. */ - if ((flags & POSIX_SPAWN_USEVFORK) != 0 - /* If no major work is done, allow using vfork. Note that we - might perform the path searching. But this would be done by - a call to execvp(), too, and such a call must be OK according - to POSIX. */ - || ((flags & (POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF - | POSIX_SPAWN_SETSCHEDPARAM | POSIX_SPAWN_SETSCHEDULER - | POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_RESETIDS)) == 0 - && file_actions == NULL)) - new_pid = __vfork (); - else - new_pid = __fork (); - - if (new_pid != 0) + && (args->xflags & SPAWN_XFLAGS_TRY_SHELL) && errno == ENOEXEC) { - if (new_pid < 0) - return errno; - - /* The call was successful. Store the PID if necessary. */ - if (pid != NULL) - *pid = new_pid; + char *const *argv = args->argv; + ptrdiff_t argc = args->argc; + + /* Construct an argument list for the shell. */ + char *new_argv[argc + 1]; + new_argv[0] = (char *) _PATH_BSHELL; + new_argv[1] = (char *) args->file; + if (argc > 1) + memcpy (new_argv + 2, argv + 1, argc * sizeof(char *)); + else + new_argv[2] = NULL; - return 0; + /* Execute the shell. */ + args->exec (new_argv[0], new_argv, args->envp); } +} - /* Set signal mask. */ - if ((flags & POSIX_SPAWN_SETSIGMASK) != 0 - && __sigprocmask (SIG_SETMASK, &attrp->__ss, NULL) != 0) - _exit (SPAWN_ERROR); +/* Function used in the clone call to setup the signals mask, posix_spawn + attributes, and file actions. */ +static int +__spawni_child (void *arguments) +{ + struct posix_spawn_args *args = arguments; + const posix_spawnattr_t *restrict attr = args->attr; + const posix_spawn_file_actions_t *file_actions = args->fa; + int ret; + + __close (args->pipe[0]); /* Set signal default action. */ - if ((flags & POSIX_SPAWN_SETSIGDEF) != 0) + if ((attr->__flags & POSIX_SPAWN_SETSIGDEF) != 0) { /* We have to iterate over all signals. This could possibly be done better but it requires system specific solutions since @@ -138,37 +107,41 @@ __spawni (pid_t *pid, const char *file, sa.sa_handler = SIG_DFL; for (sig = 1; sig <= _NSIG; ++sig) - if (__sigismember (&attrp->__sd, sig) != 0 + if (__sigismember (&attr->__sd, sig) != 0 && __sigaction (sig, &sa, NULL) != 0) - _exit (SPAWN_ERROR); - + goto fail; } #ifdef _POSIX_PRIORITY_SCHEDULING /* Set the scheduling algorithm and parameters. */ - if ((flags & (POSIX_SPAWN_SETSCHEDPARAM | POSIX_SPAWN_SETSCHEDULER)) + if ((attr->__flags & (POSIX_SPAWN_SETSCHEDPARAM | POSIX_SPAWN_SETSCHEDULER)) == POSIX_SPAWN_SETSCHEDPARAM) { - if (__sched_setparam (0, &attrp->__sp) == -1) - _exit (SPAWN_ERROR); + if (__sched_setparam (0, &attr->__sp) == -1) + goto fail; } - else if ((flags & POSIX_SPAWN_SETSCHEDULER) != 0) + else if ((attr->__flags & POSIX_SPAWN_SETSCHEDULER) != 0) { - if (__sched_setscheduler (0, attrp->__policy, &attrp->__sp) == -1) - _exit (SPAWN_ERROR); + if (__sched_setscheduler (0, attr->__policy, &attr->__sp) == -1) + goto fail; } #endif + /* Set the process session ID. */ + if ((attr->__flags & POSIX_SPAWN_SETSID) != 0 + && __setsid () < 0) + goto fail; + /* Set the process group ID. */ - if ((flags & POSIX_SPAWN_SETPGROUP) != 0 - && __setpgid (0, attrp->__pgrp) != 0) - _exit (SPAWN_ERROR); + if ((attr->__flags & POSIX_SPAWN_SETPGROUP) != 0 + && __setpgid (0, attr->__pgrp) != 0) + goto fail; /* Set the effective user and group IDs. */ - if ((flags & POSIX_SPAWN_RESETIDS) != 0 + if ((attr->__flags & POSIX_SPAWN_RESETIDS) != 0 && (local_seteuid (__getuid ()) != 0 - || local_setegid (__getgid ()) != 0)) - _exit (SPAWN_ERROR); + || local_setegid (__getgid ())) != 0) + goto fail; /* Execute the file actions. */ if (file_actions != NULL) @@ -184,9 +157,9 @@ __spawni (pid_t *pid, const char *file, switch (action->tag) { case spawn_do_close: - if (close_not_cancel (action->action.close_action.fd) != 0) + if (__close_nocancel (action->action.close_action.fd) != 0) { - if (! have_fdlimit) + if (have_fdlimit == 0) { __getrlimit64 (RLIMIT_NOFILE, &fdlimit); have_fdlimit = true; @@ -195,33 +168,37 @@ __spawni (pid_t *pid, const char *file, /* Only signal errors for file descriptors out of range. */ if (action->action.close_action.fd < 0 || action->action.close_action.fd >= fdlimit.rlim_cur) - /* Signal the error. */ - _exit (SPAWN_ERROR); + goto fail; } break; case spawn_do_open: { - int new_fd = open_not_cancel (action->action.open_action.path, + /* POSIX states that if fildes was already an open file descriptor, + it shall be closed before the new file is opened. This avoid + pontential issues when posix_spawn plus addopen action is called + with the process already at maximum number of file descriptor + opened and also for multiple actions on single-open special + paths (like /dev/watchdog). */ + __close_nocancel (action->action.open_action.fd); + + int new_fd = __open_nocancel (action->action.open_action.path, action->action.open_action.oflag | O_LARGEFILE, action->action.open_action.mode); if (new_fd == -1) - /* The `open' call failed. */ - _exit (SPAWN_ERROR); + goto fail; /* Make sure the desired file descriptor is used. */ if (new_fd != action->action.open_action.fd) { if (__dup2 (new_fd, action->action.open_action.fd) != action->action.open_action.fd) - /* The `dup2' call failed. */ - _exit (SPAWN_ERROR); + goto fail; - if (close_not_cancel (new_fd) != 0) - /* The `close' call failed. */ - _exit (SPAWN_ERROR); + if (__close_nocancel (new_fd) != 0) + goto fail; } } break; @@ -230,85 +207,111 @@ __spawni (pid_t *pid, const char *file, if (__dup2 (action->action.dup2_action.fd, action->action.dup2_action.newfd) != action->action.dup2_action.newfd) - /* The `dup2' call failed. */ - _exit (SPAWN_ERROR); + goto fail; break; } } } - if ((xflags & SPAWN_XFLAGS_USE_PATH) == 0 || strchr (file, '/') != NULL) - { - /* The FILE parameter is actually a path. */ - __execve (file, argv, envp); + /* Set the initial signal mask of the child if POSIX_SPAWN_SETSIGMASK + is set, otherwise restore the previous one. */ + __sigprocmask (SIG_SETMASK, (attr->__flags & POSIX_SPAWN_SETSIGMASK) + ? &attr->__ss : &args->oldmask, 0); + + args->exec (args->file, args->argv, args->envp); + + /* This is compatibility function required to enable posix_spawn run + script without shebang definition for older posix_spawn versions + (2.15). */ + maybe_script_execute (args); + +fail: + /* errno should have an appropriate non-zero value; otherwise, + there's a bug in glibc or the kernel. For lack of an error code + (EINTERNALBUG) describing that, use ECHILD. Another option would + be to set args->err to some negative sentinel and have the parent + abort(), but that seems needlessly harsh. */ + ret = errno ? : ECHILD; + if (ret) + /* Since sizeof errno < PIPE_BUF, the write is atomic. */ + while (__write_nocancel (args->pipe[1], &ret, sizeof (ret)) < 0); - maybe_script_execute (file, argv, envp, xflags); + _exit (SPAWN_ERROR); +} - /* Oh, oh. `execve' returns. This is bad. */ - _exit (SPAWN_ERROR); - } +/* Spawn a new process executing PATH with the attributes describes in *ATTRP. + Before running the process perform the actions described in FILE-ACTIONS. */ +int +__spawnix (pid_t *pid, const char *file, + const posix_spawn_file_actions_t *file_actions, + const posix_spawnattr_t *attrp, char *const argv[], + char *const envp[], int xflags, + int (*exec) (const char *, char *const *, char *const *)) +{ + struct posix_spawn_args args; + int ec; - /* We have to search for FILE on the path. */ - path = getenv ("PATH"); - if (path == NULL) - { - /* There is no `PATH' in the environment. - The default search path is the current directory - followed by the path `confstr' returns for `_CS_PATH'. */ - len = confstr (_CS_PATH, (char *) NULL, 0); - path = (char *) __alloca (1 + len); - path[0] = ':'; - (void) confstr (_CS_PATH, path + 1, len); - } + if (__pipe2 (args.pipe, O_CLOEXEC)) + return errno; - len = strlen (file) + 1; - pathlen = strlen (path); - name = __alloca (pathlen + len + 1); - /* Copy the file name at the top. */ - name = (char *) memcpy (name + pathlen + 1, file, len); - /* And add the slash. */ - *--name = '/'; + /* Disable asynchronous cancellation. */ + int state; + __libc_ptf_call (__pthread_setcancelstate, + (PTHREAD_CANCEL_DISABLE, &state), 0); - p = path; - do - { - char *startp; + ptrdiff_t argc = 0; + ptrdiff_t limit = INT_MAX - 1; + while (argv[argc++] != NULL) + if (argc == limit) + { + errno = E2BIG; + return errno; + } - path = p; - p = __strchrnul (path, ':'); + args.file = file; + args.exec = exec; + args.fa = file_actions; + args.attr = attrp ? attrp : &(const posix_spawnattr_t) { 0 }; + args.argv = argv; + args.argc = argc; + args.envp = envp; + args.xflags = xflags; - if (p == path) - /* Two adjacent colons, or a colon at the beginning or the end - of `PATH' means to search the current directory. */ - startp = name + 1; + /* Generate the new process. */ + pid_t new_pid = __fork (); + + if (new_pid == 0) + __spawni_child (&args); + else if (new_pid > 0) + { + __close (args.pipe[1]); + + if (__read (args.pipe[0], &ec, sizeof ec) != sizeof ec) + ec = 0; else - startp = (char *) memcpy (name - (p - path), path, p - path); + __waitpid (new_pid, &(int) { 0 }, 0); + } + else + ec = errno; - /* Try to execute this name. If it works, execv will not return. */ - __execve (startp, argv, envp); + __close (args.pipe[0]); - maybe_script_execute (startp, argv, envp, xflags); + if ((ec == 0) && (pid != NULL)) + *pid = new_pid; - switch (errno) - { - case EACCES: - case ENOENT: - case ESTALE: - case ENOTDIR: - /* Those errors indicate the file is missing or not executable - by us, in which case we want to just try the next path - directory. */ - break; - - default: - /* Some other error means we found an executable file, but - something went wrong executing it; return the error to our - caller. */ - _exit (SPAWN_ERROR); - } - } - while (*p++ != '\0'); + __libc_ptf_call (__pthread_setcancelstate, (state, NULL), 0); - /* Return with an error. */ - _exit (SPAWN_ERROR); + return ec; +} + +int +__spawni (pid_t * pid, const char *file, + const posix_spawn_file_actions_t * acts, + const posix_spawnattr_t * attrp, char *const argv[], + char *const envp[], int xflags) +{ + /* It uses __execvpex to avoid run ENOEXEC in non compatibility mode (it + will be handled by maybe_script_execute). */ + return __spawnix (pid, file, acts, attrp, argv, envp, xflags, + xflags & SPAWN_XFLAGS_USE_PATH ? __execvpex : __execve); } diff --git a/sysdeps/posix/sprofil.c b/sysdeps/posix/sprofil.c index b46721a7ce..d9d639aaad 100644 --- a/sysdeps/posix/sprofil.c +++ b/sysdeps/posix/sprofil.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2016 Free Software Foundation, Inc. +/* Copyright (C) 2001-2018 Free Software Foundation, Inc. Contributed by David Mosberger-Tang <davidm@hpl.hp.com>. This file is part of the GNU C Library. @@ -21,6 +21,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <sigsetops.h> #include <sys/time.h> #include <sys/profil.h> diff --git a/sysdeps/posix/sysconf.c b/sysdeps/posix/sysconf.c index 892f76d55c..8b74ad6184 100644 --- a/sysdeps/posix/sysconf.c +++ b/sysdeps/posix/sysconf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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 @@ -29,6 +29,7 @@ #include <sys/stat.h> #include <sys/sysinfo.h> #include <sys/types.h> +#include <sys/uio.h> #include <regex.h> #define NEED_SPEC_ARRAY 0 @@ -93,7 +94,7 @@ __sysconf (int name) #endif case _SC_TZNAME_MAX: - return MAX (__tzname_max (), _POSIX_TZNAME_MAX); + return -1; case _SC_JOB_CONTROL: #if CONF_IS_DEFINED_SET (_POSIX_JOB_CONTROL) diff --git a/sysdeps/posix/system.c b/sysdeps/posix/system.c index 8ed01aa9fb..d7594436ed 100644 --- a/sysdeps/posix/system.c +++ b/sysdeps/posix/system.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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 @@ -24,6 +24,7 @@ #include <sys/wait.h> #include <libc-lock.h> #include <sysdep-cancel.h> +#include <sigsetops.h> #define SHELL_PATH "/bin/sh" /* Path of the shell. */ diff --git a/sysdeps/posix/sysv_signal.c b/sysdeps/posix/sysv_signal.c index c70f50d01e..2727ab0ee3 100644 --- a/sysdeps/posix/sysv_signal.c +++ b/sysdeps/posix/sysv_signal.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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 @@ -18,7 +18,7 @@ #include <errno.h> #include <signal.h> #include <string.h> /* For the real memset prototype. */ - +#include <sigsetops.h> /* Tolerate non-threads versions of Posix */ #ifndef SA_ONESHOT @@ -46,8 +46,7 @@ __sysv_signal (int sig, __sighandler_t handler) } act.sa_handler = handler; - if (__sigemptyset (&act.sa_mask) < 0) - return SIG_ERR; + __sigemptyset (&act.sa_mask); act.sa_flags = SA_ONESHOT | SA_NOMASK | SA_INTERRUPT; act.sa_flags &= ~SA_RESTART; if (__sigaction (sig, &act, &oact) < 0) diff --git a/sysdeps/posix/telldir.c b/sysdeps/posix/telldir.c index 85dc58bd8a..8caea582f9 100644 --- a/sysdeps/posix/telldir.c +++ b/sysdeps/posix/telldir.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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/sysdeps/posix/tempname.c b/sysdeps/posix/tempname.c index 93be738e12..432262a03b 100644 --- a/sysdeps/posix/tempname.c +++ b/sysdeps/posix/tempname.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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/sysdeps/posix/time.c b/sysdeps/posix/time.c index 2afe174788..6d0bb4bafc 100644 --- a/sysdeps/posix/time.c +++ b/sysdeps/posix/time.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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/sysdeps/posix/timespec_get.c b/sysdeps/posix/timespec_get.c index 01346ab1a9..6a40b64b8c 100644 --- a/sysdeps/posix/timespec_get.c +++ b/sysdeps/posix/timespec_get.c @@ -1,5 +1,5 @@ /* timespec_get -- C11 interface to sample a clock. Generic POSIX.1 version. - Copyright (C) 2013-2016 Free Software Foundation, Inc. + Copyright (C) 2013-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/sysdeps/posix/truncate.c b/sysdeps/posix/truncate.c index 82a77b5a9a..388e87734f 100644 --- a/sysdeps/posix/truncate.c +++ b/sysdeps/posix/truncate.c @@ -1,5 +1,5 @@ /* Truncate a file given by name. Generic POSIX.1 version. - Copyright (C) 1995-2016 Free Software Foundation, Inc. + Copyright (C) 1995-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/sysdeps/posix/ttyname.c b/sysdeps/posix/ttyname.c index 23a250cd9b..3dae5e8411 100644 --- a/sysdeps/posix/ttyname.c +++ b/sysdeps/posix/ttyname.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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 @@ -28,13 +28,12 @@ char *__ttyname; static char *getttyname (int fd, dev_t mydev, ino_t myino, - int save, int *dostat) internal_function; + int save, int *dostat); libc_freeres_ptr (static char *getttyname_name); static char * -internal_function getttyname (int fd, dev_t mydev, ino_t myino, int save, int *dostat) { static const char dev[] = "/dev"; diff --git a/sysdeps/posix/ttyname_r.c b/sysdeps/posix/ttyname_r.c index 6da98b3510..725de7c4fb 100644 --- a/sysdeps/posix/ttyname_r.c +++ b/sysdeps/posix/ttyname_r.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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 @@ -33,10 +33,9 @@ static const char dev[] = "/dev"; static int getttyname_r (int fd, char *buf, size_t buflen, dev_t mydev, ino_t myino, int save, - int *dostat) __THROW internal_function; + int *dostat) __THROW; static int -internal_function getttyname_r (int fd, char *buf, size_t buflen, dev_t mydev, ino_t myino, int save, int *dostat) { diff --git a/sysdeps/posix/ulimit.c b/sysdeps/posix/ulimit.c index 47c9ff2e41..3a4c64dc90 100644 --- a/sysdeps/posix/ulimit.c +++ b/sysdeps/posix/ulimit.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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/sysdeps/posix/usleep.c b/sysdeps/posix/usleep.c index f0e28f2d7a..3a3cd202c9 100644 --- a/sysdeps/posix/usleep.c +++ b/sysdeps/posix/usleep.c @@ -1,5 +1,5 @@ /* Implementation of the BSD usleep function using nanosleep. - 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/sysdeps/posix/utime.c b/sysdeps/posix/utime.c index c0d2736ae2..63e4898c8d 100644 --- a/sysdeps/posix/utime.c +++ b/sysdeps/posix/utime.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* utime -- Change access and modification times of file. Posix version. + Copyright (C) 1991-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/sysdeps/posix/utimes.c b/sysdeps/posix/utimes.c index 4dc2946b18..a76eaf18a0 100644 --- a/sysdeps/posix/utimes.c +++ b/sysdeps/posix/utimes.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1995-2016 Free Software Foundation, Inc. +/* utimes -- Change access and modification times of file. Posix version. + Copyright (C) 1995-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/sysdeps/posix/wait.c b/sysdeps/posix/wait.c index 7f1d71a45f..2abcf24ab9 100644 --- a/sysdeps/posix/wait.c +++ b/sysdeps/posix/wait.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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,7 @@ /* Wait for a child to die. When one does, put its status in *STAT_LOC and return its process ID. For errors, return (pid_t) -1. */ __pid_t -__libc_wait (__WAIT_STATUS_DEFN stat_loc) +__libc_wait (int *stat_loc) { return __waitpid (WAIT_ANY, (int *) stat_loc, 0); } diff --git a/sysdeps/posix/wait3.c b/sysdeps/posix/wait3.c index 2e76892bff..c3f977d62b 100644 --- a/sysdeps/posix/wait3.c +++ b/sysdeps/posix/wait3.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1992-2016 Free Software Foundation, Inc. +/* Copyright (C) 1992-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 @@ -26,14 +26,14 @@ there. If the WUNTRACED bit is set in OPTIONS, return status for stopped children; otherwise don't. */ pid_t -__wait3 (__WAIT_STATUS stat_loc, int options, struct rusage *usage) +__wait3 (int *stat_loc, int options, struct rusage *usage) { if (usage != NULL) { __set_errno (ENOSYS); return (pid_t) -1; } - return __waitpid (WAIT_ANY, stat_loc.__iptr, options); + return __waitpid (WAIT_ANY, stat_loc, options); } weak_alias (__wait3, wait3) diff --git a/sysdeps/posix/waitid.c b/sysdeps/posix/waitid.c index 14bf15e735..3207c742c2 100644 --- a/sysdeps/posix/waitid.c +++ b/sysdeps/posix/waitid.c @@ -1,5 +1,5 @@ /* Pseudo implementation of waitid. - Copyright (C) 1997-2016 Free Software Foundation, Inc. + Copyright (C) 1997-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1997. @@ -80,7 +80,7 @@ OUR_WAITID (idtype_t idtype, id_t id, siginfo_t *infop, int options) #endif #ifdef WEXITED || ((options & (WEXITED|WSTOPPED|WCONTINUED)) - != (WEXITED | (options & WUNTRACED))) + != (WEXITED | (options & WSTOPPED))) #endif ) { diff --git a/sysdeps/posix/writev.c b/sysdeps/posix/writev.c index 99edfdfade..dbabe0d9ca 100644 --- a/sysdeps/posix/writev.c +++ b/sysdeps/posix/writev.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-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 @@ -88,4 +88,5 @@ __writev (int fd, const struct iovec *vector, int count) return bytes_written; } +libc_hidden_def (__writev) weak_alias (__writev, writev) |