jehanne/sys/src/lib/jehanne/9sys/dirread.c

107 lines
1.9 KiB
C

/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
#define PORTABLE_SYSCALLS
#include <u.h>
#include <libc.h>
#include <9P2000.h>
static
int32_t
dirpackage(uint8_t *buf, int32_t ts, Dir **d)
{
char *s;
int32_t 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 = jehanne_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((uint8_t*)&buf[i]);
if(nn >= n || jehanne_convM2D(&buf[i], m, *d + nn, s) != m){
jehanne_free(*d);
*d = nil;
return -1;
}
nn++;
s += m;
}
return nn;
}
int32_t
jehanne_dirread(int fd, Dir **d)
{
uint8_t *buf;
int32_t ts;
buf = jehanne_malloc(DIRMAX);
if(buf == nil)
return -1;
ts = jehanne_read(fd, buf, DIRMAX);
if(ts >= 0)
ts = dirpackage(buf, ts, d);
jehanne_free(buf);
return ts;
}
int32_t
jehanne_dirreadall(int fd, Dir **d)
{
uint8_t *buf, *nbuf;
int32_t n, ts;
buf = nil;
ts = 0;
for(;;){
nbuf = jehanne_realloc(buf, ts+DIRMAX);
if(nbuf == nil){
jehanne_free(buf);
return -1;
}
buf = nbuf;
n = jehanne_read(fd, buf+ts, DIRMAX);
if(n <= 0)
break;
ts += n;
}
if(ts >= 0)
ts = dirpackage(buf, ts, d);
jehanne_free(buf);
if(ts == 0 && n < 0)
return -1;
return ts;
}