Sophie

Sophie

distrib > Fedora > 13 > i386 > media > updates-src > by-pkgid > 4b866545d03360c56a47dc93f05762a2 > files > 2

nss_db-2.2.3-0.5.pre1.fc13.src.rpm

diff -up ./src/db-initgroups.c.initgr ./src/db-initgroups.c
--- a/src/db-initgroups.c.initgr	2011-04-21 13:37:34.913687000 -0400
+++ b/src/db-initgroups.c	2011-04-21 14:13:11.826667000 -0400
@@ -0,0 +1,192 @@
+/* Initgroups handling in nss_db module.
+   Copyright (C) 2011 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <alloca.h>
+#include <ctype.h>
+#include <errno.h>
+#include <grp.h>
+#include <paths.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+
+#include "nss_db.h"
+
+/* Declared in glibc's include/grp.h.  */
+extern int _nss_files_parse_grent (char *line, struct group *result,
+                                   void *data, size_t datalen, int *errnop);
+
+
+enum nss_status
+_nss_db_initgroups_dyn (const char *user, gid_t group, long int *start,
+			long int *size, gid_t **groupsp, long int limit,
+			int *errnop)
+{
+  DB *db = NULL;
+  DB_ENV *dbenv = NULL;
+
+  /* Open the database.  */
+  enum nss_status status = internal_setent (_PATH_VARDB "group.db", &db,
+					    &dbenv);
+  if (status == NSS_STATUS_SUCCESS)
+    {
+      unsigned int entidx = 0;
+
+      size_t linelen = 1024;
+      void *line = alloca (linelen);
+      bool line_use_malloc = false;
+
+      size_t buflen = 1024;
+      void *buffer = alloca (buflen);
+      bool buffer_use_malloc = false;
+
+      size_t alloca_used = linelen + buflen;
+
+      gid_t *groups = *groupsp;
+
+      while (1)
+	{
+	  char buf[20];
+	  DBT key;
+
+	  key.size = snprintf (key.data = buf, sizeof buf, "0%u", entidx++);
+	  key.flags = 0;
+
+	  DBT value;
+	  value.flags = 0;
+	  int err = db->get (db, NULL, &key, &value, 0);
+	  if (err)
+	    {
+	      if (err != DB_NOTFOUND)
+		{
+		  if (err > 0)
+		    *errnop = err;
+		  status = NSS_STATUS_UNAVAIL;
+		}
+	      break;
+	    }
+
+	  /* We need a copy of the value we can modify.  */
+	  if (linelen < value.size)
+	    {
+	      size_t newlinelen = MAX (2 * linelen, value.size);
+
+	      if (line_use_malloc 
+		  || ! __libc_use_alloca (alloca_used + newlinelen))
+		{
+		  void *newline = realloc (line_use_malloc ? line : NULL,
+					   newlinelen);
+		  if (newline == NULL)
+		    {
+		      *errnop = ENOMEM;
+		      status = NSS_STATUS_TRYAGAIN;
+		      goto out;
+		    }
+		  line = newline;
+		  linelen = newlinelen;
+		  line_use_malloc = true;
+		}
+	      else
+		{
+		  line = extend_alloca (line, linelen, newlinelen);
+		  alloca_used += newlinelen;
+		}
+	    }
+
+	  /* Copy and find beginning.  */
+	  char *p = memcpy (line, value.data, value.size);
+	  while (isspace (*p))
+	    ++p;
+
+	  struct group grp;
+	  while ((err = _nss_files_parse_grent (p, &grp, buffer, buflen,
+						errnop)) == -1)
+	    {
+	      size_t newbuflen = MAX (2 * buflen, value.size);
+	      if (buffer_use_malloc 
+		  || ! __libc_use_alloca (alloca_used + newbuflen))
+		{
+		  void *newbuf = realloc (buffer_use_malloc ? buffer : NULL,
+					  newbuflen);
+		  if (newbuf == NULL)
+		    {
+		      *errnop = ENOMEM;
+		      status = NSS_STATUS_TRYAGAIN;
+		      goto out;
+		    }
+		  buffer = newbuf;
+		  buflen = newbuflen;
+		  buffer_use_malloc = true;
+		}
+	      else
+		{
+		  buffer = extend_alloca (buffer, buflen, newbuflen);
+		  alloca_used += newbuflen;
+		}
+	    }
+
+	  if (err > 0 && grp.gr_gid != group)
+	    for (char **m = grp.gr_mem; *m != NULL; ++m)
+	      if (strcmp (*m, user) == 0)
+		{
+		  /* Matches user.  Insert this group.  */
+		  if (*start == *size)
+		    {
+		      /* Need a bigger buffer.  */
+		      if (limit > 0 && *size == limit)
+			/* We reached the maximum.  */
+			goto out;
+
+		      long int newsize;
+		      if (limit <= 0)
+			newsize = 2 * *size;
+		      else
+			newsize = MIN (limit, 2 * *size);
+
+		      gid_t *newgroups = realloc (groups,
+						  newsize * sizeof (*groups));
+		      if (newgroups == NULL)
+			{
+			  *errnop = ENOMEM;
+			  status = NSS_STATUS_TRYAGAIN;
+			  goto out;
+			}
+		      *groupsp = groups = newgroups;
+		      *size = newsize;
+		    }
+
+		  groups[*start] = grp.gr_gid;
+		  *start += 1;
+		  
+		  break;
+		}
+	}
+
+    out:
+      if (buffer_use_malloc)
+	free (buffer);
+      if (line_use_malloc)
+	free (line);
+
+      internal_endent (&db, &dbenv);
+    }
+
+  return status;
+}
--- a/src/Makefile.am.initgr	2011-04-21 13:43:11.698540000 -0400
+++ b/src/Makefile.am	2011-04-21 14:12:27.750429000 -0400
@@ -11,14 +11,15 @@ localedir = $(datadir)/locale
 
 noinst_HEADERS = db-compat.h netgroup.h nss_db.h
 
-INCLUDES = @DB_CFLAGS@ -D_GNU_SOURCE \
+INCLUDES = @DB_CFLAGS@ -D_GNU_SOURCE -std=gnu99 \
 	-I../intl -DLOCALEDIR=\"$(localedir)\"
 
 EXTRA_DIST = libnss_db.map
 
 slib_LTLIBRARIES = libnss_db.la
 libnss_db_la_SOURCES = db-alias.c db-ethers.c db-netgrp.c db-grp.c db-proto.c \
-	db-pwd.c db-rpc.c db-service.c db-spwd.c db-compat.c db-open.c
+	db-pwd.c db-rpc.c db-service.c db-spwd.c db-compat.c db-open.c \
+	db-initgroups.c
 EXTRA_libnss_db_la_SOURCES = libnss_db.map db-XXX.c \
 	files-ethers.c files-grp.c files-parse.c files-proto.c files-pwd.c \
 	files-rpc.c files-service.c files-spwd.c
--- a/src/nss_db.h.initgr	2011-04-21 13:37:16.346212000 -0400
+++ b/src/nss_db.h	2011-04-21 14:22:05.644573000 -0400
@@ -31,4 +31,25 @@ extern enum nss_status internal_setent (
 /* Close the database *DBP.  */
 extern void internal_endent (DB **dbp, DB_ENV **dbenvp);
 
+
+/* The following are defined in glibc in include/alloca.h.  */
+extern int __libc_alloca_cutoff (size_t size) __attribute__ ((const));
+#define PTHREAD_STACK_MIN 16384
+#define __libc_use_alloca(size) \
+  (__builtin_expect ((size) <= PTHREAD_STACK_MIN / 4, 1)		      \
+		     || __libc_alloca_cutoff (size))
+#if defined __i386__ || defined __x86_64__
+# define extend_alloca(buf, len, newlen) \
+  (__typeof (buf)) ({ size_t __newlen = (newlen);			      \
+                      char *__newbuf = alloca (__newlen);		      \
+                      if (__newbuf + __newlen == (char *) buf)		      \
+                        len += __newlen;				      \
+                      else						      \
+                        len = __newlen;					      \
+                      __newbuf; })
+#else
+# define extend_alloca(buf, len, newlen) \
+  alloca (((len) = (newlen)))
+#endif
+
 #endif	/* nss_db.h */
--- a/src/libnss_db.map.initgr	2011-04-26 15:31:20.775659000 -0400
+++ b/src/libnss_db.map	2011-04-26 15:31:42.134332000 -0400
@@ -14,6 +14,7 @@
     _nss_db_setaliasent; _nss_db_setetherent; _nss_db_setgrent;
     _nss_db_setnetgrent; _nss_db_setprotoent; _nss_db_setpwent;
     _nss_db_setrpcent; _nss_db_setservent; _nss_db_setspent;
+    _nss_db_initgroups_dyn;
   local:
     *;
 };