OSDN Git Service

2008-11-24 Joel Sherrill <joel.sherrill@oarcorp.com>
authorjjohnstn <jjohnstn>
Mon, 24 Nov 2008 20:42:33 +0000 (20:42 +0000)
committerjjohnstn <jjohnstn>
Mon, 24 Nov 2008 20:42:33 +0000 (20:42 +0000)
        * libc/posix/scandir.c: Fix memory leaks.

newlib/ChangeLog
newlib/libc/posix/scandir.c

index 1a8c559..5e676cf 100644 (file)
@@ -1,5 +1,9 @@
 2008-11-24  Joel Sherrill <joel.sherrill@oarcorp.com>
 
+       * libc/posix/scandir.c: Fix memory leaks. 
+
+2008-11-24  Joel Sherrill <joel.sherrill@oarcorp.com>
+
        * libc/posix/Makefile.am: Compile readdir_r.c
        * libc/posix/Makefile.in: Regenerated.
 
index ef3e9db..96a66de 100644 (file)
@@ -78,18 +78,25 @@ _DEFUN(scandir, (dirname, namelist, select, dcomp),
        struct stat stb;
        long arraysz;
        DIR *dirp;
+       int successful = 0;
+       int rc = 0;
+
+       dirp = NULL;
+       names = NULL;
 
        if ((dirp = opendir(dirname)) == NULL)
                return(-1);
 #ifdef HAVE_DD_LOCK
        __lock_acquire_recursive(dirp->dd_lock);
 #endif
-       if (fstat(dirp->dd_fd, &stb) < 0) {
-#ifdef HAVE_DD_LOCK
-               __lock_release_recursive(dirp->dd_lock);
-#endif
-               return(-1);
-       }
+       if (fstat(dirp->dd_fd, &stb) < 0)
+               goto cleanup;
+
+       /*
+        * If there were no directory entries, then bail.
+        */
+       if (stb.st_size == 0)
+               goto cleanup;
 
        /*
         * estimate the array size by taking the size of the directory file
@@ -97,12 +104,8 @@ _DEFUN(scandir, (dirname, namelist, select, dcomp),
         */
        arraysz = (stb.st_size / 24);
        names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
-       if (names == NULL) {
-#ifdef HAVE_DD_LOCK
-               __lock_release_recursive(dirp->dd_lock);
-#endif
-               return(-1);
-       }
+       if (names == NULL)
+               goto cleanup;
 
        nitems = 0;
        while ((d = readdir(dirp)) != NULL) {
@@ -112,12 +115,8 @@ _DEFUN(scandir, (dirname, namelist, select, dcomp),
                 * Make a minimum size copy of the data
                 */
                p = (struct dirent *)malloc(DIRSIZ(d));
-               if (p == NULL) {
-#ifdef HAVE_DD_LOCK
-                       __lock_release_recursive(dirp->dd_lock);
-#endif
-                       return(-1);
-               }
+               if (p == NULL)
+                       goto cleanup;
                p->d_ino = d->d_ino;
                p->d_reclen = d->d_reclen;
 #ifdef _DIRENT_HAVE_D_NAMLEN
@@ -131,32 +130,38 @@ _DEFUN(scandir, (dirname, namelist, select, dcomp),
                 * realloc the maximum size.
                 */
                if (++nitems >= arraysz) {
-                       if (fstat(dirp->dd_fd, &stb) < 0) {
-#ifdef HAVE_DD_LOCK
-                               __lock_release_recursive(dirp->dd_lock);
-#endif
-                               return(-1);     /* just might have grown */
-                       }
+                       if (fstat(dirp->dd_fd, &stb) < 0)
+                               goto cleanup;
                        arraysz = stb.st_size / 12;
-                       names = (struct dirent **)realloc((char *)names,
+                       names = (struct dirent **)reallocf((char *)names,
                                arraysz * sizeof(struct dirent *));
-                       if (names == NULL) {
-#ifdef HAVE_DD_LOCK
-                               __lock_release_recursive(dirp->dd_lock);
-#endif
-                               return(-1);
-                       }
+                       if (names == NULL)
+                               goto cleanup;
                }
                names[nitems-1] = p;
        }
+       successful = 1;
+cleanup:
        closedir(dirp);
-       if (nitems && dcomp != NULL)
-               qsort(names, nitems, sizeof(struct dirent *), (void *)dcomp);
-       *namelist = names;
+       if (successful) {
+               if (nitems && dcomp != NULL)
+                       qsort(names, nitems, sizeof(struct dirent *), (void *)dcomp);
+               *namelist = names;
+               rc = nitems;
+       } else {  /* We were unsuccessful, clean up storage and return -1.  */
+               if ( names ) {
+                       int i;
+                       for (i=0; i < nitems; i++ )
+                               free( names[i] );
+                       free( names );
+               }
+               rc = -1;
+       }
+
 #ifdef HAVE_DD_LOCK
        __lock_release_recursive(dirp->dd_lock);
 #endif
-       return(nitems);
+       return(rc);
 }
 
 /*