Fix the freaddir implementation for the stand-alone interpreter.

Bug pointed out by: Jan Beich <jbeich@tormail.org>
This commit is contained in:
marcel 2013-08-09 19:10:56 +00:00
parent 2895e1352c
commit b239ca1a30

View File

@ -518,12 +518,12 @@ static void pfread(FICL_VM *pVM)
static void pfreaddir(FICL_VM *pVM) static void pfreaddir(FICL_VM *pVM)
{ {
#ifdef TESTMAIN #ifdef TESTMAIN
static union { static struct dirent dirent;
struct dirent dirent; struct stat sb;
char buf[512]; char *buf;
} u; off_t off, ptr;
off_t off; u_int blksz;
int len; int bufsz;
#endif #endif
struct dirent *d; struct dirent *d;
int fd; int fd;
@ -539,11 +539,39 @@ static void pfreaddir(FICL_VM *pVM)
* We do the best we can to make freaddir work, but it's not at * We do the best we can to make freaddir work, but it's not at
* all guaranteed. * all guaranteed.
*/ */
off = lseek(fd, 0LL, SEEK_CUR); d = NULL;
len = getdents(fd, u.buf, sizeof(u.buf)); buf = NULL;
d = (len != -1) ? &u.dirent : NULL; do {
if (d != NULL) if (fd == -1)
lseek(fd, off + d->d_reclen, SEEK_SET); break;
if (fstat(fd, &sb) == -1)
break;
blksz = (sb.st_blksize) ? sb.st_blksize : getpagesize();
if ((blksz & (blksz - 1)) != 0)
break;
buf = malloc(blksz);
if (buf == NULL)
break;
off = lseek(fd, 0LL, SEEK_CUR);
if (off == -1)
break;
ptr = off;
if (lseek(fd, 0, SEEK_SET) == -1)
break;
bufsz = getdents(fd, buf, blksz);
while (bufsz > 0 && bufsz <= ptr) {
ptr -= bufsz;
bufsz = getdents(fd, buf, blksz);
}
if (bufsz <= 0)
break;
d = (void *)(buf + ptr);
dirent = *d;
off += d->d_reclen;
d = (lseek(fd, off, SEEK_SET) != off) ? NULL : &dirent;
} while (0);
if (buf != NULL)
free(buf);
#else #else
d = readdirfd(fd); d = readdirfd(fd);
#endif #endif