## diffname bitsy/devsac.c 2000/1015 ## diff -e /dev/null /n/emeliedump/2000/1015/sys/src/9/bitsy/devsac.c 0a #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "../port/error.h" enum { OPERM = 0x3, /* mask of all permission types in open mode */ Nram = 512, CacheSize = 20, OffsetSize = 4, /* size in bytes of an offset */ }; typedef struct SacPath SacPath; typedef struct Sac Sac; typedef struct SacHeader SacHeader; typedef struct SacDir SacDir; typedef struct Cache Cache; enum { Magic = 0x5acf5, }; struct SacDir { char name[NAMELEN]; char uid[NAMELEN]; char gid[NAMELEN]; uchar qid[4]; uchar mode[4]; uchar atime[4]; uchar mtime[4]; uchar length[8]; uchar blocks[8]; }; struct SacHeader { uchar magic[4]; uchar length[8]; uchar blocksize[4]; uchar md5[16]; }; struct Sac { SacDir; SacPath *path; }; struct SacPath { Ref; SacPath *up; long blocks; int entry; int nentry; }; struct Cache { long block; ulong age; uchar *data; }; enum { Pexec = 1, Pwrite = 2, Pread = 4, Pother = 1, Pgroup = 8, Powner = 64, }; static char *sacfs = "fs.sac"; static uchar *data; static int blocksize; static Sac root; static Cache cache[CacheSize]; static ulong cacheage; static void sacdir(Chan *, SacDir*, char*); static ulong getl(void *p); static Sac *saccpy(Sac *s); static Sac *saclookup(Sac *s, char *name); static int sacdirread(Chan *, char *p, long off, long cnt); static void loadblock(void *buf, uchar *offset, int blocksize); static void sacfree(Sac*); static void sacinit(void) { SacHeader *hdr; uchar *p; char *s; int i; print("sacinit\n"); s = getconf("flash"); if(s == nil) { print("devsac: no flash file system\n"); return; } p = (uchar*)strtoul(s, 0, 0); if(p == 0) { print("devsac: bad address for flash file system\n"); return; } data = tarlookup(p, sacfs, &i); if(data == 0) { print("devsac: could not find file: %s\n", sacfs); return; } hdr = (SacHeader*)data; if(getl(hdr->magic) != Magic) { print("devsac: bad magic\n"); return; } blocksize = getl(hdr->blocksize); root.SacDir = *(SacDir*)(data + sizeof(SacHeader)); p = malloc(CacheSize*blocksize); if(p == nil) error("allocating cache"); for(i=0; iqid = (Qid){getl(root.qid), 0}; c->dev = dev; c->aux = saccpy(&root); return c; } static Chan* sacclone(Chan *c, Chan *nc) { nc = devclone(c, nc); nc->aux = saccpy(c->aux); return nc; } static int sacwalk(Chan *c, char *name) { Sac *sac; //print("walk %s\n", name); isdir(c); if(name[0]=='.' && name[1]==0) return 1; if(name[0]=='.' && name[1]=='.' && name[2]==0) return 1; sac = c->aux; sac = saclookup(sac, name); if(sac == nil) { strncpy(up->error, Enonexist, NAMELEN); return 0; } c->aux = sac; c->qid = (Qid){getl(sac->qid), 0}; return 1; } static Chan* sacopen(Chan *c, int omode) { ulong t, mode; Sac *sac; static int access[] = { 0400, 0200, 0600, 0100 }; sac = c->aux; mode = getl(sac->mode); if(strcmp(up->user, sac->uid) == 0) mode = mode; else if(strcmp(up->user, sac->gid) == 0) mode = mode<<3; else mode = mode<<6; t = access[omode&3]; if((t & mode) != t) error(Eperm); c->offset = 0; c->mode = openmode(omode); c->flag |= COPEN; return c; } static long sacread(Chan *c, void *a, long n, vlong voff) { Sac *sac; char *buf, *buf2; int nn, cnt, i, j; uchar *blocks; long length; long off = voff; buf = a; cnt = n; if(c->qid.path & CHDIR){ cnt = (cnt/DIRLEN)*DIRLEN; if(off%DIRLEN) error("i/o error"); return sacdirread(c, buf, off, cnt); } sac = c->aux; length = getl(sac->length); if(off >= length) return 0; if(cnt > length-off) cnt = length-off; if(cnt == 0) return 0; n = cnt; blocks = data + getl(sac->blocks); buf2 = malloc(blocksize); while(cnt > 0) { i = off/blocksize; nn = blocksize; if(nn > length-i*blocksize) nn = length-i*blocksize; loadblock(buf2, blocks+i*OffsetSize, nn); j = off-i*blocksize; nn -= j; if(nn > cnt) nn = cnt; memmove(buf, buf2+j, nn); cnt -= nn; off += nn; buf += nn; } free(buf2); return n; } static long sacwrite(Chan *, void *, long, vlong) { error(Eperm); return 0; } static void sacclose(Chan* c) { Sac *sac = c->aux; c->aux = nil; sacfree(sac); } static void sacstat(Chan *c, char *db) { sacdir(c, c->aux, db); } static Sac* saccpy(Sac *s) { Sac *ss; ss = malloc(sizeof(Sac)); *ss = *s; if(ss->path) incref(ss->path); return ss; } static SacPath * sacpathalloc(SacPath *p, long blocks, int entry, int nentry) { SacPath *pp = malloc(sizeof(SacPath)); pp->ref = 1; pp->blocks = blocks; pp->entry = entry; pp->nentry = nentry; pp->up = p; return pp; } static void sacpathfree(SacPath *p) { if(p == nil) return; if(decref(p) > 0) return; sacpathfree(p->up); free(p); } static void sacfree(Sac *s) { sacpathfree(s->path); free(s); } static void sacdir(Chan *c, SacDir *s, char *buf) { Dir dir; memmove(dir.name, s->name, NAMELEN); dir.qid = (Qid){getl(s->qid), 0}; dir.mode = getl(s->mode); dir.length = getl(s->length); if(dir.mode &CHDIR) dir.length *= DIRLEN; memmove(dir.uid, s->uid, NAMELEN); memmove(dir.gid, s->gid, NAMELEN); dir.atime = getl(s->atime); dir.mtime = getl(s->mtime); dir.type = devtab[c->type]->dc; dir.dev = c->dev; convD2M(&dir, buf); } static void loadblock(void *buf, uchar *offset, int blocksize) { long block, n; ulong age; int i, j; block = getl(offset); if(block < 0) { block = -block; cacheage++; // age has wraped if(cacheage == 0) { for(i=0; ipath; if(p == nil || p->up == nil) { sacpathfree(p); *s = root; return s; } p = p->up; blocks = data + p->blocks; per = blocksize/sizeof(SacDir); i = p->entry/per; n = per; if(n > p->nentry-i*per) n = p->nentry-i*per; buf = malloc(per*sizeof(SacDir)); loadblock(buf, blocks + i*OffsetSize, n*sizeof(SacDir)); s->SacDir = buf[p->entry-i*per]; free(buf); incref(p); sacpathfree(s->path); s->path = p; return s; } static int sacdirread(Chan *c, char *p, long off, long cnt) { uchar *blocks; SacDir *buf; int iblock, per, i, j, n, ndir; Sac *s; s = c->aux; blocks = data + getl(s->blocks); per = blocksize/sizeof(SacDir); ndir = getl(s->length); off /= DIRLEN; cnt /= DIRLEN; if(off >= ndir) return 0; if(cnt > ndir-off) cnt = ndir-off; iblock = -1; buf = malloc(per*sizeof(SacDir)); for(i=off; i ndir-j*per) n = ndir-j*per; loadblock(buf, blocks + j*OffsetSize, n*sizeof(SacDir)); iblock = j; } j *= per; sacdir(c, buf+i-j, p); p += DIRLEN; } free(buf); return cnt*DIRLEN; } static Sac* saclookup(Sac *s, char *name) { int ndir; int i, j, k, n, per; uchar *blocks; SacDir *buf; int iblock; SacDir *sd; if(strcmp(name, "..") == 0) return sacparent(s); blocks = data + getl(s->blocks); per = blocksize/sizeof(SacDir); ndir = getl(s->length); buf = malloc(per*sizeof(SacDir)); iblock = -1; // linear search for(i=0; i ndir-j*per) n = ndir-j*per; loadblock(buf, blocks + j*OffsetSize, n*sizeof(SacDir)); iblock = j; } j *= per; sd = buf+i-j; k = strcmp(name, sd->name); if(k == 0) { s->path = sacpathalloc(s->path, getl(s->blocks), i, ndir); s->SacDir = *sd; free(buf); return s; } } free(buf); return 0; } static ulong getl(void *p) { uchar *a = p; return (a[0]<<24) | (a[1]<<16) | (a[2]<<8) | a[3]; } Dev sacdevtab = { 'C', "sac", devreset, sacinit, sacattach, sacclone, sacwalk, sacstat, sacopen, devcreate, sacclose, sacread, devbread, sacwrite, devbwrite, devremove, devwstat, }; . ## diffname bitsy/devsac.c 2000/1016 ## diff -e /n/emeliedump/2000/1015/sys/src/9/bitsy/devsac.c /n/emeliedump/2000/1016/sys/src/9/bitsy/devsac.c 123c print("devsac: bad magic\n"); . 104,115c p = (uchar*)Flash_tar+4; . 101d ## diffname bitsy/devsac.c 2000/1208 ## diff -e /n/emeliedump/2000/1016/sys/src/9/bitsy/devsac.c /n/emeliedump/2000/1208/sys/src/9/bitsy/devsac.c 164,165d ## diffname bitsy/devsac.c 2001/0529 ## diff -e /n/emeliedump/2000/1208/sys/src/9/bitsy/devsac.c /n/emeliedump/2001/0529/sys/src/9/bitsy/devsac.c 140c path = getl(root.qid); if(path & CHDIR) c->qid.type = QTDIR; else c->qid.type = QTFILE; c->qid.path = path & ~CHDIR; c->qid.vers = 0; . 129a int opath; . 29,31c char name[KNAMELEN]; char uid[KNAMELEN]; char gid[KNAMELEN]; . ## diffname bitsy/devsac.c 2001/0531 ## diff -e /n/emeliedump/2001/0529/sys/src/9/bitsy/devsac.c /n/emeliedump/2001/0531/sys/src/9/bitsy/devsac.c 177,178c if(nc == nil){ nc = devclone(c); nc->type = 0; /* device doesn't know about this channel yet */ alloc = 1; } wq->clone = nc; for(j=0; jaux; sac = saclookup(sac, name); if(sac == nil) { strncpy(up->error, Enonexist, NAMELEN); return 0; } nc->aux = sac; pathtoqid(getl(sac->qid), &nc->qid); } . 168,175c alloc = 0; wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid)); if(waserror()){ if(alloc && wq->clone!=nil) cclose(wq->clone); free(wq); return nil; . 166c if(nname > 0) isdir(c); . 164a int i, j, alloc; Walkqid *wq; char *n; Dir dir; . 161,162c static Walkqid* sacwalk(Chan *c, Chan *nc, char **name, int nname) . 142,147c pathtoqid(path, &c->qid; . 96a pathtoqid(ulong path, Qid *q) { if(path & CHDIR) q->type = QTDIR; else q->type = QTFILE; q->path = path & ~(CHDIR|CHAPPEND|CHEXCL|CHMOUNT); q->vers = 0; } static void . 29,31c char name[NAMELEN]; char uid[NAMELEN]; char gid[NAMELEN]; . 8a /* * definitions from the old 9P. we need these because sac files * are encoded using the old definitions. */ #define NAMELEN 28 #define CHDIR 0x80000000 /* mode bit for directories */ #define CHAPPEND 0x40000000 /* mode bit for append only files */ #define CHEXCL 0x20000000 /* mode bit for exclusive use files */ #define CHMOUNT 0x10000000 /* mode bit for mounted channel */ #define CHREAD 0x4 /* mode bit for read permission */ #define CHWRITE 0x2 /* mode bit for write permission */ #define CHEXEC 0x1 /* mode bit for execute permission */ . ## diffname bitsy/devsac.c 2001/0601 ## diff -e /n/emeliedump/2001/0531/sys/src/9/bitsy/devsac.c /n/emeliedump/2001/0601/sys/src/9/bitsy/devsac.c 554d 494c return sofar; . 489,491c n = sacdir(c, buf+i, p, cnt - sofar); if(n == 0) break; if(off > 0) off -= n; else { p += n; sofar += n; } . 487d 472,482c buf = malloc(blocksize); sofar = 0; for(j = 0; j < ndir; j++) { i = j%per; if(i == 0) { . 465c int per, i, j, n, ndir; long sofar; . 461c sacdirread(Chan *c, uchar *p, long off, long cnt) . 459a /* n**2 alg to read a directory */ . 381c return convD2M(&dir, db, n); . 373,376d 369,371c dir.name = s->name; dir.uid = s->uid; dir.gid = s->gid; dir.muid = s->uid; pathtoqid(getl(s->qid), &dir.qid); omodetomode(getl(s->mode), &dir.mode); . 364,365c static int sacdir(Chan *c, SacDir *s, uchar *db, int n) . 318c n = sacdir(c, c->aux, db, n); if(n == 0) error(Ebadarg); return n; . 314,316c static int sacstat(Chan *c, uchar *db, int n) . 263,268c if(c->qid.type & QTDIR) return sacdirread(c, a, off, cnt); . 222c poperror(); if(wq->nqid < nname){ if(alloc) cclose(wq->clone); wq->clone = nil; } return wq; . 217c break; . 215a if(j == 0) error(Enonexist); . 214c sac = saclookup(sac, n); . 210,212c n = name[j]; if(strcmp(n, ".") == 0){ wq->qid[wq->nqid++] = nc->qid; continue; } . 203d 188d 185c int j, alloc; . 173,180d 166,167c pathtoqid(getl(root.qid), &c->qid); . 155d 121a omodetomode(ulong om, ulong *m) { ulong nm; nm = om & ~(CHDIR|CHAPPEND|CHEXCL|CHMOUNT); if(om & CHDIR) nm |= DMDIR; *m = nm; } static void . 105,108c static Sac *saclookup(Sac *s, char *name); static int sacdirread(Chan *, uchar *p, long off, long cnt); static void loadblock(void *buf, uchar *offset, int blocksize); static void sacfree(Sac*); . 102c static int sacdir(Chan *, SacDir*, uchar*, int); . ## diffname bitsy/devsac.c 2001/0605 ## diff -e /n/emeliedump/2001/0601/sys/src/9/bitsy/devsac.c /n/emeliedump/2001/0605/sys/src/9/bitsy/devsac.c 538c s->path = sacpathalloc(s->path, getl(s->blocks), i, ndir); . 314a . 223a wq->qid[wq->nqid++] = nc->qid; . 222d 202a nc->aux = saccpy(c->aux); . ## diffname bitsy/devsac.c 2001/0616 ## diff -e /n/emeliedump/2001/0605/sys/src/9/bitsy/devsac.c /n/emeliedump/2001/0616/sys/src/9/bitsy/devsac.c 227a // listprint(name, wq->nqid, j); . 181a static void listprint(char **name, int nname, int j) { int i; print("%d ", j); for(i = 0; i< nname; i++) print("%s/", name[i]); print("\n"); } . 142,143c p = (uchar*)Flash_tar; data = tarlookup(p, sacfs, &i); if(data == 0) { print("devsac: could not find file: %s\n", sacfs); return; } . ## diffname bitsy/devsac.c 2001/0617 ## diff -e /n/emeliedump/2001/0616/sys/src/9/bitsy/devsac.c /n/emeliedump/2001/0617/sys/src/9/bitsy/devsac.c 234c strncpy(up->error, Enonexist, ERRMAX); . ## diffname bitsy/devsac.c 2001/0809 ## diff -e /n/emeliedump/2001/0617/sys/src/9/bitsy/devsac.c /n/emeliedump/2001/0809/sys/src/9/bitsy/devsac.c 142c p = (uchar*)Flash_tar+4; . 139c p = (uchar*)Flash_tar; . ## diffname bitsy/devsac.c 2001/0924 ## diff -e /n/emeliedump/2001/0809/sys/src/9/bitsy/devsac.c /n/emeliedump/2001/0924/sys/src/9/bitsy/devsac.c 234c kstrcpy(up->errstr, Enonexist, ERRMAX); . ## diffname bitsy/devsac.c 2002/0109 ## diff -e /n/emeliedump/2001/0924/sys/src/9/bitsy/devsac.c /n/emeliedump/2002/0109/sys/src/9/bitsy/devsac.c 578a devshutdown, . ## diffname bitsy/devsac.c 2002/0413 # deleted ## diff -e /n/emeliedump/2002/0109/sys/src/9/bitsy/devsac.c /n/emeliedump/2002/0413/sys/src/9/bitsy/devsac.c 1,592d