Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <auth.h>
4
#include <fcall.h>
5
#include "dat.h"
6
#include "fns.h"
7
 
8
static Xfile*	clean(Xfile*);
9
 
10
#define	FIDMOD	127	/* prime */
11
 
12
static Xdata*	xhead;
13
static Xfile*	xfiles[FIDMOD];
14
static Xfile*	freelist;
15
 
16
Xdata*
17
getxdata(char *name)
18
{
19
	int fd;
20
	Dir *dir;
21
	Xdata *xf, *fxf;
22
	int flag;
23
 
24
	if(name[0] == 0)
25
		name = deffile;
26
	if(name == 0)
27
		error(Enofile);
28
	flag = (access(name, 6) == 0) ? ORDWR : OREAD;
29
	fd = open(name, flag);
30
	if(fd < 0)
31
		error(Enonexist);
32
	dir = nil;
33
	if(waserror()){
34
		close(fd);
35
		free(dir);
36
		nexterror();
37
	}
38
	if((dir = dirfstat(fd)) == nil)
39
		error("I/O error");
40
	if((dir->qid.type & ~QTTMP) != QTFILE)
41
		error("attach name not a plain file");
42
	for(fxf=0,xf=xhead; xf; xf=xf->next){
43
		if(xf->name == 0){
44
			if(fxf == 0)
45
				fxf = xf;
46
			continue;
47
		}
48
		if(xf->qid.path != dir->qid.path || xf->qid.vers != dir->qid.vers)
49
			continue;
50
		if(xf->type != dir->type || xf->fdev != dir->dev)
51
			continue;
52
		xf->ref++;
53
		chat("incref=%d, \"%s\", dev=%d...", xf->ref, xf->name, xf->dev);
54
		close(fd);
55
		poperror();
56
		free(dir);
57
		return xf;
58
	}
59
	if(fxf==0){
60
		fxf = ealloc(sizeof(Xfs));
61
		fxf->next = xhead;
62
		xhead = fxf;
63
	}
64
	chat("alloc \"%s\", dev=%d...", name, fd);
65
	fxf->ref = 1;
66
	fxf->name = strcpy(ealloc(strlen(name)+1), name);
67
	fxf->qid = dir->qid;
68
	fxf->type = dir->type;
69
	fxf->fdev = dir->dev;
70
	fxf->dev = fd;
71
	free(dir);
72
	poperror();
73
	return fxf;
74
}
75
 
76
static void
77
putxdata(Xdata *d)
78
{
79
	if(d->ref <= 0)
80
		panic(0, "putxdata");
81
	d->ref--;
82
	chat("decref=%d, \"%s\", dev=%d...", d->ref, d->name, d->dev);
83
	if(d->ref == 0){
84
		chat("purgebuf...");
85
		purgebuf(d);
86
		close(d->dev);
87
		free(d->name);
88
		d->name = 0;
89
	}
90
}
91
 
92
void
93
refxfs(Xfs *xf, int delta)
94
{
95
	xf->ref += delta;
96
	if(xf->ref == 0){
97
		if(xf->d)
98
			putxdata(xf->d);
99
		if(xf->ptr)
100
			free(xf->ptr);
101
		free(xf);
102
	}
103
}
104
 
105
Xfile*
106
xfile(int fid, int flag)
107
{
108
	int k = fid%FIDMOD;
109
	Xfile **hp=&xfiles[k], *f, *pf;
110
 
111
	for(f=*hp,pf=0; f; pf=f,f=f->next)
112
		if(f->fid == fid)
113
			break;
114
	if(f && pf){
115
		pf->next = f->next;
116
		f->next = *hp;
117
		*hp = f;
118
	}
119
	switch(flag){
120
	default:
121
		panic(0, "xfile");
122
	case Asis:
123
		if(f == 0)
124
			error("unassigned fid");
125
		return f;
126
	case Clean:
127
		break;
128
	case Clunk:
129
		if(f){
130
			*hp = f->next;
131
			clean(f);
132
			f->next = freelist;
133
			freelist = f;
134
		}
135
		return 0;
136
	}
137
	if(f)
138
		return clean(f);
139
	if(f = freelist)	/* assign = */
140
		freelist = f->next;
141
	else
142
		f = ealloc(sizeof(Xfile));
143
	f->next = *hp;
144
	*hp = f;
145
	f->xf = 0;
146
	f->fid = fid;
147
	f->flags = 0;
148
	f->qid = (Qid){0,0,0};
149
	f->len = 0;
150
	f->ptr = 0;
151
	return f;
152
}
153
 
154
static Xfile *
155
clean(Xfile *f)
156
{
157
	if(f->xf){
158
		refxfs(f->xf, -1);
159
		f->xf = 0;
160
	}
161
	if(f->len){
162
		free(f->ptr);
163
		f->len = 0;
164
	}
165
	f->ptr = 0;
166
	f->flags = 0;
167
	f->qid = (Qid){0,0,0};
168
	return f;
169
}
170