diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /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-x | sys/src/ape/lib/ap/plan9/dirread.c | 119 |
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; +} |