9660srv: import from Plan 9
This commit is contained in:
parent
29e9b5683e
commit
78a779a383
9 changed files with 2135 additions and 0 deletions
170
src/cmd/9660srv/xfile.c
Normal file
170
src/cmd/9660srv/xfile.c
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <auth.h>
|
||||
#include <fcall.h>
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
|
||||
static Xfile* clean(Xfile*);
|
||||
|
||||
#define FIDMOD 127 /* prime */
|
||||
|
||||
static Xdata* xhead;
|
||||
static Xfile* xfiles[FIDMOD];
|
||||
static Xfile* freelist;
|
||||
|
||||
Xdata*
|
||||
getxdata(char *name)
|
||||
{
|
||||
int fd;
|
||||
Dir *dir;
|
||||
Xdata *xf, *fxf;
|
||||
int flag;
|
||||
|
||||
if(name[0] == 0)
|
||||
name = deffile;
|
||||
if(name == 0)
|
||||
error(Enofile);
|
||||
flag = (access(name, 6) == 0) ? ORDWR : OREAD;
|
||||
fd = open(name, flag);
|
||||
if(fd < 0)
|
||||
error(Enonexist);
|
||||
dir = nil;
|
||||
if(waserror()){
|
||||
close(fd);
|
||||
free(dir);
|
||||
nexterror();
|
||||
}
|
||||
if((dir = dirfstat(fd)) == nil)
|
||||
error("I/O error");
|
||||
if((dir->qid.type & ~QTTMP) != QTFILE)
|
||||
error("attach name not a plain file");
|
||||
for(fxf=0,xf=xhead; xf; xf=xf->next){
|
||||
if(xf->name == 0){
|
||||
if(fxf == 0)
|
||||
fxf = xf;
|
||||
continue;
|
||||
}
|
||||
if(xf->qid.path != dir->qid.path || xf->qid.vers != dir->qid.vers)
|
||||
continue;
|
||||
if(xf->type != dir->type || xf->fdev != dir->dev)
|
||||
continue;
|
||||
xf->ref++;
|
||||
chat("incref=%d, \"%s\", dev=%d...", xf->ref, xf->name, xf->dev);
|
||||
close(fd);
|
||||
poperror();
|
||||
free(dir);
|
||||
return xf;
|
||||
}
|
||||
if(fxf==0){
|
||||
fxf = ealloc(sizeof(Xfs));
|
||||
fxf->next = xhead;
|
||||
xhead = fxf;
|
||||
}
|
||||
chat("alloc \"%s\", dev=%d...", name, fd);
|
||||
fxf->ref = 1;
|
||||
fxf->name = strcpy(ealloc(strlen(name)+1), name);
|
||||
fxf->qid = dir->qid;
|
||||
fxf->type = dir->type;
|
||||
fxf->fdev = dir->dev;
|
||||
fxf->dev = fd;
|
||||
free(dir);
|
||||
poperror();
|
||||
return fxf;
|
||||
}
|
||||
|
||||
static void
|
||||
putxdata(Xdata *d)
|
||||
{
|
||||
if(d->ref <= 0)
|
||||
panic(0, "putxdata");
|
||||
d->ref--;
|
||||
chat("decref=%d, \"%s\", dev=%d...", d->ref, d->name, d->dev);
|
||||
if(d->ref == 0){
|
||||
chat("purgebuf...");
|
||||
purgebuf(d);
|
||||
close(d->dev);
|
||||
free(d->name);
|
||||
d->name = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
refxfs(Xfs *xf, int delta)
|
||||
{
|
||||
xf->ref += delta;
|
||||
if(xf->ref == 0){
|
||||
if(xf->d)
|
||||
putxdata(xf->d);
|
||||
if(xf->ptr)
|
||||
free(xf->ptr);
|
||||
free(xf);
|
||||
}
|
||||
}
|
||||
|
||||
Xfile*
|
||||
xfile(int fid, int flag)
|
||||
{
|
||||
int k = fid%FIDMOD;
|
||||
Xfile **hp=&xfiles[k], *f, *pf;
|
||||
|
||||
for(f=*hp,pf=0; f; pf=f,f=f->next)
|
||||
if(f->fid == fid)
|
||||
break;
|
||||
if(f && pf){
|
||||
pf->next = f->next;
|
||||
f->next = *hp;
|
||||
*hp = f;
|
||||
}
|
||||
switch(flag){
|
||||
default:
|
||||
panic(0, "xfile");
|
||||
case Asis:
|
||||
if(f == 0)
|
||||
error("unassigned fid");
|
||||
return f;
|
||||
case Clean:
|
||||
break;
|
||||
case Clunk:
|
||||
if(f){
|
||||
*hp = f->next;
|
||||
clean(f);
|
||||
f->next = freelist;
|
||||
freelist = f;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if(f)
|
||||
return clean(f);
|
||||
if(f = freelist) /* assign = */
|
||||
freelist = f->next;
|
||||
else
|
||||
f = ealloc(sizeof(Xfile));
|
||||
f->next = *hp;
|
||||
*hp = f;
|
||||
f->xf = 0;
|
||||
f->fid = fid;
|
||||
f->flags = 0;
|
||||
f->qid = (Qid){0,0,0};
|
||||
f->len = 0;
|
||||
f->ptr = 0;
|
||||
return f;
|
||||
}
|
||||
|
||||
static Xfile *
|
||||
clean(Xfile *f)
|
||||
{
|
||||
if(f->xf){
|
||||
refxfs(f->xf, -1);
|
||||
f->xf = 0;
|
||||
}
|
||||
if(f->len){
|
||||
free(f->ptr);
|
||||
f->len = 0;
|
||||
}
|
||||
f->ptr = 0;
|
||||
f->flags = 0;
|
||||
f->qid = (Qid){0,0,0};
|
||||
return f;
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue