fa3bfd
commit 9a3c6a6ff602c88d7155139a7d7d0000b7b7e946
fa3bfd
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
fa3bfd
Date:   Thu Jan 2 10:05:27 2014 +0530
fa3bfd
fa3bfd
    Fix return code from getent netgroup when the netgroup is not found (bz #16366)
fa3bfd
12745e
diff -pruN glibc-2.17-c758a686/nscd/netgroupcache.c glibc-2.17-c758a686/nscd/netgroupcache.c
12745e
--- glibc-2.17-c758a686/nscd/netgroupcache.c	2013-12-03 20:41:12.000000000 -0500
12745e
+++ glibc-2.17-c758a686/nscd/netgroupcache.c	2013-12-19 08:36:52.253000000 -0500
2e9afc
@@ -65,6 +65,55 @@ struct dataset
2e9afc
   char strdata[0];
2e9afc
 };
2e9afc
 
2e9afc
+/* Sends a notfound message and prepares a notfound dataset to write to the
2e9afc
+   cache.  Returns true if there was enough memory to allocate the dataset and
2e9afc
+   returns the dataset in DATASETP, total bytes to write in TOTALP and the
2e9afc
+   timeout in TIMEOUTP.  KEY_COPY is set to point to the copy of the key in the
2e9afc
+   dataset. */
2e9afc
+static bool
2e9afc
+do_notfound (struct database_dyn *db, int fd, request_header *req,
2e9afc
+	       const char *key, struct dataset **datasetp, ssize_t *totalp,
2e9afc
+	       time_t *timeoutp, char **key_copy)
2e9afc
+{
2e9afc
+  struct dataset *dataset;
2e9afc
+  ssize_t total;
2e9afc
+  time_t timeout;
2e9afc
+  bool cacheable = false;
2e9afc
+
2e9afc
+  total = sizeof (notfound);
2e9afc
+  timeout = time (NULL) + db->negtimeout;
2e9afc
+
2e9afc
+  if (fd != -1)
2e9afc
+    TEMP_FAILURE_RETRY (send (fd, &notfound, total, MSG_NOSIGNAL));
2e9afc
+
2e9afc
+  dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, 1);
2e9afc
+  /* If we cannot permanently store the result, so be it.  */
2e9afc
+  if (dataset != NULL)
2e9afc
+    {
2e9afc
+      dataset->head.allocsize = sizeof (struct dataset) + req->key_len;
2e9afc
+      dataset->head.recsize = total;
2e9afc
+      dataset->head.notfound = true;
2e9afc
+      dataset->head.nreloads = 0;
2e9afc
+      dataset->head.usable = true;
2e9afc
+
2e9afc
+      /* Compute the timeout time.  */
2e9afc
+      timeout = dataset->head.timeout = time (NULL) + db->negtimeout;
2e9afc
+      dataset->head.ttl = db->negtimeout;
2e9afc
+
2e9afc
+      /* This is the reply.  */
2e9afc
+      memcpy (&dataset->resp, &notfound, total);
2e9afc
+
2e9afc
+      /* Copy the key data.  */
2e9afc
+      memcpy (dataset->strdata, key, req->key_len);
2e9afc
+      *key_copy = dataset->strdata;
2e9afc
+
2e9afc
+      cacheable = true;
2e9afc
+    }
2e9afc
+  *timeoutp = timeout;
2e9afc
+  *totalp = total;
2e9afc
+  *datasetp = dataset;
2e9afc
+  return cacheable;
2e9afc
+}
2e9afc
 
2e9afc
 static time_t
2e9afc
 addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
2e9afc
@@ -84,6 +133,7 @@ addgetnetgrentX (struct database_dyn *db
2e9afc
   struct dataset *dataset;
2e9afc
   bool cacheable = false;
2e9afc
   ssize_t total;
2e9afc
+  bool found = false;
2e9afc
 
2e9afc
   char *key_copy = NULL;
2e9afc
   struct __netgrent data;
2e9afc
@@ -103,35 +153,8 @@ addgetnetgrentX (struct database_dyn *db
2e9afc
       && __nss_database_lookup ("netgroup", NULL, NULL, &netgroup_database))
2e9afc
     {
2e9afc
       /* No such service.  */
2e9afc
-      total = sizeof (notfound);
2e9afc
-      timeout = time (NULL) + db->negtimeout;
2e9afc
-
2e9afc
-      if (fd != -1)
2e9afc
-	TEMP_FAILURE_RETRY (send (fd, &notfound, total, MSG_NOSIGNAL));
2e9afc
-
2e9afc
-      dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, 1);
2e9afc
-      /* If we cannot permanently store the result, so be it.  */
2e9afc
-      if (dataset != NULL)
2e9afc
-	{
2e9afc
-	  dataset->head.allocsize = sizeof (struct dataset) + req->key_len;
2e9afc
-	  dataset->head.recsize = total;
2e9afc
-	  dataset->head.notfound = true;
2e9afc
-	  dataset->head.nreloads = 0;
2e9afc
-	  dataset->head.usable = true;
2e9afc
-
2e9afc
-	  /* Compute the timeout time.  */
2e9afc
-	  timeout = dataset->head.timeout = time (NULL) + db->negtimeout;
2e9afc
-	  dataset->head.ttl = db->negtimeout;
2e9afc
-
2e9afc
-	  /* This is the reply.  */
2e9afc
-	  memcpy (&dataset->resp, &notfound, total);
2e9afc
-
2e9afc
-	  /* Copy the key data.  */
2e9afc
-	  memcpy (dataset->strdata, key, req->key_len);
2e9afc
-
2e9afc
-	  cacheable = true;
2e9afc
-	}
2e9afc
-
2e9afc
+      cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout,
2e9afc
+			       &key_copy);
2e9afc
       goto writeout;
2e9afc
     }
2e9afc
 
2e9afc
@@ -167,6 +190,7 @@ addgetnetgrentX (struct database_dyn *db
2e9afc
 
2e9afc
 	  if (status == NSS_STATUS_SUCCESS)
2e9afc
 	    {
2e9afc
+	      found = true;
2e9afc
 	      union
2e9afc
 	      {
2e9afc
 		enum nss_status (*f) (struct __netgrent *, char *, size_t,
2e9afc
@@ -325,6 +349,15 @@ addgetnetgrentX (struct database_dyn *db
2e9afc
 	}
2e9afc
     }
2e9afc
 
2e9afc
+  /* No results.  Return a failure and write out a notfound record in the
2e9afc
+     cache.  */
2e9afc
+  if (!found)
2e9afc
+    {
2e9afc
+      cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout,
2e9afc
+			       &key_copy);
2e9afc
+      goto writeout;
2e9afc
+    }
2e9afc
+
2e9afc
   total = buffilled;
2e9afc
 
2e9afc
   /* Fill in the dataset.  */