xref: /plan9/sys/src/cmd/aux/flashfs/entry.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1*9a747e4fSDavid du Colombier #include <u.h>
2*9a747e4fSDavid du Colombier #include <libc.h>
3*9a747e4fSDavid du Colombier #include <auth.h>
4*9a747e4fSDavid du Colombier #include <fcall.h>
5*9a747e4fSDavid du Colombier #include <thread.h>
6*9a747e4fSDavid du Colombier #include <9p.h>
7*9a747e4fSDavid du Colombier #include "flashfs.h"
8*9a747e4fSDavid du Colombier 
9*9a747e4fSDavid du Colombier static	int	nextfnum;
10*9a747e4fSDavid du Colombier static	Intmap*	map;
11*9a747e4fSDavid du Colombier static	Dir	dirproto;
12*9a747e4fSDavid du Colombier 
13*9a747e4fSDavid du Colombier static	char	user[]	= "flash";
14*9a747e4fSDavid du Colombier 
15*9a747e4fSDavid du Colombier 	Entry	*root;
16*9a747e4fSDavid du Colombier 	ulong	used;
17*9a747e4fSDavid du Colombier 	ulong	limit;
18*9a747e4fSDavid du Colombier 	ulong	maxwrite;
19*9a747e4fSDavid du Colombier 
20*9a747e4fSDavid du Colombier enum
21*9a747e4fSDavid du Colombier {
22*9a747e4fSDavid du Colombier 	debug	= 0,
23*9a747e4fSDavid du Colombier };
24*9a747e4fSDavid du Colombier 
25*9a747e4fSDavid du Colombier static int
fnum(void)26*9a747e4fSDavid du Colombier fnum(void)
27*9a747e4fSDavid du Colombier {
28*9a747e4fSDavid du Colombier 	return ++nextfnum;
29*9a747e4fSDavid du Colombier }
30*9a747e4fSDavid du Colombier 
31*9a747e4fSDavid du Colombier static void
maxfnum(int n)32*9a747e4fSDavid du Colombier maxfnum(int n)
33*9a747e4fSDavid du Colombier {
34*9a747e4fSDavid du Colombier 	if(n > nextfnum)
35*9a747e4fSDavid du Colombier 		nextfnum = n;
36*9a747e4fSDavid du Colombier }
37*9a747e4fSDavid du Colombier 
38*9a747e4fSDavid du Colombier static int
hash(char * s)39*9a747e4fSDavid du Colombier hash(char *s)
40*9a747e4fSDavid du Colombier {
41*9a747e4fSDavid du Colombier 	int c, d, h;
42*9a747e4fSDavid du Colombier 
43*9a747e4fSDavid du Colombier 	h = 0;
44*9a747e4fSDavid du Colombier 	while((c = *s++) != '\0') {
45*9a747e4fSDavid du Colombier 		d = c;
46*9a747e4fSDavid du Colombier 		c ^= c << 6;
47*9a747e4fSDavid du Colombier 		h += (c << 11) ^ (c >> 1);
48*9a747e4fSDavid du Colombier 		h ^= (d << 14) + (d << 7) + (d << 4) + d;
49*9a747e4fSDavid du Colombier 	}
50*9a747e4fSDavid du Colombier 
51*9a747e4fSDavid du Colombier 	if(h < 0)
52*9a747e4fSDavid du Colombier 		return ~h;
53*9a747e4fSDavid du Colombier 	return h;
54*9a747e4fSDavid du Colombier }
55*9a747e4fSDavid du Colombier 
56*9a747e4fSDavid du Colombier static void
dirinit(Entry * e)57*9a747e4fSDavid du Colombier dirinit(Entry *e)
58*9a747e4fSDavid du Colombier {
59*9a747e4fSDavid du Colombier 	Entry **t;
60*9a747e4fSDavid du Colombier 
61*9a747e4fSDavid du Colombier 	e->size = 0;
62*9a747e4fSDavid du Colombier 	t = emalloc9p(HSIZE * sizeof(Entry*));
63*9a747e4fSDavid du Colombier 	memset(t, 0, HSIZE * sizeof(Entry*));
64*9a747e4fSDavid du Colombier 	e->htab = t;
65*9a747e4fSDavid du Colombier 	e->files = nil;
66*9a747e4fSDavid du Colombier 	e->readers = nil;
67*9a747e4fSDavid du Colombier }
68*9a747e4fSDavid du Colombier 
69*9a747e4fSDavid du Colombier static void
fileinit(Entry * e)70*9a747e4fSDavid du Colombier fileinit(Entry *e)
71*9a747e4fSDavid du Colombier {
72*9a747e4fSDavid du Colombier 	e->size = 0;
73*9a747e4fSDavid du Colombier 	e->gen[0].head = nil;
74*9a747e4fSDavid du Colombier 	e->gen[0].tail = nil;
75*9a747e4fSDavid du Colombier 	e->gen[1].head = nil;
76*9a747e4fSDavid du Colombier 	e->gen[1].tail = nil;
77*9a747e4fSDavid du Colombier }
78*9a747e4fSDavid du Colombier 
79*9a747e4fSDavid du Colombier static void
elfree(Extent * x)80*9a747e4fSDavid du Colombier elfree(Extent *x)
81*9a747e4fSDavid du Colombier {
82*9a747e4fSDavid du Colombier 	Extent *t;
83*9a747e4fSDavid du Colombier 
84*9a747e4fSDavid du Colombier 	while(x != nil) {
85*9a747e4fSDavid du Colombier 		t = x->next;
86*9a747e4fSDavid du Colombier 		used -= x->size;
87*9a747e4fSDavid du Colombier 		free(x);
88*9a747e4fSDavid du Colombier 		x = t;
89*9a747e4fSDavid du Colombier 	}
90*9a747e4fSDavid du Colombier }
91*9a747e4fSDavid du Colombier 
92*9a747e4fSDavid du Colombier static void
extfree(Entry * e)93*9a747e4fSDavid du Colombier extfree(Entry *e)
94*9a747e4fSDavid du Colombier {
95*9a747e4fSDavid du Colombier 	elfree(e->gen[0].head);
96*9a747e4fSDavid du Colombier 	elfree(e->gen[1].head);
97*9a747e4fSDavid du Colombier }
98*9a747e4fSDavid du Colombier 
99*9a747e4fSDavid du Colombier static void
efree(Entry * e)100*9a747e4fSDavid du Colombier efree(Entry *e)
101*9a747e4fSDavid du Colombier {
102*9a747e4fSDavid du Colombier 	if(debug)
103*9a747e4fSDavid du Colombier 		fprint(2, "free %s\n", e->name);
104*9a747e4fSDavid du Colombier 
105*9a747e4fSDavid du Colombier 	if(e->mode & DMDIR)
106*9a747e4fSDavid du Colombier 		free(e->htab);
107*9a747e4fSDavid du Colombier 	else
108*9a747e4fSDavid du Colombier 		extfree(e);
109*9a747e4fSDavid du Colombier 
110*9a747e4fSDavid du Colombier 	free(e->name);
111*9a747e4fSDavid du Colombier 	free(e);
112*9a747e4fSDavid du Colombier }
113*9a747e4fSDavid du Colombier 
114*9a747e4fSDavid du Colombier void
einit(void)115*9a747e4fSDavid du Colombier einit(void)
116*9a747e4fSDavid du Colombier {
117*9a747e4fSDavid du Colombier 	Entry *e;
118*9a747e4fSDavid du Colombier 
119*9a747e4fSDavid du Colombier 	e = emalloc9p(sizeof(Entry));
120*9a747e4fSDavid du Colombier 	e->ref = 1;
121*9a747e4fSDavid du Colombier 	e->parent = nil;
122*9a747e4fSDavid du Colombier 	dirinit(e);
123*9a747e4fSDavid du Colombier 	e->name = estrdup9p("");
124*9a747e4fSDavid du Colombier 	e->fnum = 0;
125*9a747e4fSDavid du Colombier 	e->mode = DMDIR | 0775;
126*9a747e4fSDavid du Colombier 	e->mnum = 0;
127*9a747e4fSDavid du Colombier 	e->mtime = 0;
128*9a747e4fSDavid du Colombier 	root = e;
129*9a747e4fSDavid du Colombier 	map = allocmap(nil);
130*9a747e4fSDavid du Colombier }
131*9a747e4fSDavid du Colombier 
132*9a747e4fSDavid du Colombier static void
dumptree(Entry * e,int n)133*9a747e4fSDavid du Colombier dumptree(Entry *e, int n)
134*9a747e4fSDavid du Colombier {
135*9a747e4fSDavid du Colombier 	Entry *l;
136*9a747e4fSDavid du Colombier 
137*9a747e4fSDavid du Colombier 	if(debug)
138*9a747e4fSDavid du Colombier 		fprint(2, "%d %s %d\n", n, e->name, e->ref);
139*9a747e4fSDavid du Colombier 
140*9a747e4fSDavid du Colombier 	if(e->mode & DMDIR) {
141*9a747e4fSDavid du Colombier 		n++;
142*9a747e4fSDavid du Colombier 		for(l = e->files; l != nil; l = l->fnext)
143*9a747e4fSDavid du Colombier 			dumptree(l, n);
144*9a747e4fSDavid du Colombier 	}
145*9a747e4fSDavid du Colombier }
146*9a747e4fSDavid du Colombier 
147*9a747e4fSDavid du Colombier void
edump(void)148*9a747e4fSDavid du Colombier edump(void)
149*9a747e4fSDavid du Colombier {
150*9a747e4fSDavid du Colombier 	if(debug)
151*9a747e4fSDavid du Colombier 		dumptree(root, 0);
152*9a747e4fSDavid du Colombier }
153*9a747e4fSDavid du Colombier 
154*9a747e4fSDavid du Colombier Entry *
elookup(ulong key)155*9a747e4fSDavid du Colombier elookup(ulong key)
156*9a747e4fSDavid du Colombier {
157*9a747e4fSDavid du Colombier 	if(key == 0)
158*9a747e4fSDavid du Colombier 		return root;
159*9a747e4fSDavid du Colombier 	maxfnum(key);
160*9a747e4fSDavid du Colombier 	return lookupkey(map, key);
161*9a747e4fSDavid du Colombier }
162*9a747e4fSDavid du Colombier 
163*9a747e4fSDavid du Colombier Extent *
esum(Entry * e,int sect,ulong addr,int * more)164*9a747e4fSDavid du Colombier esum(Entry *e, int sect, ulong addr, int *more)
165*9a747e4fSDavid du Colombier {
166*9a747e4fSDavid du Colombier 	Exts *x;
167*9a747e4fSDavid du Colombier 	Extent *t, *u;
168*9a747e4fSDavid du Colombier 
169*9a747e4fSDavid du Colombier 	x = &e->gen[eparity];
170*9a747e4fSDavid du Colombier 	t = x->tail;
171*9a747e4fSDavid du Colombier 	if(t == nil || t->sect != sect || t->addr != addr)
172*9a747e4fSDavid du Colombier 		return nil;
173*9a747e4fSDavid du Colombier 	u = t->prev;
174*9a747e4fSDavid du Colombier 	if(u != nil) {
175*9a747e4fSDavid du Colombier 		u->next = nil;
176*9a747e4fSDavid du Colombier 		*more = 1;
177*9a747e4fSDavid du Colombier 	}
178*9a747e4fSDavid du Colombier 	else {
179*9a747e4fSDavid du Colombier 		x->head = nil;
180*9a747e4fSDavid du Colombier 		*more = 0;
181*9a747e4fSDavid du Colombier 	}
182*9a747e4fSDavid du Colombier 	x->tail = u;
183*9a747e4fSDavid du Colombier 	x = &e->gen[eparity^1];
184*9a747e4fSDavid du Colombier 	u = x->head;
185*9a747e4fSDavid du Colombier 	t->next = u;
186*9a747e4fSDavid du Colombier 	x->head = t;
187*9a747e4fSDavid du Colombier 	if(u == nil)
188*9a747e4fSDavid du Colombier 		x->tail = t;
189*9a747e4fSDavid du Colombier 	else
190*9a747e4fSDavid du Colombier 		u->prev = t;
191*9a747e4fSDavid du Colombier 	return t;
192*9a747e4fSDavid du Colombier }
193*9a747e4fSDavid du Colombier 
194*9a747e4fSDavid du Colombier void
edestroy(Entry * e)195*9a747e4fSDavid du Colombier edestroy(Entry *e)
196*9a747e4fSDavid du Colombier {
197*9a747e4fSDavid du Colombier 	e->ref--;
198*9a747e4fSDavid du Colombier 	if(e->ref == 0)
199*9a747e4fSDavid du Colombier 		efree(e);
200*9a747e4fSDavid du Colombier }
201*9a747e4fSDavid du Colombier 
202*9a747e4fSDavid du Colombier Entry *
ecreate(Entry * d,char * name,ulong n,ulong mode,ulong mtime,char ** err)203*9a747e4fSDavid du Colombier ecreate(Entry *d, char *name, ulong n, ulong mode, ulong mtime, char **err)
204*9a747e4fSDavid du Colombier {
205*9a747e4fSDavid du Colombier 	int h;
206*9a747e4fSDavid du Colombier 	Entry *e, *f;
207*9a747e4fSDavid du Colombier 
208*9a747e4fSDavid du Colombier 	h = hash(name) & HMASK;
209*9a747e4fSDavid du Colombier 	for(e = d->htab[h]; e != nil; e = e->hnext) {
210*9a747e4fSDavid du Colombier 		if(strcmp(e->name, name) == 0) {
211*9a747e4fSDavid du Colombier 			*err = Eexists;
212*9a747e4fSDavid du Colombier 			return nil;
213*9a747e4fSDavid du Colombier 		}
214*9a747e4fSDavid du Colombier 	}
215*9a747e4fSDavid du Colombier 
216*9a747e4fSDavid du Colombier 	e = emalloc9p(sizeof(Entry));
217*9a747e4fSDavid du Colombier 	e->ref = 1;
218*9a747e4fSDavid du Colombier 	e->parent = d;
219*9a747e4fSDavid du Colombier 	d->ref++;
220*9a747e4fSDavid du Colombier 	f = d->htab[h];
221*9a747e4fSDavid du Colombier 	e->hnext = f;
222*9a747e4fSDavid du Colombier 	e->hprev = nil;
223*9a747e4fSDavid du Colombier 	if(f != nil)
224*9a747e4fSDavid du Colombier 		f->hprev = e;
225*9a747e4fSDavid du Colombier 	d->htab[h] = e;
226*9a747e4fSDavid du Colombier 	f = d->files;
227*9a747e4fSDavid du Colombier 	e->fnext = f;
228*9a747e4fSDavid du Colombier 	e->fprev = nil;
229*9a747e4fSDavid du Colombier 	if(f != nil)
230*9a747e4fSDavid du Colombier 		f->fprev = e;
231*9a747e4fSDavid du Colombier 	d->files = e;
232*9a747e4fSDavid du Colombier 
233*9a747e4fSDavid du Colombier 	d->ref--;
234*9a747e4fSDavid du Colombier 	e->ref++;
235*9a747e4fSDavid du Colombier 	e->name = estrdup9p(name);
236*9a747e4fSDavid du Colombier 	if(n == 0)
237*9a747e4fSDavid du Colombier 		n = fnum();
238*9a747e4fSDavid du Colombier 	else
239*9a747e4fSDavid du Colombier 		maxfnum(n);
240*9a747e4fSDavid du Colombier 	insertkey(map, n, e);
241*9a747e4fSDavid du Colombier 	e->fnum = n;
242*9a747e4fSDavid du Colombier 	e->mode = mode & d->mode;
243*9a747e4fSDavid du Colombier 	e->mnum = 0;
244*9a747e4fSDavid du Colombier 	e->mtime = mtime;
245*9a747e4fSDavid du Colombier 
246*9a747e4fSDavid du Colombier 	if(e->mode & DMDIR)
247*9a747e4fSDavid du Colombier 		dirinit(e);
248*9a747e4fSDavid du Colombier 	else
249*9a747e4fSDavid du Colombier 		fileinit(e);
250*9a747e4fSDavid du Colombier 
251*9a747e4fSDavid du Colombier 	d->mtime = mtime;
252*9a747e4fSDavid du Colombier 	return e;
253*9a747e4fSDavid du Colombier }
254*9a747e4fSDavid du Colombier 
255*9a747e4fSDavid du Colombier void
etrunc(Entry * e,ulong n,ulong mtime)256*9a747e4fSDavid du Colombier etrunc(Entry *e, ulong n, ulong mtime)
257*9a747e4fSDavid du Colombier {
258*9a747e4fSDavid du Colombier 	extfree(e);
259*9a747e4fSDavid du Colombier 	deletekey(map, e->fnum);
260*9a747e4fSDavid du Colombier 	if(n == 0)
261*9a747e4fSDavid du Colombier 		n = fnum();
262*9a747e4fSDavid du Colombier 	else
263*9a747e4fSDavid du Colombier 		maxfnum(n);
264*9a747e4fSDavid du Colombier 	e->fnum = n;
265*9a747e4fSDavid du Colombier 	e->mnum = 0;
266*9a747e4fSDavid du Colombier 	e->mtime = mtime;
267*9a747e4fSDavid du Colombier 	insertkey(map, n, e);
268*9a747e4fSDavid du Colombier 	fileinit(e);
269*9a747e4fSDavid du Colombier 	e->parent->mtime = mtime;
270*9a747e4fSDavid du Colombier }
271*9a747e4fSDavid du Colombier 
272*9a747e4fSDavid du Colombier char *
eremove(Entry * e)273*9a747e4fSDavid du Colombier eremove(Entry *e)
274*9a747e4fSDavid du Colombier {
275*9a747e4fSDavid du Colombier 	Dirr *r;
276*9a747e4fSDavid du Colombier 	Entry *d, *n, *p;
277*9a747e4fSDavid du Colombier 
278*9a747e4fSDavid du Colombier 	d = e->parent;
279*9a747e4fSDavid du Colombier 	if(d == nil)
280*9a747e4fSDavid du Colombier 		return Eperm;
281*9a747e4fSDavid du Colombier 
282*9a747e4fSDavid du Colombier 	if((e->mode & DMDIR) != 0 && e->files != nil)
283*9a747e4fSDavid du Colombier 		return Edirnotempty;
284*9a747e4fSDavid du Colombier 
285*9a747e4fSDavid du Colombier 	p = e->hprev;
286*9a747e4fSDavid du Colombier 	n = e->hnext;
287*9a747e4fSDavid du Colombier 	if(n != nil)
288*9a747e4fSDavid du Colombier 		n->hprev = p;
289*9a747e4fSDavid du Colombier 	if(p != nil)
290*9a747e4fSDavid du Colombier 		p->hnext = n;
291*9a747e4fSDavid du Colombier 	else
292*9a747e4fSDavid du Colombier 		d->htab[hash(e->name) & HMASK] = n;
293*9a747e4fSDavid du Colombier 
294*9a747e4fSDavid du Colombier 	for(r = d->readers; r != nil; r = r->next) {
295*9a747e4fSDavid du Colombier 		if(r->cur == e)
296*9a747e4fSDavid du Colombier 			r->cur = e->fnext;
297*9a747e4fSDavid du Colombier 	}
298*9a747e4fSDavid du Colombier 
299*9a747e4fSDavid du Colombier 	p = e->fprev;
300*9a747e4fSDavid du Colombier 	n = e->fnext;
301*9a747e4fSDavid du Colombier 	if(n != nil)
302*9a747e4fSDavid du Colombier 		n->fprev = p;
303*9a747e4fSDavid du Colombier 	if(p != nil)
304*9a747e4fSDavid du Colombier 		p->fnext = n;
305*9a747e4fSDavid du Colombier 	else
306*9a747e4fSDavid du Colombier 		d->files = n;
307*9a747e4fSDavid du Colombier 
308*9a747e4fSDavid du Colombier 	e->parent = nil;
309*9a747e4fSDavid du Colombier 	d->ref--;
310*9a747e4fSDavid du Colombier 	deletekey(map, e->fnum);
311*9a747e4fSDavid du Colombier 	edestroy(e);
312*9a747e4fSDavid du Colombier 	return nil;
313*9a747e4fSDavid du Colombier }
314*9a747e4fSDavid du Colombier 
315*9a747e4fSDavid du Colombier Entry *
ewalk(Entry * d,char * name,char ** err)316*9a747e4fSDavid du Colombier ewalk(Entry *d, char *name, char **err)
317*9a747e4fSDavid du Colombier {
318*9a747e4fSDavid du Colombier 	Entry *e;
319*9a747e4fSDavid du Colombier 
320*9a747e4fSDavid du Colombier 	if((d->mode & DMDIR) == 0) {
321*9a747e4fSDavid du Colombier 		*err = Enotdir;
322*9a747e4fSDavid du Colombier 		return nil;
323*9a747e4fSDavid du Colombier 	}
324*9a747e4fSDavid du Colombier 
325*9a747e4fSDavid du Colombier 	if(strcmp(name, "..") == 0) {
326*9a747e4fSDavid du Colombier 		e = d->parent;
327*9a747e4fSDavid du Colombier 		if(e == nil)
328*9a747e4fSDavid du Colombier 			return d;
329*9a747e4fSDavid du Colombier 		edestroy(d);
330*9a747e4fSDavid du Colombier 		e->ref++;
331*9a747e4fSDavid du Colombier 		return e;
332*9a747e4fSDavid du Colombier 	}
333*9a747e4fSDavid du Colombier 
334*9a747e4fSDavid du Colombier 	for(e = d->htab[hash(name) & HMASK]; e != nil; e = e->hnext) {
335*9a747e4fSDavid du Colombier 		if(strcmp(e->name, name) == 0) {
336*9a747e4fSDavid du Colombier 			d->ref--;
337*9a747e4fSDavid du Colombier 			e->ref++;
338*9a747e4fSDavid du Colombier 			return e;
339*9a747e4fSDavid du Colombier 		}
340*9a747e4fSDavid du Colombier 	}
341*9a747e4fSDavid du Colombier 
342*9a747e4fSDavid du Colombier 	*err = Enonexist;
343*9a747e4fSDavid du Colombier 	return nil;
344*9a747e4fSDavid du Colombier }
345*9a747e4fSDavid du Colombier 
346*9a747e4fSDavid du Colombier static void
eread0(Extent * e,Extent * x,uchar * a,ulong n,ulong off)347*9a747e4fSDavid du Colombier eread0(Extent *e, Extent *x, uchar *a, ulong n, ulong off)
348*9a747e4fSDavid du Colombier {
349*9a747e4fSDavid du Colombier 	uchar *a0, *a1;
350*9a747e4fSDavid du Colombier 	ulong n0, n1, o0, o1, d, z;
351*9a747e4fSDavid du Colombier 
352*9a747e4fSDavid du Colombier 	for(;;) {
353*9a747e4fSDavid du Colombier 		while(e != nil) {
354*9a747e4fSDavid du Colombier 			if(off < e->off + e->size && off + n > e->off) {
355*9a747e4fSDavid du Colombier 				if(off >= e->off) {
356*9a747e4fSDavid du Colombier 					d = off - e->off;
357*9a747e4fSDavid du Colombier 					z = e->size - d;
358*9a747e4fSDavid du Colombier 					if(n <= z) {
359*9a747e4fSDavid du Colombier 						readdata(e->sect, a, n, e->addr + d);
360*9a747e4fSDavid du Colombier 						return;
361*9a747e4fSDavid du Colombier 					}
362*9a747e4fSDavid du Colombier 					readdata(e->sect, a, z, e->addr + d);
363*9a747e4fSDavid du Colombier 					a += z;
364*9a747e4fSDavid du Colombier 					n -= z;
365*9a747e4fSDavid du Colombier 					off += z;
366*9a747e4fSDavid du Colombier 				}
367*9a747e4fSDavid du Colombier 				else {
368*9a747e4fSDavid du Colombier 					a0 = a;
369*9a747e4fSDavid du Colombier 					n0 = e->off - off;
370*9a747e4fSDavid du Colombier 					o0 = off;
371*9a747e4fSDavid du Colombier 					a += n0;
372*9a747e4fSDavid du Colombier 					n -= n0;
373*9a747e4fSDavid du Colombier 					off += n0;
374*9a747e4fSDavid du Colombier 					z = e->size;
375*9a747e4fSDavid du Colombier 					if(n <= z) {
376*9a747e4fSDavid du Colombier 						readdata(e->sect, a, n, e->addr);
377*9a747e4fSDavid du Colombier 						a = a0;
378*9a747e4fSDavid du Colombier 						n = n0;
379*9a747e4fSDavid du Colombier 						off = o0;
380*9a747e4fSDavid du Colombier 					}
381*9a747e4fSDavid du Colombier 					else {
382*9a747e4fSDavid du Colombier 						readdata(e->sect, a, z, e->addr);
383*9a747e4fSDavid du Colombier 						a1 = a + z;
384*9a747e4fSDavid du Colombier 						n1 = n - z;
385*9a747e4fSDavid du Colombier 						o1 = off + z;
386*9a747e4fSDavid du Colombier 						if(n0 < n1) {
387*9a747e4fSDavid du Colombier 							eread0(e->next, x, a0, n0, o0);
388*9a747e4fSDavid du Colombier 							a = a1;
389*9a747e4fSDavid du Colombier 							n = n1;
390*9a747e4fSDavid du Colombier 							off = o1;
391*9a747e4fSDavid du Colombier 						}
392*9a747e4fSDavid du Colombier 						else {
393*9a747e4fSDavid du Colombier 							eread0(e->next, x, a1, n1, o1);
394*9a747e4fSDavid du Colombier 							a = a0;
395*9a747e4fSDavid du Colombier 							n = n0;
396*9a747e4fSDavid du Colombier 							off = o0;
397*9a747e4fSDavid du Colombier 						}
398*9a747e4fSDavid du Colombier 					}
399*9a747e4fSDavid du Colombier 				}
400*9a747e4fSDavid du Colombier 			}
401*9a747e4fSDavid du Colombier 			e = e->next;
402*9a747e4fSDavid du Colombier 		}
403*9a747e4fSDavid du Colombier 
404*9a747e4fSDavid du Colombier 		if(x == nil)
405*9a747e4fSDavid du Colombier 			break;
406*9a747e4fSDavid du Colombier 
407*9a747e4fSDavid du Colombier 		e = x;
408*9a747e4fSDavid du Colombier 		x = nil;
409*9a747e4fSDavid du Colombier 	}
410*9a747e4fSDavid du Colombier 
411*9a747e4fSDavid du Colombier 	memset(a, 0, n);
412*9a747e4fSDavid du Colombier }
413*9a747e4fSDavid du Colombier 
414*9a747e4fSDavid du Colombier ulong
eread(Entry * e,int parity,void * a,ulong n,ulong off)415*9a747e4fSDavid du Colombier eread(Entry *e, int parity, void *a, ulong n, ulong off)
416*9a747e4fSDavid du Colombier {
417*9a747e4fSDavid du Colombier 	if(n + off >= e->size)
418*9a747e4fSDavid du Colombier 		n = e->size - off;
419*9a747e4fSDavid du Colombier 	if(n <= 0)
420*9a747e4fSDavid du Colombier 		return 0;
421*9a747e4fSDavid du Colombier 	eread0(e->gen[parity].head, e->gen[parity^1].head, a, n, off);
422*9a747e4fSDavid du Colombier 	return n;
423*9a747e4fSDavid du Colombier }
424*9a747e4fSDavid du Colombier 
425*9a747e4fSDavid du Colombier void
ewrite(Entry * e,Extent * x,int parity,ulong mtime)426*9a747e4fSDavid du Colombier ewrite(Entry *e, Extent *x, int parity, ulong mtime)
427*9a747e4fSDavid du Colombier {
428*9a747e4fSDavid du Colombier 	ulong z;
429*9a747e4fSDavid du Colombier 	Extent *t;
430*9a747e4fSDavid du Colombier 
431*9a747e4fSDavid du Colombier 	t = e->gen[parity].head;
432*9a747e4fSDavid du Colombier 	x->next = t;
433*9a747e4fSDavid du Colombier 	x->prev = nil;
434*9a747e4fSDavid du Colombier 	e->gen[parity].head = x;
435*9a747e4fSDavid du Colombier 	if(t == nil)
436*9a747e4fSDavid du Colombier 		e->gen[parity].tail = x;
437*9a747e4fSDavid du Colombier 	else
438*9a747e4fSDavid du Colombier 		t->prev = x;
439*9a747e4fSDavid du Colombier 	if(mtime != 0)
440*9a747e4fSDavid du Colombier 		e->mtime = mtime;
441*9a747e4fSDavid du Colombier 	used += x->size;
442*9a747e4fSDavid du Colombier 	z = x->off + x->size;
443*9a747e4fSDavid du Colombier 	if(z > e->size)
444*9a747e4fSDavid du Colombier 		e->size = z;
445*9a747e4fSDavid du Colombier }
446*9a747e4fSDavid du Colombier 
447*9a747e4fSDavid du Colombier ulong
echmod(Entry * e,ulong mode,ulong mnum)448*9a747e4fSDavid du Colombier echmod(Entry *e, ulong mode, ulong mnum)
449*9a747e4fSDavid du Colombier {
450*9a747e4fSDavid du Colombier 	if(mnum != 0)
451*9a747e4fSDavid du Colombier 		e->mnum = mnum;
452*9a747e4fSDavid du Colombier 	else
453*9a747e4fSDavid du Colombier 		e->mnum++;
454*9a747e4fSDavid du Colombier 	e->mode &= ~0777;
455*9a747e4fSDavid du Colombier 	e->mode |= mode;
456*9a747e4fSDavid du Colombier 	return e->mnum;
457*9a747e4fSDavid du Colombier }
458*9a747e4fSDavid du Colombier 
459*9a747e4fSDavid du Colombier Qid
eqid(Entry * e)460*9a747e4fSDavid du Colombier eqid(Entry *e)
461*9a747e4fSDavid du Colombier {
462*9a747e4fSDavid du Colombier 	Qid qid;
463*9a747e4fSDavid du Colombier 
464*9a747e4fSDavid du Colombier 	if(e->mode & DMDIR)
465*9a747e4fSDavid du Colombier 		qid.type = QTDIR;
466*9a747e4fSDavid du Colombier 	else
467*9a747e4fSDavid du Colombier 		qid.type = 0;
468*9a747e4fSDavid du Colombier 	qid.path = e->fnum;
469*9a747e4fSDavid du Colombier 	return qid;
470*9a747e4fSDavid du Colombier }
471*9a747e4fSDavid du Colombier 
472*9a747e4fSDavid du Colombier void
estat(Entry * e,Dir * d,int alloc)473*9a747e4fSDavid du Colombier estat(Entry *e, Dir *d, int alloc)
474*9a747e4fSDavid du Colombier {
475*9a747e4fSDavid du Colombier 	d->type = 'z';
476*9a747e4fSDavid du Colombier 	d->dev = 0;
477*9a747e4fSDavid du Colombier 	if(alloc) {
478*9a747e4fSDavid du Colombier 		d->uid = estrdup9p(user);
479*9a747e4fSDavid du Colombier 		d->gid = estrdup9p(user);
480*9a747e4fSDavid du Colombier 		d->muid = estrdup9p(user);
481*9a747e4fSDavid du Colombier 		d->name = estrdup9p(e->name);
482*9a747e4fSDavid du Colombier 	}
483*9a747e4fSDavid du Colombier 	else {
484*9a747e4fSDavid du Colombier 		d->uid = user;
485*9a747e4fSDavid du Colombier 		d->gid = user;
486*9a747e4fSDavid du Colombier 		d->muid = user;
487*9a747e4fSDavid du Colombier 		d->name = e->name;
488*9a747e4fSDavid du Colombier 	}
489*9a747e4fSDavid du Colombier 	d->mode = e->mode;
490*9a747e4fSDavid du Colombier 	d->length = e->size;
491*9a747e4fSDavid du Colombier 	d->atime = e->mtime;
492*9a747e4fSDavid du Colombier 	d->mtime = e->mtime;
493*9a747e4fSDavid du Colombier 	d->qid = eqid(e);
494*9a747e4fSDavid du Colombier }
495*9a747e4fSDavid du Colombier 
496*9a747e4fSDavid du Colombier Dirr *
ediropen(Entry * e)497*9a747e4fSDavid du Colombier ediropen(Entry *e)
498*9a747e4fSDavid du Colombier {
499*9a747e4fSDavid du Colombier 	Dirr *d, *t;
500*9a747e4fSDavid du Colombier 
501*9a747e4fSDavid du Colombier 	d = emalloc9p(sizeof(Dirr));
502*9a747e4fSDavid du Colombier 	d->dir = e;
503*9a747e4fSDavid du Colombier 	d->cur = e->files;
504*9a747e4fSDavid du Colombier 	t = e->readers;
505*9a747e4fSDavid du Colombier 	d->next = t;
506*9a747e4fSDavid du Colombier 	d->prev = nil;
507*9a747e4fSDavid du Colombier 	if(t != nil)
508*9a747e4fSDavid du Colombier 		t->prev = d;
509*9a747e4fSDavid du Colombier 	e->readers = d;
510*9a747e4fSDavid du Colombier 	e->ref++;
511*9a747e4fSDavid du Colombier 	return d;
512*9a747e4fSDavid du Colombier }
513*9a747e4fSDavid du Colombier 
514*9a747e4fSDavid du Colombier int
edirread(Dirr * r,char * a,long n)515*9a747e4fSDavid du Colombier edirread(Dirr *r, char *a, long n)
516*9a747e4fSDavid du Colombier {
517*9a747e4fSDavid du Colombier 	Dir d;
518*9a747e4fSDavid du Colombier 	Entry *e;
519*9a747e4fSDavid du Colombier 	int m, x;
520*9a747e4fSDavid du Colombier 
521*9a747e4fSDavid du Colombier 	m = 0;
522*9a747e4fSDavid du Colombier 	for(e = r->cur; e != nil; e = e->fnext) {
523*9a747e4fSDavid du Colombier 		estat(e, &d, 0);
524*9a747e4fSDavid du Colombier 		x = convD2M(&d, (uchar *)a, n);
525*9a747e4fSDavid du Colombier 		if(x <= BIT16SZ)
526*9a747e4fSDavid du Colombier 			break;
527*9a747e4fSDavid du Colombier 		a += x;
528*9a747e4fSDavid du Colombier 		n -= x;
529*9a747e4fSDavid du Colombier 		m += x;
530*9a747e4fSDavid du Colombier 	}
531*9a747e4fSDavid du Colombier 
532*9a747e4fSDavid du Colombier 	r->cur = e;
533*9a747e4fSDavid du Colombier 	return m;
534*9a747e4fSDavid du Colombier }
535*9a747e4fSDavid du Colombier 
536*9a747e4fSDavid du Colombier void
edirclose(Dirr * d)537*9a747e4fSDavid du Colombier edirclose(Dirr *d)
538*9a747e4fSDavid du Colombier {
539*9a747e4fSDavid du Colombier 	Entry *e;
540*9a747e4fSDavid du Colombier 	Dirr *p, *n;
541*9a747e4fSDavid du Colombier 
542*9a747e4fSDavid du Colombier 	e = d->dir;
543*9a747e4fSDavid du Colombier 	p = d->prev;
544*9a747e4fSDavid du Colombier 	n = d->next;
545*9a747e4fSDavid du Colombier 	if(n != nil)
546*9a747e4fSDavid du Colombier 		n->prev = p;
547*9a747e4fSDavid du Colombier 	if(p != nil)
548*9a747e4fSDavid du Colombier 		p->next = n;
549*9a747e4fSDavid du Colombier 	else
550*9a747e4fSDavid du Colombier 		e->readers = n;
551*9a747e4fSDavid du Colombier 
552*9a747e4fSDavid du Colombier 	edestroy(e);
553*9a747e4fSDavid du Colombier 	free(d);
554*9a747e4fSDavid du Colombier }
555*9a747e4fSDavid du Colombier 
556*9a747e4fSDavid du Colombier static	Renum	R;
557*9a747e4fSDavid du Colombier 
558*9a747e4fSDavid du Colombier static void
xrenum(Extent * x)559*9a747e4fSDavid du Colombier xrenum(Extent *x)
560*9a747e4fSDavid du Colombier {
561*9a747e4fSDavid du Colombier 	while(x != nil) {
562*9a747e4fSDavid du Colombier 		if(x->sect == R.old)
563*9a747e4fSDavid du Colombier 			x->sect = R.new;
564*9a747e4fSDavid du Colombier 		x = x->next;
565*9a747e4fSDavid du Colombier 	}
566*9a747e4fSDavid du Colombier }
567*9a747e4fSDavid du Colombier 
568*9a747e4fSDavid du Colombier static void
renum(Entry * e)569*9a747e4fSDavid du Colombier renum(Entry *e)
570*9a747e4fSDavid du Colombier {
571*9a747e4fSDavid du Colombier 	if(e->mode & DMDIR) {
572*9a747e4fSDavid du Colombier 		for(e = e->files; e != nil; e = e->fnext)
573*9a747e4fSDavid du Colombier 			renum(e);
574*9a747e4fSDavid du Colombier 	}
575*9a747e4fSDavid du Colombier 	else {
576*9a747e4fSDavid du Colombier 		xrenum(e->gen[0].head);
577*9a747e4fSDavid du Colombier 		xrenum(e->gen[1].head);
578*9a747e4fSDavid du Colombier 	}
579*9a747e4fSDavid du Colombier }
580*9a747e4fSDavid du Colombier 
581*9a747e4fSDavid du Colombier void
erenum(Renum * r)582*9a747e4fSDavid du Colombier erenum(Renum *r)
583*9a747e4fSDavid du Colombier {
584*9a747e4fSDavid du Colombier 	R = *r;
585*9a747e4fSDavid du Colombier 	renum(root);
586*9a747e4fSDavid du Colombier }
587