Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#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;
}