diff options
author | Otto Moerbeek <otto@cvs.openbsd.org> | 2004-11-26 20:09:57 +0000 |
---|---|---|
committer | Otto Moerbeek <otto@cvs.openbsd.org> | 2004-11-26 20:09:57 +0000 |
commit | 4157921535281a74d8ad3b91b803cdead55d4792 (patch) | |
tree | 4e0c47ae0cd75348e395d1bb67a81e2e3abbfc9c /usr.bin | |
parent | 8f40035a88fee575709a5aa28fed7b098e3854ad (diff) |
Fix the getdirentries() loop memory handling and EOF detection.
Also fix typo in sizeof. Problem spotted by YAMAMOTO Takashi; this
diff joint work with millert@
ok millert@
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/diff/diffdir.c | 37 |
1 files changed, 22 insertions, 15 deletions
diff --git a/usr.bin/diff/diffdir.c b/usr.bin/diff/diffdir.c index 1a870701533..771052243fb 100644 --- a/usr.bin/diff/diffdir.c +++ b/usr.bin/diff/diffdir.c @@ -1,4 +1,4 @@ -/* $OpenBSD: diffdir.c,v 1.28 2004/10/02 18:13:24 millert Exp $ */ +/* $OpenBSD: diffdir.c,v 1.29 2004/11/26 20:09:56 otto Exp $ */ /* * Copyright (c) 2003 Todd C. Miller <Todd.Miller@courtesan.com> @@ -21,7 +21,7 @@ */ #ifndef lint -static const char rcsid[] = "$OpenBSD: diffdir.c,v 1.28 2004/10/02 18:13:24 millert Exp $"; +static const char rcsid[] = "$OpenBSD: diffdir.c,v 1.29 2004/11/26 20:09:56 otto Exp $"; #endif /* not lint */ #include <sys/param.h> @@ -165,7 +165,7 @@ static struct dirent ** slurpdir(char *path, char **bufp, int enoentok) { char *buf, *ebuf, *cp; - size_t bufsize; + size_t bufsize, have, need; long base; int fd, nbytes, entries; struct stat sb; @@ -181,28 +181,35 @@ slurpdir(char *path, char **bufp, int enoentok) } return (&dummy); } - fstat(fd, &sb); + if (fstat(fd, &sb) == -1) { + warn("%s", path); + close(fd); + return (NULL); + } + + need = roundup(sb.st_blksize, sizeof(struct dirent)); + have = bufsize = roundup(MAX(sb.st_size, sb.st_blksize), + sizeof(struct dirent)) + need; + ebuf = buf = emalloc(bufsize); - bufsize = 0; - ebuf = buf = NULL; do { - bufsize += roundup(MAX(sb.st_size, sb.st_blksize), - sizeof(struct dirent)); - if (buf == NULL) - buf = ebuf = emalloc(bufsize); - else { + if (have < need) { + bufsize += need; + have += need; cp = erealloc(buf, bufsize); ebuf = cp + (ebuf - buf); buf = cp; } - nbytes = getdirentries(fd, ebuf, bufsize, &base); + nbytes = getdirentries(fd, ebuf, have, &base); if (nbytes == -1) { - free(buf); warn("%s", path); + free(buf); + close(fd); return (NULL); } ebuf += nbytes; - } while (nbytes == bufsize); + have -= nbytes; + } while (nbytes != 0); close(fd); /* @@ -232,7 +239,7 @@ slurpdir(char *path, char **bufp, int enoentok) } dirlist[entries] = NULL; - qsort(dirlist, entries, sizeof(struct dir *), dircompare); + qsort(dirlist, entries, sizeof(struct dirent *), dircompare); *bufp = buf; return (dirlist); |