Date: Fri, 9 Aug 2013 19:10:57 +0000 (UTC) From: Marcel Moolenaar <marcel@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r254155 - head/sys/boot/ficl Message-ID: <201308091910.r79JAvkD081933@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: marcel Date: Fri Aug 9 19:10:56 2013 New Revision: 254155 URL: http://svnweb.freebsd.org/changeset/base/254155 Log: Fix the freaddir implementation for the stand-alone interpreter. Bug pointed out by: Jan Beich <jbeich@tormail.org> Modified: head/sys/boot/ficl/loader.c Modified: head/sys/boot/ficl/loader.c ============================================================================== --- head/sys/boot/ficl/loader.c Fri Aug 9 18:57:18 2013 (r254154) +++ head/sys/boot/ficl/loader.c Fri Aug 9 19:10:56 2013 (r254155) @@ -518,12 +518,12 @@ static void pfread(FICL_VM *pVM) static void pfreaddir(FICL_VM *pVM) { #ifdef TESTMAIN - static union { - struct dirent dirent; - char buf[512]; - } u; - off_t off; - int len; + static struct dirent dirent; + struct stat sb; + char *buf; + off_t off, ptr; + u_int blksz; + int bufsz; #endif struct dirent *d; 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 * all guaranteed. */ - off = lseek(fd, 0LL, SEEK_CUR); - len = getdents(fd, u.buf, sizeof(u.buf)); - d = (len != -1) ? &u.dirent : NULL; - if (d != NULL) - lseek(fd, off + d->d_reclen, SEEK_SET); + d = NULL; + buf = NULL; + do { + if (fd == -1) + 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 d = readdirfd(fd); #endif
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201308091910.r79JAvkD081933>