8 Chunk= 1024, /* chunk size for buffered data */
9 Nfile= 128, /* maximum number of cached files */
12 /* a file (with cached data) */
15 char *mem; /* part of file cached in memory */
16 ulong len; /* length of cached data */
17 long off; /* current offset into tpath */
18 short fd; /* fd to cache file */
21 ulong atime; /* time of last access */
26 static File files[Nfile];
31 * lookup a file, create one if not found. if there are no
32 * free files, free the last oldest clean one.
45 for(fp = files; fp < &files[Nfile]; fp++){
48 if(fp->dirty == 0 && (oldest == 0 || oldest->atime > fp->atime))
52 if(fp == &files[Nfile]){
53 uncache(oldest->node);
100 * satisfy read first from in memory chunk and then from temporary
101 * file. It's up to the caller to make sure that the file is valid.
104 fileread(Node *node, char *a, long off, int n)
114 if(off + n > fp->len)
117 for(sofar = 0; sofar < n; sofar += i, off += i, a += i){
124 memmove(a, fp->mem + off, i);
128 if(seek(fp->fd, off, 0) < 0){
132 i = read(fp->fd, a, n-sofar);
145 uncachedir(Node *parent, Node *child)
149 if(parent == 0 || parent == child)
151 for(sp = parent->children; sp; sp = sp->sibs)
155 if(sp->fp->dirty == 0)
167 strcpy(template, "/tmp/ftpXXXXXXXXXXX");
169 if(strcmp(template, "/") == 0){
170 fprint(2, "ftpfs can't create tmp file %s: %r\n", template);
174 uncachedir(fp->node->parent, fp->node);
176 fp->fd = create(template, ORDWR|ORCLOSE, 0600);
177 fp->template = strdup(template);
184 * write cached data (first Chunk bytes stay in memory)
187 filewrite(Node *node, char *a, long off, int n)
195 fp->mem = malloc(Chunk);
197 return seterr("out of memory");
200 for(sofar = 0; sofar < n; sofar += i, off += i, a += i){
205 memmove(fp->mem + off, a, i);
209 if(createtmp(fp) < 0)
210 return seterr("can't create temp file");
212 if(seek(fp->fd, off, 0) < 0){
214 return seterr("can't seek temp file");
216 i = write(fp->fd, a, n-sofar);
219 return seterr("can't write temp file");
226 if(off > node->d->length)
227 node->d->length = off;
232 * mark a file as dirty
235 filedirty(Node *node)
244 * mark a file as clean
247 fileclean(Node *node)
254 fileisdirty(Node *node)
256 return node->fp && node->fp->dirty;