]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
(lookup): Always set errno and h_errno if
authorUlrich Drepper <drepper@redhat.com>
Fri, 30 Jan 1998 17:14:18 +0000 (17:14 +0000)
committerUlrich Drepper <drepper@redhat.com>
Fri, 30 Jan 1998 17:14:18 +0000 (17:14 +0000)
applicable.  Fix return value and error checking.
(CONCAT(_nss_db_get,ENTNAME_r)): Loop around to skip over unparsable lines.
(DB_LOOKUP): Allocate space for terminating null byte. [PR libc/404]

nss/nss_db/db-XXX.c

index 22a24aae5b1c5c7512a3c2d5f08ab6b70e3dadc3..edf9de81c539838aa7eaaef4dbb6709c4835a54c 100644 (file)
@@ -1,5 +1,5 @@
 /* Common code for DB-based databases in nss_db module.
-   Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998 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
@@ -149,18 +149,65 @@ static enum nss_status
 lookup (const DBT *key, struct STRUCTURE *result,
        void *buffer, int buflen H_ERRNO_PROTO)
 {
+  char *p;
   enum nss_status status;
+  int err;
   DBT value;
 
   /* Open the database.  */
   status = internal_setent (keep_db);
   if (status != NSS_STATUS_SUCCESS)
-    return status;
+    {
+      H_ERRNO_SET (NETDB_INTERNAL);
+      return status;
+    }
 
   /* Succeed iff it matches a value that parses correctly.  */
-  status = (((*db->get) (db, key, &value, 0) == 0 &&
-            parse_line (value.data, result, buffer, buflen))
-           ? NSS_STATUS_SUCCESS : NSS_STATUS_NOTFOUND);
+  err = (*db->get) (db, key, &value, 0);
+  if (err < 0)
+    {
+      H_ERRNO_SET (NETDB_INTERNAL);
+      status = NSS_STATUS_UNAVAIL;
+    }
+  else if (err != 0)
+    {
+      H_ERRNO_SET (HOST_NOT_FOUND);
+      status = NSS_STATUS_NOTFOUND;
+    }
+  else
+    {
+      /* Skip leading blanks.  */
+      p = (char *) value.data;
+      while (isspace (*p))
+       ++p;
+
+      err = parse_line (p, result, buffer, buflen);
+
+      if (err == 0)
+       {
+         /* If the key begins with '0' we are trying to get the next
+            entry.  We want to ignore unparsable lines in this case.  */
+         if (((char *) key->data)[0] == '0')
+           {
+             /* Super magical return value.  We need to tell our caller
+                that it should continue looping.  This value cannot
+                happen in other cases.  */
+             status = NSS_STATUS_RETURN;
+           }
+         else
+           {
+             H_ERRNO_SET (HOST_NOT_FOUND);
+             status = NSS_STATUS_NOTFOUND;
+           }
+       }
+      else if (err < 0)
+       {
+         H_ERRNO_SET (NETDB_INTERNAL);
+         status = NSS_STATUS_TRYAGAIN;
+       }
+      else
+       status = NSS_STATUS_SUCCESS;
+    }
 
   if (! keep_db)
     internal_endent ();
@@ -192,7 +239,7 @@ _nss_db_get##name##_r (proto,                                                     \
 {                                                                            \
   DBT key;                                                                   \
   enum nss_status status;                                                    \
-  const size_t size = (keysize);                                             \
+  const size_t size = (keysize) + 1;                                         \
   key.data = __alloca (size);                                                \
   key.size = KEYPRINTF keypattern;                                           \
   __libc_lock_lock (lock);                                                   \
@@ -217,8 +264,14 @@ CONCAT(_nss_db_get,ENTNAME_r) (struct STRUCTURE *result,
   DBT key;
 
   __libc_lock_lock (lock);
-  key.size = 1 + snprintf (key.data = buf, sizeof buf, "0%u", entidx++);
-  status = lookup (&key, result, buffer, buflen H_ERRNO_ARG);
+  /* Loop until we find a valid entry or hit EOF.  See above for the
+     special meaning of the status value.  */
+  do
+    {
+      key.size = snprintf (key.data = buf, sizeof buf, "0%u", entidx++);
+      status = lookup (&key, result, buffer, buflen H_ERRNO_ARG);
+    }
+  while (status == NSS_STATUS_RETURN);
   __libc_lock_unlock (lock);
 
   return status;