ref: 3c8246a31ce776976ee95310efa2c6e64a471993
dir: /sys/src/ape/lib/ap/plan9/dirread.c/
#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; }