summaryrefslogtreecommitdiff
path: root/sys/src/ape/lib/ap/plan9/dirread.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/ape/lib/ap/plan9/dirread.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/ape/lib/ap/plan9/dirread.c')
-rwxr-xr-xsys/src/ape/lib/ap/plan9/dirread.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/sys/src/ape/lib/ap/plan9/dirread.c b/sys/src/ape/lib/ap/plan9/dirread.c
new file mode 100755
index 000000000..e03d32d77
--- /dev/null
+++ b/sys/src/ape/lib/ap/plan9/dirread.c
@@ -0,0 +1,119 @@
+#include "lib.h"
+#include <string.h>
+#include <stdlib.h>
+#include "sys9.h"
+#include "dir.h"
+
+static int
+statcheck(uchar *buf, uint nbuf)
+{
+ uchar *ebuf;
+ int i;
+
+ ebuf = buf + nbuf;
+
+ buf += STATFIXLEN - 4 * BIT16SZ;
+
+ for(i = 0; i < 4; i++){
+ if(buf + BIT16SZ > ebuf)
+ return -1;
+ buf += BIT16SZ + GBIT16(buf);
+ }
+
+ if(buf != ebuf)
+ return -1;
+
+ return 0;
+}
+
+static
+long
+dirpackage(uchar *buf, long ts, Dir **d)
+{
+ char *s;
+ long ss, i, n, nn, m;
+
+ if(ts == 0){
+ *d = nil;
+ 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);
+ return -1;
+ }
+ nn++;
+ s += m;
+ }
+
+ return nn;
+}
+
+long
+_dirread(int fd, Dir **d)
+{
+ uchar *buf;
+ long ts;
+
+ buf = malloc(DIRMAX);
+ if(buf == nil)
+ return -1;
+ ts = _READ(fd, buf, DIRMAX);
+ if(ts >= 0)
+ ts = dirpackage(buf, ts, d);
+ free(buf);
+ return ts;
+}
+
+long
+_dirreadall(int fd, 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 = _READ(fd, buf+ts, DIRMAX);
+ if(n <= 0)
+ break;
+ ts += n;
+ }
+ if(ts >= 0)
+ ts = dirpackage(buf, ts, d);
+ free(buf);
+ return ts;
+}