blob_repeat \
check \
check_addrinfo \
+ check_aliasent \
check_dns_packet \
+ check_ether_addr \
+ check_group \
check_hostent \
check_netent \
+ check_passwd \
+ check_protoent \
+ check_rpcent \
+ check_servent \
+ check_sgrp \
+ check_spwd \
delayed_exit \
dtotimespec \
dtotimespec-time64 \
support_enter_network_namespace \
support_format_address_family \
support_format_addrinfo \
+ support_format_aliasent \
support_format_dns_packet \
+ support_format_ether_addr \
+ support_format_group \
support_format_herrno \
support_format_hostent \
support_format_netent \
+ support_format_passwd \
+ support_format_protoent \
+ support_format_rpcent \
+ support_format_servent \
+ support_format_sgrp \
+ support_format_spwd \
support_fuse \
support_isolate_in_subprocess \
support_mem_access \
tst-support_capture_subprocess \
tst-support_descriptors \
tst-support_format_dns_packet \
+ tst-support_format_nss \
tst-support_fuse \
tst-support_quote_blob \
tst-support_quote_blob_wide \
--- /dev/null
+/* Compare struct aliasent values against a formatted string.
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/check_nss.h>
+
+#include <support/format_nss.h>
+
+void
+check_aliasent (const char *description, const struct aliasent *e,
+ const char *expected)
+{
+ char *formatted = support_format_aliasent (e);
+ support_check_nss (description, "aliasent", formatted, expected);
+}
--- /dev/null
+/* Compare struct ether_addr values against a formatted string.
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/check_nss.h>
+
+#include <support/format_nss.h>
+
+void
+check_ether_addr (const char *description, const struct ether_addr *e,
+ const char *expected)
+{
+ char *formatted = support_format_ether_addr (e);
+ support_check_nss (description, "ether_addr", formatted, expected);
+}
--- /dev/null
+/* Compare struct group values against a formatted string.
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/check_nss.h>
+
+#include <support/format_nss.h>
+
+void
+check_group (const char *description, const struct group *g,
+ const char *expected)
+{
+ char *formatted = support_format_group (g);
+ support_check_nss (description, "group", formatted, expected);
+}
__BEGIN_DECLS
struct addrinfo;
+struct aliasent;
+struct ether_addr;
+struct group;
struct hostent;
struct netent;
+struct passwd;
+struct protoent;
+struct rpcent;
+struct servent;
+struct sgrp;
+struct spwd;
/* Compare the data structures against the expected values (which have
to be formatted according to the support_format_* functions in
failure is recorded, and a diff is written to standard output. */
void check_addrinfo (const char *query_description,
const struct addrinfo *, int ret, const char *expected);
+void check_aliasent (const char *description, const struct aliasent *,
+ const char *expected);
void check_dns_packet (const char *query_description,
const unsigned char *, size_t, const char *expected);
+void check_ether_addr (const char *description, const struct ether_addr *,
+ const char *expected);
+void check_group (const char *description, const struct group *,
+ const char *expected);
void check_hostent (const char *query_description,
const struct hostent *, const char *expected);
void check_netent (const char *query_description,
const struct netent *, const char *expected);
+void check_passwd (const char *description, const struct passwd *,
+ const char *expected);
+void check_protoent (const char *description, const struct protoent *,
+ const char *expected);
+void check_rpcent (const char *description, const struct rpcent *,
+ const char *expected);
+void check_servent (const char *description, const struct servent *,
+ const char *expected);
+void check_sgrp (const char *description, const struct sgrp *,
+ const char *expected);
+void check_spwd (const char *description, const struct spwd *,
+ const char *expected);
/* Helper routine for implementing the functions above. Report an
error if ACTUAL and EXPECTED are not equal. ACTUAL is always freed. */
--- /dev/null
+/* Compare struct passwd values against a formatted string.
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/check_nss.h>
+
+#include <support/format_nss.h>
+
+void
+check_passwd (const char *description, const struct passwd *p,
+ const char *expected)
+{
+ char *formatted = support_format_passwd (p);
+ support_check_nss (description, "passwd", formatted, expected);
+}
--- /dev/null
+/* Compare struct protoent values against a formatted string.
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/check_nss.h>
+
+#include <support/format_nss.h>
+
+void
+check_protoent (const char *description, const struct protoent *e,
+ const char *expected)
+{
+ char *formatted = support_format_protoent (e);
+ support_check_nss (description, "protoent", formatted, expected);
+}
--- /dev/null
+/* Compare struct rpcent values against a formatted string.
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/check_nss.h>
+
+#include <support/format_nss.h>
+
+void
+check_rpcent (const char *description, const struct rpcent *e,
+ const char *expected)
+{
+ char *formatted = support_format_rpcent (e);
+ support_check_nss (description, "rpcent", formatted, expected);
+}
--- /dev/null
+/* Compare struct servent values against a formatted string.
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/check_nss.h>
+
+#include <support/format_nss.h>
+
+void
+check_servent (const char *description, const struct servent *e,
+ const char *expected)
+{
+ char *formatted = support_format_servent (e);
+ support_check_nss (description, "servent", formatted, expected);
+}
--- /dev/null
+/* Compare struct sgrp values against a formatted string.
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/check_nss.h>
+
+#include <support/format_nss.h>
+
+void
+check_sgrp (const char *description, const struct sgrp *s,
+ const char *expected)
+{
+ char *formatted = support_format_sgrp (s);
+ support_check_nss (description, "sgrp", formatted, expected);
+}
--- /dev/null
+/* Compare struct spwd values against a formatted string.
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/check_nss.h>
+
+#include <support/format_nss.h>
+
+void
+check_spwd (const char *description, const struct spwd *s,
+ const char *expected)
+{
+ char *formatted = support_format_spwd (s);
+ support_check_nss (description, "spwd", formatted, expected);
+}
__BEGIN_DECLS
struct addrinfo;
+struct aliasent;
+struct ether_addr;
+struct group;
struct hostent;
struct netent;
+struct passwd;
+struct protoent;
+struct rpcent;
+struct servent;
+struct sgrp;
+struct spwd;
/* The following functions format their arguments as human-readable
strings (which can span multiple lines). The caller must free the
result. */
char *support_format_address_family (int);
char *support_format_addrinfo (const struct addrinfo *, int ret);
+char *support_format_aliasent (const struct aliasent *);
char *support_format_dns_packet (const unsigned char *buffer, size_t length);
+char *support_format_ether_addr (const struct ether_addr *);
+char *support_format_group (const struct group *);
char *support_format_herrno (int);
char *support_format_hostent (const struct hostent *);
char *support_format_netent (const struct netent *);
+char *support_format_passwd (const struct passwd *);
+char *support_format_protoent (const struct protoent *);
+char *support_format_rpcent (const struct rpcent *);
+char *support_format_servent (const struct servent *);
+char *support_format_sgrp (const struct sgrp *);
+char *support_format_spwd (const struct spwd *);
__END_DECLS
--- /dev/null
+/* Convert a struct aliasent object to a string.
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/format_nss.h>
+
+#include <aliases.h>
+#include <errno.h>
+#include <support/support.h>
+#include <support/xmemstream.h>
+
+char *
+support_format_aliasent (const struct aliasent *e)
+{
+ if (e == NULL)
+ xasprintf ("errno: (errno %d, %m)\n", errno);
+
+ struct xmemstream mem;
+ xopen_memstream (&mem);
+
+ fprintf (mem.out, "name: %s\n", e->alias_name);
+ for (size_t i = 0; i < e->alias_members_len; ++i)
+ fprintf (mem.out, "member: %s\n", e->alias_members[i]);
+ fprintf (mem.out, "local: %d\n", e->alias_local);
+
+ xfclose_memstream (&mem);
+ return mem.buffer;
+}
--- /dev/null
+/* Convert a struct ether_addr object to a string.
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/format_nss.h>
+
+#include <errno.h>
+#include <netinet/ether.h>
+#include <support/support.h>
+
+char *
+support_format_ether_addr (const struct ether_addr *e)
+{
+ if (e == NULL)
+ return xasprintf ("error: (errno %d, %m)\n", errno);
+
+ char buf[sizeof ("xx:xx:xx:xx:xx:xx")];
+ return xasprintf ("address: %s\n", ether_ntoa_r (e, buf));
+}
--- /dev/null
+/* Convert a struct group object to a string.
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/format_nss.h>
+
+#include <errno.h>
+#include <grp.h>
+#include <support/support.h>
+#include <support/xmemstream.h>
+
+char *
+support_format_group (const struct group *g)
+{
+ if (g == NULL)
+ return xasprintf ("error: (errno %d, %m)\n", errno);
+
+ struct xmemstream mem;
+ xopen_memstream (&mem);
+
+ fprintf (mem.out, "name: %s\n", g->gr_name);
+ fprintf (mem.out, "passwd: %s\n", g->gr_passwd);
+ fprintf (mem.out, "gid: %u\n", (unsigned) g->gr_gid);
+ for (char **mp = g->gr_mem; *mp != NULL; ++mp)
+ fprintf (mem.out, "member: %s\n", *mp);
+
+ xfclose_memstream (&mem);
+ return mem.buffer;
+}
--- /dev/null
+/* Convert a struct passwd object to a string.
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/format_nss.h>
+
+#include <errno.h>
+#include <pwd.h>
+#include <support/support.h>
+#include <support/xmemstream.h>
+
+char *
+support_format_passwd (const struct passwd *p)
+{
+ if (p == NULL)
+ return xasprintf ("error: (errno %d, %m)\n", errno);
+
+ struct xmemstream mem;
+ xopen_memstream (&mem);
+
+ fprintf (mem.out, "name: %s\n", p->pw_name);
+ fprintf (mem.out, "passwd: %s\n", p->pw_passwd);
+ fprintf (mem.out, "uid: %u\n", (unsigned int) p->pw_uid);
+ fprintf (mem.out, "gid: %u\n", (unsigned int) p->pw_gid);
+ fprintf (mem.out, "gecos: %s\n", p->pw_gecos);
+ fprintf (mem.out, "dir: %s\n", p->pw_dir);
+ fprintf (mem.out, "shell: %s\n", p->pw_shell);
+
+ xfclose_memstream (&mem);
+ return mem.buffer;
+}
--- /dev/null
+/* Convert a struct protoent object to a string.
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/format_nss.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <support/support.h>
+#include <support/xmemstream.h>
+
+char *
+support_format_protoent (const struct protoent *e)
+{
+ if (e == NULL)
+ return xasprintf ("error: (errno %d, %m)\n", errno);
+
+ struct xmemstream mem;
+ xopen_memstream (&mem);
+
+ fprintf (mem.out, "name: %s\n", e->p_name);
+ for (char **ap = e->p_aliases; *ap != NULL; ++ap)
+ fprintf (mem.out, "alias: %s\n", *ap);
+ fprintf (mem.out, "proto: %d\n", e->p_proto);
+
+ xfclose_memstream (&mem);
+ return mem.buffer;
+}
--- /dev/null
+/* Convert a struct rpcent object to a string.
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/format_nss.h>
+
+#include <errno.h>
+#include <rpc/netdb.h>
+#include <support/support.h>
+#include <support/xmemstream.h>
+
+char *
+support_format_rpcent (const struct rpcent *r)
+{
+ if (r == NULL)
+ return xasprintf ("error: (errno %d, %m)\n", errno);
+
+ struct xmemstream mem;
+ xopen_memstream (&mem);
+
+ fprintf (mem.out, "name: %s\n", r->r_name);
+ fprintf (mem.out, "number: %d\n", r->r_number);
+ for (char **ap = r->r_aliases; *ap != NULL; ++ap)
+ fprintf (mem.out, "alias: %s\n", *ap);
+
+ xfclose_memstream (&mem);
+ return mem.buffer;
+}
--- /dev/null
+/* Convert a struct servent object to a string.
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/format_nss.h>
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <netdb.h>
+#include <support/support.h>
+#include <support/xmemstream.h>
+
+char *
+support_format_servent (const struct servent *e)
+{
+ if (e == NULL)
+ return xasprintf ("error: (errno %d, %m)\n", errno);
+
+ struct xmemstream mem;
+ xopen_memstream (&mem);
+
+ fprintf (mem.out, "name: %s\n", e->s_name);
+ for (char **ap = e->s_aliases; *ap != NULL; ++ap)
+ fprintf (mem.out, "alias: %s\n", *ap);
+ fprintf (mem.out, "port: %d\n", ntohs (e->s_port));
+ fprintf (mem.out, "proto: %s\n", e->s_proto);
+
+ xfclose_memstream (&mem);
+ return mem.buffer;
+}
--- /dev/null
+/* Convert a struct sgrp object to a string.
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/format_nss.h>
+
+#include <errno.h>
+#include <gshadow.h>
+#include <support/support.h>
+#include <support/xmemstream.h>
+
+char *
+support_format_sgrp (const struct sgrp *s)
+{
+ if (s == NULL)
+ return xasprintf ("error: (errno %d, %m)\n", errno);
+
+ struct xmemstream mem;
+ xopen_memstream (&mem);
+
+ fprintf (mem.out, "name: %s\n", s->sg_namp);
+ fprintf (mem.out, "passwd: %s\n", s->sg_passwd);
+ for (char **ap = s->sg_adm; *ap != NULL; ++ap)
+ fprintf (mem.out, "admin: %s\n", *ap);
+ for (char **mp = s->sg_mem; *mp != NULL; ++mp)
+ fprintf (mem.out, "member: %s\n", *mp);
+
+ xfclose_memstream (&mem);
+ return mem.buffer;
+}
--- /dev/null
+/* Convert a struct spwd object to a string.
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/format_nss.h>
+
+#include <errno.h>
+#include <shadow.h>
+#include <support/support.h>
+#include <support/xmemstream.h>
+
+char *
+support_format_spwd (const struct spwd *s)
+{
+ if (s == NULL)
+ return xasprintf ("error: (errno %d, %m)\n", errno);
+
+ struct xmemstream mem;
+ xopen_memstream (&mem);
+
+ fprintf (mem.out, "sp_namp: %s\n", s->sp_namp);
+ fprintf (mem.out, "sp_pwdp: %s\n", s->sp_pwdp);
+ fprintf (mem.out, "sp_lstchg: %ld\n", s->sp_lstchg);
+ fprintf (mem.out, "sp_min: %ld\n", s->sp_min);
+ fprintf (mem.out, "sp_max: %ld\n", s->sp_max);
+ fprintf (mem.out, "sp_warn: %ld\n", s->sp_warn);
+ fprintf (mem.out, "sp_inact: %ld\n", s->sp_inact);
+ fprintf (mem.out, "sp_expire: %ld\n", s->sp_expire);
+ fprintf (mem.out, "sp_flag: %lu\n", s->sp_flag);
+
+ xfclose_memstream (&mem);
+ return mem.buffer;
+}
--- /dev/null
+/* Tests for the support_format_* functions.
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <support/check_nss.h>
+#include <support/format_nss.h>
+
+#include <aliases.h>
+#include <arpa/inet.h>
+#include <grp.h>
+#include <gshadow.h>
+#include <netdb.h>
+#include <netinet/ether.h>
+#include <pwd.h>
+#include <rpc/netdb.h>
+#include <shadow.h>
+
+static void
+test_format_address_family (void)
+{
+ support_check_nss ("AF_INET", "address_family",
+ support_format_address_family (AF_INET),
+ "INET");
+ support_check_nss ("AF_INET6", "address_family",
+ support_format_address_family (AF_INET6),
+ "INET6");
+ support_check_nss ("AF_LOCAL", "address_family",
+ support_format_address_family (AF_LOCAL),
+ "LOCAL");
+ support_check_nss ("AF_UNSPEC", "address_family",
+ support_format_address_family (AF_UNSPEC),
+ "UNSPEC");
+ support_check_nss ("unknown family", "address_family",
+ support_format_address_family (12345),
+ "<unknown address family 12345>");
+}
+
+static void
+test_format_herrno (void)
+{
+ support_check_nss ("HOST_NOT_FOUND", "herrno",
+ support_format_herrno (HOST_NOT_FOUND),
+ "HOST_NOT_FOUND");
+ support_check_nss ("NO_ADDRESS", "herrno",
+ support_format_herrno (NO_ADDRESS),
+ "NO_ADDRESS");
+ support_check_nss ("NO_RECOVERY", "herrno",
+ support_format_herrno (NO_RECOVERY),
+ "NO_RECOVERY");
+ support_check_nss ("TRY_AGAIN", "herrno",
+ support_format_herrno (TRY_AGAIN),
+ "TRY_AGAIN");
+ support_check_nss ("invalid herrno", "herrno",
+ support_format_herrno (12345),
+ "<invalid h_errno value 12345>\n");
+}
+
+static void
+test_format_passwd (void)
+{
+ struct passwd p =
+ {
+ .pw_name = (char *) "testuser",
+ .pw_passwd = (char *) "x",
+ .pw_uid = 1000,
+ .pw_gid = 1000,
+ .pw_gecos = (char *) "Test User",
+ .pw_dir = (char *) "/home/testuser",
+ .pw_shell = (char *) "/bin/bash"
+ };
+ support_check_nss ("passwd", "passwd",
+ support_format_passwd (&p),
+ "name: testuser\n"
+ "passwd: x\n"
+ "uid: 1000\n"
+ "gid: 1000\n"
+ "gecos: Test User\n"
+ "dir: /home/testuser\n"
+ "shell: /bin/bash\n");
+}
+
+static void
+test_format_group (void)
+{
+ char *members[] = { (char *) "user1", (char *) "user2", NULL };
+ struct group g =
+ {
+ .gr_name = (char *) "testgroup",
+ .gr_passwd = (char *) "x",
+ .gr_gid = 100,
+ .gr_mem = members
+ };
+ support_check_nss ("group with members", "group",
+ support_format_group (&g),
+ "name: testgroup\n"
+ "passwd: x\n"
+ "gid: 100\n"
+ "member: user1\n"
+ "member: user2\n");
+
+ char *no_members[] = { NULL };
+ struct group g_empty =
+ {
+ .gr_name = (char *) "emptygroup",
+ .gr_passwd = (char *) "",
+ .gr_gid = 200,
+ .gr_mem = no_members
+ };
+ support_check_nss ("group without members", "group",
+ support_format_group (&g_empty),
+ "name: emptygroup\n"
+ "passwd: \n"
+ "gid: 200\n");
+}
+
+static void
+test_format_spwd (void)
+{
+ struct spwd s =
+ {
+ .sp_namp = (char *) "testuser",
+ .sp_pwdp = (char *) "$6$rounds=5000$hash",
+ .sp_lstchg = 19000,
+ .sp_min = 0,
+ .sp_max = 99999,
+ .sp_warn = 7,
+ .sp_inact = -1,
+ .sp_expire = -1,
+ .sp_flag = 0
+ };
+ support_check_nss ("spwd", "spwd",
+ support_format_spwd (&s),
+ "sp_namp: testuser\n"
+ "sp_pwdp: $6$rounds=5000$hash\n"
+ "sp_lstchg: 19000\n"
+ "sp_min: 0\n"
+ "sp_max: 99999\n"
+ "sp_warn: 7\n"
+ "sp_inact: -1\n"
+ "sp_expire: -1\n"
+ "sp_flag: 0\n");
+}
+
+static void
+test_format_sgrp (void)
+{
+ char *admins[] = { (char *) "admin1", NULL };
+ char *members[] = { (char *) "user1", (char *) "user2", NULL };
+ struct sgrp s =
+ {
+ .sg_namp = (char *) "testgroup",
+ .sg_passwd = (char *) "!",
+ .sg_adm = admins,
+ .sg_mem = members
+ };
+ support_check_nss ("sgrp", "sgrp",
+ support_format_sgrp (&s),
+ "name: testgroup\n"
+ "passwd: !\n"
+ "admin: admin1\n"
+ "member: user1\n"
+ "member: user2\n");
+
+ char *no_admins[] = { NULL };
+ char *no_members[] = { NULL };
+ struct sgrp s_empty =
+ {
+ .sg_namp = (char *) "emptygroup",
+ .sg_passwd = (char *) "",
+ .sg_adm = no_admins,
+ .sg_mem = no_members
+ };
+ support_check_nss ("sgrp empty", "sgrp",
+ support_format_sgrp (&s_empty),
+ "name: emptygroup\n"
+ "passwd: \n");
+}
+
+static void
+test_format_protoent (void)
+{
+ char *aliases[] = { (char *) "ICMP", NULL };
+ struct protoent p =
+ {
+ .p_name = (char *) "icmp",
+ .p_aliases = aliases,
+ .p_proto = 1
+ };
+ support_check_nss ("protoent with alias", "protoent",
+ support_format_protoent (&p),
+ "name: icmp\n"
+ "alias: ICMP\n"
+ "proto: 1\n");
+
+ char *no_aliases[] = { NULL };
+ struct protoent p_no_alias =
+ {
+ .p_name = (char *) "tcp",
+ .p_aliases = no_aliases,
+ .p_proto = 6
+ };
+ support_check_nss ("protoent without alias", "protoent",
+ support_format_protoent (&p_no_alias),
+ "name: tcp\n"
+ "proto: 6\n");
+}
+
+static void
+test_format_servent (void)
+{
+ char *aliases[] = { (char *) "WWW", (char *) "www-http", NULL };
+ struct servent s =
+ {
+ .s_name = (char *) "http",
+ .s_aliases = aliases,
+ .s_port = htons (80),
+ .s_proto = (char *) "tcp"
+ };
+ support_check_nss ("servent", "servent",
+ support_format_servent (&s),
+ "name: http\n"
+ "alias: WWW\n"
+ "alias: www-http\n"
+ "port: 80\n"
+ "proto: tcp\n");
+}
+
+static void
+test_format_rpcent (void)
+{
+ char *aliases[] = { (char *) "portmap", (char *) "sunrpc", NULL };
+ struct rpcent r =
+ {
+ .r_name = (char *) "portmapper",
+ .r_aliases = aliases,
+ .r_number = 100000
+ };
+ support_check_nss ("rpcent", "rpcent",
+ support_format_rpcent (&r),
+ "name: portmapper\n"
+ "number: 100000\n"
+ "alias: portmap\n"
+ "alias: sunrpc\n");
+}
+
+static void
+test_format_aliasent (void)
+{
+ char *members[] =
+ { (char *) "user1@example.com", (char *) "user2@example.com" };
+ struct aliasent a =
+ {
+ .alias_name = (char *) "staff",
+ .alias_members_len = 2,
+ .alias_members = members,
+ .alias_local = 0
+ };
+ support_check_nss ("aliasent", "aliasent",
+ support_format_aliasent (&a),
+ "name: staff\n"
+ "member: user1@example.com\n"
+ "member: user2@example.com\n"
+ "local: 0\n");
+}
+
+static void
+test_format_ether_addr (void)
+{
+ struct ether_addr e = { { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 } };
+ support_check_nss ("ether_addr", "ether_addr",
+ support_format_ether_addr (&e),
+ "address: 0:11:22:33:44:55\n");
+}
+
+static void
+test_format_hostent (void)
+{
+ char addr1[4] = { 192, 0, 2, 1 };
+ char addr2[4] = { 192, 0, 2, 2 };
+ char *addr_list[] = { addr1, addr2, NULL };
+ char *aliases[] = { (char *) "www.example", NULL };
+ struct hostent h =
+ {
+ .h_name = (char *) "example.com",
+ .h_aliases = aliases,
+ .h_addrtype = AF_INET,
+ .h_length = 4,
+ .h_addr_list = addr_list
+ };
+ support_check_nss ("hostent IPv4", "hostent",
+ support_format_hostent (&h),
+ "name: example.com\n"
+ "alias: www.example\n"
+ "address: 192.0.2.1\n"
+ "address: 192.0.2.2\n");
+
+ char addr6[16] = { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1 };
+ char *addr6_list[] = { addr6, NULL };
+ char *no_aliases[] = { NULL };
+ struct hostent h6 =
+ {
+ .h_name = (char *) "ipv6.example.com",
+ .h_aliases = no_aliases,
+ .h_addrtype = AF_INET6,
+ .h_length = 16,
+ .h_addr_list = addr6_list
+ };
+ support_check_nss ("hostent IPv6", "hostent",
+ support_format_hostent (&h6),
+ "name: ipv6.example.com\n"
+ "address: 2001:db8::1\n");
+}
+
+static void
+test_format_netent (void)
+{
+ char *aliases[] = { (char *) "localnet", NULL };
+ struct netent n =
+ {
+ .n_name = (char *) "loopback",
+ .n_aliases = aliases,
+ .n_addrtype = AF_INET,
+ .n_net = 0x7f000000
+ };
+ support_check_nss ("netent", "netent",
+ support_format_netent (&n),
+ "name: loopback\n"
+ "alias: localnet\n"
+ "net: 0x7f000000\n");
+}
+
+static void
+test_format_addrinfo (void)
+{
+ /* Test successful result with IPv4 address. */
+ struct sockaddr_in sin =
+ {
+ .sin_family = AF_INET,
+ .sin_port = htons (80),
+ .sin_addr = { htonl (0xc0000201) } /* 192.0.2.1 */
+ };
+ struct addrinfo ai =
+ {
+ .ai_flags = 0,
+ .ai_family = AF_INET,
+ .ai_socktype = SOCK_STREAM,
+ .ai_protocol = IPPROTO_TCP,
+ .ai_addrlen = sizeof (sin),
+ .ai_addr = (struct sockaddr *) &sin,
+ .ai_canonname = NULL,
+ .ai_next = NULL
+ };
+ support_check_nss ("addrinfo IPv4 STREAM/TCP", "addrinfo",
+ support_format_addrinfo (&ai, 0),
+ "address: STREAM/TCP 192.0.2.1 80\n");
+
+ /* Test with canonname. */
+ struct addrinfo ai_canon =
+ {
+ .ai_flags = AI_CANONNAME,
+ .ai_family = AF_INET,
+ .ai_socktype = SOCK_DGRAM,
+ .ai_protocol = IPPROTO_UDP,
+ .ai_addrlen = sizeof (sin),
+ .ai_addr = (struct sockaddr *) &sin,
+ .ai_canonname = (char *) "canonical.example.com",
+ .ai_next = NULL
+ };
+ support_check_nss ("addrinfo with canonname", "addrinfo",
+ support_format_addrinfo (&ai_canon, 0),
+ "flags: AI_CANONNAME\n"
+ "canonname: canonical.example.com\n"
+ "address: DGRAM/UDP 192.0.2.1 80\n");
+
+ /* Test error case. */
+ support_check_nss ("addrinfo EAI_NONAME", "addrinfo",
+ support_format_addrinfo (NULL, EAI_NONAME),
+ "error: Name or service not known\n");
+}
+
+static int
+do_test (void)
+{
+ test_format_address_family ();
+ test_format_herrno ();
+ test_format_passwd ();
+ test_format_group ();
+ test_format_spwd ();
+ test_format_sgrp ();
+ test_format_protoent ();
+ test_format_servent ();
+ test_format_rpcent ();
+ test_format_aliasent ();
+ test_format_ether_addr ();
+ test_format_hostent ();
+ test_format_netent ();
+ test_format_addrinfo ();
+ return 0;
+}
+
+#include <support/test-driver.c>