]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Add self-contained test for NSS.
authorUlrich Drepper <drepper@redhat.com>
Wed, 11 Aug 2010 14:25:02 +0000 (07:25 -0700)
committerUlrich Drepper <drepper@redhat.com>
Wed, 11 Aug 2010 14:25:02 +0000 (07:25 -0700)
While at it fix interaction between __nss_configure_lookup and nscd.
Otherwise the test fails if nscd is runnung.

ChangeLog
grp/initgroups.c
nss/Makefile
nss/getXXbyYY_r.c
nss/nss_files/files-parse.c
nss/nss_test1.c [new file with mode: 0644]
nss/nsswitch.c
nss/nsswitch.h
nss/tst-nss-test1.c [new file with mode: 0644]
shlib-versions
sysdeps/posix/getaddrinfo.c

index 281191def543c83dee8f6932e24ba81648923c96..8d267c9ccb84ff80f62864099a60476310c670e3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2010-08-11  Ulrich Drepper  <drepper@redhat.com>
+
+       * nss/Makefile: Add rules to build and run tst-nss-test1.
+       * shlib-versions: Add entry for libnss_test1.
+       * nss/nss_test1.c: New file.
+       * nss/tst-nss-test1.c: New file.
+
+       * nss/nsswitch.c (__nss_database_custom): Define new variable.
+       (__nss_configure_lookup): Set appropriate entry in
+       __nss_configure_lookup to true.
+       * nss/nsswitch.h: Define enum with indeces of databases in
+       databases and __nss_database_custom arrays.  Declare
+       __nss_database_custom.
+       * grp/initgroups.c (internal_getgrouplist): Use __nss_database_custom
+       to avoid using nscd when custom rules are installed.
+       * nss/getXXbyYY_r.c: Likewise.
+       * sysdeps/posix/getaddrinfo.c (gaih_inet): Likewise.
+
+       * nss/nss_files/files-parse.c: Whitespace fixes.
+
 2010-08-09  Ulrich Drepper  <drepper@redhat.com>
 
        [BZ #11883]
index cab63e52bfa504848818cf629454f65e522b19c7..180e653c30e6ee19f8124e3093367a93367042cd 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989,91,93,1996-2005,2006,2008 Free Software Foundation, Inc.
+/* Copyright (C) 1989,91,93,1996-2006,2008,2010 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
@@ -56,7 +56,8 @@ internal_getgrouplist (const char *user, gid_t group, long int *size,
   if (__nss_not_use_nscd_group > 0
       && ++__nss_not_use_nscd_group > NSS_NSCD_RETRY)
     __nss_not_use_nscd_group = 0;
-  if (!__nss_not_use_nscd_group)
+  if (!__nss_not_use_nscd_group
+      && !__nss_database_custom[NSS_DBSIDX_group])
     {
       int n = __nscd_getgrouplist (user, group, size, groupsp, limit);
       if (n >= 0)
index 670e6b2f16ddc50537812c37cd8e7741c646881e..04165b7604b6bffb49d9ab9a95931b49825e384d 100644 (file)
@@ -1,4 +1,5 @@
-# Copyright (C) 1996-1998,2000-2002,2007,2009 Free Software Foundation, Inc.
+# Copyright (C) 1996-1998,2000-2002,2007,2009,2010
+# 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
@@ -39,7 +40,7 @@ databases             = proto service hosts network grp pwd rpc ethers \
 others                  := getent
 install-bin             := getent
 
-tests                  = test-netdb
+tests                  = test-netdb tst-nss-test1
 xtests                 = bug-erange
 
 include ../Makeconfig
@@ -84,3 +85,14 @@ endif
 # a statically-linked program that hasn't already loaded it.
 $(services:%=$(objpfx)libnss_%.so): $(common-objpfx)libc.so \
                                    $(common-objpfx)libc_nonshared.a
+
+
+distribute             += nss_test1.c
+
+CFLAGS-nss_test1.c = -DNOT_IN_libc=1
+$(objpfx)/libnss_test1.so: $(objpfx)nss_test1.os $(common-objpfx)libc.so \
+                          $(common-objpfx)libc_nonshared.a
+       $(build-module)
+$(objpfx)/libnss_test1.so$(libnss_test1.so-version): $(objpfx)/libnss_test1.so
+       $(make-link)
+$(objpfx)tst-nss-test1.out: $(objpfx)/libnss_test1.so$(libnss_test1.so-version)
index 16dadd70ef493919bf0e5c6db80b962aea88cac7..0dbb0030e93e61880e120d0ab5793afbab97679d 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-2004, 2006, 2007, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2004,2006,2007,2009,2010 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
 
@@ -87,6 +87,8 @@
 # define NOT_USENSCD_NAME ADD_NOT_NSCDUSE (DATABASE_NAME)
 # define ADD_NOT_NSCDUSE(name) ADD_NOT_NSCDUSE1 (name)
 # define ADD_NOT_NSCDUSE1(name) __nss_not_use_nscd_##name
+# define CONCAT2(arg1, arg2) CONCAT2_2 (arg1, arg2)
+# define CONCAT2_2(arg1, arg2) arg1##arg2
 #endif
 
 #define FUNCTION_NAME_STRING STRINGIZE (FUNCTION_NAME)
@@ -186,7 +188,8 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
   if (NOT_USENSCD_NAME > 0 && ++NOT_USENSCD_NAME > NSS_NSCD_RETRY)
     NOT_USENSCD_NAME = 0;
 
-  if (!NOT_USENSCD_NAME)
+  if (!NOT_USENSCD_NAME
+      && !__nss_database_custom[CONCAT2 (NSS_DBSIDX_, DATABASE_NAME)])
     {
       nscd_status = NSCD_NAME (ADD_VARIABLES, resbuf, buffer, buflen, result
                               H_ERRNO_VAR);
index 3603762f8ed9b4ff8b0a87b5de810325d858808c..66604bf94eb9ee1967c04647f402a9080e3e4e4a 100644 (file)
@@ -1,5 +1,5 @@
 /* Common code for file-based database parsers in nss_files module.
-   Copyright (C) 1996-2000, 2003, 2004, 2009 Free Software Foundation, Inc.
+   Copyright (C) 1996-2000,2003,2004,2009,2010 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -29,7 +29,7 @@
    DATABASE -- string of the database file's name ("hosts", "passwd").
 
    ENTDATA -- if defined, `struct ENTDATA' is used by the parser to store
-              things pointed to by the resultant `struct STRUCTURE'.
+             things pointed to by the resultant `struct STRUCTURE'.
 
    NEED_H_ERRNO - defined iff an arg `int *herrnop' is used.
 
@@ -229,7 +229,7 @@ strtou32 (const char *nptr, char **endptr, int base)
   char **list = parse_list (&line, buf_start, buf_end, '\0', errnop);        \
   if (list)                                                                  \
     result->TRAILING_LIST_MEMBER = list;                                     \
-  else                                                                               \
+  else                                                                       \
     return -1;         /* -1 indicates we ran out of space.  */              \
 }
 
diff --git a/nss/nss_test1.c b/nss/nss_test1.c
new file mode 100644 (file)
index 0000000..3beb488
--- /dev/null
@@ -0,0 +1,154 @@
+#include <errno.h>
+#include <nss.h>
+#include <pthread.h>
+#include <string.h>
+
+
+#define COPY_IF_ROOM(s) \
+  ({ size_t len_ = strlen (s) + 1;             \
+     char *start_ = cp;                                \
+     buflen - (cp - buffer) < len_             \
+     ? NULL                                    \
+     : (cp = mempcpy (cp, s, len_), start_); })
+
+
+/* Password handling.  */
+#include <pwd.h>
+
+static struct passwd pwd_data[] =
+  {
+#define PWD(u) \
+    { .pw_name = (char *) "name" #u, .pw_passwd = (char *) "*", .pw_uid = u,  \
+      .pw_gid = 100, .pw_gecos = (char *) "*", .pw_dir = (char *) "*",       \
+      .pw_shell = (char *) "*" }
+    PWD (100),
+    PWD (30),
+    PWD (200),
+    PWD (60),
+    PWD (20000)
+  };
+#define npwd_data (sizeof (pwd_data) / sizeof (pwd_data[0]))
+
+static size_t pwd_iter;
+#define CURPWD pwd_data[pwd_iter]
+
+static pthread_mutex_t pwd_lock = PTHREAD_MUTEX_INITIALIZER;
+
+
+enum nss_status
+_nss_test1_setpwent (int stayopen)
+{
+  pwd_iter = 0;
+  return NSS_STATUS_SUCCESS;
+}
+
+
+enum nss_status
+_nss_test1_endpwent (void)
+{
+  return NSS_STATUS_SUCCESS;
+}
+
+
+enum nss_status
+_nss_test1_getpwent_r (struct passwd *result, char *buffer, size_t buflen,
+                      int *errnop)
+{
+  char *cp = buffer;
+  int res = NSS_STATUS_SUCCESS;
+
+  pthread_mutex_lock (&pwd_lock);
+
+  if (pwd_iter >= npwd_data)
+    res = NSS_STATUS_NOTFOUND;
+  else
+    {
+      result->pw_name = COPY_IF_ROOM (CURPWD.pw_name);
+      result->pw_passwd = COPY_IF_ROOM (CURPWD.pw_passwd);
+      result->pw_uid = CURPWD.pw_uid;
+      result->pw_gid = CURPWD.pw_gid;
+      result->pw_gecos = COPY_IF_ROOM (CURPWD.pw_gecos);
+      result->pw_dir = COPY_IF_ROOM (CURPWD.pw_dir);
+      result->pw_shell = COPY_IF_ROOM (CURPWD.pw_shell);
+
+      if (result->pw_name == NULL || result->pw_passwd == NULL
+         || result->pw_gecos == NULL || result->pw_dir == NULL
+         || result->pw_shell == NULL)
+       {
+         *errnop = ERANGE;
+         res = NSS_STATUS_TRYAGAIN;
+       }
+
+      ++pwd_iter;
+    }
+
+  pthread_mutex_unlock (&pwd_lock);
+
+  return res;
+}
+
+
+enum nss_status
+_nss_test1_getpwuid_r (uid_t uid, struct passwd *result, char *buffer,
+                      size_t buflen, int *errnop)
+{
+  for (size_t idx = 0; idx < npwd_data; ++idx)
+    if (pwd_data[idx].pw_uid == uid)
+      {
+       char *cp = buffer;
+       int res = NSS_STATUS_SUCCESS;
+
+       result->pw_name = COPY_IF_ROOM (pwd_data[idx].pw_name);
+       result->pw_passwd = COPY_IF_ROOM (pwd_data[idx].pw_passwd);
+       result->pw_uid = pwd_data[idx].pw_uid;
+       result->pw_gid = pwd_data[idx].pw_gid;
+       result->pw_gecos = COPY_IF_ROOM (pwd_data[idx].pw_gecos);
+       result->pw_dir = COPY_IF_ROOM (pwd_data[idx].pw_dir);
+       result->pw_shell = COPY_IF_ROOM (pwd_data[idx].pw_shell);
+
+       if (result->pw_name == NULL || result->pw_passwd == NULL
+           || result->pw_gecos == NULL || result->pw_dir == NULL
+           || result->pw_shell == NULL)
+         {
+           *errnop = ERANGE;
+           res = NSS_STATUS_TRYAGAIN;
+         }
+
+       return res;
+      }
+
+  return NSS_STATUS_NOTFOUND;
+}
+
+
+enum nss_status
+_nss_test1_getpwnam_r (const char *name, struct passwd *result, char *buffer,
+                      size_t buflen, int *errnop)
+{
+  for (size_t idx = 0; idx < npwd_data; ++idx)
+    if (strcmp (pwd_data[idx].pw_name, name) == 0)
+      {
+       char *cp = buffer;
+       int res = NSS_STATUS_SUCCESS;
+
+       result->pw_name = COPY_IF_ROOM (pwd_data[idx].pw_name);
+       result->pw_passwd = COPY_IF_ROOM (pwd_data[idx].pw_passwd);
+       result->pw_uid = pwd_data[idx].pw_uid;
+       result->pw_gid = pwd_data[idx].pw_gid;
+       result->pw_gecos = COPY_IF_ROOM (pwd_data[idx].pw_gecos);
+       result->pw_dir = COPY_IF_ROOM (pwd_data[idx].pw_dir);
+       result->pw_shell = COPY_IF_ROOM (pwd_data[idx].pw_shell);
+
+       if (result->pw_name == NULL || result->pw_passwd == NULL
+           || result->pw_gecos == NULL || result->pw_dir == NULL
+           || result->pw_shell == NULL)
+         {
+           *errnop = ERANGE;
+           res = NSS_STATUS_TRYAGAIN;
+         }
+
+       return res;
+      }
+
+  return NSS_STATUS_NOTFOUND;
+}
index da94ca983870454ab3d384102cd22eb789f82565..92e6f5f91f55f6cb958ac128ecd4eb0f951796c5 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-1999, 2001-2007, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 1996-1999,2001-2007,2009,2010 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
 
@@ -71,6 +71,9 @@ static const struct
 };
 #define ndatabases (sizeof (databases) / sizeof (databases[0]))
 
+/* Flags whether custom rules for database is set.  */
+bool __nss_database_custom[NSS_DBSIDX_max];
+
 
 __libc_lock_define_initialized (static, lock)
 
@@ -265,6 +268,7 @@ __nss_configure_lookup (const char *dbname, const char *service_line)
 
   /* Install new rules.  */
   *databases[cnt].dbp = new_db;
+  __nss_database_custom[cnt] = true;
 
   __libc_lock_unlock (lock);
 
index b80edef651dde3bf10495c5f421f4c890605b11c..ae5657e88919ffce6024586c9d5ef1df7b54734a 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-1999,2001,2002,2003,2004,2007
+/* Copyright (C) 1996-1999,2001,2002,2003,2004,2007,2010
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -28,6 +28,7 @@
 #include <resolv.h>
 #include <search.h>
 #include <dlfcn.h>
+#include <stdbool.h>
 
 /* Actions performed after lookup finished.  */
 typedef enum
@@ -96,6 +97,19 @@ typedef struct name_database
 } name_database;
 
 
+/* Indices into DATABASES in nsswitch.c and __NSS_DATABASE_CUSTOM.  */
+enum
+  {
+#define DEFINE_DATABASE(arg) NSS_DBSIDX_##arg,
+#include "databases.def"
+#undef DEFINE_DATABASE
+    NSS_DBSIDX_max
+  };
+
+/* Flags whether custom rules for database is set.  */
+extern bool __nss_database_custom[NSS_DBSIDX_max];
+
+
 /* Interface functions for NSS.  */
 
 /* Get the data structure representing the specified database.
diff --git a/nss/tst-nss-test1.c b/nss/tst-nss-test1.c
new file mode 100644 (file)
index 0000000..4e443d4
--- /dev/null
@@ -0,0 +1,72 @@
+#include <nss.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+static int
+do_test (void)
+{
+  int retval = 0;
+
+  __nss_configure_lookup ("passwd", "test1");
+
+  static const unsigned int pwdids[] = { 100, 30, 200, 60, 20000 };
+#define npwdids (sizeof (pwdids) / sizeof (pwdids[0]))
+  setpwent ();
+
+  const unsigned int *np = pwdids;
+  for (struct passwd *p = getpwent (); p != NULL; ++np, p = getpwent ())
+    if (p->pw_uid != *np || strncmp (p->pw_name, "name", 4) != 0
+       || atol (p->pw_name + 4) != *np)
+      {
+       printf ("passwd entry %ju wrong (%s, %u)\n",
+               np - pwdids, p->pw_name, p->pw_uid);
+       retval = 1;
+       break;
+      }
+
+  endpwent ();
+
+  for (int i = npwdids - 1; i >= 0; --i)
+    {
+      char buf[30];
+      snprintf (buf, sizeof (buf), "name%u", pwdids[i]);
+
+      struct passwd *p = getpwnam (buf);
+      if (p == NULL || p->pw_uid != pwdids[i] || strcmp (buf, p->pw_name) != 0)
+       {
+         printf ("passwd entry \"%s\" wrong\n", buf);
+         retval = 1;
+       }
+
+      p = getpwuid (pwdids[i]);
+      if (p == NULL || p->pw_uid != pwdids[i] || strcmp (buf, p->pw_name) != 0)
+       {
+         printf ("passwd entry %u wrong\n", pwdids[i]);
+         retval = 1;
+       }
+
+      snprintf (buf, sizeof (buf), "name%u", pwdids[i] + 1);
+
+      p = getpwnam (buf);
+      if (p != NULL)
+       {
+         printf ("passwd entry \"%s\" wrong\n", buf);
+         retval = 1;
+       }
+
+      p = getpwuid (pwdids[i] + 1);
+      if (p != NULL)
+       {
+         printf ("passwd entry %u wrong\n", pwdids[i] + 1);
+         retval = 1;
+       }
+    }
+
+  return retval;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
index 65e772bbb5ffd631e4f7a83e3581e8c09dd30122..d3e840752252235af195fc4be6f351c6e7c6f662 100644 (file)
@@ -114,6 +114,10 @@ alpha.*-.*-linux.* libresolv=2.1
 .*-.*-.*               libnss_ldap=2
 .*-.*-.*               libnss_hesiod=2
 
+# Tests for NSS.  They must have the same NSS_SHLIB_REVISION number as
+# the rest.
+.*-.*-.*               libnss_test1=2
+
 # Version for libnsl with YP and NIS+ functions.
 alpha.*-.*-linux.*     libnsl=1.1
 .*-.*-.*               libnsl=1
index 2e0c7248f09e60976fe91dfbe6724564bd0b5c31..126a09ea339a15387e2e17d2222f72187c542558 100644 (file)
@@ -600,7 +600,8 @@ gaih_inet (const char *name, const struct gaih_service *service,
              && ++__nss_not_use_nscd_hosts > NSS_NSCD_RETRY)
            __nss_not_use_nscd_hosts = 0;
 
-         if (!__nss_not_use_nscd_hosts)
+         if (!__nss_not_use_nscd_hosts
+             && !__nss_database_custom[NSS_DBSIDX_hosts])
            {
              /* Try to use nscd.  */
              struct nscd_ai_result *air = NULL;