📄 entry.c
字号:
#include <u.h>#include <libc.h>#include <auth.h>#include <fcall.h>#include <thread.h>#include <9p.h>#include "flashfs.h"static int nextfnum;static Intmap* map;static Dir dirproto;static char user[] = "flash"; Entry *root; ulong used; ulong limit; ulong maxwrite;enum{ debug = 0,};static intfnum(void){ return ++nextfnum;}static voidmaxfnum(int n){ if(n > nextfnum) nextfnum = n;}static inthash(char *s){ int c, d, h; h = 0; while((c = *s++) != '\0') { d = c; c ^= c << 6; h += (c << 11) ^ (c >> 1); h ^= (d << 14) + (d << 7) + (d << 4) + d; } if(h < 0) return ~h; return h;}static voiddirinit(Entry *e){ Entry **t; e->size = 0; t = emalloc9p(HSIZE * sizeof(Entry*)); memset(t, 0, HSIZE * sizeof(Entry*)); e->htab = t; e->files = nil; e->readers = nil;}static voidfileinit(Entry *e){ e->size = 0; e->gen[0].head = nil; e->gen[0].tail = nil; e->gen[1].head = nil; e->gen[1].tail = nil;}static voidelfree(Extent *x){ Extent *t; while(x != nil) { t = x->next; used -= x->size; free(x); x = t; }}static voidextfree(Entry *e){ elfree(e->gen[0].head); elfree(e->gen[1].head);}static voidefree(Entry *e){ if(debug) fprint(2, "free %s\n", e->name); if(e->mode & DMDIR) free(e->htab); else extfree(e); free(e->name); free(e);}voideinit(void){ Entry *e; e = emalloc9p(sizeof(Entry)); e->ref = 1; e->parent = nil; dirinit(e); e->name = estrdup9p(""); e->fnum = 0; e->mode = DMDIR | 0775; e->mnum = 0; e->mtime = 0; root = e; map = allocmap(nil);}static voiddumptree(Entry *e, int n){ Entry *l; if(debug) fprint(2, "%d %s %d\n", n, e->name, e->ref); if(e->mode & DMDIR) { n++; for(l = e->files; l != nil; l = l->fnext) dumptree(l, n); }}voidedump(void){ if(debug) dumptree(root, 0);}Entry *elookup(ulong key){ if(key == 0) return root; maxfnum(key); return lookupkey(map, key);}Extent *esum(Entry *e, int sect, ulong addr, int *more){ Exts *x; Extent *t, *u; x = &e->gen[eparity]; t = x->tail; if(t == nil || t->sect != sect || t->addr != addr) return nil; u = t->prev; if(u != nil) { u->next = nil; *more = 1; } else { x->head = nil; *more = 0; } x->tail = u; x = &e->gen[eparity^1]; u = x->head; t->next = u; x->head = t; if(u == nil) x->tail = t; else u->prev = t; return t;}voidedestroy(Entry *e){ e->ref--; if(e->ref == 0) efree(e);}Entry *ecreate(Entry *d, char *name, ulong n, ulong mode, ulong mtime, char **err){ int h; Entry *e, *f; h = hash(name) & HMASK; for(e = d->htab[h]; e != nil; e = e->hnext) { if(strcmp(e->name, name) == 0) { *err = Eexists; return nil; } } e = emalloc9p(sizeof(Entry)); e->ref = 1; e->parent = d; d->ref++; f = d->htab[h]; e->hnext = f; e->hprev = nil; if(f != nil) f->hprev = e; d->htab[h] = e; f = d->files; e->fnext = f; e->fprev = nil; if(f != nil) f->fprev = e; d->files = e; d->ref--; e->ref++; e->name = estrdup9p(name); if(n == 0) n = fnum(); else maxfnum(n); insertkey(map, n, e); e->fnum = n; e->mode = mode & d->mode; e->mnum = 0; e->mtime = mtime; if(e->mode & DMDIR) dirinit(e); else fileinit(e); d->mtime = mtime; return e;}voidetrunc(Entry *e, ulong n, ulong mtime){ extfree(e); deletekey(map, e->fnum); if(n == 0) n = fnum(); else maxfnum(n); e->fnum = n; e->mnum = 0; e->mtime = mtime; insertkey(map, n, e); fileinit(e); e->parent->mtime = mtime;}char *eremove(Entry *e){ Dirr *r; Entry *d, *n, *p; d = e->parent; if(d == nil) return Eperm; if((e->mode & DMDIR) != 0 && e->files != nil) return Edirnotempty; p = e->hprev; n = e->hnext; if(n != nil) n->hprev = p; if(p != nil) p->hnext = n; else d->htab[hash(e->name) & HMASK] = n; for(r = d->readers; r != nil; r = r->next) { if(r->cur == e) r->cur = e->fnext; } p = e->fprev; n = e->fnext; if(n != nil) n->fprev = p; if(p != nil) p->fnext = n; else d->files = n; e->parent = nil; d->ref--; deletekey(map, e->fnum); edestroy(e); return nil;}Entry *ewalk(Entry *d, char *name, char **err){ Entry *e; if((d->mode & DMDIR) == 0) { *err = Enotdir; return nil; } if(strcmp(name, "..") == 0) { e = d->parent; if(e == nil) return d; edestroy(d); e->ref++; return e; } for(e = d->htab[hash(name) & HMASK]; e != nil; e = e->hnext) { if(strcmp(e->name, name) == 0) { d->ref--; e->ref++; return e; } } *err = Enonexist; return nil;}static voideread0(Extent *e, Extent *x, uchar *a, ulong n, ulong off){ uchar *a0, *a1; ulong n0, n1, o0, o1, d, z; for(;;) { while(e != nil) { if(off < e->off + e->size && off + n > e->off) { if(off >= e->off) { d = off - e->off; z = e->size - d; if(n <= z) { readdata(e->sect, a, n, e->addr + d); return; } readdata(e->sect, a, z, e->addr + d); a += z; n -= z; off += z; } else { a0 = a; n0 = e->off - off; o0 = off; a += n0; n -= n0; off += n0; z = e->size; if(n <= z) { readdata(e->sect, a, n, e->addr); a = a0; n = n0; off = o0; } else { readdata(e->sect, a, z, e->addr); a1 = a + z; n1 = n - z; o1 = off + z; if(n0 < n1) { eread0(e->next, x, a0, n0, o0); a = a1; n = n1; off = o1; } else { eread0(e->next, x, a1, n1, o1); a = a0; n = n0; off = o0; } } } } e = e->next; } if(x == nil) break; e = x; x = nil; } memset(a, 0, n);}ulongeread(Entry *e, int parity, void *a, ulong n, ulong off){ if(n + off >= e->size) n = e->size - off; if(n <= 0) return 0; eread0(e->gen[parity].head, e->gen[parity^1].head, a, n, off); return n;}voidewrite(Entry *e, Extent *x, int parity, ulong mtime){ ulong z; Extent *t; t = e->gen[parity].head; x->next = t; x->prev = nil; e->gen[parity].head = x; if(t == nil) e->gen[parity].tail = x; else t->prev = x; if(mtime != 0) e->mtime = mtime; used += x->size; z = x->off + x->size; if(z > e->size) e->size = z;}ulongechmod(Entry *e, ulong mode, ulong mnum){ if(mnum != 0) e->mnum = mnum; else e->mnum++; e->mode &= ~0777; e->mode |= mode; return e->mnum;}Qideqid(Entry *e){ Qid qid; if(e->mode & DMDIR) qid.type = QTDIR; else qid.type = 0; qid.path = e->fnum; return qid;}voidestat(Entry *e, Dir *d, int alloc){ d->type = 'z'; d->dev = 0; if(alloc) { d->uid = estrdup9p(user); d->gid = estrdup9p(user); d->muid = estrdup9p(user); d->name = estrdup9p(e->name); } else { d->uid = user; d->gid = user; d->muid = user; d->name = e->name; } d->mode = e->mode; d->length = e->size; d->atime = e->mtime; d->mtime = e->mtime; d->qid = eqid(e);}Dirr *ediropen(Entry *e){ Dirr *d, *t; d = emalloc9p(sizeof(Dirr)); d->dir = e; d->cur = e->files; t = e->readers; d->next = t; d->prev = nil; if(t != nil) t->prev = d; e->readers = d; e->ref++; return d;}intedirread(Dirr *r, char *a, long n){ Dir d; Entry *e; int m, x; m = 0; for(e = r->cur; e != nil; e = e->fnext) { estat(e, &d, 0); x = convD2M(&d, (uchar *)a, n); if(x <= BIT16SZ) break; a += x; n -= x; m += x; } r->cur = e; return m;}voidedirclose(Dirr *d){ Entry *e; Dirr *p, *n; e = d->dir; p = d->prev; n = d->next; if(n != nil) n->prev = p; if(p != nil) p->next = n; else e->readers = n; edestroy(e); free(d);}static Renum R;static voidxrenum(Extent *x){ while(x != nil) { if(x->sect == R.old) x->sect = R.new; x = x->next; }}static voidrenum(Entry *e){ if(e->mode & DMDIR) { for(e = e->files; e != nil; e = e->fnext) renum(e); } else { xrenum(e->gen[0].head); xrenum(e->gen[1].head); }}voiderenum(Renum *r){ R = *r; renum(root);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -