lib9pclient is the new libfs
diff --git a/src/lib9pclient/dirread.c b/src/lib9pclient/dirread.c
new file mode 100644
index 0000000..540cfc6
--- /dev/null
+++ b/src/lib9pclient/dirread.c
@@ -0,0 +1,99 @@
+/* Mostly copied from Plan 9's libc. */
+
+#include <u.h>
+#include <libc.h>
+#include <fcall.h>
+#include <9pclient.h>
+
+static long
+dirpackage(uchar *buf, long ts, Dir **d)
+{
+	char *s;
+	long ss, i, n, nn, m;
+
+	*d = nil;
+	if(ts <= 0)
+		return 0;
+
+	/*
+	 * first find number of all stats, check they look like stats, & size all associated strings
+	 */
+	ss = 0;
+	n = 0;
+	for(i = 0; i < ts; i += m){
+		m = BIT16SZ + GBIT16(&buf[i]);
+		if(statcheck(&buf[i], m) < 0)
+			break;
+		ss += m;
+		n++;
+	}
+
+	if(i != ts)
+		return -1;
+
+	*d = malloc(n * sizeof(Dir) + ss);
+	if(*d == nil)
+		return -1;
+
+	/*
+	 * then convert all buffers
+	 */
+	s = (char*)*d + n * sizeof(Dir);
+	nn = 0;
+	for(i = 0; i < ts; i += m){
+		m = BIT16SZ + GBIT16((uchar*)&buf[i]);
+		if(nn >= n || convM2D(&buf[i], m, *d + nn, s) != m){
+			free(*d);
+			*d = nil;
+			return -1;
+		}
+		nn++;
+		s += m;
+	}
+
+	return nn;
+}
+
+long
+fsdirread(CFid *fid, Dir **d)
+{
+	uchar *buf;
+	long ts;
+
+	buf = malloc(DIRMAX);
+	if(buf == nil)
+		return -1;
+	ts = fsread(fid, buf, DIRMAX);
+	if(ts >= 0)
+		ts = dirpackage(buf, ts, d);
+	free(buf);
+	return ts;
+}
+
+long
+fsdirreadall(CFid *fid, Dir **d)
+{
+	uchar *buf, *nbuf;
+	long n, ts;
+
+	buf = nil;
+	ts = 0;
+	for(;;){
+		nbuf = realloc(buf, ts+DIRMAX);
+		if(nbuf == nil){
+			free(buf);
+			return -1;
+		}
+		buf = nbuf;
+		n = fsread(fid, buf+ts, DIRMAX);
+		if(n <= 0)
+			break;
+		ts += n;
+	}
+	if(ts >= 0)
+		ts = dirpackage(buf, ts, d);
+	free(buf);
+	if(ts == 0 && n < 0)
+		return -1;
+	return ts;
+}