summaryrefslogtreecommitdiff
path: root/sys/src/cmd/aux/flashfs/entry.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/aux/flashfs/entry.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/aux/flashfs/entry.c')
-rwxr-xr-xsys/src/cmd/aux/flashfs/entry.c586
1 files changed, 586 insertions, 0 deletions
diff --git a/sys/src/cmd/aux/flashfs/entry.c b/sys/src/cmd/aux/flashfs/entry.c
new file mode 100755
index 000000000..8261eab23
--- /dev/null
+++ b/sys/src/cmd/aux/flashfs/entry.c
@@ -0,0 +1,586 @@
+#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 int
+fnum(void)
+{
+ return ++nextfnum;
+}
+
+static void
+maxfnum(int n)
+{
+ if(n > nextfnum)
+ nextfnum = n;
+}
+
+static int
+hash(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 void
+dirinit(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 void
+fileinit(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 void
+elfree(Extent *x)
+{
+ Extent *t;
+
+ while(x != nil) {
+ t = x->next;
+ used -= x->size;
+ free(x);
+ x = t;
+ }
+}
+
+static void
+extfree(Entry *e)
+{
+ elfree(e->gen[0].head);
+ elfree(e->gen[1].head);
+}
+
+static void
+efree(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);
+}
+
+void
+einit(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 void
+dumptree(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);
+ }
+}
+
+void
+edump(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;
+}
+
+void
+edestroy(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;
+}
+
+void
+etrunc(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 void
+eread0(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);
+}
+
+ulong
+eread(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;
+}
+
+void
+ewrite(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;
+}
+
+ulong
+echmod(Entry *e, ulong mode, ulong mnum)
+{
+ if(mnum != 0)
+ e->mnum = mnum;
+ else
+ e->mnum++;
+ e->mode &= ~0777;
+ e->mode |= mode;
+ return e->mnum;
+}
+
+Qid
+eqid(Entry *e)
+{
+ Qid qid;
+
+ if(e->mode & DMDIR)
+ qid.type = QTDIR;
+ else
+ qid.type = 0;
+ qid.path = e->fnum;
+ return qid;
+}
+
+void
+estat(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;
+}
+
+int
+edirread(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;
+}
+
+void
+edirclose(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 void
+xrenum(Extent *x)
+{
+ while(x != nil) {
+ if(x->sect == R.old)
+ x->sect = R.new;
+ x = x->next;
+ }
+}
+
+static void
+renum(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);
+ }
+}
+
+void
+erenum(Renum *r)
+{
+ R = *r;
+ renum(root);
+}