2008-11-24 Joel Sherrill <joel.sherrill@oarcorp.com>

* libc/posix/scandir.c: Fix memory leaks.
This commit is contained in:
Jeff Johnston 2008-11-24 20:42:33 +00:00
parent b45d16228b
commit df913771a7
2 changed files with 44 additions and 35 deletions

View File

@ -1,3 +1,7 @@
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

View 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);
}
/*