From: Florian Weimer Date: Thu, 12 Feb 2026 11:18:54 +0000 (+0100) Subject: support: Add missing NSS formatting and checking functions X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c9c4ff0b77d72fa0c1229ac9c52ef42379b1f5a5;p=thirdparty%2Fglibc.git support: Add missing NSS formatting and checking functions This change is largely auto-generated. The function implementations are mechanical and use the glibc-specific support framework, so this should be low-risk and therefore acceptable. The struct etherent type is currently internal-only (although it can be used by NSS modules), which is why it is not included here. Reviewed-by: DJ Delorie --- diff --git a/support/Makefile b/support/Makefile index 935503c9b3..5b59394274 100644 --- a/support/Makefile +++ b/support/Makefile @@ -28,9 +28,18 @@ libsupport-routines = \ 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 \ @@ -61,10 +70,19 @@ libsupport-routines = \ 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 \ @@ -359,6 +377,7 @@ tests = \ 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 \ diff --git a/support/check_aliasent.c b/support/check_aliasent.c new file mode 100644 index 0000000000..1545c3de61 --- /dev/null +++ b/support/check_aliasent.c @@ -0,0 +1,29 @@ +/* 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 + . */ + +#include + +#include + +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); +} diff --git a/support/check_ether_addr.c b/support/check_ether_addr.c new file mode 100644 index 0000000000..f545ccd39d --- /dev/null +++ b/support/check_ether_addr.c @@ -0,0 +1,29 @@ +/* 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 + . */ + +#include + +#include + +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); +} diff --git a/support/check_group.c b/support/check_group.c new file mode 100644 index 0000000000..e58046dda4 --- /dev/null +++ b/support/check_group.c @@ -0,0 +1,29 @@ +/* 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 + . */ + +#include + +#include + +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); +} diff --git a/support/check_nss.h b/support/check_nss.h index 6bacb9978f..66c291dc3b 100644 --- a/support/check_nss.h +++ b/support/check_nss.h @@ -25,8 +25,17 @@ __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 @@ -34,12 +43,30 @@ struct netent; 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. */ diff --git a/support/check_passwd.c b/support/check_passwd.c new file mode 100644 index 0000000000..d95864dafb --- /dev/null +++ b/support/check_passwd.c @@ -0,0 +1,29 @@ +/* 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 + . */ + +#include + +#include + +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); +} diff --git a/support/check_protoent.c b/support/check_protoent.c new file mode 100644 index 0000000000..9ff1aacfca --- /dev/null +++ b/support/check_protoent.c @@ -0,0 +1,29 @@ +/* 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 + . */ + +#include + +#include + +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); +} diff --git a/support/check_rpcent.c b/support/check_rpcent.c new file mode 100644 index 0000000000..df91351000 --- /dev/null +++ b/support/check_rpcent.c @@ -0,0 +1,29 @@ +/* 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 + . */ + +#include + +#include + +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); +} diff --git a/support/check_servent.c b/support/check_servent.c new file mode 100644 index 0000000000..2281278aa5 --- /dev/null +++ b/support/check_servent.c @@ -0,0 +1,29 @@ +/* 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 + . */ + +#include + +#include + +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); +} diff --git a/support/check_sgrp.c b/support/check_sgrp.c new file mode 100644 index 0000000000..592d7c9a26 --- /dev/null +++ b/support/check_sgrp.c @@ -0,0 +1,29 @@ +/* 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 + . */ + +#include + +#include + +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); +} diff --git a/support/check_spwd.c b/support/check_spwd.c new file mode 100644 index 0000000000..32c07e2eb6 --- /dev/null +++ b/support/check_spwd.c @@ -0,0 +1,29 @@ +/* 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 + . */ + +#include + +#include + +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); +} diff --git a/support/format_nss.h b/support/format_nss.h index a81658cfcb..08d39f93d7 100644 --- a/support/format_nss.h +++ b/support/format_nss.h @@ -25,8 +25,17 @@ __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 @@ -35,10 +44,19 @@ struct netent; 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 diff --git a/support/support_format_aliasent.c b/support/support_format_aliasent.c new file mode 100644 index 0000000000..25c180db5e --- /dev/null +++ b/support/support_format_aliasent.c @@ -0,0 +1,42 @@ +/* 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 + . */ + +#include + +#include +#include +#include +#include + +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; +} diff --git a/support/support_format_ether_addr.c b/support/support_format_ether_addr.c new file mode 100644 index 0000000000..2cfe5f218b --- /dev/null +++ b/support/support_format_ether_addr.c @@ -0,0 +1,33 @@ +/* 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 + . */ + +#include + +#include +#include +#include + +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)); +} diff --git a/support/support_format_group.c b/support/support_format_group.c new file mode 100644 index 0000000000..fb714564cd --- /dev/null +++ b/support/support_format_group.c @@ -0,0 +1,43 @@ +/* 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 + . */ + +#include + +#include +#include +#include +#include + +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; +} diff --git a/support/support_format_passwd.c b/support/support_format_passwd.c new file mode 100644 index 0000000000..cf9fdef2fc --- /dev/null +++ b/support/support_format_passwd.c @@ -0,0 +1,45 @@ +/* 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 + . */ + +#include + +#include +#include +#include +#include + +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; +} diff --git a/support/support_format_protoent.c b/support/support_format_protoent.c new file mode 100644 index 0000000000..25c177f5da --- /dev/null +++ b/support/support_format_protoent.c @@ -0,0 +1,42 @@ +/* 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 + . */ + +#include + +#include +#include +#include +#include + +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; +} diff --git a/support/support_format_rpcent.c b/support/support_format_rpcent.c new file mode 100644 index 0000000000..1b898f3e27 --- /dev/null +++ b/support/support_format_rpcent.c @@ -0,0 +1,42 @@ +/* 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 + . */ + +#include + +#include +#include +#include +#include + +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; +} diff --git a/support/support_format_servent.c b/support/support_format_servent.c new file mode 100644 index 0000000000..fbe8138222 --- /dev/null +++ b/support/support_format_servent.c @@ -0,0 +1,44 @@ +/* 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 + . */ + +#include + +#include +#include +#include +#include +#include + +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; +} diff --git a/support/support_format_sgrp.c b/support/support_format_sgrp.c new file mode 100644 index 0000000000..d9b7d12478 --- /dev/null +++ b/support/support_format_sgrp.c @@ -0,0 +1,44 @@ +/* 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 + . */ + +#include + +#include +#include +#include +#include + +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; +} diff --git a/support/support_format_spwd.c b/support/support_format_spwd.c new file mode 100644 index 0000000000..7d05e2bc13 --- /dev/null +++ b/support/support_format_spwd.c @@ -0,0 +1,47 @@ +/* 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 + . */ + +#include + +#include +#include +#include +#include + +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; +} diff --git a/support/tst-support_format_nss.c b/support/tst-support_format_nss.c new file mode 100644 index 0000000000..f3163d8c60 --- /dev/null +++ b/support/tst-support_format_nss.c @@ -0,0 +1,417 @@ +/* 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 + . */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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), + ""); +} + +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), + "\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