## diffname port/devtinyfs.c 1996/0116
## diff -e /dev/null /n/fornaxdump/1996/0116/sys/src/brazil/port/devtinyfs.c
0a
/*
* template for making a new device
*/
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
#include "devtab.h"
enum{
Qdir,
Qmedium,
Nfile= 32,
};
struct {
QLock;
Chan *c;
Dirtab file[Nfile];
int nfile;
} tinyfs;
void
tinyfsreset(void)
{
Dirtab *d;
d = tinyfs.file;
memmove(d->name, "medium");
d->qid.vers = 0;
d->qid.path = Qdata;
d->perm = 0666;
}
void
tinyfsinit(void)
{
}
Chan *
tinyfsattach(char *spec)
{
return devattach('E', spec);
}
Chan *
tinyfsclone(Chan *c, Chan *nc)
{
return devclone(c, nc);
}
int
tinyfswalk(Chan *c, char *name)
{
return devwalk(c, name, tinyfs.file, tinyfs.nfile, devgen);
}
void
tinyfsstat(Chan *c, char *db)
{
devstat(c, db, tinyfs.file, tinyfs.nfile, devgen);
}
Chan *
tinyfsopen(Chan *c, int omode)
{
return devopen(c, omode, tinyfs.file, tinyfs.nfile, devgen);
}
void
tinyfscreate(Chan *c, char *name, int omode, ulong perm)
{
Dirtab *d;
if(perm & CHDIR)
error("directory creation illegal");
if(waserror()){
qunlock(&tinyfs);
nexterror();
}
qlock(&tinyfs);
if(tinyfs.nfile == Nfile)
error("out of space");
for(d = tinyfs.file; d < tinyfs.file[tinyfs.nfile]; d++)
if(strcmp(name, d->name) == 0)
error("create race");
strncpy(d->name, name, sizeof(d->name)-1);
d->perm = perm;
d->qid.vers = 0;
d->qid.path = tinyfs.high++;
tinyfs.nfile++;
qunlock(&tinyfs);
c->mode = openmode(omode);
c->flag |= COPEN;
c->qid = d->qid;
}
void
tinyfsremove(Chan *c)
{
USED(c);
error(Eperm);
}
void
tinyfswstat(Chan *c, char *dp)
{
USED(c, dp);
error(Eperm);
}
void
tinyfsclose(Chan *c)
{
}
long
tinyfsread(Chan *c, void *a, long n, ulong offset)
{
switch(c->qid.path & ~CHDIR){
case Qdir:
return devdirread(c, a, n, tinyfstab, Ntinyfstab, devgen);
case Qdata:
break;
default:
n=0;
break;
}
return n;
}
Block*
tinyfsbread(Chan *c, long n, ulong offset)
{
return devbread(c, n, offset);
}
long
tinyfswrite(Chan *c, char *a, long n, ulong offset)
{
if(waserror()){
qunlock(&tinyfs);
nexterror();
}
qlock(&tinyfs);
qunlock(&tinyfs);
switch(c->qid.path & ~CHDIR){
case Qdata:
break;
default:
error(Ebadusefd);
}
return n;
}
long
tinyfsbwrite(Chan *c, Block *bp, ulong offset)
{
return devbwrite(c, bp, offset);
}
.
## diffname port/devtinyfs.c 1996/0120
## diff -e /n/fornaxdump/1996/0116/sys/src/brazil/port/devtinyfs.c /n/fornaxdump/1996/0120/sys/src/brazil/port/devtinyfs.c
100c
.
48a
c = namec((char*)arg[0], Aopen, arg[1], 0);
.
38a
tinyfs.nfile = 1;
.
37c
d->qid.path = Qmedium;
.
25c
Dirtab file[Nfile+1];
.
18a
Qmedium,
.
16,17d
## diffname port/devtinyfs.c 1996/0122
## diff -e /n/fornaxdump/1996/0120/sys/src/brazil/port/devtinyfs.c /n/fornaxdump/1996/0122/sys/src/brazil/port/devtinyfs.c
51c
cc = namec((char*)arg[0], Aopen, arg[1], 0);
qlock(&tinyfs);
l = &tinyfs.l;
for(fs = tinyfs.l; fs != 0; fs = fs->next){
if(eqchan(c, fs->c))
break;
l = &(fs->next);
}
if(fs){
incref(&fs->r);
qunlock(&tinyfs);
close(cc);
} else {
fs = smalloc(sizeof(*fs));
*l = fs;
fs->c = cc;
incref(&fs->r);
qunlock(&tinyfs);
}
c = devattach('E', spec);
c->aux = fs;
c->dev = fs->dev;
return c;
.
49c
FS *fs, **l;
Chan *c, *cc;
.
25a
int maxfile;
};
struct {
QLock;
FS *l;
int hidev;
.
24c
Dirtab *file;
.
22a
Ref r;
int dev;
FS *next;
.
21c
struct FS {
.
19a
typedef struct FS FS;
.
## diffname port/devtinyfs.c 1996/0123
## diff -e /n/fornaxdump/1996/0122/sys/src/brazil/port/devtinyfs.c /n/fornaxdump/1996/0123/sys/src/brazil/port/devtinyfs.c
126,140d
81a
poperror();
.
79a
if(waserror()){
free(fs);
nexterror();
}
if(fsinit(fs) < 0)
fssetup(fs);
poperror();
*l = fs;
.
77d
63a
if(waserror()){
close(cc);
unlock(&fs);
nexterror();
}
.
56a
#define GETS(x) ((x)[0]|((x)[1]<<8))
#define PUTS(x, v) {(x)[0] = (v);(x)[1] = ((v)>>8);}
#define GETL(x) (GETS(x)|(GETS(x+2)<<16))
#define PUTL(x, v) {PUTS(x, v);PUTS(x+2, (v)>>16)};
/*
* see if we have a reasonable fat/root directory
*/
static int
fsinit(FS *fs)
{
uchar buf[DIRLEN];
Dir d;
ulong x;
n = devtab[fs->c->type].read(fs->c, buf, Superlen, 0);
if(n != Superlen)
error(Eio);
x = GETL(buf);
if(x != Magic)
return -1;
fs->clustsize = GETL(buf+4);
fs->nclust = GETL(buf+8);
x = fs->clustsize*fs->nclust;
devtab[fs->c->type].stat(fs->c, buf);
convM2D(buf, &d);
if(d.length < 128)
error("tinyfs medium too small");
if(d.length < x)
return -1;
fs->fat = smalloc(2*fs->nclust);
n = devtab[fs->c->type].read(fs->c, buf, 2*fs->nclust, Superlen);
fd(n != 2*fs->nclust)
error(Eio);
x = GETS(fs->fat);
if(x == 0)
return -1;
return 0;
}
/*
* set up the fat and then a root directory (starting at first cluster (1))
*/
static void
fssetup(FS *fs)
{
uchar buf[DIRLEN];
Dir d;
devtab[fs->c->type].stat(fs->c, buf);
convM2D(buf, &d);
fs->clustsize = d.length>>16;
if(fs->clustsize < 64)
fs->clustsize = 64;
fs->nclust = (d.length - 12)/fs->clustsize;
fs->fat = smalloc(2*fs->nclust);
n = devtab[fs->c->type].write(fs->c, buf, 2*fs->nclust, Superlen);
if(n < 2*fs->nclust)
error(Eio);
n = devtab[fs->c->type].write(fs->c, buf, Superlen, 0);
if(n < Superlen)
error(Eio);
}
.
42,49d
28,30c
uchar *fat;
ulong nclust;
ulong clustsize;
.
17a
Magic= 0xfeedbeef,
Superlen= 64,
.
16c
Nfile= 32,
.
## diffname port/devtinyfs.c 1996/0131
## diff -e /n/fornaxdump/1996/0123/sys/src/brazil/port/devtinyfs.c /n/fornaxdump/1996/0131/sys/src/brazil/port/devtinyfs.c
90,94c
for(bno = 0; bno < fs->nblocks; bno++){
n = devtab[fs->c->type].read(fs->c, buf, Blen, Blen*bno);
if(n != Blen)
break;
if(checksum(buf) != 0)
continue;
switch(buf[0]){
case Tdir:
mapset(fs, bno);
break;
}
}
.
85,88c
/* bitmap for block usage */
x = (fs->nblocks + 8 - 1)/8;
fs->map = malloc(x);
memset(fs->map, 0x0, x);
for(bno = fs->nblocks; bno < x*8; bno++)
mapset(fs, bno);
.
82,83d
80c
fs->nblocks = d.length/Blen;
if(fs->nblocks < 3)
.
68,77d
66c
ulong x, bno;
.
64c
uchar buf[Blen+DIRLEN];
.
57a
static void
mapclr(FS *fs, int bno)
{
fs->map[bno>>3] &= ~(1<<(bno&7));
}
static void
mapset(FS *fs, int bno)
{
fs->map[bno>>3] |= 1<<(bno&7);
}
static int
mapalloc(FS *fs)
{
int i, j, lim;
uchar x;
qlock(fs);
lim = (fs->nblocks + 8 - 1)/8;
for(i = 0; i < lim; i++){
x = fs->map[i];
if(x == 0xff)
continue;
for(j = 0; j < 8; j++)
if((x & (1<<j)) == 0){
fs->map[i] = x|(1<<j);
qunlock(fs);
return i*8 + j;
}
}
qunlock(fs);
return -1;
}
.
55,56c
s = 0;
for(e = p + Blen; p < e; p++)
s += *p;
}
.
52,53c
static uchar
checksum(uchar *p)
{
uchar *e;
uchar s;
.
41a
#define GETS(x) ((x)[0]|((x)[1]<<8))
#define PUTS(x, v) {(x)[0] = (v);(x)[1] = ((v)>>8);}
#define GETL(x) (GETS(x)|(GETS(x+2)<<16))
#define PUTL(x, v) {PUTS(x, v);PUTS(x+2, (v)>>16)};
.
31,33c
uchar *map;
int nblocks;
.
24d
19,20c
Blen= 48,
Tdir= 0,
Tdata,
Tend,
.
16d
## diffname port/devtinyfs.c 1996/0201
## diff -e /n/fornaxdump/1996/0131/sys/src/brazil/port/devtinyfs.c /n/fornaxdump/1996/0201/sys/src/brazil/port/devtinyfs.c
276c
return devdirread(c, a, n, tinyfstab, Ntinyfstab, tinyfsgen);
.
268a
Tfs *fs, **l;
Tfile *f, *nf;
fs = c->aux;
lock(fs);
fs->ref--;
unlock(fs);
if(fs->ref)
return;
qlock(&tinyfs);
lock(fs);
if(fs->ref == 0){
for(l = &fs->l; *l;){
if(*l == fs){
*l = fs->next;
break;
}
l = &(*l)->next;
}
for(f = fs->f; f; f = nf){
nf = f->next;
free(f);
}
free(fs->map);
close(fs->c);
free(fs);
}
unlock(fs);
qunlock(&tinyfs);
.
249d
246a
unlock(fs);
c->qid.path = f - fs->f;
c->qid.vers = 1; /* creating */
.
243,245c
fs = &tinyfs.fs[c->dev];
for(;;) {
lock(fs);
for(i = 0; i < fs->fsize; i++){
f = &fs->f[i];
if(f->name[0] == 0){
strncpy(f->name, name, sizeof(f->name)-1);
break;
}
}
if(i < fs->fsize)
break;
unlock(fs);
expand(fs);
.
238c
Tfs *fs;
Tfile *f;
.
232c
Tfs *fs;
Tfile *f;
fs = &tinyfs.fs[c->dev];
if(c->path & CHDIR){
if(omode != OREAD)
error(Eperm);
} else {
lock(fs);
f = fs->f[c->path];
unlock(fs);
if(f->pin == Nopin){
if(omode != OREAD)
error(Eperm);
} else {
if(omode != ORDWR)
error(Eperm);
}
}
return devopen(c, omode, 0, 0, tinyfsgen);
.
226c
devstat(c, db, 0, 0, tinyfsgen);
.
220c
return devwalk(c, name, 0, 0, tinyfsgen);
.
204,206c
c = devattach('U', spec);
c->dev = fs - tinyfs.fs;
c->qid.path = CHDIR;
c->qid.vers = 0;
.
201a
qunlock(&tinyfs);
.
191,200c
fs->r = 1;
fsinit(fs);
tinyfs.nfs++;
.
189c
if(tinyfs.nfs >= Maxfs)
error("too many tinyfs's");
fs = &tinyfs.fs[tinyfs.nfs];
memset(fs, 0, sizeof(*fs));
.
184,186c
if(i < tinyfs.nfs){
lock(fs);
fs->r++;
unlock(fs);
.
182d
178,180c
for(i = 0; i < tinyfs.nfs; i++){
fs = &tinyfs.fs[i];
if(fs && eqchan(c, fs->c))
.
176a
.
174c
qunlock(&tinyfs);
.
169a
int i;
.
168c
Tfs *fs;
.
164a
void
tinyfsreset(void)
{
if(Nlen > NAMELEN)
panic("tinyfsreset");
}
void
tinyfsinit(void)
{
}
.
150,162c
fs = &tinyfs.fs[c->dev];
if(i >= fs->nf)
return -1;
f = &fs->f[i];
qid.path = i;
qid.vers = 0;
devdir(c, qid, f->name, f->length, eve, f->pin==Nopin?0444:0666, dp);
return 1;
.
147,148c
Tfs *fs;
Tfile *f;
Qid qid;
.
141,145c
static int
tinyfsgen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp)
.
136c
switch(mdata->type){
case Tagdata:
bno = GETS(mdata->bno);
f->len += Dlen;
break;
case Tagend:
f->len += GETS(mdata->bno);
break;
}
.
133,134c
if(fs->nfs <= fs->fsize)
expand(fs);
f = &fs->f[fs->nf++];
x = GETS(mdir->bno);
mapset(fs, bno);
strncpy(f->name, mdir->name, sizeof(f->name));
f->pin = GETS(mdir->pin);
f->bno = bno;
f->dbno = x;
}
/* follow files */
for(f = fs->f; f; f = f->next){
bno = fs->dbno;
for(;;) {
if(isalloced(fs, bno)){
freefile(f, bno);
break;
}
n = devtab[fs->c->type].read(fs->c, buf, Blen, Blen*bno);
if(n != Blen){
freefile(fs, f, bno);
break;
}
mdata = validdata(fs, buf);
if(mdata == 0){
freefile(fs, f, bno);
break;
}
.
131c
mdir = validdir(buf);
if(mdir == 0)
.
126a
/* find files */
.
122c
fs->map = smalloc(x);
.
112a
int n;
Tfile *f;
Mdir *mdir;
Mdata *mdat;
.
107,108c
static void
fsinit(Tfs *fs)
.
103a
static Mdir*
validdir(Tfs *fs, uchar *p)
{
Mdir *md;
ulong x;
if(checksum(p) != 0)
return 0;
if(buf[0] != Tagdir)
return 0;
md = (Mdir*)p;
x = GETS(md->bno);
if(x >= fs->nblocks)
return 0;
return md;
}
static Mdata*
validdata(Tfs *fs, uchar *p)
{
Mdata *md;
ulong x;
if(checksum(p) != 0)
return 0;
md = (Mdir*)p;
switch(buf[0]){
case Tagdata:
x = GETS(md->bno);
if(x >= fs->nblocks)
return 0;
break;
case Tagend:
x = GETS(md->bno);
if(x > Blen - 4)
return 0;
break;
}
return md;
}
static void
freefile(Tfs *fs, Tfile *f, ulong bend)
{
uchar buf[Blen];
ulong bno;
int n;
Mdata *md;
/* remove blocks from map */
bno = f->dbno;
while(bend != bno){
mapclr(fs, bno);
n = devtab[fs->c->type].read(fs->c, buf, Blen, Blen*bno);
if(n != Blen)
break;
md = validdata(buf);
if(md == 0)
break;
if(md->type == Tagend)
break;
bno = GETS(md->bno);
}
/* change file type to free on medium */
n = devtab[fs->c->type].read(fs->c, buf, Blen, Blen*f->bno);
if(n != Blen)
return;
buf[0] = Tagfree;
devtab[fs->c->type].write(fs->c, buf, Blen, Blen*f->bno);
/* forget we ever knew about it */
memset(f, 0, sizeof(*f));
}
static void
expand(Tfs *fs)
{
Tfile *f;
fs->fsize += 8;
f = smalloc(fs->fsize*sizeof(*f));
lock(fs);
memmove(f, fs->f, fs->nf*sizoef(f));
free(fs->f);
fs->f = f;
unlock(fs);
}
.
83a
return fs->map[bno>>3] & (1<<(bno&7));
}
static int
mapalloc(Tfs *fs)
{
.
82c
isalloced(Tfs *fs, ulong bno)
.
76c
mapset(Tfs *fs, ulong bno)
.
70c
mapclr(Tfs *fs, ulong bno)
.
48,57d
38,39c
Tfs fs[Maxfs];
short nfs;
.
33a
Tfile *f;
int nf;
int fsize;
.
25,30c
/* medium representation of a Tdir */
typedef struct Mdir Mdir;
struct Mdir {
uchar type;
uchar bno[2];
uchar pin[2];
char name[Nlen];
char pad[Blen - Nlen - 6];
uchar sum;
};
/* medium representation of a Tdata/Tend */
typedef struct Mdata Mdata;
struct Mdata {
uchar type;
uchar bno[2];
char data[Dlen];
uchar sum;
};
typedef struct Tfile Tfile;
struct Tfile {
char name[NAMELEN];
ushort bno;
ushort dbno;
ushort pin;
ulong length;
};
typedef struct Tfs Tfs;
struct Tfs {
Lock;
int r;
.
20,22c
Blen= 48, /* block length */
Nlen= 28, /* name length */
Dlen= Blen - 4,
Tagdir= 'd',
Tagdata= 'D',
Tagend= 'e',
Tagfree= 'f',
Nopin= 0xffff;
.
18c
Maxfs= 10, /* max file systems */
.
## diffname port/devtinyfs.c 1996/0202
## diff -e /n/fornaxdump/1996/0201/sys/src/brazil/port/devtinyfs.c /n/fornaxdump/1996/0202/sys/src/brazil/port/devtinyfs.c
490,491c
/* dereference file and remove old versions */
if(c->qid.path != CHDIR){
f = &fs->f[c->qid.path];
f->r--;
if(f->r == 0 && f->creating){
/* remove all other files with this name */
for(i = 0; i < fs->fsize; i++){
nf = &fs->f[i];
if(f == nf)
continue;
if(strcmp(nf->name, f->name) == 0)
freefile(fs, nf, Notabno);
}
}
}
/* dereference fs and remove on zero refs */
fs->r--;
.
487,488c
qlock(fs);
.
483,485d
480a
int i;
.
459d
457c
c->qid.vers = 0;
.
451,455d
438,449c
qlock(fs);
f = newfile(fs, name);
qunlock(fs);
.
423a
qunlock(fs);
.
413,422c
qlock(fs);
if(omode == (OTRUNC|ORDWR)){
f = newfile(fs, fs->f[c->qid.path]);
c->qid.path = f - fs->f;
} else if(omode != OREAD){
qunlock(fs);
error(Eperm);
.
392c
int n;
qlock(fs);
n = devwalk(c, name, 0, 0, tinyfsgen);
if(n != 0 && c->qid.path != CHDIR){
fs = &tinyfs.fs[c->dev];
fs->f[c->qid.path].r++;
}
qunlock(fs);
return n;
.
385a
qlock(fs);
fs->r++;
qunlock(fs);
.
360c
qunlock(fs);
.
358c
qlock(fs);
.
321c
devdir(c, qid, f->name, f->length, eve, 0664, dp);
.
307a
/*
* single directory
*/
.
265a
.
228c
* Read the whole medium and build a file table and used
* block bitmap. Inconsistent files are purged.
.
226a
static Tfile*
newfile(Tfs *fs, char *name)
{
int i;
Tfile *f;
/* find free entry in file table */
for(;;) {
for(i = 0; i < fs->fsize; i++){
f = &fs->f[i];
if(f->name[0] == 0){
strncpy(f->name, name, sizeof(f->name)-1);
break;
}
}
if(i < fs->fsize)
break;
expand(fs);
}
f->creating = 1;
f->dbno = Notabno;
f->bno = mapalloc(fs);
/* write directory block */
if(waserror()){
filefree(fs, f, Notabno);
nexterror();
}
if(b->bno == Notabno)
error("out of space");
writedir(fs, f);
poperror();
return f;
}
.
224d
220d
202,206c
if(f->bno != Notabno){
n = devtab[fs->c->type].read(fs->c, buf, Blen, Blen*f->bno);
if(n != Blen)
return;
buf[0] = Tagfree;
devtab[fs->c->type].write(fs->c, buf, Blen, Blen*f->bno);
}
.
188c
while(bno != bend && bno != Notabno){
.
177a
static int
writedir(Tfs *fs, Tfile *f)
{
Mdir *md;
int n;
uchar buf[Blen];
if(f->bno == Notabno)
return Blen;
md = (Mdir*)buf;
memset(buf, 0, Blen);
md->type = Tagdir;
strncpy(md->name, f->name, sizeof(md->name)-1);
PUTS(md->bno, f->dbno);
PUTS(md->pin, f->pin);
f->sum = 0 - checksum(buf);
return devtab[fs->c->type].write(fs->c, buf, Blen, Blen*f->bno);
}
.
93a
return s;
.
63c
QLock;
.
57a
char creating;
.
53a
int r;
.
43c
/* representation of a Tdata/Tend on medium */
.
32c
/* representation of a Tdir on medium */
.
29c
Notapin= 0xffff,
Notabno= 0xffff,
.
2c
* a pity the code isn't also tiny...
.
## diffname port/devtinyfs.c 1996/0203
## diff -e /n/fornaxdump/1996/0202/sys/src/brazil/port/devtinyfs.c /n/fornaxdump/1996/0203/sys/src/brazil/port/devtinyfs.c
596,601c
fs = tinyfs.fs[c->dev];
f = &fs->f[c->qid.path];
if(offset >= f->length)
return 0;
if(n + offset >= f->length)
n = f->length - offset;
.
593,594c
Tfs *fs;
Tfile *f;
int sofar, i;
if(c->qid.path & CHDIR)
.
586d
584c
memset(fs, 0, sizeof(*fs));
.
578,581c
free(fs-f);
.
569a
unlock(fs);
qlock(&tinyfs);
.
564a
if(f->flag & Frmonclose){
freefile(fs, f, Notabno);
.
556,563c
if(f->r == 0){
if(f->creating){
/* remove all other files with this name */
for(i = 0; i < fs->fsize; i++){
nf = &fs->f[i];
if(f == nf)
continue;
if(strcmp(nf->name, f->name) == 0){
if(nf->r)
nf->flag |= Frmonclose;
else
freefile(fs, nf, Notabno);
}
}
f->flag &= ~(Frmonclose|Fcreating);
.
274c
f->flag = Fcreating;
.
60c
uchar flag;
.
30a
Fcreating= 1,
Frmonclose= 2,
.
## diffname port/devtinyfs.c 1996/0206
## diff -e /n/fornaxdump/1996/0203/sys/src/brazil/port/devtinyfs.c /n/fornaxdump/1996/0206/sys/src/brazil/port/devtinyfs.c
615a
/* walk to first data block */
bno = f->dbno;
for(sofar = 0; sofar < offset; sofar += Blen){
md = readdata(fs, bno, buf);
if(md == 0)
error(Eio);
bno = GETS(md->bno);
}
/* read first block */
i = offset%Blen;
/* read data */
for(sofar = 0; sofar+Blen < offset; sofar += Blen){
.
605a
ulong bno, tbno;
Mdata *md;
uchar buf[Blen];
.
184a
static Mdata*
readdata(Tfs *fs, ulong bno, uchar *buf)
{
if(bno >= fs->nblocks)
return 0;
n = devtab[fs->c->type].read(fs->c, buf, Blen, Blen*bno);
if(n != Blen)
return 0;
return validdata(fs, buf);
}
.
57a
Lock;
.
## diffname port/devtinyfs.c 1996/0217
## diff -e /n/fornaxdump/1996/0206/sys/src/brazil/port/devtinyfs.c /n/fornaxdump/1996/0217/sys/src/brazil/port/devtinyfs.c
673c
return sofar;
.
667,671c
/* 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;
.
664,665d
660,662c
Tfs *fs;
Tfile *f;
int sofar, i;
ulong bno, tbno;
Mdata *md;
uchar buf[Blen];
uchar *p = a;
if(c->qid.path & CHDIR)
error(Eperm);
fs = tinyfs.fs[c->dev];
f = &fs->f[c->qid.path];
/* walk to first data block */
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);
.
648c
return sofar;
.
645,646c
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;
if(i < 0)
break;
memmove(p, md->data, i);
p += i;
bno = GETS(md->bno);
offset = 0;
}
.
641,643d
634,635c
for(sofar = 0; sofar + Blen < offset; sofar += Blen){
md = readdata(fs, bno, buf, 0);
.
632c
/* walk to starting data block */
.
623c
return devdirread(c, a, n, 0, 0, tinyfsgen);
.
620a
uchar *p = a;
.
604c
free(fs->f);
.
572c
if(f->flag & Fcreating){
.
384a
if(done)
f->flag &= ~Fcreating;
.
382a
done = 1;
.
370c
mdata = validdata(fs, buf, 0);
.
360c
for(done = 0; !done;) {
.
358c
for(f = fs->f; f < &(fs->f[fs->nf]); f++){
.
344c
if(fs->nfs >= fs->fsize)
.
316c
int n, done;
.
308c
* block bitmap. Inconsistent files are purged. The medium
* had better be small or this could take a while.
.
262c
memmove(f, fs->f, fs->nf*sizeof(f));
.
233c
md = validdata(fs, buf, 0);
.
194c
return validdata(fs, buf, lenp);
.
188a
Mdata *md;
.
187c
readdata(Tfs *fs, ulong bno, uchar *buf, int *lenp)
.
180a
if(lenp)
*lenp = x;
.
179c
if(x > Dlen)
.
175a
if(lenp)
*lenp = Dlen;
.
163c
validdata(Tfs *fs, uchar *p, int *lenp)
.
## diffname port/devtinyfs.c 1996/0218
## diff -e /n/fornaxdump/1996/0217/sys/src/brazil/port/devtinyfs.c /n/fornaxdump/1996/0218/sys/src/brazil/port/devtinyfs.c
716a
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);
.
704,715c
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;
.
699,700c
if(md->type == Tagend)
break;
.
695c
/* 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 */
.
691a
if(n == 0)
return 0;
.
683c
int sofar, i, x;
.
656,657d
647,648d
628c
ulong bno;
.
606c
if(fs->r == 0){
.
604c
qunlock(fs);
.
597c
if(f->flag & Frmonclose)
.
573c
fs = &tinyfs.fs[c->dev];
.
542a
fs = &tinyfs.fs[c->dev];
.
522c
f = newfile(fs, fs->f[c->qid.path].name);
.
516c
if(c->qid.path & CHDIR){
.
491a
fs = &tinyfs.fs[c->dev];
.
490a
Tfs *fs;
.
479a
Tfs *fs;
fs = &tinyfs.fs[c->dev];
.
448c
if(fs && eqchan(cc, fs->c, 0))
.
445a
fs = 0;
.
438c
cc = namec(spec, Aopen, ORDWR, 0);
.
408a
USED(ntab, tab);
.
389c
f->length += GETS(mdata->bno);
.
386c
f->length += Dlen;
.
369c
freefile(fs, f, bno);
.
366c
bno = f->dbno;
.
351c
if(fs->nf >= fs->fsize)
.
347c
mdir = validdir(fs, buf);
.
328,329c
devtab[fs->c->type].stat(fs->c, dbuf);
convM2D(dbuf, &d);
.
326c
Mdata *mdata;
.
321a
uchar buf[Blen];
.
320c
char dbuf[DIRLEN];
.
304c
if(f->bno == Notabno)
.
301c
freefile(fs, f, Notabno);
.
279a
f = 0;
.
221c
if(devtab[fs->c->type].write(fs->c, buf, Blen, Blen*f->bno) != Blen)
error(Eio);
.
219c
md->sum = 0 - checksum(buf);
.
211c
return;
.
207d
203c
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
.
197,199c
if(devtab[fs->c->type].read(fs->c, buf, Blen, Blen*bno) != Blen)
error(Eio);
.
193,194d
170,171c
md = (Mdata*)p;
switch(md->type){
.
153c
if(p[0] != Tagdir)
.
## diffname port/devtinyfs.c 1996/0220
## diff -e /n/fornaxdump/1996/0218/sys/src/brazil/port/devtinyfs.c /n/fornaxdump/1996/0220/sys/src/brazil/port/devtinyfs.c
786c
return n;
.
778,782c
/* update finger */
if(fbno != Notabno){
f->finger = finger;
f->fbno = fbno;
}
.
776a
f->length += n;
.
770,775c
writedata(fs, bno, dbno, md->data, i+next, last == n+offset);
.
751,768c
/* point to new blocks */
if(offset == 0){
f->dbno = dbno;
writedir(fs, f);
} else {
i = last - offset;
next = offset%Dlen;
if(i > 0){
p -= i;
memmove(md->data + next, p, i);
.
745a
if(md == 0)
error(Eio);
.
743,744c
md = (Mdata*)buf;
if(f->finger < offset && f->fbno != Notabno){
next = f->finger;
bno = f->fbno;
} else {
next = 0;
bno = f->dbno;
}
for(; next < offset; next += Dlen){
.
741a
/* write blocks backwards */
p += n;
last = offset + n;
off = offset;
fbno = Notabno;
finger = 0;
for(next = (last/Dlen)*Dlen; next >= off; next -= Dlen){
bno = mapalloc(fs);
if(bno == Notabno){
error("out of space");
}
i = last - next;
p -= i;
if(last == n+offset){
writedata(fs, bno, dbno, p, i, 1);
finger = next; /* remember for later */
fbno = bno;
} else
writedata(fs, bno, dbno, p, i, 0);
dbno = bno;
last = next;
}
.
737c
freeblocks(fs, dbno, Notabno);
.
735a
dbno = Notabno;
.
728c
fs = &tinyfs.fs[c->dev];
.
716,717c
int last, next, i, off, finger;
ulong bno, dbno, fbno;
.
712c
tinyfswrite(Chan *c, void *a, long n, ulong offset)
.
710a
/*
* if we get a write error in this routine, blocks will
* be lost. They should be recovered next fsinit.
*/
.
700a
qunlock(fs);
poperror();
.
699c
off = 0;
.
694,695d
691c
if(md == 0)
error(Eio);
/* update finger for successful read */
f->finger = offset + sofar;
f->fbno = bno;
i -= off;
.
688c
off = offset%Dlen;
offset -= off;
.
683a
if(md == 0)
error(Eio);
.
681,682c
if(f->finger < offset && f->fbno != Notabno){
sofar = f->finger;
bno = f->fbno;
} else {
sofar = 0;
bno = f->dbno;
}
for(; sofar + Dlen < offset; sofar += Dlen){
.
676a
qlock(fs);
if(waserror()){
qunlock(fs);
nexterror();
}
.
673c
fs = &tinyfs.fs[c->dev];
.
664c
int sofar, i, off;
.
656c
qunlock(fs);
.
654c
fs->c = 0;
.
644,652c
if(fs->f)
free(fs->f);
fs->f = 0;
fs->nf = 0;
fs->fsize = 0;
if(fs->map)
free(fs->map);
fs->map = 0;
.
641,642d
636a
poperror();
.
634,635d
632d
630a
f->flag &= ~Fcreating;
.
615,629c
if(!waserror()){
if(c->qid.path != CHDIR){
f = &fs->f[c->qid.path];
f->r--;
if(f->r == 0){
if(f->flag & Frmonclose)
freefile(fs, f, Notabno);
else if(f->flag & Fcreating){
/* remove all other files with this name */
for(i = 0; i < fs->fsize; i++){
nf = &fs->f[i];
if(f == nf)
continue;
if(strcmp(nf->name, f->name) == 0){
if(nf->r)
nf->flag |= Frmonclose;
else
freefile(fs, nf, Notabno);
}
.
606c
Tfs *fs;
.
592,593c
Tfs *fs;
Tfile *f;
if(c->qid.path == CHDIR)
error(Eperm);
fs = &tinyfs.fs[c->dev];
f = &fs->f[c->qid.path];
qlock(fs);
freefile(fs, f, Notabno);
qunlock(fs);
.
582a
poperror();
.
580a
if(waserror()){
qunlock(fs);
nexterror();
}
.
575,576c
USED(perm);
.
563a
poperror();
.
559,560c
break;
case OREAD:
break;
default:
.
557a
fs->f[c->qid.path].r--;
.
556c
if(waserror()){
qunlock(fs);
nexterror();
}
switch(omode){
case OTRUNC|ORDWR:
case OTRUNC|OWRITE:
.
494d
492c
qunlock(fs);
.
490a
fs->f = 0;
fs->nf = 0;
fs->fsize = 0;
.
487,488d
485c
for(fs = tinyfs.fs; fs < &tinyfs.fs[Maxfs]; fs++){
qlock(fs);
if(fs->r == 0)
break;
qunlock(fs);
}
if(fs == &tinyfs.fs[Maxfs])
.
479,480c
if(i < Maxfs){
.
477a
qunlock(fs);
.
476c
qlock(fs);
if(fs->r && eqchan(cc, fs->c, 0))
.
474c
for(i = 0; i < Maxfs; i++){
.
472d
468d
465c
p = 0;
if(strcmp(spec, "hd0") == 0)
p = "#H/hd0nvram";
else
error("bad spec");
cc = namec(p, Aopen, ORDWR, 0);
.
463a
char *p;
.
439a
if(f->name[0] == 0)
return 0;
.
321a
f->fbno = Notabno;
f->r = 1;
.
314a
}
.
313c
if(i < fs->fsize){
if(i >= fs->nf)
fs->nf = i+1;
.
291,292c
if(fs->f){
memmove(f, fs->f, fs->nf*sizeof(*f));
free(fs->f);
}
.
276a
mapclr(fs, f->bno);
.
272,273c
if(devtab[fs->c->type].read(fs->c, buf, Blen, Blen*f->bno) != Blen)
.
269a
poperror();
}
static void
freefile(Tfs *fs, Tfile *f, ulong bend)
{
uchar buf[Blen];
/* remove blocks from map */
freeblocks(fs, f->dbno, bend);
.
259,260c
if(devtab[fs->c->type].read(fs->c, buf, Blen, Blen*bno) != Blen)
.
255,256c
if(waserror())
return;
.
251,252d
248c
freeblocks(Tfs *fs, ulong bno, ulong bend)
.
141,142c
return Notabno;
.
137d
128d
83d
65a
/* hint to avoid egregious reading */
ushort fbno;
ulong finger;
.
52c
uchar data[Dlen];
.
## diffname port/devtinyfs.c 1996/0221
## diff -e /n/fornaxdump/1996/0220/sys/src/brazil/port/devtinyfs.c /n/fornaxdump/1996/0221/sys/src/brazil/port/devtinyfs.c
487a
else if(strncmp(spec, "hd1") == 0)
p = "#H/hd1nvram";
else if(strncmp(spec, "sd0") == 0)
p = "#H/sd0nvram";
else if(strncmp(spec, "sd1") == 0)
p = "#H/sd1nvram";
.
486c
if(strncmp(spec, "hd0") == 0)
.
## diffname port/devtinyfs.c 1996/0223
## diff -e /n/fornaxdump/1996/0221/sys/src/brazil/port/devtinyfs.c /n/fornaxdump/1996/0223/sys/src/brazil/port/devtinyfs.c
12d
## diffname port/devtinyfs.c 1996/0226
## diff -e /n/fornaxdump/1996/0223/sys/src/brazil/port/devtinyfs.c /n/fornaxdump/1996/0226/sys/src/brazil/port/devtinyfs.c
889c
qunlock(&fs->ql);
.
823c
qunlock(&fs->ql);
.
819c
qlock(&fs->ql);
.
779c
qunlock(&fs->ql);
.
738c
qunlock(&fs->ql);
.
736c
qlock(&fs->ql);
.
714c
qunlock(&fs->ql);
.
670c
qlock(&fs->ql);
.
651c
qunlock(&fs->ql);
.
649c
qlock(&fs->ql);
.
631c
qunlock(&fs->ql);
.
627c
qunlock(&fs->ql);
.
625c
qlock(&fs->ql);
.
608c
qunlock(&fs->ql);
.
593c
qunlock(&fs->ql);
.
591c
qlock(&fs->ql);
.
569c
qunlock(&fs->ql);
.
563c
qlock(&fs->ql);
.
550c
qunlock(&fs->ql);
.
548c
qlock(&fs->ql);
.
529c
qunlock(&fs->ql);
.
519c
qunlock(&fs->ql);
.
516c
qlock(&fs->ql);
.
512c
qunlock(&fs->ql);
.
508c
qunlock(&fs->ql);
.
505c
qlock(&fs->ql);
.
485,492c
if(strncmp(spec, "hd0", 3) == 0)
p = "/dev/hd0nvram";
else if(strncmp(spec, "hd1", 3) == 0)
p = "/dev/hd1nvram";
else if(strncmp(spec, "sd0", 3) == 0)
p = "/dev/sd0nvram";
else if(strncmp(spec, "sd1", 3) == 0)
p = "/dev/sd1nvram";
.
84d
73c
QLock ql;
.
57d
## diffname port/devtinyfs.c 1997/0327
## diff -e /n/fornaxdump/1996/0226/sys/src/brazil/port/devtinyfs.c /n/emeliedump/1997/0327/sys/src/brazil/port/devtinyfs.c
892,896c
Dev tinyfsdevtab = {
tinyfsreset,
devinit,
tinyfsattach,
tinyfsclone,
tinyfswalk,
tinyfsstat,
tinyfsopen,
tinyfscreate,
tinyfsclose,
tinyfsread,
devbread,
tinyfswrite,
devbwrite,
tinyfsremove,
devwstat,
};
.
793c
static long
.
783,788d
715c
static long
.
709c
cclose(fs->c);
.
652,659c
static void
.
637c
static void
.
613c
static void
.
577c
static Chan*
.
571c
static void
.
553c
static int
.
539c
static Chan*
.
511c
cclose(cc);
.
496c
cclose(cc);
.
469,474c
static Chan*
.
462c
static void
.
411c
n = devtab[fs->c->type]->read(fs->c, buf, Blen, Blen*bno);
.
382c
n = devtab[fs->c->type]->read(fs->c, buf, Blen, Blen*bno);
.
367c
devtab[fs->c->type]->stat(fs->c, dbuf);
.
282c
devtab[fs->c->type]->write(fs->c, buf, Blen, Blen*f->bno);
.
279c
if(devtab[fs->c->type]->read(fs->c, buf, Blen, Blen*f->bno) != Blen)
.
256c
if(devtab[fs->c->type]->read(fs->c, buf, Blen, Blen*bno) != Blen)
.
241c
if(devtab[fs->c->type]->write(fs->c, buf, Blen, Blen*f->bno) != Blen)
.
220c
if(devtab[fs->c->type]->write(fs->c, &md, Blen, Blen*bno) != Blen)
.
193c
if(devtab[fs->c->type]->read(fs->c, buf, Blen, Blen*bno) != Blen)
.
## diffname port/devtinyfs.c 1997/0408
## diff -e /n/emeliedump/1997/0327/sys/src/brazil/port/devtinyfs.c /n/emeliedump/1997/0408/sys/src/brazil/port/devtinyfs.c
874a
'U',
"tinyfs",
.
## diffname port/devtinyfs.c 1999/0612
## diff -e /n/emeliedump/1997/0408/sys/src/brazil/port/devtinyfs.c /n/emeliedump/1999/0612/sys/src/brazil/port/devtinyfs.c
878,879c
devreset,
tinyfsinit,
.
875c
'F',
.
869c
qunlock(&rock.fs->ql);
.
859c
writedata(rock.fs, bno, rock.dbno, md->data, used, last == n+offset);
.
857c
memmove(md->data + used, p, i);
used += i;
.
854d
852a
/* updating a current block */
.
850,851c
/* first block in a file */
f->dbno = rock.dbno;
writedir(rock.fs, f);
.
844a
}
next += Dlen;
if(next > offset)
panic("devtinyfs1");
.
843c
if(md->type == Tagend){
if(next + Dlen < offset)
panic("devtinyfs1");
.
839,840c
used = 0;
while(bno != Notabno){
md = readdata(rock.fs, bno, buf, &used);
.
832c
if(0 && f->finger < offset && f->fbno != Notabno){
.
824,826c
} else {
writedata(rock.fs, bno, rock.dbno, p, i, 0);
}
rock.dbno = bno;
.
821c
writedata(rock.fs, bno, rock.dbno, p, i, 1);
.
817d
813,815c
off = offset; /* so we have something signed to compare against */
for(next = ((last-1)/Dlen)*Dlen; next >= off; next -= Dlen){
bno = mapalloc(rock.fs);
if(bno == Notabno)
.
810d
806a
/* files are append only, anything else is illegal */
if(offset != f->length)
error("append only");
.
802,803c
freeblocks(rock.fs, rock.dbno, Notabno);
qunlock(&rock.fs->ql);
.
795,800c
qlock(&rock.fs->ql);
rock.dbno = Notabno;
.
792,793c
p = a;
rock.fs = &tinyfs.fs[c->dev];
f = &rock.fs->f[c->qid.path];
.
784c
uchar *p;
volatile struct {
Tfs *fs;
ulong dbno;
} rock;
.
780,781c
int last, next, i, finger, off, used;
ulong bno, fbno;
.
778d
776c
tinyfswrite(Chan *c, void *a, long n, vlong offset)
.
765c
qunlock(&rock.fs->ql);
.
758,760c
if(i > n - sofar)
i = n - sofar;
memmove(p, md->data+off, i);
.
755a
offset += Dlen;
.
754c
f->finger = offset;
.
749c
md = readdata(rock.fs, bno, buf, &i);
.
738,739c
for(; sofar + Dlen <= offset; sofar += Dlen){
md = readdata(rock.fs, bno, buf, 0);
.
731c
if(0 && f->finger <= offset && f->fbno != Notabno){
.
724c
qunlock(&rock.fs->ql);
.
722c
qlock(&rock.fs->ql);
.
717,718c
p = a;
rock.fs = &tinyfs.fs[c->dev];
f = &rock.fs->f[c->qid.path];
.
712c
uchar *p;
.
706c
volatile struct { Tfs *fs; } rock;
.
704c
tinyfsread(Chan *c, void *a, long n, vlong offset)
.
700c
qunlock(&rock.fs->ql);
.
686,698c
/* dereference rock.fs and remove on zero refs */
rock.fs->r--;
if(rock.fs->r == 0){
if(rock.fs->f)
free(rock.fs->f);
rock.fs->f = 0;
rock.fs->nf = 0;
rock.fs->fsize = 0;
if(rock.fs->map)
free(rock.fs->map);
rock.fs->map = 0;
cclose(rock.fs->c);
rock.fs->c = 0;
.
676c
freefile(rock.fs, nf, Notabno);
.
668,669c
for(i = 0; i < rock.fs->fsize; i++){
nf = &rock.fs->f[i];
.
665c
freefile(rock.fs, f, Notabno);
.
661c
f = &rock.fs->f[c->qid.path];
.
656c
qlock(&rock.fs->ql);
.
654c
rock.fs = &tinyfs.fs[c->dev];
.
650c
volatile struct { Tfs *fs; } rock;
.
627c
c->qid.path = f - rock.fs->f;
.
623,624c
f = newfile(rock.fs, name);
qunlock(&rock.fs->ql);
.
620c
qunlock(&rock.fs->ql);
.
618c
qlock(&rock.fs->ql);
.
616c
rock.fs = &tinyfs.fs[c->dev];
.
611c
volatile struct { Tfs *fs; } rock;
.
601c
qunlock(&rock.fs->ql);
.
592,594c
f = newfile(rock.fs, rock.fs->f[c->qid.path].name);
rock.fs->f[c->qid.path].r--;
c->qid.path = f - rock.fs->f;
.
586c
qunlock(&rock.fs->ql);
.
584c
qlock(&rock.fs->ql);
.
578c
rock.fs = &tinyfs.fs[c->dev];
.
576a
volatile struct { Tfs *fs; } rock;
.
575d
526c
c = devattach('F', spec);
.
521c
tfsinit(fs);
.
516c
fs->c = rock.cc;
.
506c
cclose(rock.cc);
.
499c
if(fs->r && eqchan(rock.cc, fs->c, 1))
.
491c
cclose(rock.cc);
.
489c
rock.cc = fdtochan(fd, ORDWR, 0, 1);
.
477,487c
fd = atoi(spec);
if(fd < 0)
error("bad specifier");
.
473,475c
Chan *c;
volatile struct { Chan *cc; } rock;
int i, fd;
.
470c
tinyfsattach(void *spec)
.
468a
/*
* specifier is an open file descriptor
*/
.
466c
panic("tinyfsinit");
.
463c
tinyfsinit(void)
.
448c
USED(ntab);
USED(tab);
.
400a
f->fbno = Notabno;
.
375c
fs->map = malloc(x);
.
356c
tfsinit(Tfs *fs)
.
347c
return rock.f;
.
344c
writedir(rock.fs, rock.f);
.
342c
if(rock.f->bno == Notabno)
.
339c
freefile(rock.fs, rock.f, Notabno);
.
331,335c
rock.f->flag = Fcreating;
rock.f->dbno = Notabno;
rock.f->bno = mapalloc(rock.fs);
rock.f->fbno = Notabno;
rock.f->r = 1;
rock.f->pin = Notapin; // what is a pin??
.
328c
expand(rock.fs);
.
322,324c
if(i < rock.fs->fsize){
if(i >= rock.fs->nf)
rock.fs->nf = i+1;
.
314,317c
for(i = 0; i < rock.fs->fsize; i++){
rock.f = &rock.fs->f[i];
if(rock.f->name[0] == 0){
strncpy(rock.f->name, name, sizeof(rock.f->name)-1);
.
312c
rock.f = 0;
rock.fs = fs;
.
309c
volatile struct {
Tfile *f;
Tfs *fs;
} rock;
.
296c
f = malloc(fs->fsize*sizeof(*f));
.
279,281c
memset(buf, 0x55, Blen);
.
240c
.
183a
default:
return 0;
.
32c
Frmonclose= 2
.
5,12d
3a
#include "u.h"
#include "../port/lib.h"
#include "../port/error.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
.
## diffname port/devtinyfs.c 1999/0618
## diff -e /n/emeliedump/1999/0612/sys/src/brazil/port/devtinyfs.c /n/emeliedump/1999/0618/sys/src/brazil/port/devtinyfs.c
596a
case OEXEC:
.
489d
485,487c
snprint(buf, sizeof(buf), "/dev/%s", spec);
rock.cc = namec(buf, Aopen, ORDWR, 0);
.
483c
int i;
char buf[NAMELEN*2];
.
463c
devdir(c, qid, f->name, f->length, eve, 0775, dp);
.
## diffname port/devtinyfs.c 1999/0623
## diff -e /n/emeliedump/1999/0618/sys/src/brazil/port/devtinyfs.c /n/emeliedump/1999/0623/sys/src/brazil/port/devtinyfs.c
478c
tinyfsattach(char *spec)
.
## diffname port/devtinyfs.c 1999/1230
## diff -e /n/emeliedump/1999/0623/sys/src/brazil/port/devtinyfs.c /n/emeliedump/1999/1230/sys/src/9/port/devtinyfs.c
462d
457a
if(i == DEVDOTDOT){
qid.path = CHDIR;
devdir(c, qid, ".", 0, eve, 0555, dp);
return 1;
}
.
454a
qid.vers = 0;
.
|