enum
{
Chunk= 1024, /* chunk size for buffered data */
Nfile= 128, /* maximum number of cached files */
};
/* a file (with cached data) */
struct File
{
char *mem; /* part of file cached in memory */
ulong len; /* length of cached data */
long off; /* current offset into tpath */
short fd; /* fd to cache file */
char inuse;
char dirty;
ulong atime; /* time of last access */
Node *node;
char *template;
};
static File files[Nfile];
static ulong now;
static int ntmp;
/*
* lookup a file, create one if not found. if there are no
* free files, free the last oldest clean one.
*/
static File*
fileget(Node *node)
{
File *fp;
File *oldest;
/*
* satisfy read first from in memory chunk and then from temporary
* file. It's up to the caller to make sure that the file is valid.
*/
int
fileread(Node *node, char *a, long off, int n)
{
int sofar;
int i;
File *fp;
fp = node->fp;
if(fp == 0)
fatal("fileread");
if(off + n > fp->len)
n = fp->len - off;
for(sofar = 0; sofar < n; sofar += i, off += i, a += i){
if(off >= fp->len)
return sofar;
if(off < Chunk){
i = n;
if(off + i > Chunk)
i = Chunk - off;
memmove(a, fp->mem + off, i);
continue;
}
if(fp->off != off)
if(seek(fp->fd, off, 0) < 0){
fp->off = -1;
return -1;
}
i = read(fp->fd, a, n-sofar);
if(i < 0){
fp->off = -1;
return -1;
}
if(i == 0)
break;
fp->off = off + i;
}
return sofar;
}