[22/25] glob: Rewrite to use struct scratch_buffer instead of extend_alloca
diff mbox

Message ID 99e4c640472ead8a515764679be90874745dbf4d.1425285061.git.fweimer@redhat.com
State New
Headers show

Commit Message

Florian Weimer March 1, 2015, 6:49 p.m. UTC
---
 posix/glob.c | 147 +++++++++++++----------------------------------------------
 1 file changed, 31 insertions(+), 116 deletions(-)

Patch
diff mbox

diff --git a/posix/glob.c b/posix/glob.c
index 5b92776..f2756f8 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -25,6 +25,7 @@ 
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <stddef.h>
+#include <scratch_buffer.h>
 
 /* Outcomment the following line for production quality code.  */
 /* #define NDEBUG 1 */
@@ -267,7 +268,7 @@  glob (pattern, flags, errfunc, pglob)
   glob_t dirs;
   int retval = 0;
 #ifdef _LIBC
-  size_t alloca_used = 0;
+  size_t alloca_used = sizeof (struct scratch_buffer);
 #endif
 
   if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
@@ -624,33 +625,13 @@  glob (pattern, flags, errfunc, pglob)
 		{
 		  struct passwd *p;
 #   if defined HAVE_GETPWNAM_R || defined _LIBC
-		  long int pwbuflen = GETPW_R_SIZE_MAX ();
-		  char *pwtmpbuf;
 		  struct passwd pwbuf;
-		  int malloc_pwtmpbuf = 0;
 		  int save = errno;
+		  struct scratch_buffer pwtmpbuf;
+		  scratch_buffer_init (&pwtmpbuf);
 
-#    ifndef _LIBC
-		  if (pwbuflen == -1)
-		    /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.
-		       Try a moderate value.  */
-		    pwbuflen = 1024;
-#    endif
-		  if (__libc_use_alloca (alloca_used + pwbuflen))
-		    pwtmpbuf = alloca_account (pwbuflen, alloca_used);
-		  else
-		    {
-		      pwtmpbuf = malloc (pwbuflen);
-		      if (pwtmpbuf == NULL)
-			{
-			  retval = GLOB_NOSPACE;
-			  goto out;
-			}
-		      malloc_pwtmpbuf = 1;
-		    }
-
-		  while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
-			 != 0)
+		  while (getpwnam_r (name, &pwbuf,
+				     pwtmpbuf.data, pwtmpbuf.length, &p) != 0)
 		    {
 		      if (errno != ERANGE)
 			{
@@ -658,67 +639,37 @@  glob (pattern, flags, errfunc, pglob)
 			  break;
 			}
 
-		      if (!malloc_pwtmpbuf
-			  && __libc_use_alloca (alloca_used
-						+ 2 * pwbuflen))
-			pwtmpbuf = extend_alloca_account (pwtmpbuf, pwbuflen,
-							  2 * pwbuflen,
-							  alloca_used);
-		      else
+		      if (!scratch_buffer_grow (&pwtmpbuf))
 			{
-			  char *newp = realloc (malloc_pwtmpbuf
-						? pwtmpbuf : NULL,
-						2 * pwbuflen);
-			  if (newp == NULL)
-			    {
-			      if (__glibc_unlikely (malloc_pwtmpbuf))
-				free (pwtmpbuf);
-			      retval = GLOB_NOSPACE;
-			      goto out;
-			    }
-			  pwtmpbuf = newp;
-			  pwbuflen = 2 * pwbuflen;
-			  malloc_pwtmpbuf = 1;
+			  retval = GLOB_NOSPACE;
+			  goto out;
 			}
 		      __set_errno (save);
 		    }
 #   else
-		  p = getpwnam (name);
+		  p = getpwnam (namebuf.data);
 #   endif
 		  if (p != NULL)
 		    {
-		      if (!malloc_pwtmpbuf)
-			home_dir = p->pw_dir;
-		      else
+		      home_dir = strdup (p->pw_dir);
+		      malloc_home_dir = 1;
+		      if (home_dir == NULL)
 			{
-			  size_t home_dir_len = strlen (p->pw_dir) + 1;
-			  if (__libc_use_alloca (alloca_used + home_dir_len))
-			    home_dir = alloca_account (home_dir_len,
-						       alloca_used);
-			  else
-			    {
-			      home_dir = malloc (home_dir_len);
-			      if (home_dir == NULL)
-				{
-				  free (pwtmpbuf);
-				  retval = GLOB_NOSPACE;
-				  goto out;
-				}
-			      malloc_home_dir = 1;
-			    }
-			  memcpy (home_dir, p->pw_dir, home_dir_len);
-
-			  free (pwtmpbuf);
+			  scratch_buffer_free (&pwtmpbuf);
+			  retval = GLOB_NOSPACE;
+			  goto out;
 			}
 		    }
+		  scratch_buffer_free (&pwtmpbuf);
 		}
 	    }
 	  if (home_dir == NULL || home_dir[0] == '\0')
 	    {
+	      if (malloc_home_dir)
+		free (home_dir);
+	      malloc_home_dir = 0;
 	      if (flags & GLOB_TILDE_CHECK)
 		{
-		  if (__glibc_unlikely (malloc_home_dir))
-		    free (home_dir);
 		  retval = GLOB_NOMATCH;
 		  goto out;
 		}
@@ -839,57 +790,24 @@  glob (pattern, flags, errfunc, pglob)
 	  {
 	    struct passwd *p;
 #  if defined HAVE_GETPWNAM_R || defined _LIBC
-	    long int buflen = GETPW_R_SIZE_MAX ();
-	    char *pwtmpbuf;
-	    int malloc_pwtmpbuf = 0;
 	    struct passwd pwbuf;
 	    int save = errno;
+	    struct scratch_buffer pwtmpbuf;
+	    scratch_buffer_init (&pwtmpbuf);
 
-#   ifndef _LIBC
-	    if (buflen == -1)
-	      /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.  Try a
-		 moderate value.  */
-	      buflen = 1024;
-#   endif
-	    if (__libc_use_alloca (alloca_used + buflen))
-	      pwtmpbuf = alloca_account (buflen, alloca_used);
-	    else
-	      {
-		pwtmpbuf = malloc (buflen);
-		if (pwtmpbuf == NULL)
-		  {
-		  nomem_getpw:
-		    if (__glibc_unlikely (malloc_user_name))
-		      free (user_name);
-		    retval = GLOB_NOSPACE;
-		    goto out;
-		  }
-		malloc_pwtmpbuf = 1;
-	      }
-
-	    while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
+	    while (getpwnam_r (user_name, &pwbuf,
+			       pwtmpbuf.data, pwtmpbuf.length, &p) != 0)
 	      {
 		if (errno != ERANGE)
 		  {
 		    p = NULL;
 		    break;
 		  }
-		if (!malloc_pwtmpbuf
-		    && __libc_use_alloca (alloca_used + 2 * buflen))
-		  pwtmpbuf = extend_alloca_account (pwtmpbuf, buflen,
-						    2 * buflen, alloca_used);
-		else
+
+		if (!scratch_buffer_grow (&pwtmpbuf))
 		  {
-		    char *newp = realloc (malloc_pwtmpbuf ? pwtmpbuf : NULL,
-					  2 * buflen);
-		    if (newp == NULL)
-		      {
-			if (__glibc_unlikely (malloc_pwtmpbuf))
-			  free (pwtmpbuf);
-			goto nomem_getpw;
-		      }
-		    pwtmpbuf = newp;
-		    malloc_pwtmpbuf = 1;
+		    retval = GLOB_NOSPACE;
+		    goto out;
 		  }
 		__set_errno (save);
 	      }
@@ -918,8 +836,7 @@  glob (pattern, flags, errfunc, pglob)
 		    dirname = malloc (home_len + rest_len + 1);
 		    if (dirname == NULL)
 		      {
-			if (__glibc_unlikely (malloc_pwtmpbuf))
-			  free (pwtmpbuf);
+			scratch_buffer_free (&pwtmpbuf);
 			retval = GLOB_NOSPACE;
 			goto out;
 		      }
@@ -931,13 +848,11 @@  glob (pattern, flags, errfunc, pglob)
 		dirlen = home_len + rest_len;
 		dirname_modified = 1;
 
-		if (__glibc_unlikely (malloc_pwtmpbuf))
-		  free (pwtmpbuf);
+		scratch_buffer_free (&pwtmpbuf);
 	      }
 	    else
 	      {
-		if (__glibc_unlikely (malloc_pwtmpbuf))
-		  free (pwtmpbuf);
+		scratch_buffer_free (&pwtmpbuf);
 
 		if (flags & GLOB_TILDE_CHECK)
 		  /* We have to regard it as an error if we cannot find the