summaryrefslogtreecommitdiff
path: root/lib/libc/gen
diff options
context:
space:
mode:
authorTed Unangst <tedu@cvs.openbsd.org>2004-03-05 04:11:52 +0000
committerTed Unangst <tedu@cvs.openbsd.org>2004-03-05 04:11:52 +0000
commitf27b58730fc040b378fef8693bbfc5023b7df0e1 (patch)
treee8d5299819388f20319cea6f14db65f2681daec5 /lib/libc/gen
parent93d6d80307a0cffa73d6b8a221dd479cf08604bf (diff)
don't leak memory. free and netbsd via Patrick Latifi
Diffstat (limited to 'lib/libc/gen')
-rw-r--r--lib/libc/gen/scandir.c66
1 files changed, 37 insertions, 29 deletions
diff --git a/lib/libc/gen/scandir.c b/lib/libc/gen/scandir.c
index 8b51e0c7e3a..c29bb18ffb6 100644
--- a/lib/libc/gen/scandir.c
+++ b/lib/libc/gen/scandir.c
@@ -28,7 +28,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: scandir.c,v 1.7 2003/06/02 20:18:34 millert Exp $";
+static char rcsid[] = "$OpenBSD: scandir.c,v 1.8 2004/03/05 04:11:51 tedu Exp $";
#endif /* LIBC_SCCS and not lint */
/*
@@ -64,16 +64,16 @@ scandir(dirname, namelist, select, dcomp)
int (*select)(struct dirent *);
int (*dcomp)(const void *, const void *);
{
- register struct dirent *d, *p, **names;
- register size_t nitems;
+ struct dirent *d, *p, **names = NULL;
+ size_t nitems = 0;
struct stat stb;
long arraysz;
DIR *dirp;
if ((dirp = opendir(dirname)) == NULL)
- return(-1);
+ return (-1);
if (fstat(dirp->dd_fd, &stb) < 0)
- return(-1);
+ goto fail;
/*
* estimate the array size by taking the size of the directory file
@@ -82,53 +82,61 @@ scandir(dirname, namelist, select, dcomp)
arraysz = (stb.st_size / 24);
if (arraysz > SIZE_T_MAX / sizeof(struct dirent *)) {
errno = ENOMEM;
- return(-1);
+ goto fail;
}
names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
if (names == NULL)
- return(-1);
+ goto fail;
- nitems = 0;
while ((d = readdir(dirp)) != NULL) {
if (select != NULL && !(*select)(d))
continue; /* just selected names */
- /*
- * Make a minimum size copy of the data
- */
- p = (struct dirent *)malloc(DIRSIZ(d));
- if (p == NULL)
- return(-1);
- p->d_ino = d->d_ino;
- p->d_type = d->d_type;
- p->d_reclen = d->d_reclen;
- p->d_namlen = d->d_namlen;
- bcopy(d->d_name, p->d_name, p->d_namlen + 1);
+
/*
* Check to make sure the array has space left and
* realloc the maximum size.
*/
- if (++nitems >= arraysz) {
- register struct dirent **nnames;
+ if (nitems >= arraysz) {
+ struct dirent **nnames;
if (fstat(dirp->dd_fd, &stb) < 0)
- return(-1); /* just might have grown */
+ goto fail;
+
arraysz = stb.st_size / 12;
nnames = (struct dirent **)realloc((char *)names,
arraysz * sizeof(struct dirent *));
- if (nnames == NULL) {
- if (names)
- free(names);
- return(-1);
- }
+ if (nnames == NULL)
+ goto fail;
+
names = nnames;
}
- names[nitems-1] = p;
+
+ /*
+ * Make a minimum size copy of the data
+ */
+ p = (struct dirent *)malloc(DIRSIZ(d));
+ if (p == NULL)
+ goto fail;
+
+ p->d_ino = d->d_ino;
+ p->d_type = d->d_type;
+ p->d_reclen = d->d_reclen;
+ p->d_namlen = d->d_namlen;
+ bcopy(d->d_name, p->d_name, p->d_namlen + 1);
+ names[nitems++] = p;
}
closedir(dirp);
if (nitems && dcomp != NULL)
qsort(names, nitems, sizeof(struct dirent *), dcomp);
*namelist = names;
- return(nitems);
+ return (nitems);
+
+fail:
+ while (nitems > 0)
+ free(names[--nitems]);
+ free(names);
+ closedir(dirp);
+ return (-1);
}
/*