## diffname mpc/devsac.c 1999/0608
## diff -e /dev/null /n/emeliedump/1999/0608/sys/src/brazil/mpc/devsac.c
0a
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
/*
* Rather than reading /adm/users, which is a lot of work for
* a toy program, we assume all groups have the form
* NNN:user:user:
* meaning that each user is the leader of his own group.
*/
enum
{
OPERM = 0x3, /* mask of all permission types in open mode */
Nram = 512,
};
typedef struct SacPath SacPath;
typedef struct Sac Sac;
typedef struct SacHeader SacHeader;
typedef struct SacDir SacDir;
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;
vlong blocks;
int entry;
};
enum
{
Pexec = 1,
Pwrite = 2,
Pread = 4,
Pother = 1,
Pgroup = 8,
Powner = 64,
};
uchar *data = SACMEM;
int blocksize;
Sac root;
void sacstat(SacDir*, char*);
void io(void);
void usage(void);
ulong getl(void *p);
vlong getv(void *p);
void init(char*);
Sac *saccpy(Sac *s);
Sac *saclookup(Sac *s, char *name);
int sacdirread(Sac *s, char *p, long off, long cnt);
void loadblock(void *buf, uchar *offset, int blocksize);
void sacfree(Sac*);
void
devinit(void)
{
SacHeader *hdr;
hdr = (SacHeader*)data;
if(getl(hdr->magic) != Magic) {
print("devsac: bad magic");
return;
}
blocksize = getl(hdr->blocksize);
root.SacDir = *(SacDir*)(data + sizeof(SacHeader));
}
static Chan*
sacattach(char* spec)
{
Chan *c;
int dev;
dev = atoi(spec);
if(dev != 0)
error("bad specification");
// check if init found sac file system in memory
if(blocksize == 0)
error("devsac: bad magic");
c = devattach('C', spec);
c->qid = (Qid){getl(root.qid), 0};
c->dev = dev;
c->aux = saccpy(&root);
return c;
}
Chan*
sacclone(Chan *c, Chan *nc)
{
nc = devclone(c, nc);
nc->aux = saccpy(c->aux);
return nc;
}
int
devwalk(Chan *c, char *name, Dirtab *tab, int ntab, Devgen *gen)
{
Sac *sac;
isdir(c);
sac = c->aux;
if(strcmp(name, ".") == 0)
return 1;
sac = saclookup(sac, name);
if(sac == nil) {
strncpy(up->error, Enonexist, NAMELEN);
return 0;
}
c->aux = sac;
c->qid = (Qid){getl(sac->qid), 0};
op = c->path;
c->path = ptenter(&syspt, op, name);
decref(op);
return 1;
}
char *
ropen(Fid *f)
{
int mode, trunc;
if(f->open)
return Eisopen;
if(f->busy == 0)
return Enotexist;
mode = rhdr.mode;
if(f->qid.path & CHDIR){
if(mode != OREAD)
return Eperm;
thdr.qid = f->qid;
return 0;
}
if(mode & ORCLOSE)
return Erdonly;
trunc = mode & OTRUNC;
mode &= OPERM;
if(mode==OWRITE || mode==ORDWR || trunc)
return Erdonly;
if(mode==OREAD)
if(!perm(f, f->sac, Pread))
return Eperm;
if(mode==OEXEC)
if(!perm(f, f->sac, Pexec))
return Eperm;
thdr.qid = f->qid;
f->open = 1;
return 0;
}
char *
rcreate(Fid *f)
{
if(f->open)
return Eisopen;
if(f->busy == 0)
return Enotexist;
return Erdonly;
}
char*
rread(Fid *f)
{
Sac *sac;
char *buf, *buf2;
long off;
int n, cnt, i, j;
uchar *blocks;
vlong length;
if(f->busy == 0)
return Enotexist;
sac = f->sac;
thdr.count = 0;
off = rhdr.offset;
buf = thdr.data;
cnt = rhdr.count;
if(f->qid.path & CHDIR){
cnt = (rhdr.count/DIRLEN)*DIRLEN;
if(off%DIRLEN)
return "i/o error";
thdr.count = sacdirread(sac, buf, off, cnt);
return 0;
}
length = getv(sac->length);
if(off >= length) {
rhdr.count = 0;
return 0;
}
if(cnt > length-off)
cnt = length-off;
thdr.count = cnt;
if(cnt == 0)
return 0;
blocks = data + getv(sac->blocks);
buf2 = malloc(blocksize);
while(cnt > 0) {
i = off/blocksize;
loadblock(buf2, blocks+i*8, blocksize);
j = off-i*blocksize;
n = blocksize-j;
if(n > cnt)
n = cnt;
memmove(buf, buf2+j, n);
cnt -= n;
off += n;
}
free(buf2);
return 0;
}
char*
sacwrite(Fid *f)
{
if(f->busy == 0)
return Enotexist;
return Erdonly;
}
char *
rclunk(Fid *f)
{
f->busy = 0;
f->open = 0;
free(f->user);
sacfree(f->sac);
return 0;
}
char *
rremove(Fid *f)
{
f->busy = 0;
f->open = 0;
free(f->user);
sacfree(f->sac);
return Erdonly;
}
char *
rstat(Fid *f)
{
if(f->busy == 0)
return Enotexist;
sacstat(f->sac, thdr.stat);
return 0;
}
char *
rwstat(Fid *f)
{
if(f->busy == 0)
return Enotexist;
return Erdonly;
}
Sac*
saccpy(Sac *s)
{
Sac *ss;
ss = malloc(sizeof(Sac));
*ss = *s;
if(ss->path)
incref(ss->path);
return ss;
}
SacPath *
sacpathalloc(SacPath *p, vlong blocks, int entry)
{
SacPath *pp = malloc(sizeof(SacPath));
pp->ref = 1;
pp->blocks = blocks;
pp->entry = entry;
pp->up = p;
return pp;
}
static void
sacpathfree(SacPath *p)
{
if(p == nil)
return;
if(decref(p) > 0)
return;
sacpathfree(p->up);
free(p);
}
void
sacfree(Sac *s)
{
sacpathfree(s->path);
free(s);
}
void
sacstat(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 = getv(s->length);
if(dir.mode &CHDIR)
dir.length *= DIRLEN;
strcpy(dir.uid, s->uid);
strcpy(dir.gid, s->gid);
dir.atime = getl(s->atime);
dir.mtime = getl(s->mtime);
convD2M(&dir, buf);
}
void
loadblock(void *buf, uchar *offset, int blocksize)
{
vlong block, n;
block = getv(offset);
if(block < 0) {
block = -block;
n = getv(offset+8);
if(n < 0)
n = -n;
n -= block;
//fprint(2, "blocksize = %d, block = %lld n = %lld\n", blocksize, block, n);
if(unsac(buf, data+block, blocksize, n)<0)
panic("unsac failed!");
} else {
memmove(buf, data+block, blocksize);
}
}
Sac*
sacparent(Sac *s)
{
uchar *blocks;
SacDir *buf;
int per, i;
SacPath *p;
p = s->path;
if(p == nil || p->up == nil) {
pathfree(p);
*s = root;
return s;
}
p = p->up;
//fprint(2, "sacparent = %lld %d\n", p->blocks, p->entry);
blocks = data + p->blocks;
per = blocksize/sizeof(SacDir);
i = p->entry/per;
buf = malloc(per*sizeof(SacDir));
loadblock(buf, blocks + i*8, per*sizeof(SacDir));
s->SacDir = buf[p->entry-i*per];
//fprint(2, "sacparent = %s\n", s->name);
free(buf);
incref(p);
pathfree(s->path);
s->path = p;
return s;
}
int
sacdirread(Sac *s, char *p, long off, long cnt)
{
uchar *blocks;
SacDir *buf;
int iblock, per, i, j, ndir;
blocks = data + getv(s->blocks);
per = blocksize/sizeof(SacDir);
ndir = getv(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<off+cnt; i++) {
j = i/per;
if(j != iblock) {
loadblock(buf, blocks + j*8, per*sizeof(SacDir));
iblock = j;
}
j *= per;
sacstat(buf+i-j, p);
p += DIRLEN;
}
free(buf);
return cnt*DIRLEN;
}
Sac*
saclookup(Sac *s, char *name)
{
int ndir;
int top, bot, i, j, k, per;
uchar *blocks;
SacDir *buf;
int iblock;
SacDir *sd;
if(strcmp(name, "..") == 0)
return sacparent(s);
blocks = data + getv(s->blocks);
per = blocksize/sizeof(SacDir);
ndir = getv(s->length);
buf = malloc(per*sizeof(SacDir));
iblock = -1;
if(1) {
// linear search
for(i=0; i<ndir; i++) {
j = i/per;
if(j != iblock) {
loadblock(buf, blocks + j*8, per*sizeof(SacDir));
iblock = j;
}
j *= per;
sd = buf+i-j;
k = strcmp(name, sd->name);
if(k == 0) {
//print("walk %s %lld %d\n", name, getv(s->blocks), i);
s->path = sacpathalloc(s->path, getv(s->blocks), i);
s->SacDir = *sd;
free(buf);
return s;
}
}
free(buf);
return 0;
}
// binary search
top = ndir;
bot = 0;
while(bot != top){
if(bot>top)
sysfatal("binary serach failed: %d %d\n", bot, top);
i = (bot+top)>>1;
j = i/per;
if(j != iblock) {
loadblock(buf, blocks + j*8, per*sizeof(SacDir));
iblock = j;
}
j *= per;
sd = buf+i-j;
k = strcmp(name, sd->name);
if(k == 0) {
s->path = sacpathalloc(s->path, getv(s->blocks), i);
s->SacDir = *sd;
free(buf);
}
if(k < 0) {
top = i;
sd = buf;
if(strcmp(name, sd->name) < 0)
top = j;
} else {
bot = i+1;
if(ndir-j < per)
i = ndir-j;
else
i = per;
sd = buf+i-1;
if(strcmp(name, sd->name) > 0)
bot = j+i;
}
}
return 0;
}
Fid *
newfid(int fid)
{
Fid *f, *ff;
ff = 0;
for(f = fids; f; f = f->next)
if(f->fid == fid)
return f;
else if(!ff && !f->busy)
ff = f;
if(ff){
ff->fid = fid;
return ff;
}
f = malloc(sizeof *f);
//fprint(2, "newfid\n");
memset(f, 0 , sizeof(Fid));
f->fid = fid;
f->next = fids;
fids = f;
return f;
}
void
io(void)
{
char *err;
int n;
for(;;){
/*
* reading from a pipe or a network device
* will give an error after a few eof reads
* however, we cannot tell the difference
* between a zero-length read and an interrupt
* on the processes writing to us,
* so we wait for the error
*/
n = read(mfd[0], mdata, sizeof mdata);
if(n == 0)
continue;
if(n < 0)
error("mount read");
if(convM2S(mdata, &rhdr, n) == 0)
continue;
if(debug)
fprint(2, "sacfs:<-%F\n", &rhdr);
thdr.data = mdata + MAXMSG;
if(!fcalls[rhdr.type])
err = "bad fcall type";
else
err = (*fcalls[rhdr.type])(newfid(rhdr.fid));
if(err){
thdr.type = Rerror;
strncpy(thdr.ename, err, ERRLEN);
}else{
thdr.type = rhdr.type + 1;
thdr.fid = rhdr.fid;
}
thdr.tag = rhdr.tag;
if(debug)
fprint(2, "ramfs:->%F\n", &thdr);/**/
n = convS2M(&thdr, mdata);
if(write(mfd[1], mdata, n) != n)
error("mount write");
}
}
int
perm(Fid *f, Sac *s, int p)
{
ulong perm = getl(s->mode);
if((p*Pother) & perm)
return 1;
if(strcmp(f->user, s->gid)==0 && ((p*Pgroup) & perm))
return 1;
if(strcmp(f->user, s->uid)==0 && ((p*Powner) & perm))
return 1;
return 0;
}
ulong
getl(void *p)
{
uchar *a = p;
return (a[0]<<24) | (a[1]<<16) | (a[2]<<8) | a[3];
}
vlong
getv(void *p)
{
uchar *a = p;
ulong l0, l1;
vlong v;
l0 = (a[0]<<24) | (a[1]<<16) | (a[2]<<8) | a[3];
a += 4;
l1 = (a[0]<<24) | (a[1]<<16) | (a[2]<<8) | a[3];
v = l0;
v <<= 32;
v |= l1;
return v;
}
Dev sacdevtab = {
'C',
"sac",
devreset,
sacinit,
sacattach,
sacclone,
sacwalk,
sacstat,
sacopen,
devcreate,
sacclose,
sacread,
devbread,
sacwrite,
devbwrite,
devremove,
devwstat,
};
.
## diffname mpc/devsac.c 1999/0609
## diff -e /n/emeliedump/1999/0608/sys/src/brazil/mpc/devsac.c /n/emeliedump/1999/0609/sys/src/brazil/mpc/devsac.c
611c
static vlong
.
518,603c
static ulong
.
514a
free(buf);
.
499,513d
497a
return s;
.
495c
print("walk %s %lld %d\n", name, getv(s->blocks), i);
s->path = sacpathalloc(s->path, getv(s->blocks), i);
.
456,485c
// linear search
for(i=0; i<ndir; i++) {
.
442c
int i, j, k, per;
.
438c
static Sac*
.
431c
sacdir(c, buf+i-j, p);
.
412a
print("sacdirread %d %d\n", off, cnt);
s = c->aux;
.
411a
Sac *s;
.
406,407c
static int
sacdirread(Chan *c, char *p, long off, long cnt)
.
401c
sacpathfree(s->path);
.
398c
print("sacparent = %s\n", s->name);
.
391c
print("sacparent = %lld %d\n", p->blocks, p->entry);
.
385c
sacpathfree(p);
.
375c
static Sac*
.
370a
print("memmove: blocksize = %d\n", blocksize);
.
367c
print("blocksize = %d, block = %lld n = %lld\n", blocksize, block, n);
.
355c
static void
.
351a
dir.type = devtab[c->type]->dc;
dir.dev = c->dev;
.
337,338c
static void
sacdir(Chan *c, SacDir *s, char *buf)
.
330c
static void
.
307c
static SacPath *
.
300a
print("saccpy = %ux\n", ss);
.
295c
static Sac*
.
290,292c
sacdir(c, c->aux, db);
.
287,288c
static void
sacstat(Chan *c, char *db)
.
278,285d
271,275c
Sac *sac = c->aux;
print("close %ux\n", sac);
c->aux = nil;
sacfree(sac);
.
268,269c
static void
sacclose(Chan* c)
.
253,264c
error(Eperm);
.
250,251c
static long
sacwrite(Chan *, void *, long, vlong)
.
247c
return n;
.
239,244c
nn = blocksize-j;
if(nn > cnt)
nn = cnt;
memmove(buf, buf2+j, nn);
cnt -= nn;
off += nn;
.
232a
n = cnt;
.
230d
227d
224,225c
if(off >= length)
.
222a
print("data read\n");
sac = c->aux;
.
219,221c
error("i/o error");
return sacdirread(c, buf, off, cnt);
.
209,217c
buf = a;
cnt = n;
if(c->qid.path & CHDIR){
cnt = (cnt/DIRLEN)*DIRLEN;
.
204,205c
int nn, cnt, i, j;
.
199,200c
static long
sacread(Chan *c, void *a, long n, vlong off)
.
189,196c
t = access[omode&3];
if((t & mode) != t)
error(Eperm);
c->offset = 0;
c->mode = openmode(omode);
c->flag |= COPEN;
return c;
.
161,187c
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;
.
159c
ulong t, mode;
Sac *sac;
static int access[] = { 0400, 0200, 0600, 0100 };
.
156,157c
static Chan*
sacopen(Chan *c, int omode)
.
150a
print("op=%ux name = %s\n", op, name);
.
142a
sac = c->aux;
.
140,141c
if(name[0]=='.' && name[1]==0)
.
138a
print("sacwalk\n");
.
137a
Path *op;
.
134,135c
static int
sacwalk(Chan *c, char *name)
.
126c
static Chan*
.
101a
print("blocksize = %d\n", blocksize);
.
98c
print("devsac: bad magic\n");
.
95a
print("sacinit\n");
.
92,93c
static void
sacinit(void)
.
80,90c
static void sacdir(Chan *, SacDir*, char*);
static ulong getl(void *p);
static vlong getv(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*);
.
76,78c
static uchar *data = SACMEM;
static int blocksize;
static Sac root;
.
6a
#include "../port/error.h"
.
## diffname mpc/devsac.c 1999/0610
## diff -e /n/emeliedump/1999/0609/sys/src/brazil/mpc/devsac.c /n/emeliedump/1999/0610/sys/src/brazil/mpc/devsac.c
431d
375d
359d
352d
331d
327d
258d
240d
223a
buf += nn;
.
203a
//print("sacread: %s %llx %d\n", sac->name, off, n);
.
202d
153d
140c
//print("walk %s\n", name);
.
101d
## diffname mpc/devsac.c 1999/0727
## diff -e /n/emeliedump/1999/0610/sys/src/brazil/mpc/devsac.c /n/emeliedump/1999/0727/sys/src/brazil/mpc/devsac.c
152,154d
137d
## diffname mpc/devsac.c 1999/0806
## diff -e /n/emeliedump/1999/0727/sys/src/brazil/mpc/devsac.c /n/emeliedump/1999/0806/sys/src/brazil/mpc/devsac.c
322a
memmove(cache[j].data, buf, blocksize);
cache[j].age = cacheage;
cache[j].block = block;
.
316a
cacheage++;
// age has wraped
if(cacheage == 0) {
for(i=0; i<CacheSize; i++)
cache[i].age = 0;
}
j = 0;
age = cache[0].age;
for(i=0; i<CacheSize; i++) {
if(cache[i].age < age) {
age = cache[i].age;
j = i;
}
if(cache[i].block != block)
continue;
memmove(buf, cache[i].data, blocksize);
cache[i].age = cacheage;
return;
}
.
312a
ulong age;
int i, j;
.
101a
p = malloc(CacheSize*blocksize);
if(p == nil)
error("allocating cache");
for(i=0; i<CacheSize; i++) {
cache[i].data = p;
p += blocksize;
}
.
93a
uchar *p;
int i;
.
79a
static Cache cache[CacheSize];
static ulong cacheage;
.
66a
struct Cache
{
long block;
ulong age;
uchar *data;
};
.
25a
typedef struct Cache Cache;
.
19a
CacheSize = 20,
.
## diffname mpc/devsac.c 1999/0807
## diff -e /n/emeliedump/1999/0806/sys/src/brazil/mpc/devsac.c /n/emeliedump/1999/0807/sys/src/brazil/mpc/devsac.c
482,498d
466c
s->path = sacpathalloc(s->path, getl(s->blocks), i, ndir);
.
459c
n = per;
if(n > ndir-j*per)
n = ndir-j*per;
loadblock(buf, blocks + j*OffsetSize, n*sizeof(SacDir));
.
451c
ndir = getl(s->length);
.
449c
blocks = data + getl(s->blocks);
.
441c
int i, j, k, n, per;
.
426c
n = per;
if(n > ndir-j*per)
n = ndir-j*per;
loadblock(buf, blocks + j*OffsetSize, n*sizeof(SacDir));
.
414c
ndir = getl(s->length);
.
412c
blocks = data + getl(s->blocks);
.
408c
int iblock, per, i, j, n, ndir;
.
394c
loadblock(buf, blocks + i*OffsetSize, n*sizeof(SacDir));
.
392a
n = per;
if(n > p->nentry-i*per)
n = p->nentry-i*per;
.
379c
int per, i, n;
.
360c
n = getl(offset+OffsetSize);
.
337c
block = getl(offset);
.
333c
long block, n;
.
321,322c
memmove(dir.uid, s->uid, NAMELEN);
memmove(dir.gid, s->gid, NAMELEN);
.
318c
dir.length = getl(s->length);
.
286a
pp->nentry = nentry;
.
281c
sacpathalloc(SacPath *p, long blocks, int entry, int nentry)
.
234c
nn -= j;
.
232c
nn = blocksize;
if(nn > length-i*blocksize)
nn = length-i*blocksize;
loadblock(buf2, blocks+i*OffsetSize, nn);
.
228c
blocks = data + getl(sac->blocks);
.
219,220c
length = getl(sac->length);
.
208c
long length;
long off = voff;
.
202c
sacread(Chan *c, void *a, long n, vlong voff)
.
94d
66a
int nentry;
.
65c
long blocks;
.
20a
OffsetSize = 4, /* size in bytes of an offset */
.
## diffname mpc/devsac.c 1999/1231
## diff -e /n/emeliedump/1999/0807/sys/src/brazil/mpc/devsac.c /n/emeliedump/1999/1231/sys/src/9/mpc/devsac.c
164a
if(name[0]=='.' && name[1]=='.' && name[2]==0)
return 1;
.
## diffname mpc/devsac.c 2000/0516
## diff -e /n/emeliedump/1999/1231/sys/src/9/mpc/devsac.c /n/emeliedump/2000/0516/sys/src/9/mpc/devsac.c
109a
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;
}
.
106a
char *s;
.
88c
static char *sacfs = "fs.sac";
static uchar *data;
.
9,15d
## diffname mpc/devsac.c 2000/1208
## diff -e /n/emeliedump/2000/0516/sys/src/9/mpc/devsac.c /n/emeliedump/2000/1208/sys/src/9/mpc/devsac.c
176,177d
## diffname mpc/devsac.c 2001/0527 # deleted
## diff -e /n/emeliedump/2000/1208/sys/src/9/mpc/devsac.c /n/emeliedump/2001/0527/sys/src/9/mpc/devsac.c
1,528d
|