Skip site navigation (1)Skip section navigation (2)
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>