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> 2008-11-24 Joel Sherrill <joel.sherrill@oarcorp.com>
* libc/posix/Makefile.am: Compile readdir_r.c * libc/posix/Makefile.am: Compile readdir_r.c

View File

@ -78,18 +78,25 @@ _DEFUN(scandir, (dirname, namelist, select, dcomp),
struct stat stb; struct stat stb;
long arraysz; long arraysz;
DIR *dirp; DIR *dirp;
int successful = 0;
int rc = 0;
dirp = NULL;
names = NULL;
if ((dirp = opendir(dirname)) == NULL) if ((dirp = opendir(dirname)) == NULL)
return(-1); return(-1);
#ifdef HAVE_DD_LOCK #ifdef HAVE_DD_LOCK
__lock_acquire_recursive(dirp->dd_lock); __lock_acquire_recursive(dirp->dd_lock);
#endif #endif
if (fstat(dirp->dd_fd, &stb) < 0) { if (fstat(dirp->dd_fd, &stb) < 0)
#ifdef HAVE_DD_LOCK goto cleanup;
__lock_release_recursive(dirp->dd_lock);
#endif /*
return(-1); * 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 * 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); arraysz = (stb.st_size / 24);
names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *)); names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
if (names == NULL) { if (names == NULL)
#ifdef HAVE_DD_LOCK goto cleanup;
__lock_release_recursive(dirp->dd_lock);
#endif
return(-1);
}
nitems = 0; nitems = 0;
while ((d = readdir(dirp)) != NULL) { while ((d = readdir(dirp)) != NULL) {
@ -112,12 +115,8 @@ _DEFUN(scandir, (dirname, namelist, select, dcomp),
* Make a minimum size copy of the data * Make a minimum size copy of the data
*/ */
p = (struct dirent *)malloc(DIRSIZ(d)); p = (struct dirent *)malloc(DIRSIZ(d));
if (p == NULL) { if (p == NULL)
#ifdef HAVE_DD_LOCK goto cleanup;
__lock_release_recursive(dirp->dd_lock);
#endif
return(-1);
}
p->d_ino = d->d_ino; p->d_ino = d->d_ino;
p->d_reclen = d->d_reclen; p->d_reclen = d->d_reclen;
#ifdef _DIRENT_HAVE_D_NAMLEN #ifdef _DIRENT_HAVE_D_NAMLEN
@ -131,32 +130,38 @@ _DEFUN(scandir, (dirname, namelist, select, dcomp),
* realloc the maximum size. * realloc the maximum size.
*/ */
if (++nitems >= arraysz) { if (++nitems >= arraysz) {
if (fstat(dirp->dd_fd, &stb) < 0) { if (fstat(dirp->dd_fd, &stb) < 0)
#ifdef HAVE_DD_LOCK goto cleanup;
__lock_release_recursive(dirp->dd_lock);
#endif
return(-1); /* just might have grown */
}
arraysz = stb.st_size / 12; arraysz = stb.st_size / 12;
names = (struct dirent **)realloc((char *)names, names = (struct dirent **)reallocf((char *)names,
arraysz * sizeof(struct dirent *)); arraysz * sizeof(struct dirent *));
if (names == NULL) { if (names == NULL)
#ifdef HAVE_DD_LOCK goto cleanup;
__lock_release_recursive(dirp->dd_lock);
#endif
return(-1);
}
} }
names[nitems-1] = p; names[nitems-1] = p;
} }
successful = 1;
cleanup:
closedir(dirp); closedir(dirp);
if (nitems && dcomp != NULL) if (successful) {
qsort(names, nitems, sizeof(struct dirent *), (void *)dcomp); if (nitems && dcomp != NULL)
*namelist = names; 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 #ifdef HAVE_DD_LOCK
__lock_release_recursive(dirp->dd_lock); __lock_release_recursive(dirp->dd_lock);
#endif #endif
return(nitems); return(rc);
} }
/* /*