├── gen-symver ├── .gitignore ├── gen-symmap ├── src ├── main.c ├── nss_altfiles │ ├── files-sgrp.c │ ├── files-spwd.c │ ├── files-proto.c │ ├── files-rpc.c │ ├── nss_parse_line_result.c │ ├── databases.def │ ├── files-grp.c │ ├── files-pwd.c │ ├── nss_files_fopen.c │ ├── nss_fgetent_r.c │ ├── files-service.c │ ├── files-network.c │ ├── nss_readline.c │ ├── function.def │ ├── nss_database.h │ ├── nss_module.h │ ├── nss_action.h │ ├── nss_files_data.c │ ├── nss_files.h │ ├── files-XXX.c │ ├── nsswitch.h │ ├── files-parse.c │ └── files-hosts.c ├── compat.h ├── grp │ └── fgetgrent_r.c ├── pwd │ └── fgetpwent_r.c ├── resolv │ ├── res_hconf.h │ ├── mapv4v6addr.h │ └── resolv-internal.h ├── gshadow │ └── sgetsgent_r.c ├── file_change_detection.h ├── shadow │ └── sgetspent_r.c ├── libc-symver.h ├── scratch_buffer.h ├── dynarray.h ├── alloc_buffer.h └── dynarray-skeleton.c ├── updatefiles ├── README.md ├── Makefile ├── configure └── COPYING /gen-symver: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | set -e 3 | cat < 4 | * 5 | * Distributed under terms of the MIT license. 6 | */ 7 | 8 | #include "compat.h" 9 | #include 10 | #include 11 | #include 12 | 13 | #define XSTRINGIZE(y) #y 14 | #define STRINGIZE(x) XSTRINGIZE(x) 15 | 16 | static int 17 | usage (const char *prgname) 18 | { 19 | fprintf (stderr, "Usage: %s [datadir | modulename]\n", prgname); 20 | return EXIT_FAILURE; 21 | } 22 | 23 | int 24 | main (int argc, const char *argv[]) 25 | { 26 | if (argc > 2) return usage (argv[0]); 27 | 28 | if (argc == 1 || strcmp (argv[1], "datadir") == 0) { 29 | printf ("%s\n", ALTFILES_DATADIR); 30 | } else if (strcmp (argv[1], "modulename") == 0) { 31 | printf ("%s\n", STRINGIZE (ALTFILES_MODULE_NAME)); 32 | } else { 33 | return usage (argv[0]); 34 | } 35 | return EXIT_SUCCESS; 36 | } 37 | -------------------------------------------------------------------------------- /updatefiles: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # 3 | # dlfiles 4 | # Copyright (C) 2013-2014 Adrian Perez 5 | # 6 | # Distributed under terms of the MIT license. 7 | # 8 | set -eu 9 | 10 | declare -r DIST_URL_BASE='http://ftp.gnu.org/gnu/glibc/' 11 | 12 | if [[ $# -ne 1 ]] ; then 13 | cat <<-EOF 14 | Usage: $0 version 15 | EOF 16 | exit 1 17 | fi 1>&2 18 | 19 | PV_BIN=$(type -P pv) 20 | if [[ -n ${PV_BIN} ]] ; then 21 | pvcat () { "${PV_BIN}" -p -e -a "$1"; } 22 | else 23 | pvcat () { cat "$1"; } 24 | fi 25 | 26 | version=$1 27 | 28 | if [[ ! -d glibc-${version} ]] ; then 29 | if [[ ! -r glibc-${version}.tar.xz ]] ; then 30 | wget "${DIST_URL_BASE}/glibc-${version}.tar.xz" 31 | fi 32 | echo "Unpacking glibc-${version}.tar.xz ..." 33 | pvcat glibc-${version}.tar.xz | tar -xJf - 34 | fi 35 | 36 | for dst_file in src/*/*.[hc] ; do 37 | dst_file_name=${dst_file##*/} 38 | src_file=$(find "glibc-${version}" -name "${dst_file_name}") 39 | if [[ -z ${src_file} ]] ; then 40 | echo "File '$dst_file_name' not found." 1>&2 41 | else 42 | cp -v "${src_file}" "${dst_file}" 43 | fi 44 | done 45 | -------------------------------------------------------------------------------- /src/nss_altfiles/files-sgrp.c: -------------------------------------------------------------------------------- 1 | /* User file parser in nss_files module. 2 | Copyright (C) 2009-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | #include 20 | #include 21 | 22 | #define STRUCTURE sgrp 23 | #define ENTNAME sgent 24 | #define DATABASE "gshadow" 25 | struct sgent_data {}; 26 | 27 | /* Our parser function is already defined in sgetspent_r.c, so use that 28 | to parse lines from the database file. */ 29 | #define EXTERN_PARSER 30 | #include "files-parse.c" 31 | #include GENERIC 32 | 33 | DB_LOOKUP (sgnam, '.', 0, ("%s", name), 34 | { 35 | if (name[0] != '+' && name[0] != '-' 36 | && ! strcmp (name, result->sg_namp)) 37 | break; 38 | }, const char *name) 39 | -------------------------------------------------------------------------------- /src/nss_altfiles/files-spwd.c: -------------------------------------------------------------------------------- 1 | /* User file parser in nss_files module. 2 | Copyright (C) 1996-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | #include 20 | #include 21 | 22 | #define STRUCTURE spwd 23 | #define ENTNAME spent 24 | #define DATABASE "shadow" 25 | struct spent_data {}; 26 | 27 | /* Our parser function is already defined in sgetspent_r.c, so use that 28 | to parse lines from the database file. */ 29 | #define EXTERN_PARSER 30 | #include "files-parse.c" 31 | #include GENERIC 32 | 33 | DB_LOOKUP (spnam, '.', 0, ("%s", name), 34 | { 35 | if (name[0] != '+' && name[0] != '-' 36 | && ! strcmp (name, result->sp_namp)) 37 | break; 38 | }, const char *name) 39 | -------------------------------------------------------------------------------- /src/nss_altfiles/files-proto.c: -------------------------------------------------------------------------------- 1 | /* Protocols file parser in nss_files module. 2 | Copyright (C) 1996-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | #include 20 | #include 21 | 22 | #define ENTNAME protoent 23 | #define DATABASE "protocols" 24 | 25 | struct protoent_data {}; 26 | 27 | #define TRAILING_LIST_MEMBER p_aliases 28 | #define TRAILING_LIST_SEPARATOR_P isspace 29 | #include "files-parse.c" 30 | LINE_PARSER 31 | ("#", 32 | STRING_FIELD (result->p_name, isspace, 1); 33 | INT_FIELD (result->p_proto, isspace, 1, 10,); 34 | ) 35 | 36 | #include GENERIC 37 | 38 | DB_LOOKUP (protobyname, '.', 0, ("%s", name), 39 | LOOKUP_NAME (p_name, p_aliases), 40 | const char *name) 41 | 42 | DB_LOOKUP (protobynumber, '=', 20, ("%zd", (ssize_t) proto), 43 | { 44 | if (result->p_proto == proto) 45 | break; 46 | }, int proto) 47 | -------------------------------------------------------------------------------- /src/nss_altfiles/files-rpc.c: -------------------------------------------------------------------------------- 1 | /* SunRPC program number file parser in nss_files module. 2 | Copyright (C) 1996-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | #include 20 | #include 21 | 22 | #define ENTNAME rpcent 23 | #define DATABASE "rpc" 24 | 25 | struct rpcent_data {}; 26 | 27 | #define TRAILING_LIST_MEMBER r_aliases 28 | #define TRAILING_LIST_SEPARATOR_P isspace 29 | #include "files-parse.c" 30 | LINE_PARSER 31 | ("#", 32 | STRING_FIELD (result->r_name, isspace, 1); 33 | INT_FIELD (result->r_number, isspace, 1, 10,); 34 | ) 35 | 36 | #include GENERIC 37 | 38 | DB_LOOKUP (rpcbyname, '.', 0, ("%s", name), 39 | LOOKUP_NAME (r_name, r_aliases), 40 | const char *name) 41 | 42 | DB_LOOKUP (rpcbynumber, '=', 20, ("%zd", (ssize_t) number), 43 | { 44 | if (result->r_number == number) 45 | break; 46 | }, int number) 47 | -------------------------------------------------------------------------------- /src/nss_altfiles/nss_parse_line_result.c: -------------------------------------------------------------------------------- 1 | /* Implementation of __nss_parse_line_result. 2 | Copyright (C) 2020-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | #include "nss_files.h" 20 | 21 | #include 22 | #include 23 | 24 | int 25 | __nss_parse_line_result (FILE *fp, off64_t offset, int parse_line_result) 26 | { 27 | assert (parse_line_result >= -1 && parse_line_result <= 1); 28 | 29 | switch (__builtin_expect (parse_line_result, 1)) 30 | { 31 | case 1: 32 | /* Success. */ 33 | return 0; 34 | case 0: 35 | /* Parse error. */ 36 | __set_errno (EINVAL); 37 | return EINVAL; 38 | case -1: 39 | /* Out of buffer space. */ 40 | return __nss_readline_seek (fp, offset); 41 | 42 | default: 43 | __builtin_unreachable (); 44 | } 45 | } 46 | libc_hidden_def (__nss_parse_line_result) 47 | -------------------------------------------------------------------------------- /src/nss_altfiles/databases.def: -------------------------------------------------------------------------------- 1 | /* List of all databases defined for the NSS in GNU C Library. 2 | Copyright (C) 1996-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | /* This list must be kept sorted!!! If any long name is added the 20 | field size for it must be increases. */ 21 | 22 | DEFINE_DATABASE (aliases) 23 | DEFINE_DATABASE (ethers) 24 | DEFINE_DATABASE (group) 25 | DEFINE_DATABASE (group_compat) 26 | DEFINE_DATABASE (gshadow) 27 | DEFINE_DATABASE (hosts) 28 | DEFINE_DATABASE (initgroups) 29 | DEFINE_DATABASE (netgroup) 30 | DEFINE_DATABASE (networks) 31 | DEFINE_DATABASE (passwd) 32 | DEFINE_DATABASE (passwd_compat) 33 | DEFINE_DATABASE (protocols) 34 | DEFINE_DATABASE (publickey) 35 | DEFINE_DATABASE (rpc) 36 | DEFINE_DATABASE (services) 37 | DEFINE_DATABASE (shadow) 38 | DEFINE_DATABASE (shadow_compat) 39 | 40 | /* 41 | Local Variables: 42 | mode:C 43 | End: 44 | */ 45 | -------------------------------------------------------------------------------- /src/nss_altfiles/files-grp.c: -------------------------------------------------------------------------------- 1 | /* Group file parser in nss_files module. 2 | Copyright (C) 1996-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | #include 20 | #include 21 | 22 | #define STRUCTURE group 23 | #define ENTNAME grent 24 | #define DATABASE "group" 25 | struct grent_data {}; 26 | 27 | /* Our parser function is already defined in fgetgrent.c, so use that. 28 | to parse lines from the database file. */ 29 | #define EXTERN_PARSER 30 | #include "files-parse.c" 31 | #include GENERIC 32 | 33 | DB_LOOKUP (grnam, '.', 0, ("%s", name), 34 | { 35 | if (name[0] != '-' && name[0] != '+' 36 | && ! strcmp (name, result->gr_name)) 37 | break; 38 | }, const char *name) 39 | 40 | DB_LOOKUP (grgid, '=', 20, ("%lu", (unsigned long int) gid), 41 | { 42 | if (result->gr_gid == gid && result->gr_name[0] != '+' 43 | && result->gr_name[0] != '-') 44 | break; 45 | }, gid_t gid) 46 | -------------------------------------------------------------------------------- /src/nss_altfiles/files-pwd.c: -------------------------------------------------------------------------------- 1 | /* User file parser in nss_files module. 2 | Copyright (C) 1996-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | #include 20 | #include 21 | 22 | #define STRUCTURE passwd 23 | #define ENTNAME pwent 24 | #define DATABASE "passwd" 25 | struct pwent_data {}; 26 | 27 | /* Our parser function is already defined in fgetpwent_r.c, so use that 28 | to parse lines from the database file. */ 29 | #define EXTERN_PARSER 30 | #include "files-parse.c" 31 | #include GENERIC 32 | 33 | DB_LOOKUP (pwnam, '.', 0, ("%s", name), 34 | { 35 | if (name[0] != '+' && name[0] != '-' 36 | && ! strcmp (name, result->pw_name)) 37 | break; 38 | }, const char *name) 39 | 40 | DB_LOOKUP (pwuid, '=', 20, ("%lu", (unsigned long int) uid), 41 | { 42 | if (result->pw_uid == uid && result->pw_name[0] != '+' 43 | && result->pw_name[0] != '-') 44 | break; 45 | }, uid_t uid) 46 | -------------------------------------------------------------------------------- /src/nss_altfiles/nss_files_fopen.c: -------------------------------------------------------------------------------- 1 | /* Open an nss_files database file. 2 | Copyright (C) 2020-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | #include "nss_files.h" 20 | 21 | #include 22 | #include 23 | 24 | FILE * 25 | __nss_files_fopen (const char *path) 26 | { 27 | FILE *fp = fopen (path, "rce"); 28 | if (fp == NULL) 29 | return NULL; 30 | 31 | /* The stream is not shared across threads. */ 32 | __fsetlocking (fp, FSETLOCKING_BYCALLER); 33 | 34 | /* This tells libio that the file is seekable, and that fp->_offset 35 | is correct, ensuring that __ftello64 is efficient (bug 26257). */ 36 | if (__fseeko64 (fp, 0, SEEK_SET) < 0) 37 | { 38 | /* nss_files requires seekable files, to deal with repeated 39 | reads of the same line after reporting ERANGE. */ 40 | fclose (fp); 41 | __set_errno (ESPIPE); 42 | return NULL; 43 | } 44 | 45 | return fp; 46 | } 47 | libc_hidden_def (__nss_files_fopen) 48 | -------------------------------------------------------------------------------- /src/nss_altfiles/nss_fgetent_r.c: -------------------------------------------------------------------------------- 1 | /* Generic implementation of fget*ent_r. 2 | Copyright (C) 2020-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | #include 20 | #include "nss_files.h" 21 | #include 22 | 23 | int 24 | __nss_fgetent_r (FILE *fp, void *result, char *buffer, size_t buffer_length, 25 | nss_files_parse_line parser) 26 | { 27 | int ret; 28 | 29 | _IO_flockfile (fp); 30 | 31 | while (true) 32 | { 33 | off64_t original_offset; 34 | ret = __nss_readline (fp, buffer, buffer_length, &original_offset); 35 | if (ret == 0) 36 | { 37 | /* Parse the line into *RESULT. */ 38 | ret = parser (buffer, result, 39 | (struct parser_data *) buffer, buffer_length, &errno); 40 | 41 | /* Translate the result code from the parser into an errno 42 | value. Also seeks back to the start of the line if 43 | necessary. */ 44 | ret = __nss_parse_line_result (fp, original_offset, ret); 45 | 46 | if (ret == EINVAL) 47 | /* Skip over malformed lines. */ 48 | continue; 49 | } 50 | break; 51 | } 52 | 53 | _IO_funlockfile (fp); 54 | 55 | return ret; 56 | } 57 | -------------------------------------------------------------------------------- /src/compat.h: -------------------------------------------------------------------------------- 1 | /* 2 | * compat.h 3 | * Copyright (C) 2012 Adrian Perez 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define off64_t off_t 18 | #define __fseeko64 fseeko 19 | #define __ftello64 ftello 20 | #define __feof_unlocked feof_unlocked 21 | #define __fgets_unlocked fgets_unlocked 22 | #define __inet_network inet_network 23 | #define __inet_pton inet_pton 24 | 25 | static inline void 26 | fseterr_unlocked(FILE *f) 27 | { 28 | f->_flags |= _IO_ERR_SEEN; 29 | } 30 | 31 | #define _IO_flockfile flockfile 32 | #define _IO_funlockfile funlockfile 33 | 34 | #define IS_IN(_) 0 35 | 36 | #define attribute_hidden __attribute__((visibility("hidden"))) 37 | #define libc_hidden_proto(fn) 38 | #define libc_hidden_def(fn) 39 | 40 | #define __set_errno(errval) \ 41 | (errno = (errval)) 42 | 43 | #define __set_h_errno(errval) \ 44 | (h_errno = (errval)) 45 | 46 | #define __libc_lock_define_initialized(CLASS, lockvar) \ 47 | CLASS pthread_mutex_t lockvar = PTHREAD_MUTEX_INITIALIZER; 48 | 49 | #define __libc_lock_init 50 | 51 | #define __libc_lock_lock(lock) \ 52 | pthread_mutex_lock (&(lock)) 53 | 54 | #define __libc_lock_unlock(lock) \ 55 | pthread_mutex_unlock (&(lock)) 56 | 57 | #define __MAX_ALLOCA_CUTOFF 65536 58 | #define __libc_use_alloca(bytes) \ 59 | (bytes <= __MAX_ALLOCA_CUTOFF) 60 | 61 | #define extend_alloca(buf, len, newlen) \ 62 | alloca(((len) = (newlen))) 63 | 64 | #define __strcasecmp(s1, s2) \ 65 | strcasecmp(s1, s2) 66 | 67 | #define __glibc_unlikely(cond) __builtin_expect ((cond), 0) 68 | #define __glibc_likely(cond) __builtin_expect ((cond), 1) 69 | 70 | #ifndef ALTFILES_DATADIR 71 | #define ALTFILES_DATADIR "/lib" 72 | #endif /* !ALTFILES_DATADIR */ 73 | 74 | #ifndef ALTFILES_MODULE_NAME 75 | #define ALTFILES_MODULE_NAME altfiles 76 | #endif /* !ALTFILES_MODULE_NAME */ 77 | -------------------------------------------------------------------------------- /src/grp/fgetgrent_r.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1991-2024 Free Software Foundation, Inc. 2 | This file is part of the GNU C Library. 3 | 4 | The GNU C Library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | The GNU C Library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with the GNU C Library; if not, see 16 | . */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | /* Define a line parsing function using the common code 24 | used in the nss_files module. */ 25 | 26 | #define STRUCTURE group 27 | #define ENTNAME grent 28 | struct grent_data {}; 29 | 30 | #define TRAILING_LIST_MEMBER gr_mem 31 | #define TRAILING_LIST_SEPARATOR_P(c) ((c) == ',') 32 | #include "../nss_altfiles/files-parse.c" 33 | LINE_PARSER 34 | (, 35 | STRING_FIELD (result->gr_name, ISCOLON, 0); 36 | if (line[0] == '\0' 37 | && (result->gr_name[0] == '+' || result->gr_name[0] == '-')) 38 | { 39 | result->gr_passwd = NULL; 40 | result->gr_gid = 0; 41 | } 42 | else 43 | { 44 | STRING_FIELD (result->gr_passwd, ISCOLON, 0); 45 | if (result->gr_name[0] == '+' || result->gr_name[0] == '-') 46 | INT_FIELD_MAYBE_NULL (result->gr_gid, ISCOLON, 0, 10, , 0) 47 | else 48 | INT_FIELD (result->gr_gid, ISCOLON, 0, 10,) 49 | } 50 | ) 51 | 52 | 53 | /* Read one entry from the given stream. */ 54 | int 55 | __fgetgrent_r (FILE *stream, struct group *resbuf, char *buffer, size_t buflen, 56 | struct group **result) 57 | { 58 | int ret = __nss_fgetent_r (stream, resbuf, buffer, buflen, parse_line); 59 | if (ret == 0) 60 | *result = resbuf; 61 | else 62 | *result = NULL; 63 | return ret; 64 | } 65 | -------------------------------------------------------------------------------- /src/pwd/fgetpwent_r.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1991-2024 Free Software Foundation, Inc. 2 | This file is part of the GNU C Library. 3 | 4 | The GNU C Library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | The GNU C Library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with the GNU C Library; if not, see 16 | . */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | /* Define a line parsing function using the common code 24 | used in the nss_files module. */ 25 | 26 | #define STRUCTURE passwd 27 | #define ENTNAME pwent 28 | struct pwent_data {}; 29 | 30 | #include "../nss_altfiles/files-parse.c" 31 | LINE_PARSER 32 | (, 33 | STRING_FIELD (result->pw_name, ISCOLON, 0); 34 | if (line[0] == '\0' 35 | && (result->pw_name[0] == '+' || result->pw_name[0] == '-')) 36 | { 37 | /* This a special case. We allow lines containing only a `+' sign 38 | since this is used for nss_compat. All other services will 39 | reject this entry later. Initialize all other fields now. */ 40 | result->pw_passwd = NULL; 41 | result->pw_uid = 0; 42 | result->pw_gid = 0; 43 | result->pw_gecos = NULL; 44 | result->pw_dir = NULL; 45 | result->pw_shell = NULL; 46 | } 47 | else 48 | { 49 | STRING_FIELD (result->pw_passwd, ISCOLON, 0); 50 | if (result->pw_name[0] == '+' || result->pw_name[0] == '-') 51 | { 52 | INT_FIELD_MAYBE_NULL (result->pw_uid, ISCOLON, 0, 10, , 0) 53 | INT_FIELD_MAYBE_NULL (result->pw_gid, ISCOLON, 0, 10, , 0) 54 | } 55 | else 56 | { 57 | INT_FIELD (result->pw_uid, ISCOLON, 0, 10,) 58 | INT_FIELD (result->pw_gid, ISCOLON, 0, 10,) 59 | } 60 | STRING_FIELD (result->pw_gecos, ISCOLON, 0); 61 | STRING_FIELD (result->pw_dir, ISCOLON, 0); 62 | result->pw_shell = line; 63 | } 64 | ) 65 | -------------------------------------------------------------------------------- /src/resolv/res_hconf.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1993-2024 Free Software Foundation, Inc. 2 | This file is part of the GNU C Library. 3 | 4 | The GNU C Library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | The GNU C Library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with the GNU C Library; if not, see 16 | . */ 17 | 18 | #ifndef _RES_HCONF_H_ 19 | #define _RES_HCONF_H_ 20 | 21 | #include 22 | 23 | #define TRIMDOMAINS_MAX 4 24 | 25 | struct hconf 26 | { 27 | /* We keep the INITIALIZED member only for backwards compatibility. New 28 | code should just call _res_hconf_init unconditionally. For this field 29 | to be used safely, users must ensure that either (1) a call to 30 | _res_hconf_init happens-before any load from INITIALIZED, or (2) an 31 | assignment of zero to INITIALIZED happens-before any load from it, and 32 | these loads use acquire MO if the intent is to skip calling 33 | _res_hconf_init if the load returns a nonzero value. Such acquire MO 34 | loads will then synchronize with the release MO store to INITIALIZED 35 | in do_init in res_hconf.c; see pthread_once for more detail. */ 36 | int initialized; 37 | int unused1; 38 | int unused2[4]; 39 | int num_trimdomains; 40 | const char *trimdomain[TRIMDOMAINS_MAX]; 41 | unsigned int flags; 42 | # define HCONF_FLAG_INITED (1 << 0) /* initialized? */ 43 | # define HCONF_FLAG_REORDER (1 << 3) /* list best address first */ 44 | # define HCONF_FLAG_MULTI (1 << 4) /* see comments for gethtbyname() */ 45 | }; 46 | extern struct hconf _res_hconf; 47 | 48 | extern void _res_hconf_init (void) attribute_hidden; 49 | extern void _res_hconf_trim_domain (char *domain); 50 | extern void _res_hconf_trim_domains (struct hostent *hp); 51 | extern void _res_hconf_reorder_addrs (struct hostent *hp); 52 | 53 | #endif /* _RES_HCONF_H_ */ 54 | -------------------------------------------------------------------------------- /src/nss_altfiles/files-service.c: -------------------------------------------------------------------------------- 1 | /* Services file parser in nss_files module. 2 | Copyright (C) 1996-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #define ENTNAME servent 24 | #define DATABASE "services" 25 | 26 | struct servent_data {}; 27 | 28 | #define TRAILING_LIST_MEMBER s_aliases 29 | #define TRAILING_LIST_SEPARATOR_P isspace 30 | #include "files-parse.c" 31 | #define ISSLASH(c) ((c) == '/') 32 | LINE_PARSER 33 | ("#", 34 | STRING_FIELD (result->s_name, isspace, 1); 35 | INT_FIELD (result->s_port, ISSLASH, 10, 0, htons); 36 | STRING_FIELD (result->s_proto, isspace, 1); 37 | ) 38 | 39 | #include GENERIC 40 | 41 | DB_LOOKUP (servbyname, ':', 42 | strlen (name) + 2 + (proto == NULL ? 0 : strlen (proto)), 43 | ("%s/%s", name, proto ?: ""), 44 | { 45 | /* Must match both protocol (if specified) and name. */ 46 | if (proto != NULL && strcmp (result->s_proto, proto)) 47 | /* A continue statement here breaks nss_db, because it 48 | bypasses advancing to the next db entry, and it 49 | doesn't make nss_files any more efficient. */; 50 | else 51 | LOOKUP_NAME (s_name, s_aliases) 52 | }, 53 | const char *name, const char *proto) 54 | 55 | DB_LOOKUP (servbyport, '=', 21 + (proto ? strlen (proto) : 0), 56 | ("%zd/%s", (ssize_t) ntohs (port), proto ?: ""), 57 | { 58 | /* Must match both port and protocol. */ 59 | if (result->s_port == port 60 | && (proto == NULL 61 | || strcmp (result->s_proto, proto) == 0)) 62 | break; 63 | }, int port, const char *proto) 64 | -------------------------------------------------------------------------------- /src/gshadow/sgetsgent_r.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2009-2024 Free Software Foundation, Inc. 2 | This file is part of the GNU C Library. 3 | 4 | The GNU C Library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | The GNU C Library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with the GNU C Library; if not, see 16 | . */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | /* Define a line parsing function using the common code 25 | used in the nss_files module. */ 26 | 27 | #define STRUCTURE sgrp 28 | #define ENTNAME sgent 29 | struct sgent_data {}; 30 | 31 | 32 | #define TRAILING_LIST_MEMBER sg_mem 33 | #define TRAILING_LIST_SEPARATOR_P(c) ((c) == ',') 34 | #include "../nss_altfiles/files-parse.c" 35 | LINE_PARSER 36 | (, 37 | STRING_FIELD (result->sg_namp, ISCOLON, 0); 38 | if (line[0] == '\0' 39 | && (result->sg_namp[0] == '+' || result->sg_namp[0] == '-')) 40 | { 41 | result->sg_passwd = NULL; 42 | result->sg_adm = NULL; 43 | result->sg_mem = NULL; 44 | } 45 | else 46 | { 47 | STRING_FIELD (result->sg_passwd, ISCOLON, 0); 48 | STRING_LIST (result->sg_adm, ':'); 49 | } 50 | ) 51 | 52 | 53 | /* Read one shadow entry from the given stream. */ 54 | int 55 | __sgetsgent_r (const char *string, struct sgrp *resbuf, char *buffer, 56 | size_t buflen, struct sgrp **result) 57 | { 58 | char *sp; 59 | if (string < buffer || string >= buffer + buflen) 60 | { 61 | buffer[buflen - 1] = '\0'; 62 | sp = strncpy (buffer, string, buflen); 63 | if (buffer[buflen - 1] != '\0') 64 | { 65 | __set_errno (ERANGE); 66 | return ERANGE; 67 | } 68 | } 69 | else 70 | sp = (char *) string; 71 | 72 | int parse_result = parse_line (sp, resbuf, (void *) buffer, buflen, &errno); 73 | *result = parse_result > 0 ? resbuf : NULL; 74 | 75 | return *result == NULL ? errno : 0; 76 | } 77 | -------------------------------------------------------------------------------- /src/nss_altfiles/files-network.c: -------------------------------------------------------------------------------- 1 | /* Networks file parser in nss_files module. 2 | Copyright (C) 1996-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #define ENTNAME netent 26 | #define DATABASE "networks" 27 | #define NEED_H_ERRNO 28 | 29 | struct netent_data {}; 30 | 31 | #define TRAILING_LIST_MEMBER n_aliases 32 | #define TRAILING_LIST_SEPARATOR_P isspace 33 | #include "files-parse.c" 34 | LINE_PARSER 35 | ("#", 36 | { 37 | char *addr; 38 | char *cp; 39 | int n = 1; 40 | 41 | STRING_FIELD (result->n_name, isspace, 1); 42 | 43 | STRING_FIELD (addr, isspace, 1); 44 | /* 'inet_network' does not add zeroes at the end if the network number 45 | does not four byte values. We add them ourselves if necessary. */ 46 | cp = strchr (addr, '.'); 47 | if (cp != NULL) 48 | { 49 | ++n; 50 | cp = strchr (cp + 1, '.'); 51 | if (cp != NULL) 52 | { 53 | ++n; 54 | cp = strchr (cp + 1, '.'); 55 | if (cp != NULL) 56 | ++n; 57 | } 58 | } 59 | if (n < 4) 60 | { 61 | char *newp = (char *) alloca (strlen (addr) + (4 - n) * 2 + 1); 62 | cp = stpcpy (newp, addr); 63 | do 64 | { 65 | *cp++ = '.'; 66 | *cp++ = '0'; 67 | } 68 | while (++n < 4); 69 | *cp = '\0'; 70 | addr = newp; 71 | } 72 | result->n_net = __inet_network (addr); 73 | result->n_addrtype = AF_INET; 74 | 75 | }) 76 | 77 | #include "files-XXX.c" 78 | 79 | DB_LOOKUP (netbyname, ,,, 80 | LOOKUP_NAME_CASE (n_name, n_aliases), 81 | const char *name) 82 | 83 | DB_LOOKUP (netbyaddr, ,,, 84 | { 85 | if ((type == AF_UNSPEC || result->n_addrtype == type) 86 | && result->n_net == net) 87 | /* Bingo! */ 88 | break; 89 | }, uint32_t net, int type) 90 | -------------------------------------------------------------------------------- /src/file_change_detection.h: -------------------------------------------------------------------------------- 1 | /* Detecting file changes using modification times. 2 | Copyright (C) 2017-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | #ifndef _FILE_CHANGE_DETECTION_H 20 | #define _FILE_CHANGE_DETECTION_H 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | /* Items for identifying a particular file version. Excerpt from 28 | struct stat64. */ 29 | struct file_change_detection 30 | { 31 | /* Special values: 0 if file does not exist. -1 to force mismatch 32 | with the next comparison. */ 33 | off_t size; 34 | 35 | ino_t ino; 36 | struct timespec mtime; 37 | struct timespec ctime; 38 | }; 39 | 40 | /* Returns true if *LEFT and *RIGHT describe the same version of the 41 | same file. */ 42 | bool __file_is_unchanged (const struct file_change_detection *left, 43 | const struct file_change_detection *right); 44 | 45 | /* Extract file change information to *FILE from the stat buffer 46 | *ST. */ 47 | void __file_change_detection_for_stat (struct file_change_detection *file, 48 | const struct stat *st); 49 | 50 | /* Writes file change information for PATH to *FILE. Returns true on 51 | success. For benign errors, *FILE is cleared, and true is 52 | returned. For errors indicating resource outages and the like, 53 | false is returned. */ 54 | bool __file_change_detection_for_path (struct file_change_detection *file, 55 | const char *path); 56 | 57 | /* Writes file change information for the stream FP to *FILE. Returns 58 | true on success, false on failure. If FP is NULL, treat the file 59 | as non-existing. */ 60 | bool __file_change_detection_for_fp (struct file_change_detection *file, 61 | FILE *fp); 62 | 63 | #ifndef _ISOMAC 64 | libc_hidden_proto (__file_is_unchanged) 65 | libc_hidden_proto (__file_change_detection_for_stat) 66 | libc_hidden_proto (__file_change_detection_for_path) 67 | libc_hidden_proto (__file_change_detection_for_fp) 68 | #endif 69 | 70 | #endif /* _FILE_CHANGE_DETECTION_H */ 71 | -------------------------------------------------------------------------------- /src/shadow/sgetspent_r.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-2024 Free Software Foundation, Inc. 2 | This file is part of the GNU C Library. 3 | 4 | The GNU C Library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | The GNU C Library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with the GNU C Library; if not, see 16 | . */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | /* Define a line parsing function using the common code 25 | used in the nss_files module. */ 26 | 27 | #define STRUCTURE spwd 28 | #define ENTNAME spent 29 | struct spent_data {}; 30 | 31 | /* Predicate which always returns false, needed below. */ 32 | #define FALSEP(arg) 0 33 | 34 | 35 | #include "../nss_altfiles/files-parse.c" 36 | LINE_PARSER 37 | (, 38 | STRING_FIELD (result->sp_namp, ISCOLON, 0); 39 | if (line[0] == '\0' 40 | && (result->sp_namp[0] == '+' || result->sp_namp[0] == '-')) 41 | { 42 | result->sp_pwdp = NULL; 43 | result->sp_lstchg = 0; 44 | result->sp_min = 0; 45 | result->sp_max = 0; 46 | result->sp_warn = -1l; 47 | result->sp_inact = -1l; 48 | result->sp_expire = -1l; 49 | result->sp_flag = ~0ul; 50 | } 51 | else 52 | { 53 | STRING_FIELD (result->sp_pwdp, ISCOLON, 0); 54 | INT_FIELD_MAYBE_NULL (result->sp_lstchg, ISCOLON, 0, 10, (long int) (int), 55 | (long int) -1); 56 | INT_FIELD_MAYBE_NULL (result->sp_min, ISCOLON, 0, 10, (long int) (int), 57 | (long int) -1); 58 | INT_FIELD_MAYBE_NULL (result->sp_max, ISCOLON, 0, 10, (long int) (int), 59 | (long int) -1); 60 | while (isspace (*line)) 61 | ++line; 62 | if (*line == '\0') 63 | { 64 | /* The old form. */ 65 | result->sp_warn = -1l; 66 | result->sp_inact = -1l; 67 | result->sp_expire = -1l; 68 | result->sp_flag = ~0ul; 69 | } 70 | else 71 | { 72 | INT_FIELD_MAYBE_NULL (result->sp_warn, ISCOLON, 0, 10, 73 | (long int) (int), (long int) -1); 74 | INT_FIELD_MAYBE_NULL (result->sp_inact, ISCOLON, 0, 10, 75 | (long int) (int), (long int) -1); 76 | INT_FIELD_MAYBE_NULL (result->sp_expire, ISCOLON, 0, 10, 77 | (long int) (int), (long int) -1); 78 | if (*line != '\0') 79 | INT_FIELD_MAYBE_NULL (result->sp_flag, FALSEP, 0, 10, 80 | (unsigned long int), ~0ul) 81 | else 82 | result->sp_flag = ~0ul; 83 | } 84 | } 85 | ) 86 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | NSS altfiles module 2 | =================== 3 | 4 | [![Build Status](https://drone.io/github.com/aperezdc/nss-altfiles/status.png)](https://drone.io/github.com/aperezdc/nss-altfiles/latest) 5 | 6 | This is a NSS module which can read user information from files 7 | in the same format as `/etc/passwd` and `/etc/group` stored in an 8 | alternate location (`/lib` by default). 9 | 10 | As of version 2.19.0, the module supports also files mimicking 11 | other files from `/etc`, and which file types are supported can 12 | be selected at build time: 13 | 14 | - `/etc/rpc` 15 | - `/etc/protocols` 16 | - `/etc/hosts` 17 | - `/etc/networks` 18 | - `/etc/services` 19 | - `/etc/shadow` 20 | - `/etc/gshadow` 21 | 22 | Essentially, it is a tweaked copy of the sources for the NSS 23 | `files` module included with [glibc2](http://www.gnu.org/software/libc/) 24 | (or [eglibc](http://www.eglibc.org) in versions prior to 2.19.0). 25 | 26 | Usage 27 | ----- 28 | 29 | List the module the `/etc/nsswitch.conf` configuration file. 30 | For example: 31 | 32 | passwd: files altfiles 33 | group: files altfiles 34 | 35 | # Other entries follow... 36 | 37 | This will try to read files from `/etc` first, and under 38 | `/lib` (using the `altfiles` module). Modifications will be 39 | stored in the files under `/etc` (e.g. when using `passwd` 40 | to change an user passwords). 41 | 42 | Building 43 | -------- 44 | 45 | The usual `./configure && make && make install` dance will 46 | work. The `configure` script allows to change the install 47 | path and the path to the alternative data files: 48 | 49 | ./configure --prefix=/installdir/path --datadir=/var 50 | 51 | To select which file types will be supported, use the 52 | `--with-types=FOO` flag: 53 | 54 | ./configure --with-types=pwd,grp,hosts 55 | 56 | The example above would build an `altfiles` NSS module that 57 | will read user information from `/var/passwd` and `/var/group`, 58 | which is to be installed under `/installdir/path/lib`. 59 | 60 | To ease the task of packagers, the `DESTDIR` variable can 61 | be passed to `make`: 62 | 63 | make install DESTDIR=/tmp/fakerootdir 64 | 65 | Version scheme 66 | -------------- 67 | 68 | Version numbers follow the numbering of the eglibc releases, 69 | adding a local revision number: `.`. 70 | For example version `2.13.0` would contain the source files 71 | from eglibc 2.13, and the base modifications to make it the 72 | `altfiles` module; version `2.15.3` would contain the source 73 | files from eglibc 2.15, and the base modifications plus three 74 | patches. 75 | 76 | Starting from version 2.19.0, version numbers follow glibc2 77 | versions, as eglibc is no longer developed because its changes 78 | were merged back into glibc2. 79 | 80 | Git tags do also follow this versioning. 81 | 82 | Licensing 83 | --------- 84 | 85 | As eglibc and glibc are distributed under the terms of the 86 | LGPL 2.1, the same applies to the extra bits needed to make 87 | `nss_altfiles` work. 88 | 89 | See the COPYING file in the source directory for the full 90 | text of the license. 91 | 92 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # vim: filetype=make 2 | # Adrian Perez, 2014-05-21 3 | # 4 | 5 | comma := , 6 | 7 | -include config.mk 8 | 9 | ifeq ($(strip $(HANDLE_ALL)),) 10 | HANDLE_ALL := grp pwd 11 | endif 12 | 13 | ifeq ($(strip $(MODULE_NAME)),) 14 | MODULE_NAME := altfiles 15 | endif 16 | 17 | LIBDIR ?= $(PREFIX)/lib 18 | 19 | # By default, only pwd/grp are handled 20 | define def-handle 21 | HANDLE_$1 := 1 22 | endef 23 | 24 | $(foreach I,$(HANDLE_ALL),$(eval $(call def-handle,$I))) 25 | 26 | # Choose object depending on the HANDLE_foo variables 27 | O := $(if $(HANDLE_rpc), src/nss_altfiles/files-rpc.o) \ 28 | $(if $(HANDLE_proto), src/nss_altfiles/files-proto.o) \ 29 | $(if $(HANDLE_hosts), src/nss_altfiles/files-hosts.o) \ 30 | $(if $(HANDLE_network), src/nss_altfiles/files-network.o) \ 31 | $(if $(HANDLE_service), src/nss_altfiles/files-service.o) \ 32 | $(if $(HANDLE_pwd), src/nss_altfiles/files-pwd.o src/pwd/fgetpwent_r.o) \ 33 | $(if $(HANDLE_grp), src/nss_altfiles/files-grp.o src/grp/fgetgrent_r.o) \ 34 | $(if $(HANDLE_spwd), src/nss_altfiles/files-spwd.o src/shadow/sgetspent_r.o) \ 35 | $(if $(HANDLE_sgrp), src/nss_altfiles/files-sgrp.o src/gshadow/sgetsgent_r.o) \ 36 | src/nss_altfiles/nss_fgetent_r.o \ 37 | src/nss_altfiles/nss_files_data.o \ 38 | src/nss_altfiles/nss_files_fopen.o \ 39 | src/nss_altfiles/nss_parse_line_result.o \ 40 | src/nss_altfiles/nss_readline.o 41 | 42 | CFLAGS += $(EXTRA_CFLAGS) -pthread -fpic -std=gnu11 -Wall 43 | LDFLAGS += $(CFLAGS) -Wl,--as-needed 44 | CPPFLAGS += -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 \ 45 | -DALTFILES_MODULE_NAME=$(strip $(MODULE_NAME)) 46 | 47 | ifneq ($(strip $(DATADIR)),) 48 | CPPFLAGS += -DALTFILES_DATADIR='"$(strip $(DATADIR))"' 49 | endif 50 | 51 | T := libnss_$(MODULE_NAME).so.2 52 | 53 | # Support getting the number of parallel jobs via Build-API 54 | # Info: http://people.gnome.org/~walters/docs/build-api.txt 55 | # 56 | ifneq ($(strip $(BUILDAPI_JOBS)),) 57 | MAKEOPTS += -j$(BUILDAPI_JOBS) 58 | endif 59 | 60 | all: $T nss-$(MODULE_NAME)-config 61 | 62 | symbols.map: gen-symmap Makefile 63 | ./gen-symmap $(MODULE_NAME) $(HANDLE_ALL) > $@ 64 | symbols.ver: gen-symver Makefile 65 | ./gen-symver $(MODULE_NAME) > $@ 66 | 67 | $T: LDFLAGS += -Wl,-soname,$T -lpthread 68 | $T: $O symbols.map symbols.ver 69 | $(CC) -shared -o $@ $O $(LDFLAGS) -Wl,--version-script,symbols.ver symbols.map 70 | 71 | $O: src/nss_altfiles/files-XXX.c src/nss_altfiles/files-parse.c src/compat.h 72 | src/nss_altfiles/files-hosts.o: src/resolv/mapv4v6addr.h src/resolv/res_hconf.h 73 | 74 | nss-$(MODULE_NAME)-config: src/main.o 75 | $(CC) -o $@ $^ $(LDFLAGS) 76 | 77 | clean: 78 | $(RM) $O src/main.o 79 | $(RM) $T nss-$(MODULE_NAME)-config 80 | $(RM) symbols.map symbols.ver 81 | 82 | distclean: clean 83 | $(RM) config.mk 84 | 85 | install: $T 86 | install -m 755 -d $(DESTDIR)$(LIBDIR) 87 | install -m 755 $T $(DESTDIR)$(LIBDIR) 88 | 89 | export VERSION 90 | dist: 91 | @ if test -n "$$VERSION" ; then V=$$VERSION ; \ 92 | else V=$$(git tag | sed -e '/^v[0-9\.]*$$/s/^v//p' -e d | tail -1) ; fi ; \ 93 | echo "nss-altfiles-$$V.tar.xz" ; \ 94 | git archive --prefix=nss-altfiles-$$V/ v$$V | xz -9c > nss-altfiles-$$V.tar.xz 95 | 96 | .PHONY: distclean install dist 97 | -------------------------------------------------------------------------------- /src/resolv/mapv4v6addr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ++Copyright++ 1985, 1988, 1993 3 | * - 4 | * Copyright (c) 1985, 1988, 1993 5 | * The Regents of the University of California. All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 4. Neither the name of the University nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 | * SUCH DAMAGE. 30 | * - 31 | * Portions Copyright (c) 1993 by Digital Equipment Corporation. 32 | * 33 | * Permission to use, copy, modify, and distribute this software for any 34 | * purpose with or without fee is hereby granted, provided that the above 35 | * copyright notice and this permission notice appear in all copies, and that 36 | * the name of Digital Equipment Corporation not be used in advertising or 37 | * publicity pertaining to distribution of the document or software without 38 | * specific, written prior permission. 39 | * 40 | * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 41 | * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 42 | * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 43 | * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 44 | * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 45 | * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 46 | * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 47 | * SOFTWARE. 48 | * - 49 | * --Copyright-- 50 | */ 51 | 52 | #include 53 | #include 54 | 55 | static void 56 | map_v4v6_address (const char *src, char *dst) 57 | { 58 | u_char *p = (u_char *) dst; 59 | int i; 60 | 61 | /* Move the IPv4 part to the right position. */ 62 | memcpy (dst + 12, src, INADDRSZ); 63 | 64 | /* Mark this ipv6 addr as a mapped ipv4. */ 65 | for (i = 0; i < 10; i++) 66 | *p++ = 0x00; 67 | *p++ = 0xff; 68 | *p = 0xff; 69 | } 70 | -------------------------------------------------------------------------------- /src/nss_altfiles/nss_readline.c: -------------------------------------------------------------------------------- 1 | /* Read a line from an nss_files database file. 2 | Copyright (C) 2020-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | #include "nss_files.h" 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | int 26 | __nss_readline (FILE *fp, char *buf, size_t len, off64_t *poffset) 27 | { 28 | /* We need space for at least one character, the line terminator, 29 | and the NUL byte. */ 30 | if (len < 3) 31 | { 32 | *poffset = -1; 33 | __set_errno (ERANGE); 34 | return ERANGE; 35 | } 36 | 37 | while (true) 38 | { 39 | /* Keep original offset for retries. */ 40 | *poffset = __ftello64 (fp); 41 | 42 | buf[len - 1] = '\xff'; /* Marker to recognize truncation. */ 43 | if (__fgets_unlocked (buf, len, fp) == NULL) 44 | { 45 | if (__feof_unlocked (fp)) 46 | { 47 | __set_errno (ENOENT); 48 | return ENOENT; 49 | } 50 | else 51 | { 52 | /* Any other error. Do not return ERANGE in this case 53 | because the caller would retry. */ 54 | if (errno == ERANGE) 55 | __set_errno (EINVAL); 56 | return errno; 57 | } 58 | } 59 | else if (buf[len - 1] != '\xff') 60 | /* The buffer is too small. Arrange for re-reading the same 61 | line on the next call. */ 62 | return __nss_readline_seek (fp, *poffset); 63 | 64 | /* __fgets_unlocked succeeded. */ 65 | 66 | /* Remove leading whitespace. */ 67 | char *p = buf; 68 | while (isspace (*p)) 69 | ++p; 70 | if (*p == '\0' || *p == '#') 71 | /* Skip empty lines and comments. */ 72 | continue; 73 | if (p != buf) 74 | memmove (buf, p, strlen (p)); 75 | 76 | /* Return line to the caller. */ 77 | return 0; 78 | } 79 | } 80 | libc_hidden_def (__nss_readline) 81 | 82 | int 83 | __nss_readline_seek (FILE *fp, off64_t offset) 84 | { 85 | if (offset < 0 /* __ftello64 failed. */ 86 | || __fseeko64 (fp, offset, SEEK_SET) < 0) 87 | { 88 | /* Without seeking support, it is not possible to 89 | re-read the same line, so this is a hard failure. */ 90 | fseterr_unlocked (fp); 91 | __set_errno (ESPIPE); 92 | return ESPIPE; 93 | } 94 | else 95 | { 96 | __set_errno (ERANGE); 97 | return ERANGE; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/nss_altfiles/function.def: -------------------------------------------------------------------------------- 1 | /* List of all functions defined for the NSS in GNU C Library. 2 | Copyright (C) 1996-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | /* This list must be kept sorted!!! */ 20 | 21 | DEFINE_NSS_FUNCTION (endaliasent) 22 | DEFINE_NSS_FUNCTION (endetherent) 23 | DEFINE_NSS_FUNCTION (endgrent) 24 | DEFINE_NSS_FUNCTION (endhostent) 25 | DEFINE_NSS_FUNCTION (endnetent) 26 | DEFINE_NSS_FUNCTION (endnetgrent) 27 | DEFINE_NSS_FUNCTION (endprotoent) 28 | DEFINE_NSS_FUNCTION (endpwent) 29 | DEFINE_NSS_FUNCTION (endrpcent) 30 | DEFINE_NSS_FUNCTION (endservent) 31 | DEFINE_NSS_FUNCTION (endsgent) 32 | DEFINE_NSS_FUNCTION (endspent) 33 | DEFINE_NSS_FUNCTION (getaliasbyname_r) 34 | DEFINE_NSS_FUNCTION (getaliasent_r) 35 | DEFINE_NSS_FUNCTION (getcanonname_r) 36 | DEFINE_NSS_FUNCTION (getetherent_r) 37 | DEFINE_NSS_FUNCTION (getgrent_r) 38 | DEFINE_NSS_FUNCTION (getgrgid_r) 39 | DEFINE_NSS_FUNCTION (getgrnam_r) 40 | DEFINE_NSS_FUNCTION (gethostbyaddr2_r) 41 | DEFINE_NSS_FUNCTION (gethostbyaddr_r) 42 | DEFINE_NSS_FUNCTION (gethostbyname2_r) 43 | DEFINE_NSS_FUNCTION (gethostbyname3_r) 44 | DEFINE_NSS_FUNCTION (gethostbyname4_r) 45 | DEFINE_NSS_FUNCTION (gethostbyname_r) 46 | DEFINE_NSS_FUNCTION (gethostent_r) 47 | DEFINE_NSS_FUNCTION (gethostton_r) 48 | DEFINE_NSS_FUNCTION (getnetbyaddr_r) 49 | DEFINE_NSS_FUNCTION (getnetbyname_r) 50 | DEFINE_NSS_FUNCTION (getnetent_r) 51 | DEFINE_NSS_FUNCTION (getnetgrent_r) 52 | DEFINE_NSS_FUNCTION (getntohost_r) 53 | DEFINE_NSS_FUNCTION (getprotobyname_r) 54 | DEFINE_NSS_FUNCTION (getprotobynumber_r) 55 | DEFINE_NSS_FUNCTION (getprotoent_r) 56 | DEFINE_NSS_FUNCTION (getpublickey) 57 | DEFINE_NSS_FUNCTION (getpwent_r) 58 | DEFINE_NSS_FUNCTION (getpwnam_r) 59 | DEFINE_NSS_FUNCTION (getpwuid_r) 60 | DEFINE_NSS_FUNCTION (getrpcbyname_r) 61 | DEFINE_NSS_FUNCTION (getrpcbynumber_r) 62 | DEFINE_NSS_FUNCTION (getrpcent_r) 63 | DEFINE_NSS_FUNCTION (getsecretkey) 64 | DEFINE_NSS_FUNCTION (getservbyname_r) 65 | DEFINE_NSS_FUNCTION (getservbyport_r) 66 | DEFINE_NSS_FUNCTION (getservent_r) 67 | DEFINE_NSS_FUNCTION (getsgent_r) 68 | DEFINE_NSS_FUNCTION (getsgnam_r) 69 | DEFINE_NSS_FUNCTION (getspent_r) 70 | DEFINE_NSS_FUNCTION (getspnam_r) 71 | DEFINE_NSS_FUNCTION (initgroups_dyn) 72 | DEFINE_NSS_FUNCTION (netname2user) 73 | DEFINE_NSS_FUNCTION (setaliasent) 74 | DEFINE_NSS_FUNCTION (setetherent) 75 | DEFINE_NSS_FUNCTION (setgrent) 76 | DEFINE_NSS_FUNCTION (sethostent) 77 | DEFINE_NSS_FUNCTION (setnetent) 78 | DEFINE_NSS_FUNCTION (setnetgrent) 79 | DEFINE_NSS_FUNCTION (setprotoent) 80 | DEFINE_NSS_FUNCTION (setpwent) 81 | DEFINE_NSS_FUNCTION (setrpcent) 82 | DEFINE_NSS_FUNCTION (setservent) 83 | DEFINE_NSS_FUNCTION (setsgent) 84 | DEFINE_NSS_FUNCTION (setspent) 85 | -------------------------------------------------------------------------------- /src/nss_altfiles/nss_database.h: -------------------------------------------------------------------------------- 1 | /* Mapping NSS services to action lists. 2 | Copyright (C) 2020-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | #ifndef _NSS_DATABASE_H 20 | #define _NSS_DATABASE_H 21 | 22 | #include "../file_change_detection.h" 23 | 24 | /* Each "line" in nsswitch.conf maps a supported database (example: 25 | passwd) to one or more name service providers (example: files dns). 26 | Internally, each name service provider (example: dns) is a 27 | dynamically loadable module (i.e. libnss_dns.so), managed by 28 | nss_module.h. The sequence of providers and rules (example: files 29 | [SUCCESS=RETURN] dns) is mapped by nss_action.h to a cached entry 30 | which encodes the sequence of modules and rules. Keeping track of 31 | all supported databases and their corresponding actions is done 32 | here. 33 | 34 | The key entry is __nss_database_get, which provides a set of 35 | actions which can be used with nss_lookup_function() and 36 | nss_next(). Callers should assume that these functions are fast, 37 | and should not cache the result longer than needed. */ 38 | 39 | #include "nss_action.h" 40 | 41 | /* The enumeration literal in enum nss_database for the database NAME 42 | (e.g., nss_database_hosts for hosts). */ 43 | #define NSS_DATABASE_LITERAL(name) nss_database_##name 44 | 45 | enum nss_database 46 | { 47 | #define DEFINE_DATABASE(name) NSS_DATABASE_LITERAL (name), 48 | #include "databases.def" 49 | #undef DEFINE_DATABASE 50 | 51 | /* Total number of databases. */ 52 | NSS_DATABASE_COUNT 53 | }; 54 | 55 | /* Looks up the action list for DB and stores it in *ACTIONS. Returns 56 | true on success or false on failure. Success can mean that 57 | *ACTIONS is NULL. */ 58 | bool __nss_database_get (enum nss_database db, nss_action_list *actions); 59 | libc_hidden_proto (__nss_database_get) 60 | 61 | /* Like __nss_database_get, but does not reload /etc/nsswitch.conf 62 | from disk. This assumes that there has been a previous successful 63 | __nss_database_get call (which may not have returned any data). */ 64 | nss_action_list __nss_database_get_noreload (enum nss_database db) 65 | attribute_hidden; 66 | 67 | /* Internal type. Exposed only for fork handling purposes. */ 68 | struct nss_database_data 69 | { 70 | struct file_change_detection nsswitch_conf; 71 | nss_action_list services[NSS_DATABASE_COUNT]; 72 | int reload_disabled; /* Actually bool; int for atomic access. */ 73 | bool initialized; 74 | }; 75 | 76 | /* Called by fork in the parent process, before forking. */ 77 | void __nss_database_fork_prepare_parent (struct nss_database_data *data) 78 | attribute_hidden; 79 | 80 | /* Called by fork in the new subprocess, after forking. */ 81 | void __nss_database_fork_subprocess (struct nss_database_data *data) 82 | attribute_hidden; 83 | 84 | #endif /* _NSS_DATABASE_H */ 85 | -------------------------------------------------------------------------------- /configure: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | ### See http://people.gnome.org/~walters/docs/build-api.txt 4 | # buildapi-variable-no-builddir 5 | 6 | # Show help if requested. 7 | # 8 | for var in "$@" ; do 9 | if test "${var}" = "--help" ; then 10 | cat <<-EOF 11 | usage: $0 [--options] 12 | Available options: 13 | 14 | --help This help message. 15 | --prefix=PATH Installation path prefix [default: /] 16 | --datadir=PATH Path for runtime data files [default: prefix/lib/] 17 | --with-module-name=NAME 18 | Specify an alternate name for the module [default: altfiles] 19 | --with-types=TYPE1,TYPE2,... 20 | Specify the list of NSS types that the module will 21 | handle. Use "all" to support all types. 22 | [default: pwd,grp] 23 | 24 | Available NSS types and their corresponding data files: 25 | 26 | rpc \$DATADIR/rpc 27 | proto \$DATADIR/protocols 28 | hosts \$DATADIR/hosts 29 | network \$DATADIR/networks 30 | service \$DATADIR/services 31 | pwd \$DATADIR/passwd 32 | grp \$DATADIR/group 33 | spwd \$DATADIR/shadow 34 | sgrp \$DATADIR/gshadow 35 | 36 | Also, the following relevant environment variables can be set: 37 | 38 | CFLAGS Additional command line flags to be passed to the C compiler 39 | CXXFLAGS Additional command line flags to be passed to the C++ compiler 40 | 41 | NOTE: This script tries to mimic the typical usage for configure scripts 42 | generated by autotools, hence it will silently ignore unrecognized 43 | command line options. 44 | EOF 45 | exit 46 | fi 47 | done 48 | 49 | # Inspect arguments and generate config.mk 50 | # 51 | echo "# autogenerated by: $0 $*" > config.mk 52 | echo EXTRA_CFLAGS= >> config.mk 53 | echo EXTRA_CXXFLAGS= >> config.mk 54 | 55 | for var in "$@" ; do 56 | case ${var} in 57 | CFLAGS=* | CXXFLAGS=*) 58 | echo "Setting EXTRA_${var}" 59 | echo "EXTRA_${var}" >> config.mk 60 | ;; 61 | --prefix=*) 62 | var=`echo "${var}" | sed 's/^--prefix=//'` 63 | echo "Setting PREFIX=${var}" 64 | echo "PREFIX := ${var}" >> config.mk 65 | ;; 66 | --libdir=*) 67 | var=`echo "${var}" | sed 's/^--libdir=//'` 68 | echo "Setting LIBDIR=${var}" 69 | echo "LIBDIR := ${var}" >> config.mk 70 | ;; 71 | --datadir=*) 72 | var=`echo "${var}" | sed 's/^--datadir=//'` 73 | echo "Setting DATADIR=${var}" 74 | echo "DATADIR := ${var}" >> config.mk 75 | ;; 76 | --with-module-name=*) 77 | var=`echo "${var}" | sed 's/^--with-module-name=//'` 78 | echo "Setting MODULE_NAME=${var}" 79 | echo "MODULE_NAME := ${var}" >> config.mk 80 | ;; 81 | --with-types=*) 82 | var=`echo "${var}" | sed 's/^--with-types=//'` 83 | if [ "${var}" = "all" ] ; then 84 | # Pick all supported types from the conditionals in the Makefile 85 | var=`sed 's/.\+$(HANDLE_\([a-z]\+\)).*/\1/p;d' Makefile | paste -s -d ','` 86 | fi 87 | echo "Setting TYPES=${var}" 88 | # By default pwd and grp are enabled, so clear their values before 89 | # adding the ones passed to --with-types= 90 | echo "HANDLE_ALL := \$(subst \$(comma), ,$var)" >> config.mk 91 | ;; 92 | *) 93 | true 94 | ;; 95 | esac 96 | done 97 | 98 | # Inherit the CFLAGS/CXXFLAGS from the environment, if defined. 99 | # 100 | if test -n "${CFLAGS}"; then 101 | echo "Setting EXTRA_CFLAGS+=${CFLAGS} (from environment)" 102 | echo "EXTRA_CFLAGS+=${CFLAGS}" >> config.mk 103 | fi 104 | if test -n "${CXXFLAGS}"; then 105 | echo "Setting EXTRA_CXXFLAGS+=${CXXFLAGS} (from environment)" 106 | echo "EXTRA_CXXFLAGS+=${CXXFLAGS}" >> config.mk 107 | fi 108 | 109 | echo "config.mk written" 110 | -------------------------------------------------------------------------------- /src/libc-symver.h: -------------------------------------------------------------------------------- 1 | /* Symbol version management. 2 | Copyright (C) 1995-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | /* This file is included from for !_ISOMAC, and 20 | unconditionally from . */ 21 | 22 | #ifndef _LIBC_SYMVER_H 23 | #define _LIBC_SYMVER_H 1 24 | 25 | #include 26 | 27 | /* Use symbol_version_reference to specify the version a symbol 28 | reference should link to. Use symbol_version or 29 | default_symbol_version for the definition of a versioned symbol. 30 | The difference is that the latter is a no-op in non-shared 31 | builds. 32 | 33 | _set_symbol_version is similar to symbol_version_reference, except 34 | that this macro expects the name and symbol version as a single 35 | string or token sequence, with an @ or @@ separator. (A string is 36 | used in C mode and a token sequence in assembler mode.) 37 | _set_symbol_version only be used for definitions because it may 38 | introduce an alias symbol that would not be globally unique for 39 | mere references. The _set_symbol_version macro is used to define 40 | default_symbol_version and compat_symbol. */ 41 | 42 | #ifdef __ASSEMBLER__ 43 | # define symbol_version_reference(real, name, version) \ 44 | .symver real, name##@##version 45 | #else 46 | # define symbol_version_reference(real, name, version) \ 47 | __asm__ (".symver " #real "," #name "@" #version) 48 | #endif /* !__ASSEMBLER__ */ 49 | 50 | #if SYMVER_NEEDS_ALIAS 51 | /* If the assembler cannot support multiple versions for the same 52 | symbol, introduce __SInnn_ aliases to which the symbol version is 53 | attached. */ 54 | # define __symbol_version_unique_concat(x, y) __SI ## x ## _ ## y 55 | # define _symbol_version_unique_concat(x, y) \ 56 | __symbol_version_unique_concat (x, y) 57 | # define _symbol_version_unique_alias(name) \ 58 | _symbol_version_unique_concat (name, __COUNTER__) 59 | # ifdef __ASSEMBLER__ 60 | # define _set_symbol_version_2(real, alias, name_version) \ 61 | .globl alias ASM_LINE_SEP \ 62 | .equiv alias, real ASM_LINE_SEP \ 63 | .symver alias, name_version 64 | # else 65 | # define _set_symbol_version_2(real, alias, name_version) \ 66 | __asm__ (".globl " #alias "\n\t" \ 67 | ".equiv " #alias ", " #real "\n\t" \ 68 | ".symver " #alias "," name_version) 69 | # endif 70 | # define _set_symbol_version_1(real, alias, name_version) \ 71 | _set_symbol_version_2 (real, alias, name_version) 72 | /* REAL must be globally unique, so that the counter also produces 73 | globally unique symbols. */ 74 | # define _set_symbol_version(real, name_version) \ 75 | _set_symbol_version_1 (real, _symbol_version_unique_alias (real), \ 76 | name_version) 77 | # else /* !SYMVER_NEEDS_ALIAS */ 78 | # ifdef __ASSEMBLER__ 79 | # define _set_symbol_version(real, name_version) \ 80 | .symver real, name_version 81 | # else 82 | # define _set_symbol_version(real, name_version) \ 83 | __asm__ (".symver " #real "," name_version) 84 | # endif 85 | #endif /* !SYMVER_NEEDS_ALIAS */ 86 | 87 | 88 | #endif /* _LIBC_SYMVER_H */ 89 | -------------------------------------------------------------------------------- /src/nss_altfiles/nss_module.h: -------------------------------------------------------------------------------- 1 | /* Global list of NSS service modules. 2 | Copyright (c) 2020-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | #ifndef _NSS_MODULE_H 20 | #define _NSS_MODULE_H 21 | 22 | #include 23 | #include 24 | 25 | /* See nss_database.h for a summary of how this relates. */ 26 | 27 | /* Typed function pointers for all functions that can be defined by a 28 | service module. */ 29 | struct nss_module_functions 30 | { 31 | #undef DEFINE_NSS_FUNCTION 32 | #define DEFINE_NSS_FUNCTION(f) nss_##f *f; 33 | #include "function.def" 34 | }; 35 | 36 | /* Number of elements of the nss_module_functions_untyped array. */ 37 | enum 38 | { 39 | nss_module_functions_count = (sizeof (struct nss_module_functions) 40 | / sizeof (void *)) 41 | }; 42 | 43 | /* Untyped version of struct nss_module_functions, for consistent 44 | processing purposes. */ 45 | typedef void *nss_module_functions_untyped[nss_module_functions_count]; 46 | 47 | /* Locate the nss_files functions, as if by dlopen/dlsym. */ 48 | void __nss_files_functions (nss_module_functions_untyped pointers) 49 | attribute_hidden; 50 | 51 | /* Initialization state of a NSS module. */ 52 | enum nss_module_state 53 | { 54 | nss_module_uninitialized, 55 | nss_module_loaded, 56 | nss_module_failed, 57 | }; 58 | 59 | /* A NSS service module (potentially unloaded). Client code should 60 | use the functions below. */ 61 | struct nss_module 62 | { 63 | /* Actual type is enum nss_module_state. Use int due to atomic 64 | access. Used in a double-checked locking idiom. */ 65 | int state; 66 | 67 | /* The function pointers in the module. */ 68 | union 69 | { 70 | struct nss_module_functions typed; 71 | nss_module_functions_untyped untyped; 72 | } functions; 73 | 74 | /* Only used for __libc_freeres unloading. */ 75 | void *handle; 76 | 77 | /* The next module in the list. */ 78 | struct nss_module *next; 79 | 80 | /* The name of the module (as it appears in /etc/nsswitch.conf). */ 81 | char name[]; 82 | }; 83 | 84 | /* Allocates the NSS module NAME (of NAME_LENGTH bytes) and places it 85 | into the global list. If it already exists in the list, return the 86 | pre-existing module. This does not actually load the module. 87 | Returns NULL on memory allocation failure. */ 88 | struct nss_module *__nss_module_allocate (const char *name, 89 | size_t name_length) attribute_hidden; 90 | 91 | /* Ensures that MODULE is in a loaded or failed state. */ 92 | bool __nss_module_load (struct nss_module *module) attribute_hidden; 93 | 94 | /* Ensures that MODULE is loaded and returns a pointer to the function 95 | NAME defined in it. Returns NULL if MODULE could not be loaded, or 96 | if the function NAME is not defined in the module. */ 97 | void *__nss_module_get_function (struct nss_module *module, const char *name) 98 | attribute_hidden; 99 | 100 | /* Block attempts to dlopen any module we haven't already opened. */ 101 | void __nss_module_disable_loading (void); 102 | 103 | #endif /* NSS_MODULE_H */ 104 | -------------------------------------------------------------------------------- /src/nss_altfiles/nss_action.h: -------------------------------------------------------------------------------- 1 | /* NSS actions, elements in a nsswitch.conf configuration line. 2 | Copyright (c) 2020-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | #ifndef _NSS_ACTION_H 20 | #define _NSS_ACTION_H 21 | 22 | #include 23 | 24 | /* See nss_database.h for a summary of how this relates. */ 25 | 26 | #include "nsswitch.h" /* For lookup_actions. */ 27 | 28 | struct nss_module; 29 | 30 | /* A NSS action pairs a service module with the action for each result 31 | state. */ 32 | struct nss_action 33 | { 34 | /* The service module that provides the functionality (potentially 35 | not yet loaded). */ 36 | struct nss_module *module; 37 | 38 | /* Action according to result. Two bits for each lookup_actions 39 | value (from nsswitch.h), indexed by enum nss_status (from nss.h). */ 40 | unsigned int action_bits; 41 | }; 42 | 43 | /* Value to add to first nss_status value to get zero. */ 44 | #define NSS_STATUS_BIAS 2 45 | /* Number of bits per lookup action. */ 46 | #define NSS_BPL 2 47 | #define NSS_BPL_MASK ((1 << NSS_BPL) - 1) 48 | 49 | /* Index in actions of an NSS status. Note that in nss/nss.h the 50 | status starts at -2, and we shift that up to zero by adding 2. 51 | Thus for example NSS_STATUS_TRYAGAIN, which is -2, would index into 52 | the 0th bit place as expected. */ 53 | static inline int 54 | nss_actions_bits_index (enum nss_status status) 55 | { 56 | return NSS_BPL * (NSS_STATUS_BIAS + status); 57 | } 58 | 59 | /* Returns the lookup_action value for STATUS in ACTION. */ 60 | static inline lookup_actions 61 | nss_action_get (const struct nss_action *action, enum nss_status status) 62 | { 63 | return ((action->action_bits >> nss_actions_bits_index (status)) 64 | & NSS_BPL_MASK); 65 | } 66 | 67 | /* Sets the lookup_action value for STATUS in ACTION. */ 68 | static inline void 69 | nss_action_set (struct nss_action *action, 70 | enum nss_status status, lookup_actions actions) 71 | { 72 | int offset = nss_actions_bits_index (status); 73 | unsigned int mask = NSS_BPL_MASK << offset; 74 | action->action_bits = ((action->action_bits & ~mask) 75 | | ((unsigned int) actions << offset)); 76 | } 77 | 78 | static inline void 79 | nss_action_set_all (struct nss_action *action, lookup_actions actions) 80 | { 81 | unsigned int bits = actions & NSS_BPL_MASK; 82 | action->action_bits = ( bits 83 | | (bits << (NSS_BPL * 1)) 84 | | (bits << (NSS_BPL * 2)) 85 | | (bits << (NSS_BPL * 3)) 86 | | (bits << (NSS_BPL * 4)) 87 | ); 88 | } 89 | 90 | /* A list of struct nss_action objects in array terminated by an 91 | action with a NULL module. */ 92 | typedef struct nss_action *nss_action_list; 93 | 94 | /* Returns a pointer to an allocated NSS action list that has COUNT 95 | actions that matches the array at ACTIONS. */ 96 | nss_action_list __nss_action_allocate (struct nss_action *actions, 97 | size_t count) attribute_hidden; 98 | 99 | /* Returns a pointer to a list allocated by __nss_action_allocate, or 100 | NULL on error. ENOMEM means a (temporary) memory allocation error, 101 | EINVAL means that LINE is syntactically invalid. */ 102 | nss_action_list __nss_action_parse (const char *line); 103 | 104 | 105 | #endif /* _NSS_ACTION_H */ 106 | -------------------------------------------------------------------------------- /src/nss_altfiles/nss_files_data.c: -------------------------------------------------------------------------------- 1 | /* Returns a pointer to the global nss_files data structure. 2 | Copyright (C) 2021-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | #include "nss_files.h" 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #undef __libc_lock_init 27 | #undef __libc_lock_lock 28 | #undef __libc_lock_unlock 29 | #define __libc_lock_init(_) ((void) 0) 30 | #define __libc_lock_lock(_) ((void) 0) 31 | #define __libc_lock_unlock(_) ((void) 0) 32 | 33 | /* This collects all per file-data. */ 34 | struct nss_files_data 35 | { 36 | struct nss_files_per_file_data files[nss_file_count]; 37 | }; 38 | 39 | static struct nss_files_data nss_files_global = { { { NULL } }, }; 40 | 41 | /* Like __nss_files_data_open, but does not perform the open call. */ 42 | static enum nss_status 43 | __nss_files_data_get (struct nss_files_per_file_data **pdata, 44 | enum nss_files_file file, int *errnop, int *herrnop) 45 | { 46 | struct nss_files_data *data = &nss_files_global; 47 | 48 | if (data == NULL) 49 | { 50 | if (errnop != NULL) 51 | *errnop = errno; 52 | if (herrnop != NULL) 53 | { 54 | __set_h_errno (NETDB_INTERNAL); 55 | *herrnop = NETDB_INTERNAL; 56 | } 57 | return NSS_STATUS_TRYAGAIN; 58 | } 59 | 60 | *pdata = &data->files[file]; 61 | __libc_lock_lock ((*pdata)->lock); 62 | return NSS_STATUS_SUCCESS; 63 | } 64 | 65 | /* Helper function for opening the backing file at PATH. */ 66 | static enum nss_status 67 | __nss_files_data_internal_open (struct nss_files_per_file_data *data, 68 | const char *path) 69 | { 70 | enum nss_status status = NSS_STATUS_SUCCESS; 71 | 72 | if (data->stream == NULL) 73 | { 74 | data->stream = __nss_files_fopen (path); 75 | 76 | if (data->stream == NULL) 77 | status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; 78 | } 79 | 80 | return status; 81 | } 82 | 83 | 84 | enum nss_status 85 | __nss_files_data_open (struct nss_files_per_file_data **pdata, 86 | enum nss_files_file file, const char *path, 87 | int *errnop, int *herrnop) 88 | { 89 | enum nss_status status = __nss_files_data_get (pdata, file, errnop, herrnop); 90 | if (status != NSS_STATUS_SUCCESS) 91 | return status; 92 | 93 | /* Be prepared that the set*ent function was not called before. */ 94 | if ((*pdata)->stream == NULL) 95 | { 96 | int saved_errno = errno; 97 | status = __nss_files_data_internal_open (*pdata, path); 98 | __set_errno (saved_errno); 99 | if (status != NSS_STATUS_SUCCESS) 100 | __nss_files_data_put (*pdata); 101 | } 102 | 103 | return status; 104 | } 105 | 106 | libc_hidden_def (__nss_files_data_open) 107 | 108 | void 109 | __nss_files_data_put (struct nss_files_per_file_data *data) 110 | { 111 | __libc_lock_unlock (data->lock); 112 | } 113 | libc_hidden_def (__nss_files_data_put) 114 | 115 | enum nss_status 116 | __nss_files_data_setent (enum nss_files_file file, const char *path) 117 | { 118 | struct nss_files_per_file_data *data; 119 | enum nss_status status = __nss_files_data_get (&data, file, NULL, NULL); 120 | if (status != NSS_STATUS_SUCCESS) 121 | return status; 122 | 123 | if (data->stream == NULL) 124 | status = __nss_files_data_internal_open (data, path); 125 | else 126 | rewind (data->stream); 127 | 128 | __nss_files_data_put (data); 129 | return status; 130 | } 131 | libc_hidden_def (__nss_files_data_setent) 132 | 133 | enum nss_status 134 | __nss_files_data_endent (enum nss_files_file file) 135 | { 136 | /* No cleanup is necessary if not initialized. */ 137 | struct nss_files_data *data = &nss_files_global; 138 | 139 | struct nss_files_per_file_data *fdata = &data->files[file]; 140 | __libc_lock_lock (fdata->lock); 141 | if (fdata->stream != NULL) 142 | { 143 | fclose (fdata->stream); 144 | fdata->stream = NULL; 145 | } 146 | __libc_lock_unlock (fdata->lock); 147 | 148 | return NSS_STATUS_SUCCESS; 149 | } 150 | libc_hidden_def (__nss_files_data_endent) 151 | -------------------------------------------------------------------------------- /src/scratch_buffer.h: -------------------------------------------------------------------------------- 1 | /* Variable-sized buffer with on-stack default allocation. 2 | Copyright (C) 2015-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | #ifndef _SCRATCH_BUFFER_H 20 | #define _SCRATCH_BUFFER_H 21 | 22 | /* Scratch buffers with a default stack allocation and fallback to 23 | heap allocation. It is expected that this function is used in this 24 | way: 25 | 26 | struct scratch_buffer tmpbuf; 27 | scratch_buffer_init (&tmpbuf); 28 | 29 | while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length)) 30 | if (!scratch_buffer_grow (&tmpbuf)) 31 | return -1; 32 | 33 | scratch_buffer_free (&tmpbuf); 34 | return 0; 35 | 36 | The allocation functions (scratch_buffer_grow, 37 | scratch_buffer_grow_preserve, scratch_buffer_set_array_size) make 38 | sure that the heap allocation, if any, is freed, so that the code 39 | above does not have a memory leak. The buffer still remains in a 40 | state that can be deallocated using scratch_buffer_free, so a loop 41 | like this is valid as well: 42 | 43 | struct scratch_buffer tmpbuf; 44 | scratch_buffer_init (&tmpbuf); 45 | 46 | while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length)) 47 | if (!scratch_buffer_grow (&tmpbuf)) 48 | break; 49 | 50 | scratch_buffer_free (&tmpbuf); 51 | 52 | scratch_buffer_grow and scratch_buffer_grow_preserve are guaranteed 53 | to grow the buffer by at least 512 bytes. This means that when 54 | using the scratch buffer as a backing store for a non-character 55 | array whose element size, in bytes, is 512 or smaller, the scratch 56 | buffer only has to grow once to make room for at least one more 57 | element. 58 | */ 59 | 60 | #include 61 | #include 62 | #include 63 | 64 | /* Scratch buffer. Must be initialized with scratch_buffer_init 65 | before its use. */ 66 | struct scratch_buffer { 67 | void *data; /* Pointer to the beginning of the scratch area. */ 68 | size_t length; /* Allocated space at the data pointer, in bytes. */ 69 | union { max_align_t __align; char __c[1024]; } __space; 70 | }; 71 | 72 | /* Initializes *BUFFER so that BUFFER->data points to BUFFER->__space 73 | and BUFFER->length reflects the available space. */ 74 | static inline void 75 | scratch_buffer_init (struct scratch_buffer *buffer) 76 | { 77 | buffer->data = buffer->__space.__c; 78 | buffer->length = sizeof (buffer->__space); 79 | } 80 | 81 | /* Deallocates *BUFFER (if it was heap-allocated). */ 82 | static inline void 83 | scratch_buffer_free (struct scratch_buffer *buffer) 84 | { 85 | if (buffer->data != buffer->__space.__c) 86 | free (buffer->data); 87 | } 88 | 89 | /* Grow *BUFFER by some arbitrary amount. The buffer contents is NOT 90 | preserved. Return true on success, false on allocation failure (in 91 | which case the old buffer is freed). On success, the new buffer is 92 | larger than the previous size. On failure, *BUFFER is deallocated, 93 | but remains in a free-able state, and errno is set. */ 94 | bool __libc_scratch_buffer_grow (struct scratch_buffer *buffer); 95 | libc_hidden_proto (__libc_scratch_buffer_grow) 96 | 97 | /* Alias for __libc_scratch_buffer_grow. */ 98 | static __always_inline bool 99 | scratch_buffer_grow (struct scratch_buffer *buffer) 100 | { 101 | return __glibc_likely (__libc_scratch_buffer_grow (buffer)); 102 | } 103 | 104 | /* Like __libc_scratch_buffer_grow, but preserve the old buffer 105 | contents on success, as a prefix of the new buffer. */ 106 | bool __libc_scratch_buffer_grow_preserve (struct scratch_buffer *buffer); 107 | libc_hidden_proto (__libc_scratch_buffer_grow_preserve) 108 | 109 | /* Alias for __libc_scratch_buffer_grow_preserve. */ 110 | static __always_inline bool 111 | scratch_buffer_grow_preserve (struct scratch_buffer *buffer) 112 | { 113 | return __glibc_likely (__libc_scratch_buffer_grow_preserve (buffer)); 114 | } 115 | 116 | /* Grow *BUFFER so that it can store at least NELEM elements of SIZE 117 | bytes. The buffer contents are NOT preserved. Both NELEM and SIZE 118 | can be zero. Return true on success, false on allocation failure 119 | (in which case the old buffer is freed, but *BUFFER remains in a 120 | free-able state, and errno is set). It is unspecified whether this 121 | function can reduce the array size. */ 122 | bool __libc_scratch_buffer_set_array_size (struct scratch_buffer *buffer, 123 | size_t nelem, size_t size); 124 | libc_hidden_proto (__libc_scratch_buffer_set_array_size) 125 | 126 | /* Alias for __libc_scratch_set_array_size. */ 127 | static __always_inline bool 128 | scratch_buffer_set_array_size (struct scratch_buffer *buffer, 129 | size_t nelem, size_t size) 130 | { 131 | return __glibc_likely (__libc_scratch_buffer_set_array_size 132 | (buffer, nelem, size)); 133 | } 134 | 135 | #endif /* _SCRATCH_BUFFER_H */ 136 | -------------------------------------------------------------------------------- /src/resolv/resolv-internal.h: -------------------------------------------------------------------------------- 1 | /* libresolv interfaces for internal use across glibc. 2 | Copyright (C) 2016-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | #ifndef _RESOLV_INTERNAL_H 20 | #define _RESOLV_INTERNAL_H 1 21 | 22 | #include 23 | #include 24 | 25 | /* Resolver flags. Used for _flags in struct __res_state. */ 26 | #define RES_F_VC 0x00000001 /* Socket is TCP. */ 27 | #define RES_F_CONN 0x00000002 /* Socket is connected. */ 28 | #define RES_F_EDNS0ERR 0x00000004 /* EDNS0 caused errors. */ 29 | 30 | /* The structure HEADER is normally aligned on a word boundary. In 31 | some code, we need to access this structure when it may be aligned 32 | on a byte boundary. To avoid unaligned accesses, we need a typedef 33 | with alignment one. This ensures the fields are accessed with byte 34 | loads and stores. */ 35 | typedef HEADER __attribute__ ((__aligned__(1))) UHEADER; 36 | 37 | /* List of known interfaces. */ 38 | struct netaddr 39 | { 40 | int addrtype; 41 | union 42 | { 43 | struct 44 | { 45 | uint32_t addr; 46 | uint32_t mask; 47 | } ipv4; 48 | } u; 49 | }; 50 | 51 | /* Legacy function. This needs to be removed once all NSS modules 52 | have been adjusted. */ 53 | static inline bool 54 | res_use_inet6 (void) 55 | { 56 | return false; 57 | } 58 | 59 | enum 60 | { 61 | /* The advertised EDNS buffer size. The value 1200 is derived 62 | from the IPv6 minimum MTU (1280 bytes) minus some arbitrary 63 | space for tunneling overhead. If the DNS server does not react 64 | to ICMP Fragmentation Needed But DF Set messages, this should 65 | avoid all UDP fragments on current networks. Avoiding UDP 66 | fragments is desirable because it prevents fragmentation-based 67 | spoofing attacks because the randomness in a DNS packet is 68 | concentrated in the first fragment (with the headers) and does 69 | not protect subsequent fragments. */ 70 | RESOLV_EDNS_BUFFER_SIZE = 1200, 71 | }; 72 | 73 | struct resolv_context; 74 | 75 | /* Internal function for implementing res_nmkquery and res_mkquery. 76 | Also used by __res_context_query. */ 77 | int __res_context_mkquery (struct resolv_context *, int op, const char *dname, 78 | int class, int type, const unsigned char *data, 79 | unsigned char *buf, int buflen); 80 | libc_hidden_proto (__res_context_mkquery) 81 | 82 | /* Main resolver query function for use within glibc. */ 83 | int __res_context_search (struct resolv_context *, const char *, int, int, 84 | unsigned char *, int, unsigned char **, 85 | unsigned char **, int *, int *, int *); 86 | libc_hidden_proto (__res_context_search) 87 | 88 | /* Main resolver query function for use within glibc. */ 89 | int __res_context_query (struct resolv_context *, const char *, int, int, 90 | unsigned char *, int, unsigned char **, 91 | unsigned char **, int *, int *, int *); 92 | libc_hidden_proto (__res_context_query) 93 | 94 | /* Internal function used to implement the query and search 95 | functions. */ 96 | int __res_context_send (struct resolv_context *, const unsigned char *, int, 97 | const unsigned char *, int, unsigned char *, 98 | int, unsigned char **, unsigned char **, 99 | int *, int *, int *); 100 | libc_hidden_proto (__res_context_send) 101 | 102 | /* Return true if the query has been handled in RES_NOAAAA mode. For 103 | that, RES_NOAAAA must be active, and the question type must be AAAA. 104 | The caller is expected to return *RESULT as the return value. */ 105 | bool __res_handle_no_aaaa (struct resolv_context *ctx, 106 | const unsigned char *buf, int buflen, 107 | unsigned char *ans, int anssiz, int *result) 108 | attribute_hidden; 109 | 110 | /* Internal function similar to res_hostalias. */ 111 | const char *__res_context_hostalias (struct resolv_context *, 112 | const char *, char *, size_t); 113 | libc_hidden_proto (__res_context_hostalias); 114 | 115 | /* Add an OPT record to a DNS query. */ 116 | int __res_nopt (struct resolv_context *, int n0, 117 | unsigned char *buf, int buflen, int anslen); 118 | libc_hidden_proto (__res_nopt) 119 | 120 | /* Convert from presentation format (which usually means ASCII 121 | printable) to network format (which is usually some kind of binary 122 | format). The input is in the range [SRC, SRC + SRCLEN). The 123 | output is written to DST (which has to be 4 or 16 bytes long, 124 | depending on AF). Return 0 for invalid input, 1 for success, -1 125 | for an invalid address family. */ 126 | int __inet_pton_length (int af, const char *src, size_t srclen, void *); 127 | libc_hidden_proto (__inet_pton_length) 128 | 129 | /* Called as part of the thread shutdown sequence. */ 130 | void __res_thread_freeres (void) attribute_hidden; 131 | 132 | /* The Linux kernel does not enable all ICMP messages on a UDP socket 133 | by default. A call this function enables full error reporting for 134 | the socket FD. FAMILY must be AF_INET or AF_INET6. Returns 0 on 135 | success, -1 on failure. */ 136 | int __res_enable_icmp (int family, int fd) attribute_hidden; 137 | 138 | 139 | /* Returns the name server address for the indicated index. */ 140 | struct sockaddr *__res_get_nsaddr (res_state statp, unsigned int n); 141 | libc_hidden_proto (__res_get_nsaddr) 142 | 143 | 144 | #endif /* _RESOLV_INTERNAL_H */ 145 | -------------------------------------------------------------------------------- /src/nss_altfiles/nss_files.h: -------------------------------------------------------------------------------- 1 | /* Internal routines for nss_files. 2 | Copyright (C) 2020-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | #ifndef _NSS_FILES_H 20 | #define _NSS_FILES_H 21 | 22 | #include "../compat.h" 23 | #include 24 | #include 25 | #if IS_IN (libc) 26 | #include 27 | #endif 28 | 29 | /* Open PATH for reading, as a data source for nss_files. */ 30 | FILE *__nss_files_fopen (const char *path); 31 | libc_hidden_proto (__nss_files_fopen) 32 | 33 | /* Read a line from FP, storing it BUF. Strip leading blanks and skip 34 | comments. Sets errno and returns error code on failure. Special 35 | failure: ERANGE means the buffer is too small. The function writes 36 | the original offset to *POFFSET (which can be negative in the case 37 | of non-seekable input). */ 38 | int __nss_readline (FILE *fp, char *buf, size_t len, off64_t *poffset); 39 | libc_hidden_proto (__nss_readline) 40 | 41 | /* Seek FP to OFFSET. Sets errno and returns error code on failure. 42 | On success, sets errno to ERANGE and returns ERANGE (to indicate 43 | re-reading of the same input line to the caller). If OFFSET is 44 | negative, fail with ESPIPE without seeking. Intended to be used 45 | after parsing data read by __nss_readline failed with ERANGE. */ 46 | int __nss_readline_seek (FILE *fp, off64_t offset) attribute_hidden; 47 | 48 | /* Handles the result of a parse_line call (as defined by 49 | nss/nss_files/files-parse.c). Adjusts the file offset of FP as 50 | necessary. Returns 0 on success, and updates errno on failure (and 51 | returns that error code). */ 52 | int __nss_parse_line_result (FILE *fp, off64_t offset, int parse_line_result); 53 | libc_hidden_proto (__nss_parse_line_result) 54 | 55 | /* Per-file data. Used by the *ent functions that need to preserve 56 | state across calls. */ 57 | struct nss_files_per_file_data 58 | { 59 | FILE *stream; 60 | #if IS_IN (libc) 61 | /* The size of locks changes between libc and nss_files, so this 62 | member must be last and is only available in libc. */ 63 | __libc_lock_define (, lock); 64 | #endif 65 | }; 66 | 67 | /* File index for __nss_files_data_get. */ 68 | enum nss_files_file 69 | { 70 | nss_file_aliasent, 71 | nss_file_etherent, 72 | nss_file_grent, 73 | nss_file_hostent, 74 | nss_file_netent, 75 | nss_file_protoent, 76 | nss_file_pwent, 77 | nss_file_rpcent, 78 | nss_file_servent, 79 | nss_file_sgent, 80 | nss_file_spent, 81 | 82 | nss_file_count 83 | }; 84 | 85 | /* Obtains a pointer to the per-file data for FILE, which is written 86 | to *PDATA, and tries to open the file at PATH for it. On success, 87 | returns NSS_STATUS_SUCCESS, and the caller must later call 88 | __nss_files_data_put. On failure, NSS_STATUS_TRYAGAIN is returned, 89 | and *ERRNOP and *HERRNOP are updated if these pointers are not 90 | null. */ 91 | enum nss_status __nss_files_data_open (struct nss_files_per_file_data **pdata, 92 | enum nss_files_file file, 93 | const char *path, 94 | int *errnop, int *herrnop); 95 | libc_hidden_proto (__nss_files_data_open) 96 | 97 | /* Unlock the per-file data, previously obtained by 98 | __nss_files_data_open. */ 99 | void __nss_files_data_put (struct nss_files_per_file_data *data); 100 | libc_hidden_proto (__nss_files_data_put) 101 | 102 | /* Performs the set*ent operation for FILE. PATH is the file to 103 | open. */ 104 | enum nss_status __nss_files_data_setent (enum nss_files_file file, 105 | const char *path); 106 | libc_hidden_proto (__nss_files_data_setent) 107 | 108 | /* Performs the end*ent operation for FILE. */ 109 | enum nss_status __nss_files_data_endent (enum nss_files_file file); 110 | libc_hidden_proto (__nss_files_data_endent) 111 | 112 | struct parser_data; 113 | 114 | /* Instances of the parse_line function from 115 | nss/nss_files/files-parse.c. */ 116 | typedef int nss_files_parse_line (char *line, void *result, 117 | struct parser_data *data, 118 | size_t datalen, int *errnop); 119 | extern nss_files_parse_line _nss_files_parse_etherent; 120 | extern nss_files_parse_line _nss_files_parse_grent; 121 | extern nss_files_parse_line _nss_files_parse_netent; 122 | extern nss_files_parse_line _nss_files_parse_protoent; 123 | extern nss_files_parse_line _nss_files_parse_pwent; 124 | extern nss_files_parse_line _nss_files_parse_rpcent; 125 | extern nss_files_parse_line _nss_files_parse_servent; 126 | extern nss_files_parse_line _nss_files_parse_sgent; 127 | extern nss_files_parse_line _nss_files_parse_spent; 128 | 129 | libc_hidden_proto (_nss_files_parse_etherent) 130 | libc_hidden_proto (_nss_files_parse_grent) 131 | libc_hidden_proto (_nss_files_parse_netent) 132 | libc_hidden_proto (_nss_files_parse_protoent) 133 | libc_hidden_proto (_nss_files_parse_pwent) 134 | libc_hidden_proto (_nss_files_parse_rpcent) 135 | libc_hidden_proto (_nss_files_parse_servent) 136 | libc_hidden_proto (_nss_files_parse_sgent) 137 | libc_hidden_proto (_nss_files_parse_spent) 138 | 139 | NSS_DECLARE_MODULE_FUNCTIONS (files) 140 | #undef DEFINE_NSS_FUNCTION 141 | #define DEFINE_NSS_FUNCTION(x) libc_hidden_proto (_nss_files_##x) 142 | #include "function.def" 143 | #undef DEFINE_NSS_FUNCTION 144 | 145 | void _nss_files_init (void (*cb) (size_t, struct traced_file *)); 146 | libc_hidden_proto (_nss_files_init) 147 | 148 | /* Generic implementation of fget*ent_r. Reads lines from FP until 149 | EOF or a successful parse into *RESULT using PARSER. Returns 0 on 150 | success, ENOENT on EOF, ERANGE on too-small buffer. */ 151 | int __nss_fgetent_r (FILE *fp, void *result, 152 | char *buffer, size_t buffer_length, 153 | nss_files_parse_line parser) attribute_hidden; 154 | 155 | #endif /* _NSS_FILES_H */ 156 | -------------------------------------------------------------------------------- /src/dynarray.h: -------------------------------------------------------------------------------- 1 | /* Type-safe arrays which grow dynamically. Shared definitions. 2 | Copyright (C) 2017-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | /* To use the dynarray facility, you need to include 20 | and define the parameter macros 21 | documented in that file. 22 | 23 | A minimal example which provides a growing list of integers can be 24 | defined like this: 25 | 26 | struct int_array 27 | { 28 | // Pointer to result array followed by its length, 29 | // as required by DYNARRAY_FINAL_TYPE. 30 | int *array; 31 | size_t length; 32 | }; 33 | 34 | #define DYNARRAY_STRUCT dynarray_int 35 | #define DYNARRAY_ELEMENT int 36 | #define DYNARRAY_PREFIX dynarray_int_ 37 | #define DYNARRAY_FINAL_TYPE struct int_array 38 | #include 39 | 40 | To create a three-element array with elements 1, 2, 3, use this 41 | code: 42 | 43 | struct dynarray_int dyn; 44 | dynarray_int_init (&dyn); 45 | for (int i = 1; i <= 3; ++i) 46 | { 47 | int *place = dynarray_int_emplace (&dyn); 48 | assert (place != NULL); 49 | *place = i; 50 | } 51 | struct int_array result; 52 | bool ok = dynarray_int_finalize (&dyn, &result); 53 | assert (ok); 54 | assert (result.length == 3); 55 | assert (result.array[0] == 1); 56 | assert (result.array[1] == 2); 57 | assert (result.array[2] == 3); 58 | free (result.array); 59 | 60 | If the elements contain resources which must be freed, define 61 | DYNARRAY_ELEMENT_FREE appropriately, like this: 62 | 63 | struct str_array 64 | { 65 | char **array; 66 | size_t length; 67 | }; 68 | 69 | #define DYNARRAY_STRUCT dynarray_str 70 | #define DYNARRAY_ELEMENT char * 71 | #define DYNARRAY_ELEMENT_FREE(ptr) free (*ptr) 72 | #define DYNARRAY_PREFIX dynarray_str_ 73 | #define DYNARRAY_FINAL_TYPE struct str_array 74 | #include 75 | 76 | Compared to scratch buffers, dynamic arrays have the following 77 | features: 78 | 79 | - They have an element type, and are not just an untyped buffer of 80 | bytes. 81 | 82 | - When growing, previously stored elements are preserved. (It is 83 | expected that scratch_buffer_grow_preserve and 84 | scratch_buffer_set_array_size eventually go away because all 85 | current users are moved to dynamic arrays.) 86 | 87 | - Scratch buffers have a more aggressive growth policy because 88 | growing them typically means a retry of an operation (across an 89 | NSS service module boundary), which is expensive. 90 | 91 | - For the same reason, scratch buffers have a much larger initial 92 | stack allocation. */ 93 | 94 | #ifndef _DYNARRAY_H 95 | #define _DYNARRAY_H 96 | 97 | #include 98 | #include 99 | #include 100 | 101 | struct dynarray_header 102 | { 103 | size_t used; 104 | size_t allocated; 105 | void *array; 106 | }; 107 | 108 | /* Marker used in the allocated member to indicate that an error was 109 | encountered. */ 110 | static inline size_t 111 | __dynarray_error_marker (void) 112 | { 113 | return -1; 114 | } 115 | 116 | /* Internal function. See the has_failed function in 117 | dynarray-skeleton.c. */ 118 | static inline bool 119 | __dynarray_error (struct dynarray_header *list) 120 | { 121 | return list->allocated == __dynarray_error_marker (); 122 | } 123 | 124 | /* Internal function. Enlarge the dynamically allocated area of the 125 | array to make room for one more element. SCRATCH is a pointer to 126 | the scratch area (which is not heap-allocated and must not be 127 | freed). ELEMENT_SIZE is the size, in bytes, of one element. 128 | Return false on failure, true on success. */ 129 | bool __libc_dynarray_emplace_enlarge (struct dynarray_header *, 130 | void *scratch, size_t element_size); 131 | 132 | /* Internal function. Enlarge the dynamically allocated area of the 133 | array to make room for at least SIZE elements (which must be larger 134 | than the existing used part of the dynamic array). SCRATCH is a 135 | pointer to the scratch area (which is not heap-allocated and must 136 | not be freed). ELEMENT_SIZE is the size, in bytes, of one element. 137 | Return false on failure, true on success. */ 138 | bool __libc_dynarray_resize (struct dynarray_header *, size_t size, 139 | void *scratch, size_t element_size); 140 | 141 | /* Internal function. Like __libc_dynarray_resize, but clear the new 142 | part of the dynamic array. */ 143 | bool __libc_dynarray_resize_clear (struct dynarray_header *, size_t size, 144 | void *scratch, size_t element_size); 145 | 146 | /* Internal type. */ 147 | struct dynarray_finalize_result 148 | { 149 | void *array; 150 | size_t length; 151 | }; 152 | 153 | /* Internal function. Copy the dynamically-allocated area to an 154 | explicitly-sized heap allocation. SCRATCH is a pointer to the 155 | embedded scratch space. ELEMENT_SIZE is the size, in bytes, of the 156 | element type. On success, true is returned, and pointer and length 157 | are written to *RESULT. On failure, false is returned. The caller 158 | has to take care of some of the memory management; this function is 159 | expected to be called from dynarray-skeleton.c. */ 160 | bool __libc_dynarray_finalize (struct dynarray_header *list, void *scratch, 161 | size_t element_size, 162 | struct dynarray_finalize_result *result); 163 | 164 | 165 | /* Internal function. Terminate the process after an index error. 166 | SIZE is the number of elements of the dynamic array. INDEX is the 167 | lookup index which triggered the failure. */ 168 | _Noreturn void __libc_dynarray_at_failure (size_t size, size_t index); 169 | 170 | #ifndef _ISOMAC 171 | libc_hidden_proto (__libc_dynarray_emplace_enlarge) 172 | libc_hidden_proto (__libc_dynarray_resize) 173 | libc_hidden_proto (__libc_dynarray_resize_clear) 174 | libc_hidden_proto (__libc_dynarray_finalize) 175 | libc_hidden_proto (__libc_dynarray_at_failure) 176 | #endif 177 | 178 | #endif /* _DYNARRAY_H */ 179 | -------------------------------------------------------------------------------- /src/nss_altfiles/files-XXX.c: -------------------------------------------------------------------------------- 1 | /* Common code for file-based databases in nss_files module. 2 | Copyright (C) 1996-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include "nsswitch.h" 24 | #include "nss_files.h" 25 | 26 | /* These symbols are defined by the including source file: 27 | 28 | ENTNAME -- database name of the structure and functions (hostent, pwent). 29 | STRUCTURE -- struct name, define only if not ENTNAME (passwd, group). 30 | DATABASE -- string of the database file's name ("hosts", "passwd"). 31 | 32 | NEED_H_ERRNO - defined iff an arg `int *herrnop' is used. 33 | 34 | Also see files-parse.c. 35 | */ 36 | 37 | #define ENTNAME_r CONCAT(ENTNAME,_r) 38 | 39 | #define DATAFILE "/etc/" DATABASE 40 | 41 | #ifdef NEED_H_ERRNO 42 | # include 43 | # define H_ERRNO_PROTO , int *herrnop 44 | # define H_ERRNO_ARG , herrnop 45 | # define H_ERRNO_ARG_OR_NULL herrnop 46 | # define H_ERRNO_SET(val) (*herrnop = (val)) 47 | #else 48 | # define H_ERRNO_PROTO 49 | # define H_ERRNO_ARG 50 | # define H_ERRNO_ARG_OR_NULL NULL 51 | # define H_ERRNO_SET(val) ((void) 0) 52 | #endif 53 | 54 | #ifndef EXTRA_ARGS 55 | # define EXTRA_ARGS 56 | # define EXTRA_ARGS_DECL 57 | # define EXTRA_ARGS_VALUE 58 | #endif 59 | 60 | 61 | /* Maintenance of the stream open on the database file. For getXXent 62 | operations the stream needs to be held open across calls, the other 63 | getXXbyYY operations all use their own stream. */ 64 | 65 | /* Open database file if not already opened. */ 66 | static enum nss_status 67 | internal_setent (FILE **stream) 68 | { 69 | enum nss_status status = NSS_STATUS_SUCCESS; 70 | 71 | if (*stream == NULL) 72 | { 73 | *stream = __nss_files_fopen (DATAFILE); 74 | 75 | if (*stream == NULL) 76 | status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; 77 | } 78 | else 79 | rewind (*stream); 80 | 81 | return status; 82 | } 83 | 84 | 85 | /* Thread-safe, exported version of that. */ 86 | enum nss_status 87 | CONCAT(_nss_files_set,ENTNAME) (int stayopen) 88 | { 89 | return __nss_files_data_setent (CONCAT (nss_file_, ENTNAME), DATAFILE); 90 | } 91 | libc_hidden_def (CONCAT (_nss_files_set,ENTNAME)) 92 | 93 | enum nss_status 94 | CONCAT(_nss_files_end,ENTNAME) (void) 95 | { 96 | return __nss_files_data_endent (CONCAT (nss_file_, ENTNAME)); 97 | } 98 | libc_hidden_def (CONCAT (_nss_files_end,ENTNAME)) 99 | 100 | 101 | /* Parsing the database file into `struct STRUCTURE' data structures. */ 102 | static enum nss_status 103 | internal_getent (FILE *stream, struct STRUCTURE *result, 104 | char *buffer, size_t buflen, int *errnop H_ERRNO_PROTO 105 | EXTRA_ARGS_DECL) 106 | { 107 | struct parser_data *data = (void *) buffer; 108 | size_t linebuflen = buffer + buflen - data->linebuffer; 109 | int saved_errno = errno; /* Do not clobber errno on success. */ 110 | 111 | if (buflen < sizeof *data + 2) 112 | { 113 | *errnop = ERANGE; 114 | H_ERRNO_SET (NETDB_INTERNAL); 115 | return NSS_STATUS_TRYAGAIN; 116 | } 117 | 118 | while (true) 119 | { 120 | off64_t original_offset; 121 | int ret = __nss_readline (stream, data->linebuffer, linebuflen, 122 | &original_offset); 123 | if (ret == ENOENT) 124 | { 125 | /* End of file. */ 126 | H_ERRNO_SET (HOST_NOT_FOUND); 127 | __set_errno (saved_errno); 128 | return NSS_STATUS_NOTFOUND; 129 | } 130 | else if (ret == 0) 131 | { 132 | ret = __nss_parse_line_result (stream, original_offset, 133 | parse_line (data->linebuffer, 134 | result, data, buflen, 135 | errnop EXTRA_ARGS)); 136 | if (ret == 0) 137 | { 138 | /* Line has been parsed successfully. */ 139 | __set_errno (saved_errno); 140 | return NSS_STATUS_SUCCESS; 141 | } 142 | else if (ret == EINVAL) 143 | /* If it is invalid, loop to get the next line of the file 144 | to parse. */ 145 | continue; 146 | } 147 | 148 | *errnop = ret; 149 | H_ERRNO_SET (NETDB_INTERNAL); 150 | if (ret == ERANGE) 151 | /* Request larger buffer. */ 152 | return NSS_STATUS_TRYAGAIN; 153 | else 154 | /* Other read failure. */ 155 | return NSS_STATUS_UNAVAIL; 156 | } 157 | } 158 | 159 | 160 | /* Return the next entry from the database file, doing locking. */ 161 | enum nss_status 162 | CONCAT(_nss_files_get,ENTNAME_r) (struct STRUCTURE *result, char *buffer, 163 | size_t buflen, int *errnop H_ERRNO_PROTO) 164 | { 165 | /* Return next entry in host file. */ 166 | 167 | struct nss_files_per_file_data *data; 168 | enum nss_status status = __nss_files_data_open (&data, 169 | CONCAT (nss_file_, ENTNAME), 170 | DATAFILE, 171 | errnop, H_ERRNO_ARG_OR_NULL); 172 | if (status != NSS_STATUS_SUCCESS) 173 | return status; 174 | 175 | status = internal_getent (data->stream, result, buffer, buflen, errnop 176 | H_ERRNO_ARG EXTRA_ARGS_VALUE); 177 | 178 | __nss_files_data_put (data); 179 | return status; 180 | } 181 | libc_hidden_def (CONCAT (_nss_files_get,ENTNAME_r)) 182 | 183 | /* Macro for defining lookup functions for this file-based database. 184 | 185 | NAME is the name of the lookup; e.g. `hostbyname'. 186 | 187 | DB_CHAR, KEYPATTERN, KEYSIZE are ignored here but used by db-XXX.c 188 | e.g. `1 + sizeof (id) * 4'. 189 | 190 | PROTO is the potentially empty list of other parameters. 191 | 192 | BREAK_IF_MATCH is a block of code which compares `struct STRUCTURE *result' 193 | to the lookup key arguments and does `break;' if they match. */ 194 | 195 | #define DB_LOOKUP(name, db_char, keysize, keypattern, break_if_match, proto...)\ 196 | enum nss_status \ 197 | _nss_files_get##name##_r (proto, \ 198 | struct STRUCTURE *result, char *buffer, \ 199 | size_t buflen, int *errnop H_ERRNO_PROTO) \ 200 | { \ 201 | enum nss_status status; \ 202 | FILE *stream = NULL; \ 203 | \ 204 | /* Open file. */ \ 205 | status = internal_setent (&stream); \ 206 | \ 207 | if (status == NSS_STATUS_SUCCESS) \ 208 | { \ 209 | while ((status = internal_getent (stream, result, buffer, buflen, errnop \ 210 | H_ERRNO_ARG EXTRA_ARGS_VALUE)) \ 211 | == NSS_STATUS_SUCCESS) \ 212 | { break_if_match } \ 213 | \ 214 | fclose (stream); \ 215 | } \ 216 | \ 217 | return status; \ 218 | } \ 219 | libc_hidden_def (_nss_files_get##name##_r) 220 | -------------------------------------------------------------------------------- /src/nss_altfiles/nsswitch.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1996-2024 Free Software Foundation, Inc. 2 | This file is part of the GNU C Library. 3 | 4 | The GNU C Library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | The GNU C Library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with the GNU C Library; if not, see 16 | . */ 17 | 18 | #ifndef _NSSWITCH_H 19 | #define _NSSWITCH_H 1 20 | 21 | /* This is an *internal* header. */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | /* Actions performed after lookup finished. */ 32 | typedef enum 33 | { 34 | NSS_ACTION_CONTINUE, 35 | NSS_ACTION_RETURN, 36 | NSS_ACTION_MERGE 37 | } lookup_actions; 38 | 39 | struct nss_action; 40 | 41 | typedef struct service_library 42 | { 43 | /* Name of service (`files', `dns', `nis', ...). */ 44 | const char *name; 45 | /* Pointer to the loaded shared library. */ 46 | void *lib_handle; 47 | /* And the link to the next entry. */ 48 | struct service_library *next; 49 | } service_library; 50 | 51 | 52 | /* For mapping a function name to a function pointer. It is known in 53 | nsswitch.c:nss_lookup_function that a string pointer for the lookup key 54 | is the first member. */ 55 | typedef struct 56 | { 57 | const char *fct_name; 58 | void *fct_ptr; 59 | } known_function; 60 | 61 | 62 | /* To access the action based on the status value use this macro. */ 63 | #define nss_next_action(ni, status) nss_action_get (ni, status) 64 | 65 | 66 | #ifdef USE_NSCD 67 | /* Indices into DATABASES in nsswitch.c and __NSS_DATABASE_CUSTOM. */ 68 | enum 69 | { 70 | # define DEFINE_DATABASE(arg) NSS_DBSIDX_##arg, 71 | # include "databases.def" 72 | # undef DEFINE_DATABASE 73 | NSS_DBSIDX_max 74 | }; 75 | 76 | /* Flags whether custom rules for database is set. */ 77 | extern bool __nss_database_custom[NSS_DBSIDX_max] attribute_hidden; 78 | #endif 79 | 80 | /* Warning for NSS functions, which don't require dlopen if glibc 81 | was built with --enable-static-nss. */ 82 | #ifdef DO_STATIC_NSS 83 | # define nss_interface_function(name) 84 | #else 85 | # define nss_interface_function(name) static_link_warning (name) 86 | #endif 87 | 88 | 89 | /* Interface functions for NSS. */ 90 | 91 | /* Put first function with name FCT_NAME for SERVICE in FCTP. The 92 | position is remembered in NI. The function returns a value < 0 if 93 | an error occurred or no such function exists. */ 94 | extern int __nss_lookup (struct nss_action **ni, const char *fct_name, 95 | const char *fct2_name, void **fctp); 96 | libc_hidden_proto (__nss_lookup) 97 | 98 | /* Determine the next step in the lookup process according to the 99 | result STATUS of the call to the last function returned by 100 | `__nss_lookup' or `__nss_next'. NI specifies the last function 101 | examined. The function return a value > 0 if the process should 102 | stop with the last result of the last function call to be the 103 | result of the entire lookup. The returned value is 0 if there is 104 | another function to use and < 0 if an error occurred. 105 | 106 | If ALL_VALUES is nonzero, the return value will not be > 0 as long as 107 | there is a possibility the lookup process can ever use following 108 | services. In other words, only if all four lookup results have 109 | the action RETURN associated the lookup process stops before the 110 | natural end. */ 111 | extern int __nss_next2 (struct nss_action **ni, const char *fct_name, 112 | const char *fct2_name, void **fctp, int status, 113 | int all_values) attribute_hidden; 114 | libc_hidden_proto (__nss_next2) 115 | extern int __nss_next (struct nss_action **ni, const char *fct_name, void **fctp, 116 | int status, int all_values); 117 | 118 | /* Search for the service described in NI for a function named FCT_NAME 119 | and return a pointer to this function if successful. */ 120 | extern void *__nss_lookup_function (struct nss_action *ni, const char *fct_name); 121 | libc_hidden_proto (__nss_lookup_function) 122 | 123 | 124 | /* Called by NSCD to disable recursive calls and enable special handling 125 | when used in nscd. */ 126 | struct traced_file; 127 | extern void __nss_disable_nscd (void (*) (size_t, struct traced_file *)); 128 | 129 | 130 | typedef int (*db_lookup_function) (struct nss_action **, const char *, const char *, 131 | void **); 132 | typedef enum nss_status (*setent_function) (int); 133 | typedef enum nss_status (*endent_function) (void); 134 | typedef enum nss_status (*getent_function) (void *, char *, size_t, 135 | int *, int *); 136 | typedef int (*getent_r_function) (void *, char *, size_t, 137 | void **result, int *); 138 | 139 | extern void __nss_setent (const char *func_name, 140 | db_lookup_function lookup_fct, 141 | struct nss_action **nip, struct nss_action **startp, 142 | struct nss_action **last_nip, int stayon, 143 | int *stayon_tmp, int res) 144 | attribute_hidden; 145 | extern void __nss_endent (const char *func_name, 146 | db_lookup_function lookup_fct, 147 | struct nss_action **nip, struct nss_action **startp, 148 | struct nss_action **last_nip, int res) 149 | attribute_hidden; 150 | extern int __nss_getent_r (const char *getent_func_name, 151 | const char *setent_func_name, 152 | db_lookup_function lookup_fct, 153 | struct nss_action **nip, struct nss_action **startp, 154 | struct nss_action **last_nip, int *stayon_tmp, 155 | int res, 156 | void *resbuf, char *buffer, size_t buflen, 157 | void **result, int *h_errnop) 158 | attribute_hidden; 159 | extern void *__nss_getent (getent_r_function func, 160 | void **resbuf, char **buffer, size_t buflen, 161 | size_t *buffer_size, int *h_errnop) 162 | attribute_hidden; 163 | struct resolv_context; 164 | struct hostent; 165 | extern int __nss_hostname_digits_dots_context (struct resolv_context *, 166 | const char *name, 167 | struct hostent *resbuf, 168 | char **buffer, 169 | size_t *buffer_size, 170 | size_t buflen, 171 | struct hostent **result, 172 | enum nss_status *status, int af, 173 | int *h_errnop) attribute_hidden; 174 | extern int __nss_hostname_digits_dots (const char *name, 175 | struct hostent *resbuf, char **buffer, 176 | size_t *buffer_size, size_t buflen, 177 | struct hostent **result, 178 | enum nss_status *status, int af, 179 | int *h_errnop); 180 | libc_hidden_proto (__nss_hostname_digits_dots) 181 | 182 | /* Maximum number of aliases we allow. */ 183 | #define MAX_NR_ALIASES 48 184 | #define MAX_NR_ADDRS 48 185 | 186 | /* Prototypes for __nss_*_lookup2 functions. */ 187 | #define DEFINE_DATABASE(arg) \ 188 | extern struct nss_action *__nss_##arg##_database attribute_hidden; \ 189 | int __nss_##arg##_lookup2 (struct nss_action **, const char *, \ 190 | const char *, void **); \ 191 | libc_hidden_proto (__nss_##arg##_lookup2) 192 | #include "databases.def" 193 | #undef DEFINE_DATABASE 194 | 195 | #include "nss_module.h" 196 | #include "nss_action.h" 197 | #include "nss_database.h" 198 | 199 | #endif /* nsswitch.h */ 200 | -------------------------------------------------------------------------------- /src/nss_altfiles/files-parse.c: -------------------------------------------------------------------------------- 1 | /* Common code for file-based database parsers in nss_files module. 2 | Copyright (C) 1996-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include "nss_files.h" 25 | 26 | /* These symbols are defined by the including source file: 27 | 28 | ENTNAME -- database name of the structure and functions (hostent, pwent). 29 | STRUCTURE -- struct name, define only if not ENTNAME (passwd, group). 30 | DATABASE -- string of the database file's name ("hosts", "passwd"). 31 | 32 | ENTDATA -- if defined, `struct ENTDATA' is used by the parser to store 33 | things pointed to by the resultant `struct STRUCTURE'. 34 | 35 | NEED_H_ERRNO - defined iff an arg `int *herrnop' is used. 36 | 37 | EXTRA_ARGS -- defined iff extra parameters must be passed to the parser 38 | EXTRA_ARGS_DECL -- declaration for these extra parameters 39 | EXTRA_ARGS_VALUE -- values to be passed for these parameters 40 | 41 | Also see files-XXX.c. */ 42 | 43 | #ifndef EXTRA_ARGS 44 | # define EXTRA_ARGS 45 | # define EXTRA_ARGS_DECL 46 | # define EXTRA_ARGS_VALUE 47 | #endif 48 | 49 | #define CONCAT(a,b) CONCAT1(a,b) 50 | #define CONCAT1(a,b) a##b 51 | 52 | #ifndef STRUCTURE 53 | # define STRUCTURE ENTNAME 54 | #endif 55 | 56 | 57 | struct parser_data 58 | { 59 | #ifdef ENTDATA 60 | struct ENTDATA entdata; 61 | # define ENTDATA_DECL(data) struct ENTDATA *const entdata = &data->entdata; 62 | #else 63 | # define ENTDATA_DECL(data) 64 | #endif 65 | char linebuffer[0]; 66 | }; 67 | 68 | #ifdef ENTDATA 69 | /* The function can't be exported, because the entdata structure 70 | is defined only in files-foo.c. */ 71 | # define parser_stclass static 72 | # define nss_files_parse_hidden_def(name) 73 | #else 74 | /* Export the line parser function so it can be used in nss_db. */ 75 | # define parser_stclass /* Global */ 76 | # define parse_line CONCAT(_nss_files_parse_,ENTNAME) 77 | # define nss_files_parse_hidden_def(name) libc_hidden_def (name) 78 | #endif 79 | 80 | 81 | #ifdef EXTERN_PARSER 82 | 83 | /* The parser is defined in a different module. */ 84 | extern int parse_line (char *line, void *result, 85 | struct parser_data *data, size_t datalen, int *errnop 86 | EXTRA_ARGS_DECL); 87 | 88 | # define LINE_PARSER(EOLSET, BODY) /* Do nothing */ 89 | 90 | #else 91 | 92 | /* Define a line parsing function. */ 93 | 94 | # define LINE_PARSER(EOLSET, BODY) \ 95 | parser_stclass int \ 96 | parse_line (char *line, void *generic_result, \ 97 | struct parser_data *data, size_t datalen, int *errnop \ 98 | EXTRA_ARGS_DECL) \ 99 | { \ 100 | struct STRUCTURE *result = generic_result; \ 101 | ENTDATA_DECL (data) \ 102 | BUFFER_PREPARE \ 103 | char *p = strpbrk (line, EOLSET "\n"); \ 104 | if (p != NULL) \ 105 | *p = '\0'; \ 106 | BODY; \ 107 | TRAILING_LIST_PARSER; \ 108 | return 1; \ 109 | } \ 110 | nss_files_parse_hidden_def (parse_line) 111 | 112 | 113 | # define STRING_FIELD(variable, terminator_p, swallow) \ 114 | { \ 115 | variable = line; \ 116 | while (*line != '\0' && !terminator_p (*line)) \ 117 | ++line; \ 118 | if (*line != '\0') \ 119 | { \ 120 | *line = '\0'; \ 121 | do \ 122 | ++line; \ 123 | while (swallow && terminator_p (*line)); \ 124 | } \ 125 | } 126 | 127 | # define STRING_LIST(variable, terminator_c) \ 128 | { \ 129 | char **list = parse_list (&line, buf_start, buf_end, terminator_c, \ 130 | errnop); \ 131 | if (list) \ 132 | variable = list; \ 133 | else \ 134 | return -1; /* -1 indicates we ran out of space. */ \ 135 | \ 136 | /* Determine the new end of the buffer. */ \ 137 | while (*list != NULL) \ 138 | ++list; \ 139 | buf_start = (char *) (list + 1); \ 140 | } 141 | 142 | /* Helper function. */ 143 | static inline uint32_t 144 | __attribute__ ((always_inline)) 145 | strtou32 (const char *nptr, char **endptr, int base) 146 | { 147 | unsigned long int val = strtoul (nptr, endptr, base); 148 | 149 | /* Match the 32-bit behavior on 64-bit platforms. */ 150 | if (sizeof (long int) > 4 && val > 0xffffffff) 151 | val = 0xffffffff; 152 | 153 | return val; 154 | } 155 | 156 | # define INT_FIELD(variable, terminator_p, swallow, base, convert) \ 157 | { \ 158 | char *endp; \ 159 | variable = convert (strtou32 (line, &endp, base)); \ 160 | if (endp == line) \ 161 | return 0; \ 162 | else if (terminator_p (*endp)) \ 163 | do \ 164 | ++endp; \ 165 | while (swallow && terminator_p (*endp)); \ 166 | else if (*endp != '\0') \ 167 | return 0; \ 168 | line = endp; \ 169 | } 170 | 171 | # define INT_FIELD_MAYBE_NULL(variable, terminator_p, swallow, base, convert, default) \ 172 | { \ 173 | char *endp; \ 174 | if (*line == '\0') \ 175 | /* We expect some more input, so don't allow the string to end here. */ \ 176 | return 0; \ 177 | variable = convert (strtou32 (line, &endp, base)); \ 178 | if (endp == line) \ 179 | variable = default; \ 180 | if (terminator_p (*endp)) \ 181 | do \ 182 | ++endp; \ 183 | while (swallow && terminator_p (*endp)); \ 184 | else if (*endp != '\0') \ 185 | return 0; \ 186 | line = endp; \ 187 | } 188 | 189 | # define ISCOLON(c) ((c) == ':') 190 | 191 | 192 | # ifndef TRAILING_LIST_MEMBER 193 | # define BUFFER_PREPARE /* Nothing to do. */ 194 | # define TRAILING_LIST_PARSER /* Nothing to do. */ 195 | # else 196 | 197 | # define BUFFER_PREPARE \ 198 | char *buf_start = NULL; \ 199 | char *buf_end = (char *) data + datalen; \ 200 | if (line >= data->linebuffer && line < buf_end) \ 201 | /* Find the end of the line buffer, we will use the space in \ 202 | DATA after it for storing the vector of pointers. */ \ 203 | buf_start = strchr (line, '\0') + 1; \ 204 | else \ 205 | /* LINE does not point within DATA->linebuffer, so that space is \ 206 | not being used for scratch space right now. We can use all of \ 207 | it for the pointer vector storage. */ \ 208 | buf_start = data->linebuffer; \ 209 | 210 | # define TRAILING_LIST_PARSER \ 211 | { \ 212 | if (buf_start == NULL) \ 213 | { \ 214 | if (line >= data->linebuffer && line < buf_end) \ 215 | /* Find the end of the line buffer, we will use the space in \ 216 | DATA after it for storing the vector of pointers. */ \ 217 | buf_start = strchr (line, '\0') + 1; \ 218 | else \ 219 | /* LINE does not point within DATA->linebuffer, so that space is \ 220 | not being used for scratch space right now. We can use all of \ 221 | it for the pointer vector storage. */ \ 222 | buf_start = data->linebuffer; \ 223 | } \ 224 | \ 225 | char **list = parse_list (&line, buf_start, buf_end, '\0', errnop); \ 226 | if (list) \ 227 | result->TRAILING_LIST_MEMBER = list; \ 228 | else \ 229 | return -1; /* -1 indicates we ran out of space. */ \ 230 | } 231 | 232 | static inline char ** 233 | __attribute ((always_inline)) 234 | parse_list (char **linep, char *eol, char *buf_end, int terminator_c, 235 | int *errnop) 236 | { 237 | char *line = *linep; 238 | char **list, **p; 239 | 240 | /* Adjust the pointer so it is aligned for storing pointers. */ 241 | eol += __alignof__ (char *) - 1; 242 | eol -= ((uintptr_t) eol) % __alignof__ (char *); 243 | /* We will start the storage here for the vector of pointers. */ 244 | list = (char **) eol; 245 | 246 | p = list; 247 | while (1) 248 | { 249 | if ((char *) (p + 2) > buf_end) 250 | { 251 | /* We cannot fit another pointer in the buffer. */ 252 | *errnop = ERANGE; 253 | return NULL; 254 | } 255 | 256 | if (*line == '\0') 257 | break; 258 | if (*line == terminator_c) 259 | { 260 | ++line; 261 | break; 262 | } 263 | 264 | /* Skip leading white space. This might not be portable but useful. */ 265 | while (isspace (*line)) 266 | ++line; 267 | 268 | char *elt = line; 269 | while (1) 270 | { 271 | if (*line == '\0' || *line == terminator_c 272 | || TRAILING_LIST_SEPARATOR_P (*line)) 273 | { 274 | /* End of the next entry. */ 275 | if (line > elt) 276 | /* We really found some data. */ 277 | *p++ = elt; 278 | 279 | /* Terminate string if necessary. */ 280 | if (*line != '\0') 281 | { 282 | char endc = *line; 283 | *line++ = '\0'; 284 | if (endc == terminator_c) 285 | goto out; 286 | } 287 | break; 288 | } 289 | ++line; 290 | } 291 | } 292 | out: 293 | *p = NULL; 294 | *linep = line; 295 | 296 | return list; 297 | } 298 | 299 | # endif /* TRAILING_LIST_MEMBER */ 300 | #endif /* EXTERN_PARSER */ 301 | 302 | 303 | #define LOOKUP_NAME(nameelt, aliaselt) \ 304 | { \ 305 | char **ap; \ 306 | if (! strcmp (name, result->nameelt)) \ 307 | break; \ 308 | for (ap = result->aliaselt; *ap; ++ap) \ 309 | if (! strcmp (name, *ap)) \ 310 | break; \ 311 | if (*ap) \ 312 | break; \ 313 | } 314 | 315 | #define LOOKUP_NAME_CASE(nameelt, aliaselt) \ 316 | { \ 317 | char **ap; \ 318 | if (! __strcasecmp (name, result->nameelt)) \ 319 | break; \ 320 | for (ap = result->aliaselt; *ap; ++ap) \ 321 | if (! __strcasecmp (name, *ap)) \ 322 | break; \ 323 | if (*ap) \ 324 | break; \ 325 | } 326 | 327 | 328 | /* This is defined by db-*.c to include "../nss_db/db-XXX.c" instead. */ 329 | #ifndef GENERIC 330 | # define GENERIC "files-XXX.c" 331 | #endif 332 | -------------------------------------------------------------------------------- /src/alloc_buffer.h: -------------------------------------------------------------------------------- 1 | /* Allocation from a fixed-size buffer. 2 | Copyright (C) 2017-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | /* Allocation buffers are used to carve out sub-allocations from a 20 | larger allocation. Their primary application is in writing NSS 21 | modules, which receive a caller-allocated buffer in which they are 22 | expected to store variable-length results: 23 | 24 | void *buffer = ...; 25 | size_t buffer_size = ...; 26 | 27 | struct alloc_buffer buf = alloc_buffer_create (buffer, buffer_size); 28 | result->gr_name = alloc_buffer_copy_string (&buf, name); 29 | 30 | // Allocate a list of group_count groups and copy strings into it. 31 | char **group_list = alloc_buffer_alloc_array 32 | (&buf, char *, group_count + 1); 33 | if (group_list == NULL) 34 | return ...; // Request a larger buffer. 35 | for (int i = 0; i < group_count; ++i) 36 | group_list[i] = alloc_buffer_copy_string (&buf, group_list_src[i]); 37 | group_list[group_count] = NULL; 38 | ... 39 | 40 | if (alloc_buffer_has_failed (&buf)) 41 | return ...; // Request a larger buffer. 42 | result->gr_mem = group_list; 43 | ... 44 | 45 | Note that it is not necessary to check the results of individual 46 | allocation operations if the returned pointer is not dereferenced. 47 | Allocation failure is sticky, so one check using 48 | alloc_buffer_has_failed at the end covers all previous failures. 49 | 50 | A different use case involves combining multiple heap allocations 51 | into a single, large one. In the following example, an array of 52 | doubles and an array of ints is allocated: 53 | 54 | size_t double_array_size = ...; 55 | size_t int_array_size = ...; 56 | 57 | void *heap_ptr; 58 | struct alloc_buffer buf = alloc_buffer_allocate 59 | (double_array_size * sizeof (double) + int_array_size * sizeof (int), 60 | &heap_ptr); 61 | _Static_assert (__alignof__ (double) >= __alignof__ (int), 62 | "no padding after double array"); 63 | double *double_array = alloc_buffer_alloc_array 64 | (&buf, double, double_array_size); 65 | int *int_array = alloc_buffer_alloc_array (&buf, int, int_array_size); 66 | if (alloc_buffer_has_failed (&buf)) 67 | return ...; // Report error. 68 | ... 69 | free (heap_ptr); 70 | 71 | The advantage over manual coding is that the computation of the 72 | allocation size does not need an overflow check. In case of an 73 | overflow, one of the subsequent allocations from the buffer will 74 | fail. The initial size computation is checked for consistency at 75 | run time, too. */ 76 | 77 | #ifndef _ALLOC_BUFFER_H 78 | #define _ALLOC_BUFFER_H 79 | 80 | #include 81 | #include 82 | #include 83 | #include 84 | #include 85 | 86 | /* struct alloc_buffer objects refer to a region of bytes in memory of a 87 | fixed size. The functions below can be used to allocate single 88 | objects and arrays from this memory region, or write to its end. 89 | On allocation failure (or if an attempt to write beyond the end of 90 | the buffer with one of the copy functions), the buffer enters a 91 | failed state. 92 | 93 | struct alloc_buffer objects can be copied. The backing buffer will 94 | be shared, but the current write position will be independent. 95 | 96 | Conceptually, the memory region consists of a current write pointer 97 | and a limit, beyond which the write pointer cannot move. */ 98 | struct alloc_buffer 99 | { 100 | /* uintptr_t is used here to simplify the alignment code, and to 101 | avoid issues undefined subtractions if the buffer covers more 102 | than half of the address space (which would result in differences 103 | which could not be represented as a ptrdiff_t value). */ 104 | uintptr_t __alloc_buffer_current; 105 | uintptr_t __alloc_buffer_end; 106 | }; 107 | 108 | enum 109 | { 110 | /* The value for the __alloc_buffer_current member which marks the 111 | buffer as invalid (together with a zero-length buffer). */ 112 | __ALLOC_BUFFER_INVALID_POINTER = 0, 113 | }; 114 | 115 | /* Internal function. Terminate the process using __libc_fatal. */ 116 | void __libc_alloc_buffer_create_failure (void *start, size_t size); 117 | #ifndef _ISOMAC 118 | libc_hidden_proto (__libc_alloc_buffer_create_failure) 119 | #endif 120 | 121 | /* Create a new allocation buffer. The byte range from START to START 122 | + SIZE - 1 must be valid, and the allocation buffer allocates 123 | objects from that range. If START is NULL (so that SIZE must be 124 | 0), the buffer is marked as failed immediately. */ 125 | static inline struct alloc_buffer 126 | alloc_buffer_create (void *start, size_t size) 127 | { 128 | uintptr_t current = (uintptr_t) start; 129 | uintptr_t end = (uintptr_t) start + size; 130 | if (end < current) 131 | __libc_alloc_buffer_create_failure (start, size); 132 | return (struct alloc_buffer) { current, end }; 133 | } 134 | 135 | /* Internal function. See alloc_buffer_allocate below. */ 136 | struct alloc_buffer __libc_alloc_buffer_allocate (size_t size, void **pptr) 137 | __attribute__ ((nonnull (2))); 138 | #ifndef _ISOMAC 139 | libc_hidden_proto (__libc_alloc_buffer_allocate) 140 | #endif 141 | 142 | /* Allocate a buffer of SIZE bytes using malloc. The returned buffer 143 | is in a failed state if malloc fails. *PPTR points to the start of 144 | the buffer and can be used to free it later, after the returned 145 | buffer has been freed. */ 146 | static __always_inline __attribute__ ((nonnull (2))) 147 | struct alloc_buffer alloc_buffer_allocate (size_t size, void **pptr) 148 | { 149 | return __libc_alloc_buffer_allocate (size, pptr); 150 | } 151 | 152 | /* Mark the buffer as failed. */ 153 | static inline void __attribute__ ((nonnull (1))) 154 | alloc_buffer_mark_failed (struct alloc_buffer *buf) 155 | { 156 | buf->__alloc_buffer_current = __ALLOC_BUFFER_INVALID_POINTER; 157 | buf->__alloc_buffer_end = __ALLOC_BUFFER_INVALID_POINTER; 158 | } 159 | 160 | /* Return the remaining number of bytes in the buffer. */ 161 | static __always_inline __attribute__ ((nonnull (1))) size_t 162 | alloc_buffer_size (const struct alloc_buffer *buf) 163 | { 164 | return buf->__alloc_buffer_end - buf->__alloc_buffer_current; 165 | } 166 | 167 | /* Return true if the buffer has been marked as failed. */ 168 | static inline bool __attribute__ ((nonnull (1))) 169 | alloc_buffer_has_failed (const struct alloc_buffer *buf) 170 | { 171 | return buf->__alloc_buffer_current == __ALLOC_BUFFER_INVALID_POINTER; 172 | } 173 | 174 | /* Add a single byte to the buffer (consuming the space for this 175 | byte). Mark the buffer as failed if there is not enough room. */ 176 | static inline void __attribute__ ((nonnull (1))) 177 | alloc_buffer_add_byte (struct alloc_buffer *buf, unsigned char b) 178 | { 179 | if (__glibc_likely (buf->__alloc_buffer_current < buf->__alloc_buffer_end)) 180 | { 181 | *(unsigned char *) buf->__alloc_buffer_current = b; 182 | ++buf->__alloc_buffer_current; 183 | } 184 | else 185 | alloc_buffer_mark_failed (buf); 186 | } 187 | 188 | /* Obtain a pointer to LENGTH bytes in BUF, and consume these bytes. 189 | NULL is returned if there is not enough room, and the buffer is 190 | marked as failed, or if the buffer has already failed. 191 | (Zero-length allocations from an empty buffer which has not yet 192 | failed succeed.) The buffer contents is not modified. */ 193 | static inline __attribute__ ((nonnull (1))) void * 194 | alloc_buffer_alloc_bytes (struct alloc_buffer *buf, size_t length) 195 | { 196 | if (length <= alloc_buffer_size (buf)) 197 | { 198 | void *result = (void *) buf->__alloc_buffer_current; 199 | buf->__alloc_buffer_current += length; 200 | return result; 201 | } 202 | else 203 | { 204 | alloc_buffer_mark_failed (buf); 205 | return NULL; 206 | } 207 | } 208 | 209 | /* Internal function. Statically assert that the type size is 210 | constant and valid. */ 211 | static __always_inline size_t 212 | __alloc_buffer_assert_size (size_t size) 213 | { 214 | if (!__builtin_constant_p (size)) 215 | { 216 | __errordecl (error, "type size is not constant"); 217 | error (); 218 | } 219 | else if (size == 0) 220 | { 221 | __errordecl (error, "type size is zero"); 222 | error (); 223 | } 224 | return size; 225 | } 226 | 227 | /* Internal function. Statically assert that the type alignment is 228 | constant and valid. */ 229 | static __always_inline size_t 230 | __alloc_buffer_assert_align (size_t align) 231 | { 232 | if (!__builtin_constant_p (align)) 233 | { 234 | __errordecl (error, "type alignment is not constant"); 235 | error (); 236 | } 237 | else if (align == 0) 238 | { 239 | __errordecl (error, "type alignment is zero"); 240 | error (); 241 | } 242 | else if (!powerof2 (align)) 243 | { 244 | __errordecl (error, "type alignment is not a power of two"); 245 | error (); 246 | } 247 | return align; 248 | } 249 | 250 | /* Internal function. Obtain a pointer to an object. */ 251 | static inline __attribute__ ((nonnull (1))) void * 252 | __alloc_buffer_alloc (struct alloc_buffer *buf, size_t size, size_t align) 253 | { 254 | if (size == 1 && align == 1) 255 | return alloc_buffer_alloc_bytes (buf, size); 256 | 257 | uintptr_t current = buf->__alloc_buffer_current; 258 | uintptr_t aligned = roundup (current, align); 259 | uintptr_t new_current = aligned + size; 260 | if (aligned >= current /* No overflow in align step. */ 261 | && new_current >= size /* No overflow in size computation. */ 262 | && new_current <= buf->__alloc_buffer_end) /* Room in buffer. */ 263 | { 264 | buf->__alloc_buffer_current = new_current; 265 | return (void *) aligned; 266 | } 267 | else 268 | { 269 | alloc_buffer_mark_failed (buf); 270 | return NULL; 271 | } 272 | } 273 | 274 | /* Obtain a TYPE * pointer to an object in BUF of TYPE. Consume these 275 | bytes from the buffer. Return NULL and mark the buffer as failed 276 | if there is not enough room in the buffer, or if the buffer has 277 | failed before. */ 278 | #define alloc_buffer_alloc(buf, type) \ 279 | ((type *) __alloc_buffer_alloc \ 280 | (buf, __alloc_buffer_assert_size (sizeof (type)), \ 281 | __alloc_buffer_assert_align (__alignof__ (type)))) 282 | 283 | /* Internal function. Obtain a pointer to an object which is 284 | subsequently added. */ 285 | static inline const __attribute__ ((nonnull (1))) void * 286 | __alloc_buffer_next (struct alloc_buffer *buf, size_t align) 287 | { 288 | if (align == 1) 289 | return (const void *) buf->__alloc_buffer_current; 290 | 291 | uintptr_t current = buf->__alloc_buffer_current; 292 | uintptr_t aligned = roundup (current, align); 293 | if (aligned >= current /* No overflow in align step. */ 294 | && aligned <= buf->__alloc_buffer_end) /* Room in buffer. */ 295 | { 296 | buf->__alloc_buffer_current = aligned; 297 | return (const void *) aligned; 298 | } 299 | else 300 | { 301 | alloc_buffer_mark_failed (buf); 302 | return NULL; 303 | } 304 | } 305 | 306 | /* Like alloc_buffer_alloc, but do not advance the pointer beyond the 307 | object (so a subsequent call to alloc_buffer_next or 308 | alloc_buffer_alloc returns the same pointer). Note that the buffer 309 | is still aligned according to the requirements of TYPE, potentially 310 | consuming buffer space. The effect of this function is similar to 311 | allocating a zero-length array from the buffer. 312 | 313 | It is possible to use the return pointer to write to the buffer and 314 | consume the written bytes using alloc_buffer_alloc_bytes (which 315 | does not change the buffer contents), but the calling code needs to 316 | perform manual length checks using alloc_buffer_size. For example, 317 | to read as many int32_t values that are available in the input file 318 | and can fit into the remaining buffer space, you can use this: 319 | 320 | int32_t array = alloc_buffer_next (buf, int32_t); 321 | size_t ret = fread (array, sizeof (int32_t), 322 | alloc_buffer_size (buf) / sizeof (int32_t), fp); 323 | if (ferror (fp)) 324 | handle_error (); 325 | alloc_buffer_alloc_array (buf, int32_t, ret); 326 | 327 | The alloc_buffer_alloc_array call makes the actually-used part of 328 | the buffer permanent. The remaining part of the buffer (not filled 329 | with data from the file) can be used for something else. 330 | 331 | This manual length checking can easily introduce errors, so this 332 | coding style is not recommended. */ 333 | #define alloc_buffer_next(buf, type) \ 334 | ((type *) __alloc_buffer_next \ 335 | (buf, __alloc_buffer_assert_align (__alignof__ (type)))) 336 | 337 | /* Internal function. Allocate an array. */ 338 | void * __libc_alloc_buffer_alloc_array (struct alloc_buffer *buf, 339 | size_t size, size_t align, 340 | size_t count) 341 | __attribute__ ((nonnull (1))); 342 | #ifndef _ISOMAC 343 | libc_hidden_proto (__libc_alloc_buffer_alloc_array) 344 | #endif 345 | 346 | /* Obtain a TYPE * pointer to an array of COUNT objects in BUF of 347 | TYPE. Consume these bytes from the buffer. Return NULL and mark 348 | the buffer as failed if there is not enough room in the buffer, 349 | or if the buffer has failed before. (Zero-length allocations from 350 | an empty buffer which has not yet failed succeed.) */ 351 | #define alloc_buffer_alloc_array(buf, type, count) \ 352 | ((type *) __libc_alloc_buffer_alloc_array \ 353 | (buf, __alloc_buffer_assert_size (sizeof (type)), \ 354 | __alloc_buffer_assert_align (__alignof__ (type)), \ 355 | count)) 356 | 357 | /* Internal function. See alloc_buffer_copy_bytes below. */ 358 | struct alloc_buffer __libc_alloc_buffer_copy_bytes (struct alloc_buffer, 359 | const void *, size_t) 360 | __attribute__ ((nonnull (2))); 361 | #ifndef _ISOMAC 362 | libc_hidden_proto (__libc_alloc_buffer_copy_bytes) 363 | #endif 364 | 365 | /* Copy SIZE bytes starting at SRC into the buffer. If there is not 366 | enough room in the buffer, the buffer is marked as failed. No 367 | alignment of the buffer is performed. */ 368 | static inline __attribute__ ((nonnull (1, 2))) void 369 | alloc_buffer_copy_bytes (struct alloc_buffer *buf, const void *src, size_t size) 370 | { 371 | *buf = __libc_alloc_buffer_copy_bytes (*buf, src, size); 372 | } 373 | 374 | /* Internal function. See alloc_buffer_copy_string below. */ 375 | struct alloc_buffer __libc_alloc_buffer_copy_string (struct alloc_buffer, 376 | const char *) 377 | __attribute__ ((nonnull (2))); 378 | #ifndef _ISOMAC 379 | libc_hidden_proto (__libc_alloc_buffer_copy_string) 380 | #endif 381 | 382 | /* Copy the string at SRC into the buffer, including its null 383 | terminator. If there is not enough room in the buffer, the buffer 384 | is marked as failed. Return a pointer to the string. */ 385 | static inline __attribute__ ((nonnull (1, 2))) char * 386 | alloc_buffer_copy_string (struct alloc_buffer *buf, const char *src) 387 | { 388 | char *result = (char *) buf->__alloc_buffer_current; 389 | *buf = __libc_alloc_buffer_copy_string (*buf, src); 390 | if (alloc_buffer_has_failed (buf)) 391 | result = NULL; 392 | return result; 393 | } 394 | 395 | #endif /* _ALLOC_BUFFER_H */ 396 | -------------------------------------------------------------------------------- /src/nss_altfiles/files-hosts.c: -------------------------------------------------------------------------------- 1 | /* Hosts file parser in nss_files module. 2 | Copyright (C) 1996-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | #include "../compat.h" 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include "../resolv/resolv-internal.h" 26 | #include "../scratch_buffer.h" 27 | #include "../alloc_buffer.h" 28 | #include 29 | 30 | /* Get implementation for some internal functions. */ 31 | #include "../resolv/mapv4v6addr.h" 32 | #include "../resolv/res_hconf.h" 33 | 34 | 35 | #define ENTNAME hostent 36 | #define DATABASE "hosts" 37 | #define NEED_H_ERRNO 38 | 39 | #define EXTRA_ARGS , af, flags 40 | #define EXTRA_ARGS_DECL , int af, int flags 41 | 42 | #define ENTDATA hostent_data 43 | struct hostent_data 44 | { 45 | unsigned char host_addr[16]; /* IPv4 or IPv6 address. */ 46 | char *h_addr_ptrs[2]; /* Points to that and null terminator. */ 47 | }; 48 | 49 | #define TRAILING_LIST_MEMBER h_aliases 50 | #define TRAILING_LIST_SEPARATOR_P isspace 51 | #include "files-parse.c" 52 | LINE_PARSER 53 | ("#", 54 | { 55 | char *addr; 56 | 57 | STRING_FIELD (addr, isspace, 1); 58 | 59 | /* Parse address. */ 60 | if (__inet_pton (af == AF_UNSPEC ? AF_INET : af, addr, entdata->host_addr) 61 | > 0) 62 | af = af == AF_UNSPEC ? AF_INET : af; 63 | else 64 | { 65 | if (af == AF_INET6 && (flags & AI_V4MAPPED) != 0 66 | && __inet_pton (AF_INET, addr, entdata->host_addr) > 0) 67 | map_v4v6_address ((char *) entdata->host_addr, 68 | (char *) entdata->host_addr); 69 | else if (af == AF_INET 70 | && __inet_pton (AF_INET6, addr, entdata->host_addr) > 0) 71 | { 72 | if (IN6_IS_ADDR_V4MAPPED (entdata->host_addr)) 73 | memcpy (entdata->host_addr, entdata->host_addr + 12, INADDRSZ); 74 | else if (IN6_IS_ADDR_LOOPBACK (entdata->host_addr)) 75 | { 76 | in_addr_t localhost = htonl (INADDR_LOOPBACK); 77 | memcpy (entdata->host_addr, &localhost, sizeof (localhost)); 78 | } 79 | else 80 | /* Illegal address: ignore line. */ 81 | return 0; 82 | } 83 | else if (af == AF_UNSPEC 84 | && __inet_pton (AF_INET6, addr, entdata->host_addr) > 0) 85 | af = AF_INET6; 86 | else 87 | /* Illegal address: ignore line. */ 88 | return 0; 89 | } 90 | 91 | /* We always return entries of the requested form. */ 92 | result->h_addrtype = af; 93 | result->h_length = af == AF_INET ? INADDRSZ : IN6ADDRSZ; 94 | 95 | /* Store a pointer to the address in the expected form. */ 96 | entdata->h_addr_ptrs[0] = (char *) entdata->host_addr; 97 | entdata->h_addr_ptrs[1] = NULL; 98 | result->h_addr_list = entdata->h_addr_ptrs; 99 | 100 | STRING_FIELD (result->h_name, isspace, 1); 101 | }) 102 | 103 | #define EXTRA_ARGS_VALUE , AF_INET, 0 104 | #include "files-XXX.c" 105 | #undef EXTRA_ARGS_VALUE 106 | 107 | /* We only need to consider IPv4 mapped addresses if the input to the 108 | gethostbyaddr() function is an IPv6 address. */ 109 | #define EXTRA_ARGS_VALUE \ 110 | , af, (len == IN6ADDRSZ ? AI_V4MAPPED : 0) 111 | DB_LOOKUP (hostbyaddr, ,,, 112 | { 113 | if (result->h_length == (int) len 114 | && ! memcmp (addr, result->h_addr_list[0], len)) 115 | break; 116 | }, const void *addr, socklen_t len, int af) 117 | #undef EXTRA_ARGS_VALUE 118 | 119 | /* Type of the address and alias arrays. */ 120 | #define DYNARRAY_STRUCT array 121 | #define DYNARRAY_ELEMENT char * 122 | #define DYNARRAY_PREFIX array_ 123 | #include "../dynarray-skeleton.c" 124 | 125 | static enum nss_status 126 | gethostbyname3_multi (FILE * stream, const char *name, int af, 127 | struct hostent *result, char *buffer, size_t buflen, 128 | int *errnop, int *herrnop) 129 | { 130 | assert (af == AF_INET || af == AF_INET6); 131 | 132 | /* We have to get all host entries from the file. */ 133 | struct scratch_buffer tmp_buffer; 134 | scratch_buffer_init (&tmp_buffer); 135 | struct hostent tmp_result_buf; 136 | struct array addresses; 137 | array_init (&addresses); 138 | struct array aliases; 139 | array_init (&aliases); 140 | enum nss_status status; 141 | 142 | /* Preserve the addresses and aliases encountered so far. */ 143 | for (size_t i = 0; result->h_addr_list[i] != NULL; ++i) 144 | array_add (&addresses, result->h_addr_list[i]); 145 | for (size_t i = 0; result->h_aliases[i] != NULL; ++i) 146 | array_add (&aliases, result->h_aliases[i]); 147 | 148 | /* The output buffer re-uses now-unused space at the end of the 149 | buffer, starting with the aliases array. It comes last in the 150 | data produced by internal_getent. (The alias names themselves 151 | are still located in the line read in internal_getent, which is 152 | stored at the beginning of the buffer.) */ 153 | struct alloc_buffer outbuf; 154 | { 155 | char *bufferend = (char *) result->h_aliases; 156 | outbuf = alloc_buffer_create (bufferend, buffer + buflen - bufferend); 157 | } 158 | 159 | while (true) 160 | { 161 | status = internal_getent (stream, &tmp_result_buf, tmp_buffer.data, 162 | tmp_buffer.length, errnop, herrnop, af, 0); 163 | /* Enlarge the buffer if necessary. */ 164 | if (status == NSS_STATUS_TRYAGAIN && *herrnop == NETDB_INTERNAL 165 | && *errnop == ERANGE) 166 | { 167 | if (!scratch_buffer_grow (&tmp_buffer)) 168 | { 169 | *errnop = ENOMEM; 170 | /* *herrnop and status already have the right value. */ 171 | break; 172 | } 173 | /* Loop around and retry with a larger buffer. */ 174 | } 175 | else if (status == NSS_STATUS_SUCCESS) 176 | { 177 | /* A line was read. Check that it matches the search 178 | criteria. */ 179 | 180 | int matches = 1; 181 | struct hostent *old_result = result; 182 | result = &tmp_result_buf; 183 | /* The following piece is a bit clumsy but we want to use 184 | the `LOOKUP_NAME_CASE' value. The optimizer should do 185 | its job. */ 186 | do 187 | { 188 | LOOKUP_NAME_CASE (h_name, h_aliases) 189 | result = old_result; 190 | } 191 | while ((matches = 0)); 192 | 193 | /* If the line matches, we need to copy the addresses and 194 | aliases, so that we can reuse tmp_buffer for the next 195 | line. */ 196 | if (matches) 197 | { 198 | /* Record the addresses. */ 199 | for (size_t i = 0; tmp_result_buf.h_addr_list[i] != NULL; ++i) 200 | { 201 | /* Allocate the target space in the output buffer, 202 | depending on the address family. */ 203 | void *target; 204 | if (af == AF_INET) 205 | { 206 | assert (tmp_result_buf.h_length == 4); 207 | target = alloc_buffer_alloc (&outbuf, struct in_addr); 208 | } 209 | else if (af == AF_INET6) 210 | { 211 | assert (tmp_result_buf.h_length == 16); 212 | target = alloc_buffer_alloc (&outbuf, struct in6_addr); 213 | } 214 | else 215 | __builtin_unreachable (); 216 | 217 | if (target == NULL) 218 | { 219 | /* Request a larger output buffer. */ 220 | *errnop = ERANGE; 221 | *herrnop = NETDB_INTERNAL; 222 | status = NSS_STATUS_TRYAGAIN; 223 | break; 224 | } 225 | memcpy (target, tmp_result_buf.h_addr_list[i], 226 | tmp_result_buf.h_length); 227 | array_add (&addresses, target); 228 | } 229 | 230 | /* Record the aliases. */ 231 | for (size_t i = 0; tmp_result_buf.h_aliases[i] != NULL; ++i) 232 | { 233 | char *alias = tmp_result_buf.h_aliases[i]; 234 | array_add (&aliases, 235 | alloc_buffer_copy_string (&outbuf, alias)); 236 | } 237 | 238 | /* If the real name is different add, it also to the 239 | aliases. This means that there is a duplication in 240 | the alias list but this is really the user's 241 | problem. */ 242 | { 243 | char *new_name = tmp_result_buf.h_name; 244 | if (strcmp (old_result->h_name, new_name) != 0) 245 | array_add (&aliases, 246 | alloc_buffer_copy_string (&outbuf, new_name)); 247 | } 248 | 249 | /* Report memory allocation failures during the 250 | expansion of the temporary arrays. */ 251 | if (array_has_failed (&addresses) || array_has_failed (&aliases)) 252 | { 253 | *errnop = ENOMEM; 254 | *herrnop = NETDB_INTERNAL; 255 | status = NSS_STATUS_UNAVAIL; 256 | break; 257 | } 258 | 259 | /* Request a larger output buffer if we ran out of room. */ 260 | if (alloc_buffer_has_failed (&outbuf)) 261 | { 262 | *errnop = ERANGE; 263 | *herrnop = NETDB_INTERNAL; 264 | status = NSS_STATUS_TRYAGAIN; 265 | break; 266 | } 267 | 268 | result = old_result; 269 | } /* If match was found. */ 270 | 271 | /* If no match is found, loop around and fetch another 272 | line. */ 273 | 274 | } /* status == NSS_STATUS_SUCCESS. */ 275 | else 276 | /* internal_getent returned an error. */ 277 | break; 278 | } /* while (true) */ 279 | 280 | /* Propagate the NSS_STATUS_TRYAGAIN error to the caller. It means 281 | that we may not have loaded the complete result. 282 | NSS_STATUS_NOTFOUND, however, means that we reached the end of 283 | the file successfully. */ 284 | if (status != NSS_STATUS_TRYAGAIN) 285 | status = NSS_STATUS_SUCCESS; 286 | 287 | if (status == NSS_STATUS_SUCCESS) 288 | { 289 | /* Copy the address and alias arrays into the output buffer and 290 | add NULL terminators. The pointed-to elements were directly 291 | written into the output buffer above and do not need to be 292 | copied again. */ 293 | size_t addresses_count = array_size (&addresses); 294 | size_t aliases_count = array_size (&aliases); 295 | char **out_addresses = alloc_buffer_alloc_array 296 | (&outbuf, char *, addresses_count + 1); 297 | char **out_aliases = alloc_buffer_alloc_array 298 | (&outbuf, char *, aliases_count + 1); 299 | if (out_addresses == NULL || out_aliases == NULL) 300 | { 301 | /* The output buffer is not large enough. */ 302 | *errnop = ERANGE; 303 | *herrnop = NETDB_INTERNAL; 304 | status = NSS_STATUS_TRYAGAIN; 305 | /* Fall through to function exit. */ 306 | } 307 | else 308 | { 309 | /* Everything is allocated in place. Make the copies and 310 | adjust the array pointers. */ 311 | memcpy (out_addresses, array_begin (&addresses), 312 | addresses_count * sizeof (char *)); 313 | out_addresses[addresses_count] = NULL; 314 | memcpy (out_aliases, array_begin (&aliases), 315 | aliases_count * sizeof (char *)); 316 | out_aliases[aliases_count] = NULL; 317 | 318 | result->h_addr_list = out_addresses; 319 | result->h_aliases = out_aliases; 320 | 321 | status = NSS_STATUS_SUCCESS; 322 | } 323 | } 324 | 325 | scratch_buffer_free (&tmp_buffer); 326 | array_free (&addresses); 327 | array_free (&aliases); 328 | return status; 329 | } 330 | 331 | enum nss_status 332 | _nss_files_gethostbyname3_r (const char *name, int af, struct hostent *result, 333 | char *buffer, size_t buflen, int *errnop, 334 | int *herrnop, int32_t *ttlp, char **canonp) 335 | { 336 | FILE *stream = NULL; 337 | uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct hostent_data); 338 | buffer += pad; 339 | buflen = buflen > pad ? buflen - pad : 0; 340 | 341 | /* Open file. */ 342 | enum nss_status status = internal_setent (&stream); 343 | 344 | if (status == NSS_STATUS_SUCCESS) 345 | { 346 | while ((status = internal_getent (stream, result, buffer, buflen, errnop, 347 | herrnop, af, 0)) 348 | == NSS_STATUS_SUCCESS) 349 | { 350 | LOOKUP_NAME_CASE (h_name, h_aliases) 351 | } 352 | 353 | if (status == NSS_STATUS_SUCCESS 354 | && _res_hconf.flags & HCONF_FLAG_MULTI) 355 | status = gethostbyname3_multi 356 | (stream, name, af, result, buffer, buflen, errnop, herrnop); 357 | 358 | fclose (stream); 359 | } 360 | 361 | if (canonp && status == NSS_STATUS_SUCCESS) 362 | *canonp = result->h_name; 363 | 364 | return status; 365 | } 366 | libc_hidden_def (_nss_files_gethostbyname3_r) 367 | 368 | enum nss_status 369 | _nss_files_gethostbyname_r (const char *name, struct hostent *result, 370 | char *buffer, size_t buflen, int *errnop, 371 | int *herrnop) 372 | { 373 | return _nss_files_gethostbyname3_r (name, AF_INET, result, buffer, buflen, 374 | errnop, herrnop, NULL, NULL); 375 | } 376 | libc_hidden_def (_nss_files_gethostbyname_r) 377 | 378 | enum nss_status 379 | _nss_files_gethostbyname2_r (const char *name, int af, struct hostent *result, 380 | char *buffer, size_t buflen, int *errnop, 381 | int *herrnop) 382 | { 383 | return _nss_files_gethostbyname3_r (name, af, result, buffer, buflen, 384 | errnop, herrnop, NULL, NULL); 385 | } 386 | libc_hidden_def (_nss_files_gethostbyname2_r) 387 | 388 | enum nss_status 389 | _nss_files_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, 390 | char *buffer, size_t buflen, int *errnop, 391 | int *herrnop, int32_t *ttlp) 392 | { 393 | FILE *stream = NULL; 394 | 395 | /* Open file. */ 396 | enum nss_status status = internal_setent (&stream); 397 | 398 | if (status == NSS_STATUS_SUCCESS) 399 | { 400 | bool any = false; 401 | bool got_canon = false; 402 | while (1) 403 | { 404 | /* Align the buffer for the next record. */ 405 | uintptr_t pad = (-(uintptr_t) buffer 406 | % __alignof__ (struct hostent_data)); 407 | buffer += pad; 408 | buflen = buflen > pad ? buflen - pad : 0; 409 | 410 | struct hostent result; 411 | status = internal_getent (stream, &result, buffer, buflen, errnop, 412 | herrnop, AF_UNSPEC, 0); 413 | if (status != NSS_STATUS_SUCCESS) 414 | break; 415 | 416 | int naliases = 0; 417 | if (__strcasecmp (name, result.h_name) != 0) 418 | { 419 | for (; result.h_aliases[naliases] != NULL; ++naliases) 420 | if (! __strcasecmp (name, result.h_aliases[naliases])) 421 | break; 422 | if (result.h_aliases[naliases] == NULL) 423 | continue; 424 | 425 | /* We know this alias exist. Count it. */ 426 | ++naliases; 427 | } 428 | 429 | /* Determine how much memory has been used so far. */ 430 | // XXX It is not necessary to preserve the aliases array 431 | while (result.h_aliases[naliases] != NULL) 432 | ++naliases; 433 | char *bufferend = (char *) &result.h_aliases[naliases + 1]; 434 | assert (buflen >= bufferend - buffer); 435 | buflen -= bufferend - buffer; 436 | buffer = bufferend; 437 | 438 | /* We found something. */ 439 | any = true; 440 | 441 | /* Create the record the caller expects. There is only one 442 | address. */ 443 | assert (result.h_addr_list[1] == NULL); 444 | if (*pat == NULL) 445 | { 446 | uintptr_t pad = (-(uintptr_t) buffer 447 | % __alignof__ (struct gaih_addrtuple)); 448 | buffer += pad; 449 | buflen = buflen > pad ? buflen - pad : 0; 450 | 451 | if (__builtin_expect (buflen < sizeof (struct gaih_addrtuple), 452 | 0)) 453 | { 454 | *errnop = ERANGE; 455 | *herrnop = NETDB_INTERNAL; 456 | status = NSS_STATUS_TRYAGAIN; 457 | break; 458 | } 459 | 460 | *pat = (struct gaih_addrtuple *) buffer; 461 | buffer += sizeof (struct gaih_addrtuple); 462 | buflen -= sizeof (struct gaih_addrtuple); 463 | } 464 | 465 | (*pat)->next = NULL; 466 | (*pat)->name = got_canon ? NULL : result.h_name; 467 | got_canon = true; 468 | (*pat)->family = result.h_addrtype; 469 | memcpy ((*pat)->addr, result.h_addr_list[0], result.h_length); 470 | (*pat)->scopeid = 0; 471 | 472 | pat = &((*pat)->next); 473 | 474 | /* If we only look for the first matching entry we are done. */ 475 | if ((_res_hconf.flags & HCONF_FLAG_MULTI) == 0) 476 | break; 477 | } 478 | 479 | /* If we have to look for multiple records and found one, this 480 | is a success. */ 481 | if (status == NSS_STATUS_NOTFOUND && any) 482 | { 483 | assert ((_res_hconf.flags & HCONF_FLAG_MULTI) != 0); 484 | status = NSS_STATUS_SUCCESS; 485 | } 486 | 487 | fclose (stream); 488 | } 489 | else if (status == NSS_STATUS_TRYAGAIN) 490 | { 491 | *errnop = errno; 492 | *herrnop = TRY_AGAIN; 493 | } 494 | else 495 | { 496 | *errnop = errno; 497 | *herrnop = NO_DATA; 498 | } 499 | 500 | return status; 501 | } 502 | libc_hidden_def (_nss_files_gethostbyname4_r) 503 | -------------------------------------------------------------------------------- /src/dynarray-skeleton.c: -------------------------------------------------------------------------------- 1 | /* Type-safe arrays which grow dynamically. 2 | Copyright (C) 2017-2024 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, see 17 | . */ 18 | 19 | /* Pre-processor macros which act as parameters: 20 | 21 | DYNARRAY_STRUCT 22 | The struct tag of dynamic array to be defined. 23 | DYNARRAY_ELEMENT 24 | The type name of the element type. Elements are copied 25 | as if by memcpy, and can change address as the dynamic 26 | array grows. 27 | DYNARRAY_PREFIX 28 | The prefix of the functions which are defined. 29 | 30 | The following parameters are optional: 31 | 32 | DYNARRAY_ELEMENT_FREE 33 | DYNARRAY_ELEMENT_FREE (E) is evaluated to deallocate the 34 | contents of elements. E is of type DYNARRAY_ELEMENT *. 35 | DYNARRAY_ELEMENT_INIT 36 | DYNARRAY_ELEMENT_INIT (E) is evaluated to initialize a new 37 | element. E is of type DYNARRAY_ELEMENT *. 38 | If DYNARRAY_ELEMENT_FREE but not DYNARRAY_ELEMENT_INIT is 39 | defined, new elements are automatically zero-initialized. 40 | Otherwise, new elements have undefined contents. 41 | DYNARRAY_INITIAL_SIZE 42 | The size of the statically allocated array (default: 43 | at least 2, more elements if they fit into 128 bytes). 44 | Must be a preprocessor constant. If DYNARRAY_INITIAL_SIZE is 0, 45 | there is no statically allocated array at, and all non-empty 46 | arrays are heap-allocated. 47 | DYNARRAY_FINAL_TYPE 48 | The name of the type which holds the final array. If not 49 | defined, is PREFIX##finalize not provided. DYNARRAY_FINAL_TYPE 50 | must be a struct type, with members of type DYNARRAY_ELEMENT and 51 | size_t at the start (in this order). 52 | 53 | These macros are undefined after this header file has been 54 | included. 55 | 56 | The following types are provided (their members are private to the 57 | dynarray implementation): 58 | 59 | struct DYNARRAY_STRUCT 60 | 61 | The following functions are provided: 62 | 63 | void DYNARRAY_PREFIX##init (struct DYNARRAY_STRUCT *); 64 | void DYNARRAY_PREFIX##free (struct DYNARRAY_STRUCT *); 65 | bool DYNARRAY_PREFIX##has_failed (const struct DYNARRAY_STRUCT *); 66 | void DYNARRAY_PREFIX##mark_failed (struct DYNARRAY_STRUCT *); 67 | size_t DYNARRAY_PREFIX##size (const struct DYNARRAY_STRUCT *); 68 | DYNARRAY_ELEMENT *DYNARRAY_PREFIX##begin (const struct DYNARRAY_STRUCT *); 69 | DYNARRAY_ELEMENT *DYNARRAY_PREFIX##end (const struct DYNARRAY_STRUCT *); 70 | DYNARRAY_ELEMENT *DYNARRAY_PREFIX##at (struct DYNARRAY_STRUCT *, size_t); 71 | void DYNARRAY_PREFIX##add (struct DYNARRAY_STRUCT *, DYNARRAY_ELEMENT); 72 | DYNARRAY_ELEMENT *DYNARRAY_PREFIX##emplace (struct DYNARRAY_STRUCT *); 73 | bool DYNARRAY_PREFIX##resize (struct DYNARRAY_STRUCT *, size_t); 74 | void DYNARRAY_PREFIX##remove_last (struct DYNARRAY_STRUCT *); 75 | void DYNARRAY_PREFIX##clear (struct DYNARRAY_STRUCT *); 76 | 77 | The following functions are provided are provided if the 78 | prerequisites are met: 79 | 80 | bool DYNARRAY_PREFIX##finalize (struct DYNARRAY_STRUCT *, 81 | DYNARRAY_FINAL_TYPE *); 82 | (if DYNARRAY_FINAL_TYPE is defined) 83 | DYNARRAY_ELEMENT *DYNARRAY_PREFIX##finalize (struct DYNARRAY_STRUCT *, 84 | size_t *); 85 | (if DYNARRAY_FINAL_TYPE is not defined) 86 | */ 87 | 88 | #include "dynarray.h" 89 | 90 | #include 91 | #include 92 | #include 93 | 94 | #ifndef DYNARRAY_STRUCT 95 | # error "DYNARRAY_STRUCT must be defined" 96 | #endif 97 | 98 | #ifndef DYNARRAY_ELEMENT 99 | # error "DYNARRAY_ELEMENT must be defined" 100 | #endif 101 | 102 | #ifndef DYNARRAY_PREFIX 103 | # error "DYNARRAY_PREFIX must be defined" 104 | #endif 105 | 106 | #ifdef DYNARRAY_INITIAL_SIZE 107 | # if DYNARRAY_INITIAL_SIZE < 0 108 | # error "DYNARRAY_INITIAL_SIZE must be non-negative" 109 | # endif 110 | # if DYNARRAY_INITIAL_SIZE > 0 111 | # define DYNARRAY_HAVE_SCRATCH 1 112 | # else 113 | # define DYNARRAY_HAVE_SCRATCH 0 114 | # endif 115 | #else 116 | /* Provide a reasonable default which limits the size of 117 | DYNARRAY_STRUCT. */ 118 | # define DYNARRAY_INITIAL_SIZE \ 119 | (sizeof (DYNARRAY_ELEMENT) > 64 ? 2 : 128 / sizeof (DYNARRAY_ELEMENT)) 120 | # define DYNARRAY_HAVE_SCRATCH 1 121 | #endif 122 | 123 | /* Public type definitions. */ 124 | 125 | /* All fields of this struct are private to the implementation. */ 126 | struct DYNARRAY_STRUCT 127 | { 128 | union 129 | { 130 | struct dynarray_header dynarray_abstract; 131 | struct 132 | { 133 | /* These fields must match struct dynarray_header. */ 134 | size_t used; 135 | size_t allocated; 136 | DYNARRAY_ELEMENT *array; 137 | } dynarray_header; 138 | } u; 139 | 140 | #if DYNARRAY_HAVE_SCRATCH 141 | /* Initial inline allocation. */ 142 | DYNARRAY_ELEMENT scratch[DYNARRAY_INITIAL_SIZE]; 143 | #endif 144 | }; 145 | 146 | /* Internal use only: Helper macros. */ 147 | 148 | /* Ensure macro-expansion of DYNARRAY_PREFIX. */ 149 | #define DYNARRAY_CONCAT0(prefix, name) prefix##name 150 | #define DYNARRAY_CONCAT1(prefix, name) DYNARRAY_CONCAT0(prefix, name) 151 | #define DYNARRAY_NAME(name) DYNARRAY_CONCAT1(DYNARRAY_PREFIX, name) 152 | 153 | /* Use DYNARRAY_FREE instead of DYNARRAY_NAME (free), 154 | so that Gnulib does not change 'free' to 'rpl_free'. */ 155 | #define DYNARRAY_FREE DYNARRAY_CONCAT1 (DYNARRAY_NAME (f), ree) 156 | 157 | /* Address of the scratch buffer if any. */ 158 | #if DYNARRAY_HAVE_SCRATCH 159 | # define DYNARRAY_SCRATCH(list) (list)->scratch 160 | #else 161 | # define DYNARRAY_SCRATCH(list) NULL 162 | #endif 163 | 164 | /* Internal use only: Helper functions. */ 165 | 166 | /* Internal function. Call DYNARRAY_ELEMENT_FREE with the array 167 | elements. Name mangling needed due to the DYNARRAY_ELEMENT_FREE 168 | macro expansion. */ 169 | static inline void 170 | DYNARRAY_NAME (free__elements__) (DYNARRAY_ELEMENT *__dynarray_array, 171 | size_t __dynarray_used) 172 | { 173 | #ifdef DYNARRAY_ELEMENT_FREE 174 | for (size_t __dynarray_i = 0; __dynarray_i < __dynarray_used; ++__dynarray_i) 175 | DYNARRAY_ELEMENT_FREE (&__dynarray_array[__dynarray_i]); 176 | #endif /* DYNARRAY_ELEMENT_FREE */ 177 | } 178 | 179 | /* Internal function. Free the non-scratch array allocation. */ 180 | static inline void 181 | DYNARRAY_NAME (free__array__) (struct DYNARRAY_STRUCT *list) 182 | { 183 | #if DYNARRAY_HAVE_SCRATCH 184 | if (list->u.dynarray_header.array != list->scratch) 185 | free (list->u.dynarray_header.array); 186 | #else 187 | free (list->u.dynarray_header.array); 188 | #endif 189 | } 190 | 191 | /* Public functions. */ 192 | 193 | /* Initialize a dynamic array object. This must be called before any 194 | use of the object. */ 195 | __nonnull ((1)) 196 | static void 197 | DYNARRAY_NAME (init) (struct DYNARRAY_STRUCT *list) 198 | { 199 | list->u.dynarray_header.used = 0; 200 | list->u.dynarray_header.allocated = DYNARRAY_INITIAL_SIZE; 201 | list->u.dynarray_header.array = DYNARRAY_SCRATCH (list); 202 | } 203 | 204 | /* Deallocate the dynamic array and its elements. */ 205 | __attribute_maybe_unused__ __nonnull ((1)) 206 | static void 207 | DYNARRAY_FREE (struct DYNARRAY_STRUCT *list) 208 | { 209 | DYNARRAY_NAME (free__elements__) 210 | (list->u.dynarray_header.array, list->u.dynarray_header.used); 211 | DYNARRAY_NAME (free__array__) (list); 212 | DYNARRAY_NAME (init) (list); 213 | } 214 | 215 | /* Return true if the dynamic array is in an error state. */ 216 | __nonnull ((1)) 217 | static inline bool 218 | DYNARRAY_NAME (has_failed) (const struct DYNARRAY_STRUCT *list) 219 | { 220 | return list->u.dynarray_header.allocated == __dynarray_error_marker (); 221 | } 222 | 223 | /* Mark the dynamic array as failed. All elements are deallocated as 224 | a side effect. */ 225 | __nonnull ((1)) 226 | static void 227 | DYNARRAY_NAME (mark_failed) (struct DYNARRAY_STRUCT *list) 228 | { 229 | DYNARRAY_NAME (free__elements__) 230 | (list->u.dynarray_header.array, list->u.dynarray_header.used); 231 | DYNARRAY_NAME (free__array__) (list); 232 | list->u.dynarray_header.array = DYNARRAY_SCRATCH (list); 233 | list->u.dynarray_header.used = 0; 234 | list->u.dynarray_header.allocated = __dynarray_error_marker (); 235 | } 236 | 237 | /* Return the number of elements which have been added to the dynamic 238 | array. */ 239 | __nonnull ((1)) 240 | static inline size_t 241 | DYNARRAY_NAME (size) (const struct DYNARRAY_STRUCT *list) 242 | { 243 | return list->u.dynarray_header.used; 244 | } 245 | 246 | /* Return a pointer to the array element at INDEX. Terminate the 247 | process if INDEX is out of bounds. */ 248 | __nonnull ((1)) 249 | static inline DYNARRAY_ELEMENT * 250 | DYNARRAY_NAME (at) (struct DYNARRAY_STRUCT *list, size_t index) 251 | { 252 | if (__glibc_unlikely (index >= DYNARRAY_NAME (size) (list))) 253 | __libc_dynarray_at_failure (DYNARRAY_NAME (size) (list), index); 254 | return list->u.dynarray_header.array + index; 255 | } 256 | 257 | /* Return a pointer to the first array element, if any. For a 258 | zero-length array, the pointer can be NULL even though the dynamic 259 | array has not entered the failure state. */ 260 | __nonnull ((1)) 261 | static inline DYNARRAY_ELEMENT * 262 | DYNARRAY_NAME (begin) (struct DYNARRAY_STRUCT *list) 263 | { 264 | return list->u.dynarray_header.array; 265 | } 266 | 267 | /* Return a pointer one element past the last array element. For a 268 | zero-length array, the pointer can be NULL even though the dynamic 269 | array has not entered the failure state. */ 270 | __nonnull ((1)) 271 | static inline DYNARRAY_ELEMENT * 272 | DYNARRAY_NAME (end) (struct DYNARRAY_STRUCT *list) 273 | { 274 | return list->u.dynarray_header.array + list->u.dynarray_header.used; 275 | } 276 | 277 | /* Internal function. Slow path for the add function below. */ 278 | static void 279 | DYNARRAY_NAME (add__) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item) 280 | { 281 | if (__glibc_unlikely 282 | (!__libc_dynarray_emplace_enlarge (&list->u.dynarray_abstract, 283 | DYNARRAY_SCRATCH (list), 284 | sizeof (DYNARRAY_ELEMENT)))) 285 | { 286 | DYNARRAY_NAME (mark_failed) (list); 287 | return; 288 | } 289 | 290 | /* Copy the new element and increase the array length. */ 291 | list->u.dynarray_header.array[list->u.dynarray_header.used++] = item; 292 | } 293 | 294 | /* Add ITEM at the end of the array, enlarging it by one element. 295 | Mark *LIST as failed if the dynamic array allocation size cannot be 296 | increased. */ 297 | __nonnull ((1)) 298 | static inline void 299 | DYNARRAY_NAME (add) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item) 300 | { 301 | /* Do nothing in case of previous error. */ 302 | if (DYNARRAY_NAME (has_failed) (list)) 303 | return; 304 | 305 | /* Enlarge the array if necessary. */ 306 | if (__glibc_unlikely (list->u.dynarray_header.used 307 | == list->u.dynarray_header.allocated)) 308 | { 309 | DYNARRAY_NAME (add__) (list, item); 310 | return; 311 | } 312 | 313 | /* Copy the new element and increase the array length. */ 314 | list->u.dynarray_header.array[list->u.dynarray_header.used++] = item; 315 | } 316 | 317 | /* Internal function. Building block for the emplace functions below. 318 | Assumes space for one more element in *LIST. */ 319 | static inline DYNARRAY_ELEMENT * 320 | DYNARRAY_NAME (emplace__tail__) (struct DYNARRAY_STRUCT *list) 321 | { 322 | DYNARRAY_ELEMENT *result 323 | = &list->u.dynarray_header.array[list->u.dynarray_header.used]; 324 | ++list->u.dynarray_header.used; 325 | #if defined (DYNARRAY_ELEMENT_INIT) 326 | DYNARRAY_ELEMENT_INIT (result); 327 | #elif defined (DYNARRAY_ELEMENT_FREE) 328 | memset (result, 0, sizeof (*result)); 329 | #endif 330 | return result; 331 | } 332 | 333 | /* Internal function. Slow path for the emplace function below. */ 334 | static DYNARRAY_ELEMENT * 335 | DYNARRAY_NAME (emplace__) (struct DYNARRAY_STRUCT *list) 336 | { 337 | if (__glibc_unlikely 338 | (!__libc_dynarray_emplace_enlarge (&list->u.dynarray_abstract, 339 | DYNARRAY_SCRATCH (list), 340 | sizeof (DYNARRAY_ELEMENT)))) 341 | { 342 | DYNARRAY_NAME (mark_failed) (list); 343 | return NULL; 344 | } 345 | return DYNARRAY_NAME (emplace__tail__) (list); 346 | } 347 | 348 | /* Allocate a place for a new element in *LIST and return a pointer to 349 | it. The pointer can be NULL if the dynamic array cannot be 350 | enlarged due to a memory allocation failure. */ 351 | __attribute_maybe_unused__ __attribute_warn_unused_result__ __nonnull ((1)) 352 | static 353 | /* Avoid inlining with the larger initialization code. */ 354 | #if !(defined (DYNARRAY_ELEMENT_INIT) || defined (DYNARRAY_ELEMENT_FREE)) 355 | inline 356 | #endif 357 | DYNARRAY_ELEMENT * 358 | DYNARRAY_NAME (emplace) (struct DYNARRAY_STRUCT *list) 359 | { 360 | /* Do nothing in case of previous error. */ 361 | if (DYNARRAY_NAME (has_failed) (list)) 362 | return NULL; 363 | 364 | /* Enlarge the array if necessary. */ 365 | if (__glibc_unlikely (list->u.dynarray_header.used 366 | == list->u.dynarray_header.allocated)) 367 | return (DYNARRAY_NAME (emplace__) (list)); 368 | return DYNARRAY_NAME (emplace__tail__) (list); 369 | } 370 | 371 | /* Change the size of *LIST to SIZE. If SIZE is larger than the 372 | existing size, new elements are added (which can be initialized). 373 | Otherwise, the list is truncated, and elements are freed. Return 374 | false on memory allocation failure (and mark *LIST as failed). */ 375 | __attribute_maybe_unused__ __nonnull ((1)) 376 | static bool 377 | DYNARRAY_NAME (resize) (struct DYNARRAY_STRUCT *list, size_t size) 378 | { 379 | if (size > list->u.dynarray_header.used) 380 | { 381 | bool ok; 382 | #if defined (DYNARRAY_ELEMENT_INIT) 383 | /* The new elements have to be initialized. */ 384 | size_t old_size = list->u.dynarray_header.used; 385 | ok = __libc_dynarray_resize (&list->u.dynarray_abstract, 386 | size, DYNARRAY_SCRATCH (list), 387 | sizeof (DYNARRAY_ELEMENT)); 388 | if (ok) 389 | for (size_t i = old_size; i < size; ++i) 390 | { 391 | DYNARRAY_ELEMENT_INIT (&list->u.dynarray_header.array[i]); 392 | } 393 | #elif defined (DYNARRAY_ELEMENT_FREE) 394 | /* Zero initialization is needed so that the elements can be 395 | safely freed. */ 396 | ok = __libc_dynarray_resize_clear 397 | (&list->u.dynarray_abstract, size, 398 | DYNARRAY_SCRATCH (list), sizeof (DYNARRAY_ELEMENT)); 399 | #else 400 | ok = __libc_dynarray_resize (&list->u.dynarray_abstract, 401 | size, DYNARRAY_SCRATCH (list), 402 | sizeof (DYNARRAY_ELEMENT)); 403 | #endif 404 | if (__glibc_unlikely (!ok)) 405 | DYNARRAY_NAME (mark_failed) (list); 406 | return ok; 407 | } 408 | else 409 | { 410 | /* The list has shrunk in size. Free the removed elements. */ 411 | DYNARRAY_NAME (free__elements__) 412 | (list->u.dynarray_header.array + size, 413 | list->u.dynarray_header.used - size); 414 | list->u.dynarray_header.used = size; 415 | return true; 416 | } 417 | } 418 | 419 | /* Remove the last element of LIST if it is present. */ 420 | __attribute_maybe_unused__ __nonnull ((1)) 421 | static void 422 | DYNARRAY_NAME (remove_last) (struct DYNARRAY_STRUCT *list) 423 | { 424 | /* used > 0 implies that the array is the non-failed state. */ 425 | if (list->u.dynarray_header.used > 0) 426 | { 427 | size_t new_length = list->u.dynarray_header.used - 1; 428 | #ifdef DYNARRAY_ELEMENT_FREE 429 | DYNARRAY_ELEMENT_FREE (&list->u.dynarray_header.array[new_length]); 430 | #endif 431 | list->u.dynarray_header.used = new_length; 432 | } 433 | } 434 | 435 | /* Remove all elements from the list. The elements are freed, but the 436 | list itself is not. */ 437 | __attribute_maybe_unused__ __nonnull ((1)) 438 | static void 439 | DYNARRAY_NAME (clear) (struct DYNARRAY_STRUCT *list) 440 | { 441 | /* free__elements__ does nothing if the list is in the failed 442 | state. */ 443 | DYNARRAY_NAME (free__elements__) 444 | (list->u.dynarray_header.array, list->u.dynarray_header.used); 445 | list->u.dynarray_header.used = 0; 446 | } 447 | 448 | #ifdef DYNARRAY_FINAL_TYPE 449 | /* Transfer the dynamic array to a permanent location at *RESULT. 450 | Returns true on success on false on allocation failure. In either 451 | case, *LIST is re-initialized and can be reused. A NULL pointer is 452 | stored in *RESULT if LIST refers to an empty list. On success, the 453 | pointer in *RESULT is heap-allocated and must be deallocated using 454 | free. */ 455 | __attribute_maybe_unused__ __attribute_warn_unused_result__ __nonnull ((1, 2)) 456 | static bool 457 | DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list, 458 | DYNARRAY_FINAL_TYPE *result) 459 | { 460 | struct dynarray_finalize_result res; 461 | if (__libc_dynarray_finalize (&list->u.dynarray_abstract, 462 | DYNARRAY_SCRATCH (list), 463 | sizeof (DYNARRAY_ELEMENT), &res)) 464 | { 465 | /* On success, the result owns all the data. */ 466 | DYNARRAY_NAME (init) (list); 467 | *result = (DYNARRAY_FINAL_TYPE) { res.array, res.length }; 468 | return true; 469 | } 470 | else 471 | { 472 | /* On error, we need to free all data. */ 473 | DYNARRAY_FREE (list); 474 | errno = ENOMEM; 475 | return false; 476 | } 477 | } 478 | #else /* !DYNARRAY_FINAL_TYPE */ 479 | /* Transfer the dynamic array to a heap-allocated array and return a 480 | pointer to it. The pointer is NULL if memory allocation fails, or 481 | if the array is empty, so this function should be used only for 482 | arrays which are known not be empty (usually because they always 483 | have a sentinel at the end). If LENGTHP is not NULL, the array 484 | length is written to *LENGTHP. *LIST is re-initialized and can be 485 | reused. */ 486 | __attribute_maybe_unused__ __attribute_warn_unused_result__ __nonnull ((1)) 487 | static DYNARRAY_ELEMENT * 488 | DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list, size_t *lengthp) 489 | { 490 | struct dynarray_finalize_result res; 491 | if (__libc_dynarray_finalize (&list->u.dynarray_abstract, 492 | DYNARRAY_SCRATCH (list), 493 | sizeof (DYNARRAY_ELEMENT), &res)) 494 | { 495 | /* On success, the result owns all the data. */ 496 | DYNARRAY_NAME (init) (list); 497 | if (lengthp != NULL) 498 | *lengthp = res.length; 499 | return res.array; 500 | } 501 | else 502 | { 503 | /* On error, we need to free all data. */ 504 | DYNARRAY_FREE (list); 505 | errno = ENOMEM; 506 | return NULL; 507 | } 508 | } 509 | #endif /* !DYNARRAY_FINAL_TYPE */ 510 | 511 | /* Undo macro definitions. */ 512 | 513 | #undef DYNARRAY_CONCAT0 514 | #undef DYNARRAY_CONCAT1 515 | #undef DYNARRAY_NAME 516 | #undef DYNARRAY_SCRATCH 517 | #undef DYNARRAY_HAVE_SCRATCH 518 | 519 | #undef DYNARRAY_STRUCT 520 | #undef DYNARRAY_ELEMENT 521 | #undef DYNARRAY_PREFIX 522 | #undef DYNARRAY_ELEMENT_FREE 523 | #undef DYNARRAY_ELEMENT_INIT 524 | #undef DYNARRAY_INITIAL_SIZE 525 | #undef DYNARRAY_FINAL_TYPE 526 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | 2 | GNU LESSER GENERAL PUBLIC LICENSE 3 | Version 2.1, February 1999 4 | 5 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 6 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 7 | Everyone is permitted to copy and distribute verbatim copies 8 | of this license document, but changing it is not allowed. 9 | 10 | [This is the first released version of the Lesser GPL. It also counts 11 | as the successor of the GNU Library Public License, version 2, hence 12 | the version number 2.1.] 13 | 14 | Preamble 15 | 16 | The licenses for most software are designed to take away your 17 | freedom to share and change it. By contrast, the GNU General Public 18 | Licenses are intended to guarantee your freedom to share and change 19 | free software--to make sure the software is free for all its users. 20 | 21 | This license, the Lesser General Public License, applies to some 22 | specially designated software packages--typically libraries--of the 23 | Free Software Foundation and other authors who decide to use it. You 24 | can use it too, but we suggest you first think carefully about whether 25 | this license or the ordinary General Public License is the better 26 | strategy to use in any particular case, based on the explanations below. 27 | 28 | When we speak of free software, we are referring to freedom of use, 29 | not price. Our General Public Licenses are designed to make sure that 30 | you have the freedom to distribute copies of free software (and charge 31 | for this service if you wish); that you receive source code or can get 32 | it if you want it; that you can change the software and use pieces of 33 | it in new free programs; and that you are informed that you can do 34 | these things. 35 | 36 | To protect your rights, we need to make restrictions that forbid 37 | distributors to deny you these rights or to ask you to surrender these 38 | rights. These restrictions translate to certain responsibilities for 39 | you if you distribute copies of the library or if you modify it. 40 | 41 | For example, if you distribute copies of the library, whether gratis 42 | or for a fee, you must give the recipients all the rights that we gave 43 | you. You must make sure that they, too, receive or can get the source 44 | code. If you link other code with the library, you must provide 45 | complete object files to the recipients, so that they can relink them 46 | with the library after making changes to the library and recompiling 47 | it. And you must show them these terms so they know their rights. 48 | 49 | We protect your rights with a two-step method: (1) we copyright the 50 | library, and (2) we offer you this license, which gives you legal 51 | permission to copy, distribute and/or modify the library. 52 | 53 | To protect each distributor, we want to make it very clear that 54 | there is no warranty for the free library. Also, if the library is 55 | modified by someone else and passed on, the recipients should know 56 | that what they have is not the original version, so that the original 57 | author's reputation will not be affected by problems that might be 58 | introduced by others. 59 | 60 | Finally, software patents pose a constant threat to the existence of 61 | any free program. We wish to make sure that a company cannot 62 | effectively restrict the users of a free program by obtaining a 63 | restrictive license from a patent holder. Therefore, we insist that 64 | any patent license obtained for a version of the library must be 65 | consistent with the full freedom of use specified in this license. 66 | 67 | Most GNU software, including some libraries, is covered by the 68 | ordinary GNU General Public License. This license, the GNU Lesser 69 | General Public License, applies to certain designated libraries, and 70 | is quite different from the ordinary General Public License. We use 71 | this license for certain libraries in order to permit linking those 72 | libraries into non-free programs. 73 | 74 | When a program is linked with a library, whether statically or using 75 | a shared library, the combination of the two is legally speaking a 76 | combined work, a derivative of the original library. The ordinary 77 | General Public License therefore permits such linking only if the 78 | entire combination fits its criteria of freedom. The Lesser General 79 | Public License permits more lax criteria for linking other code with 80 | the library. 81 | 82 | We call this license the "Lesser" General Public License because it 83 | does Less to protect the user's freedom than the ordinary General 84 | Public License. It also provides other free software developers Less 85 | of an advantage over competing non-free programs. These disadvantages 86 | are the reason we use the ordinary General Public License for many 87 | libraries. However, the Lesser license provides advantages in certain 88 | special circumstances. 89 | 90 | For example, on rare occasions, there may be a special need to 91 | encourage the widest possible use of a certain library, so that it becomes 92 | a de-facto standard. To achieve this, non-free programs must be 93 | allowed to use the library. A more frequent case is that a free 94 | library does the same job as widely used non-free libraries. In this 95 | case, there is little to gain by limiting the free library to free 96 | software only, so we use the Lesser General Public License. 97 | 98 | In other cases, permission to use a particular library in non-free 99 | programs enables a greater number of people to use a large body of 100 | free software. For example, permission to use the GNU C Library in 101 | non-free programs enables many more people to use the whole GNU 102 | operating system, as well as its variant, the GNU/Linux operating 103 | system. 104 | 105 | Although the Lesser General Public License is Less protective of the 106 | users' freedom, it does ensure that the user of a program that is 107 | linked with the Library has the freedom and the wherewithal to run 108 | that program using a modified version of the Library. 109 | 110 | The precise terms and conditions for copying, distribution and 111 | modification follow. Pay close attention to the difference between a 112 | "work based on the library" and a "work that uses the library". The 113 | former contains code derived from the library, whereas the latter must 114 | be combined with the library in order to run. 115 | 116 | GNU LESSER GENERAL PUBLIC LICENSE 117 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 118 | 119 | 0. This License Agreement applies to any software library or other 120 | program which contains a notice placed by the copyright holder or 121 | other authorized party saying it may be distributed under the terms of 122 | this Lesser General Public License (also called "this License"). 123 | Each licensee is addressed as "you". 124 | 125 | A "library" means a collection of software functions and/or data 126 | prepared so as to be conveniently linked with application programs 127 | (which use some of those functions and data) to form executables. 128 | 129 | The "Library", below, refers to any such software library or work 130 | which has been distributed under these terms. A "work based on the 131 | Library" means either the Library or any derivative work under 132 | copyright law: that is to say, a work containing the Library or a 133 | portion of it, either verbatim or with modifications and/or translated 134 | straightforwardly into another language. (Hereinafter, translation is 135 | included without limitation in the term "modification".) 136 | 137 | "Source code" for a work means the preferred form of the work for 138 | making modifications to it. For a library, complete source code means 139 | all the source code for all modules it contains, plus any associated 140 | interface definition files, plus the scripts used to control compilation 141 | and installation of the library. 142 | 143 | Activities other than copying, distribution and modification are not 144 | covered by this License; they are outside its scope. The act of 145 | running a program using the Library is not restricted, and output from 146 | such a program is covered only if its contents constitute a work based 147 | on the Library (independent of the use of the Library in a tool for 148 | writing it). Whether that is true depends on what the Library does 149 | and what the program that uses the Library does. 150 | 151 | 1. You may copy and distribute verbatim copies of the Library's 152 | complete source code as you receive it, in any medium, provided that 153 | you conspicuously and appropriately publish on each copy an 154 | appropriate copyright notice and disclaimer of warranty; keep intact 155 | all the notices that refer to this License and to the absence of any 156 | warranty; and distribute a copy of this License along with the 157 | Library. 158 | 159 | You may charge a fee for the physical act of transferring a copy, 160 | and you may at your option offer warranty protection in exchange for a 161 | fee. 162 | 163 | 2. You may modify your copy or copies of the Library or any portion 164 | of it, thus forming a work based on the Library, and copy and 165 | distribute such modifications or work under the terms of Section 1 166 | above, provided that you also meet all of these conditions: 167 | 168 | a) The modified work must itself be a software library. 169 | 170 | b) You must cause the files modified to carry prominent notices 171 | stating that you changed the files and the date of any change. 172 | 173 | c) You must cause the whole of the work to be licensed at no 174 | charge to all third parties under the terms of this License. 175 | 176 | d) If a facility in the modified Library refers to a function or a 177 | table of data to be supplied by an application program that uses 178 | the facility, other than as an argument passed when the facility 179 | is invoked, then you must make a good faith effort to ensure that, 180 | in the event an application does not supply such function or 181 | table, the facility still operates, and performs whatever part of 182 | its purpose remains meaningful. 183 | 184 | (For example, a function in a library to compute square roots has 185 | a purpose that is entirely well-defined independent of the 186 | application. Therefore, Subsection 2d requires that any 187 | application-supplied function or table used by this function must 188 | be optional: if the application does not supply it, the square 189 | root function must still compute square roots.) 190 | 191 | These requirements apply to the modified work as a whole. If 192 | identifiable sections of that work are not derived from the Library, 193 | and can be reasonably considered independent and separate works in 194 | themselves, then this License, and its terms, do not apply to those 195 | sections when you distribute them as separate works. But when you 196 | distribute the same sections as part of a whole which is a work based 197 | on the Library, the distribution of the whole must be on the terms of 198 | this License, whose permissions for other licensees extend to the 199 | entire whole, and thus to each and every part regardless of who wrote 200 | it. 201 | 202 | Thus, it is not the intent of this section to claim rights or contest 203 | your rights to work written entirely by you; rather, the intent is to 204 | exercise the right to control the distribution of derivative or 205 | collective works based on the Library. 206 | 207 | In addition, mere aggregation of another work not based on the Library 208 | with the Library (or with a work based on the Library) on a volume of 209 | a storage or distribution medium does not bring the other work under 210 | the scope of this License. 211 | 212 | 3. You may opt to apply the terms of the ordinary GNU General Public 213 | License instead of this License to a given copy of the Library. To do 214 | this, you must alter all the notices that refer to this License, so 215 | that they refer to the ordinary GNU General Public License, version 2, 216 | instead of to this License. (If a newer version than version 2 of the 217 | ordinary GNU General Public License has appeared, then you can specify 218 | that version instead if you wish.) Do not make any other change in 219 | these notices. 220 | 221 | Once this change is made in a given copy, it is irreversible for 222 | that copy, so the ordinary GNU General Public License applies to all 223 | subsequent copies and derivative works made from that copy. 224 | 225 | This option is useful when you wish to copy part of the code of 226 | the Library into a program that is not a library. 227 | 228 | 4. You may copy and distribute the Library (or a portion or 229 | derivative of it, under Section 2) in object code or executable form 230 | under the terms of Sections 1 and 2 above provided that you accompany 231 | it with the complete corresponding machine-readable source code, which 232 | must be distributed under the terms of Sections 1 and 2 above on a 233 | medium customarily used for software interchange. 234 | 235 | If distribution of object code is made by offering access to copy 236 | from a designated place, then offering equivalent access to copy the 237 | source code from the same place satisfies the requirement to 238 | distribute the source code, even though third parties are not 239 | compelled to copy the source along with the object code. 240 | 241 | 5. A program that contains no derivative of any portion of the 242 | Library, but is designed to work with the Library by being compiled or 243 | linked with it, is called a "work that uses the Library". Such a 244 | work, in isolation, is not a derivative work of the Library, and 245 | therefore falls outside the scope of this License. 246 | 247 | However, linking a "work that uses the Library" with the Library 248 | creates an executable that is a derivative of the Library (because it 249 | contains portions of the Library), rather than a "work that uses the 250 | library". The executable is therefore covered by this License. 251 | Section 6 states terms for distribution of such executables. 252 | 253 | When a "work that uses the Library" uses material from a header file 254 | that is part of the Library, the object code for the work may be a 255 | derivative work of the Library even though the source code is not. 256 | Whether this is true is especially significant if the work can be 257 | linked without the Library, or if the work is itself a library. The 258 | threshold for this to be true is not precisely defined by law. 259 | 260 | If such an object file uses only numerical parameters, data 261 | structure layouts and accessors, and small macros and small inline 262 | functions (ten lines or less in length), then the use of the object 263 | file is unrestricted, regardless of whether it is legally a derivative 264 | work. (Executables containing this object code plus portions of the 265 | Library will still fall under Section 6.) 266 | 267 | Otherwise, if the work is a derivative of the Library, you may 268 | distribute the object code for the work under the terms of Section 6. 269 | Any executables containing that work also fall under Section 6, 270 | whether or not they are linked directly with the Library itself. 271 | 272 | 6. As an exception to the Sections above, you may also combine or 273 | link a "work that uses the Library" with the Library to produce a 274 | work containing portions of the Library, and distribute that work 275 | under terms of your choice, provided that the terms permit 276 | modification of the work for the customer's own use and reverse 277 | engineering for debugging such modifications. 278 | 279 | You must give prominent notice with each copy of the work that the 280 | Library is used in it and that the Library and its use are covered by 281 | this License. You must supply a copy of this License. If the work 282 | during execution displays copyright notices, you must include the 283 | copyright notice for the Library among them, as well as a reference 284 | directing the user to the copy of this License. Also, you must do one 285 | of these things: 286 | 287 | a) Accompany the work with the complete corresponding 288 | machine-readable source code for the Library including whatever 289 | changes were used in the work (which must be distributed under 290 | Sections 1 and 2 above); and, if the work is an executable linked 291 | with the Library, with the complete machine-readable "work that 292 | uses the Library", as object code and/or source code, so that the 293 | user can modify the Library and then relink to produce a modified 294 | executable containing the modified Library. (It is understood 295 | that the user who changes the contents of definitions files in the 296 | Library will not necessarily be able to recompile the application 297 | to use the modified definitions.) 298 | 299 | b) Use a suitable shared library mechanism for linking with the 300 | Library. A suitable mechanism is one that (1) uses at run time a 301 | copy of the library already present on the user's computer system, 302 | rather than copying library functions into the executable, and (2) 303 | will operate properly with a modified version of the library, if 304 | the user installs one, as long as the modified version is 305 | interface-compatible with the version that the work was made with. 306 | 307 | c) Accompany the work with a written offer, valid for at 308 | least three years, to give the same user the materials 309 | specified in Subsection 6a, above, for a charge no more 310 | than the cost of performing this distribution. 311 | 312 | d) If distribution of the work is made by offering access to copy 313 | from a designated place, offer equivalent access to copy the above 314 | specified materials from the same place. 315 | 316 | e) Verify that the user has already received a copy of these 317 | materials or that you have already sent this user a copy. 318 | 319 | For an executable, the required form of the "work that uses the 320 | Library" must include any data and utility programs needed for 321 | reproducing the executable from it. However, as a special exception, 322 | the materials to be distributed need not include anything that is 323 | normally distributed (in either source or binary form) with the major 324 | components (compiler, kernel, and so on) of the operating system on 325 | which the executable runs, unless that component itself accompanies 326 | the executable. 327 | 328 | It may happen that this requirement contradicts the license 329 | restrictions of other proprietary libraries that do not normally 330 | accompany the operating system. Such a contradiction means you cannot 331 | use both them and the Library together in an executable that you 332 | distribute. 333 | 334 | 7. You may place library facilities that are a work based on the 335 | Library side-by-side in a single library together with other library 336 | facilities not covered by this License, and distribute such a combined 337 | library, provided that the separate distribution of the work based on 338 | the Library and of the other library facilities is otherwise 339 | permitted, and provided that you do these two things: 340 | 341 | a) Accompany the combined library with a copy of the same work 342 | based on the Library, uncombined with any other library 343 | facilities. This must be distributed under the terms of the 344 | Sections above. 345 | 346 | b) Give prominent notice with the combined library of the fact 347 | that part of it is a work based on the Library, and explaining 348 | where to find the accompanying uncombined form of the same work. 349 | 350 | 8. You may not copy, modify, sublicense, link with, or distribute 351 | the Library except as expressly provided under this License. Any 352 | attempt otherwise to copy, modify, sublicense, link with, or 353 | distribute the Library is void, and will automatically terminate your 354 | rights under this License. However, parties who have received copies, 355 | or rights, from you under this License will not have their licenses 356 | terminated so long as such parties remain in full compliance. 357 | 358 | 9. You are not required to accept this License, since you have not 359 | signed it. However, nothing else grants you permission to modify or 360 | distribute the Library or its derivative works. These actions are 361 | prohibited by law if you do not accept this License. Therefore, by 362 | modifying or distributing the Library (or any work based on the 363 | Library), you indicate your acceptance of this License to do so, and 364 | all its terms and conditions for copying, distributing or modifying 365 | the Library or works based on it. 366 | 367 | 10. Each time you redistribute the Library (or any work based on the 368 | Library), the recipient automatically receives a license from the 369 | original licensor to copy, distribute, link with or modify the Library 370 | subject to these terms and conditions. You may not impose any further 371 | restrictions on the recipients' exercise of the rights granted herein. 372 | You are not responsible for enforcing compliance by third parties with 373 | this License. 374 | 375 | 11. If, as a consequence of a court judgment or allegation of patent 376 | infringement or for any other reason (not limited to patent issues), 377 | conditions are imposed on you (whether by court order, agreement or 378 | otherwise) that contradict the conditions of this License, they do not 379 | excuse you from the conditions of this License. If you cannot 380 | distribute so as to satisfy simultaneously your obligations under this 381 | License and any other pertinent obligations, then as a consequence you 382 | may not distribute the Library at all. For example, if a patent 383 | license would not permit royalty-free redistribution of the Library by 384 | all those who receive copies directly or indirectly through you, then 385 | the only way you could satisfy both it and this License would be to 386 | refrain entirely from distribution of the Library. 387 | 388 | If any portion of this section is held invalid or unenforceable under any 389 | particular circumstance, the balance of the section is intended to apply, 390 | and the section as a whole is intended to apply in other circumstances. 391 | 392 | It is not the purpose of this section to induce you to infringe any 393 | patents or other property right claims or to contest validity of any 394 | such claims; this section has the sole purpose of protecting the 395 | integrity of the free software distribution system which is 396 | implemented by public license practices. Many people have made 397 | generous contributions to the wide range of software distributed 398 | through that system in reliance on consistent application of that 399 | system; it is up to the author/donor to decide if he or she is willing 400 | to distribute software through any other system and a licensee cannot 401 | impose that choice. 402 | 403 | This section is intended to make thoroughly clear what is believed to 404 | be a consequence of the rest of this License. 405 | 406 | 12. If the distribution and/or use of the Library is restricted in 407 | certain countries either by patents or by copyrighted interfaces, the 408 | original copyright holder who places the Library under this License may add 409 | an explicit geographical distribution limitation excluding those countries, 410 | so that distribution is permitted only in or among countries not thus 411 | excluded. In such case, this License incorporates the limitation as if 412 | written in the body of this License. 413 | 414 | 13. The Free Software Foundation may publish revised and/or new 415 | versions of the Lesser General Public License from time to time. 416 | Such new versions will be similar in spirit to the present version, 417 | but may differ in detail to address new problems or concerns. 418 | 419 | Each version is given a distinguishing version number. If the Library 420 | specifies a version number of this License which applies to it and 421 | "any later version", you have the option of following the terms and 422 | conditions either of that version or of any later version published by 423 | the Free Software Foundation. If the Library does not specify a 424 | license version number, you may choose any version ever published by 425 | the Free Software Foundation. 426 | 427 | 14. If you wish to incorporate parts of the Library into other free 428 | programs whose distribution conditions are incompatible with these, 429 | write to the author to ask for permission. For software which is 430 | copyrighted by the Free Software Foundation, write to the Free 431 | Software Foundation; we sometimes make exceptions for this. Our 432 | decision will be guided by the two goals of preserving the free status 433 | of all derivatives of our free software and of promoting the sharing 434 | and reuse of software generally. 435 | 436 | NO WARRANTY 437 | 438 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 439 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 440 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 441 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 442 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 443 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 444 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 445 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 446 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 447 | 448 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 449 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 450 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 451 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 452 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 453 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 454 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 455 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 456 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 457 | DAMAGES. 458 | 459 | END OF TERMS AND CONDITIONS 460 | 461 | How to Apply These Terms to Your New Libraries 462 | 463 | If you develop a new library, and you want it to be of the greatest 464 | possible use to the public, we recommend making it free software that 465 | everyone can redistribute and change. You can do so by permitting 466 | redistribution under these terms (or, alternatively, under the terms of the 467 | ordinary General Public License). 468 | 469 | To apply these terms, attach the following notices to the library. It is 470 | safest to attach them to the start of each source file to most effectively 471 | convey the exclusion of warranty; and each file should have at least the 472 | "copyright" line and a pointer to where the full notice is found. 473 | 474 | 475 | Copyright (C) 476 | 477 | This library is free software; you can redistribute it and/or 478 | modify it under the terms of the GNU Lesser General Public 479 | License as published by the Free Software Foundation; either 480 | version 2.1 of the License, or (at your option) any later version. 481 | 482 | This library is distributed in the hope that it will be useful, 483 | but WITHOUT ANY WARRANTY; without even the implied warranty of 484 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 485 | Lesser General Public License for more details. 486 | 487 | You should have received a copy of the GNU Lesser General Public 488 | License along with this library; if not, write to the Free Software 489 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 490 | 491 | Also add information on how to contact you by electronic and paper mail. 492 | 493 | You should also get your employer (if you work as a programmer) or your 494 | school, if any, to sign a "copyright disclaimer" for the library, if 495 | necessary. Here is a sample; alter the names: 496 | 497 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 498 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. 499 | 500 | , 1 April 1990 501 | Ty Coon, President of Vice 502 | 503 | That's all there is to it! 504 | 505 | 506 | --------------------------------------------------------------------------------