@@ 150,7 150,7 @@ validdir(Tfs *fs, uchar *p)
if(checksum(p) != 0)
return 0;
- if(buf[0] != Tagdir)
+ if(p[0] != Tagdir)
return 0;
md = (Mdir*)p;
x = GETS(md->bno);
@@ 167,8 167,8 @@ validdata(Tfs *fs, uchar *p, int *lenp)
if(checksum(p) != 0)
return 0;
- md = (Mdir*)p;
- switch(buf[0]){
+ md = (Mdata*)p;
+ switch(md->type){
case Tagdata:
x = GETS(md->bno);
if(x >= fs->nblocks)
@@ 190,25 190,47 @@ validdata(Tfs *fs, uchar *p, int *lenp)
static Mdata*
readdata(Tfs *fs, ulong bno, uchar *buf, int *lenp)
{
- Mdata *md;
-
if(bno >= fs->nblocks)
return 0;
- n = devtab[fs->c->type].read(fs->c, buf, Blen, Blen*bno);
- if(n != Blen)
- return 0;
+ if(devtab[fs->c->type].read(fs->c, buf, Blen, Blen*bno) != Blen)
+ error(Eio);
return validdata(fs, buf, lenp);
}
-static int
+static void
+writedata(Tfs *fs, ulong bno, ulong next, uchar *buf, int len, int last)
+{
+ Mdata md;
+
+ if(bno >= fs->nblocks)
+ error(Eio);
+ if(len > Dlen)
+ len = Dlen;
+ if(len < 0)
+ error(Eio);
+ memset(&md, 0, sizeof(md));
+ if(last){
+ md.type = Tagend;
+ PUTS(md.bno, len);
+ } else {
+ md.type = Tagdata;
+ PUTS(md.bno, next);
+ }
+ memmove(md.data, buf, len);
+ md.sum = 0 - checksum((uchar*)&md);
+
+ if(devtab[fs->c->type].write(fs->c, &md, Blen, Blen*bno) != Blen)
+ error(Eio);
+}
+
+static void
writedir(Tfs *fs, Tfile *f)
{
Mdir *md;
- int n;
uchar buf[Blen];
if(f->bno == Notabno)
- return Blen;
+ return;
md = (Mdir*)buf;
memset(buf, 0, Blen);
@@ 216,9 238,10 @@ writedir(Tfs *fs, Tfile *f)
strncpy(md->name, f->name, sizeof(md->name)-1);
PUTS(md->bno, f->dbno);
PUTS(md->pin, f->pin);
- f->sum = 0 - checksum(buf);
+ md->sum = 0 - checksum(buf);
- return devtab[fs->c->type].write(fs->c, buf, Blen, Blen*f->bno);
+ if(devtab[fs->c->type].write(fs->c, buf, Blen, Blen*f->bno) != Blen)
+ error(Eio);
}
static void
@@ 277,6 300,7 @@ newfile(Tfs *fs, char *name)
Tfile *f;
/* find free entry in file table */
+ f = 0;
for(;;) {
for(i = 0; i < fs->fsize; i++){
f = &fs->f[i];
@@ 298,10 322,10 @@ newfile(Tfs *fs, char *name)
/* write directory block */
if(waserror()){
- filefree(fs, f, Notabno);
+ freefile(fs, f, Notabno);
nexterror();
}
- if(b->bno == Notabno)
+ if(f->bno == Notabno)
error("out of space");
writedir(fs, f);
poperror();
@@ 317,16 341,17 @@ newfile(Tfs *fs, char *name)
static void
fsinit(Tfs *fs)
{
- uchar buf[Blen+DIRLEN];
+ char dbuf[DIRLEN];
Dir d;
+ uchar buf[Blen];
ulong x, bno;
int n, done;
Tfile *f;
Mdir *mdir;
- Mdata *mdat;
+ Mdata *mdata;
- devtab[fs->c->type].stat(fs->c, buf);
- convM2D(buf, &d);
+ devtab[fs->c->type].stat(fs->c, dbuf);
+ convM2D(dbuf, &d);
fs->nblocks = d.length/Blen;
if(fs->nblocks < 3)
error("tinyfs medium too small");
@@ 344,11 369,11 @@ fsinit(Tfs *fs)
if(n != Blen)
break;
- mdir = validdir(buf);
+ mdir = validdir(fs, buf);
if(mdir == 0)
continue;
- if(fs->nfs >= fs->fsize)
+ if(fs->nf >= fs->fsize)
expand(fs);
f = &fs->f[fs->nf++];
@@ 363,10 388,10 @@ fsinit(Tfs *fs)
/* follow files */
for(f = fs->f; f < &(fs->f[fs->nf]); f++){
- bno = fs->dbno;
+ bno = f->dbno;
for(done = 0; !done;) {
if(isalloced(fs, bno)){
- freefile(f, bno);
+ freefile(fs, f, bno);
break;
}
n = devtab[fs->c->type].read(fs->c, buf, Blen, Blen*bno);
@@ 383,10 408,10 @@ fsinit(Tfs *fs)
switch(mdata->type){
case Tagdata:
bno = GETS(mdata->bno);
- f->len += Dlen;
+ f->length += Dlen;
break;
case Tagend:
- f->len += GETS(mdata->bno);
+ f->length += GETS(mdata->bno);
done = 1;
break;
}
@@ 406,6 431,8 @@ tinyfsgen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp)
Tfile *f;
Qid qid;
+ USED(ntab, tab);
+
fs = &tinyfs.fs[c->dev];
if(i >= fs->nf)
return -1;
@@ 435,7 462,7 @@ tinyfsattach(char *spec)
Chan *c, *cc;
int i;
- cc = namec((char*)arg[0], Aopen, arg[1], 0);
+ cc = namec(spec, Aopen, ORDWR, 0);
if(waserror()){
close(cc);
qunlock(&tinyfs);
@@ 443,9 470,10 @@ tinyfsattach(char *spec)
}
qlock(&tinyfs);
+ fs = 0;
for(i = 0; i < tinyfs.nfs; i++){
fs = &tinyfs.fs[i];
- if(fs && eqchan(c, fs->c))
+ if(fs && eqchan(cc, fs->c, 0))
break;
}
if(i < tinyfs.nfs){
@@ 477,6 505,10 @@ tinyfsattach(char *spec)
Chan *
tinyfsclone(Chan *c, Chan *nc)
{
+ Tfs *fs;
+
+ fs = &tinyfs.fs[c->dev];
+
qlock(fs);
fs->r++;
qunlock(fs);
@@ 488,6 520,9 @@ int
tinyfswalk(Chan *c, char *name)
{
int n;
+ Tfs *fs;
+
+ fs = &tinyfs.fs[c->dev];
qlock(fs);
n = devwalk(c, name, 0, 0, tinyfsgen);
@@ 513,13 548,13 @@ tinyfsopen(Chan *c, int omode)
fs = &tinyfs.fs[c->dev];
- if(c->path & CHDIR){
+ if(c->qid.path & CHDIR){
if(omode != OREAD)
error(Eperm);
} else {
qlock(fs);
if(omode == (OTRUNC|ORDWR)){
- f = newfile(fs, fs->f[c->qid.path]);
+ f = newfile(fs, fs->f[c->qid.path].name);
c->qid.path = f - fs->f;
} else if(omode != OREAD){
qunlock(fs);
@@ 540,6 575,8 @@ tinyfscreate(Chan *c, char *name, int omode, ulong perm)
if(perm & CHDIR)
error("directory creation illegal");
+ fs = &tinyfs.fs[c->dev];
+
qlock(fs);
f = newfile(fs, name);
qunlock(fs);
@@ 570,7 607,7 @@ tinyfsclose(Chan *c)
Tfile *f, *nf;
int i;
- fs = c->aux;
+ fs = &tinyfs.fs[c->dev];
qlock(fs);
@@ 594,16 631,16 @@ tinyfsclose(Chan *c)
}
f->flag &= ~(Frmonclose|Fcreating);
}
- if(f->flag & Frmonclose){
+ if(f->flag & Frmonclose)
freefile(fs, f, Notabno);
}
}
/* dereference fs and remove on zero refs */
fs->r--;
- unlock(fs);
+ qunlock(fs);
qlock(&tinyfs);
- if(fs->ref == 0){
+ if(fs->r == 0){
for(l = &fs->l; *l;){
if(*l == fs){
*l = fs->next;
@@ 625,7 662,7 @@ tinyfsread(Chan *c, void *a, long n, ulong offset)
Tfs *fs;
Tfile *f;
int sofar, i;
- ulong bno, tbno;
+ ulong bno;
Mdata *md;
uchar buf[Blen];
uchar *p = a;
@@ 644,8 681,6 @@ tinyfsread(Chan *c, void *a, long n, ulong offset)
bno = f->dbno;
for(sofar = 0; sofar + Blen < offset; sofar += Blen){
md = readdata(fs, bno, buf, 0);
- if(md == 0)
- error(Eio);
bno = GETS(md->bno);
}
@@ 653,8 688,6 @@ tinyfsread(Chan *c, void *a, long n, ulong offset)
offset = offset%Blen;
for(sofar = 0; sofar < n; sofar += i){
md = readdata(fs, bno, buf, &i);
- if(md == 0)
- error(Eio);
i -= offset;
if(i > n)
i = n;
@@ 680,7 713,7 @@ tinyfswrite(Chan *c, char *a, long n, ulong offset)
{
Tfs *fs;
Tfile *f;
- int sofar, i;
+ int sofar, i, x;
ulong bno, tbno;
Mdata *md;
uchar buf[Blen];
@@ 689,32 722,67 @@ tinyfswrite(Chan *c, char *a, long n, ulong offset)
if(c->qid.path & CHDIR)
error(Eperm);
+ if(n == 0)
+ return 0;
+
fs = tinyfs.fs[c->dev];
f = &fs->f[c->qid.path];
- /* walk to first data block */
+ /* files are append only, anything else is illegal */
+ if(offset != f->length)
+ error("append only");
+
+ qlock(fs);
+ if(waserror()){
+ f->flag |= Frmonclose;
+ qunlock(fs);
+ nexterror();
+ }
+
+ /* walk to last data block */
bno = f->dbno;
for(sofar = 0; sofar + Blen < offset; sofar += Blen){
md = readdata(fs, bno, buf, 0);
- if(md == 0)
- error(Eio);
+ if(md->type == Tagend)
+ break;
bno = GETS(md->bno);
}
- /* write data */
- offset = offset%Blen;
- for(sofar = 0; sofar < n; sofar += i){
- md = readdata(fs, bno, buf, 0);
- if(md == 0)
- error(Eio);
- i = Blen - offset;
- if(i > n)
- i = n;
- memmove(p, a, i);
- bno = GETS(md->bno);
- offset = 0;
+ sofar = 0;
+ i = offset%Dlen;
+ if(i){
+ x = n;
+ if(i + x > Dlen)
+ x = Dlen - i;
+ memmove(md->data + i, p, sofar);
+ f->length += x;
+ sofar += x;
}
+ while(x = n - sofar) {
+ tbno = mapalloc(fs);
+ if(f->length == 0){
+ f->dbno = tbno;
+ writedir(fs, f);
+ } else {
+ writedata(fs, bno, tbno, md->data, Dlen, 0);
+ }
+ if(x > Dlen)
+ x = Dlen;
+ memmove(md->data, p + sofar, x);
+ sofar += x;
+ f->length += x;
+ bno = tbno;
+ }
+
+ i = f->length%Dlen;
+ if(i == 0)
+ i = Dlen;
+ writedata(fs, bno, tbno, md->data, i, 1);
+
+ poperror();
+ qunlock(fs);
+
return sofar;
}