1219b2ee8SDavid du Colombier /*
2219b2ee8SDavid du Colombier * 10th edition 4K file system
3219b2ee8SDavid du Colombier */
4219b2ee8SDavid du Colombier #include <u.h>
5219b2ee8SDavid du Colombier #include <libc.h>
6219b2ee8SDavid du Colombier #include <auth.h>
7219b2ee8SDavid du Colombier #include <fcall.h>
8219b2ee8SDavid du Colombier #include "tapefs.h"
9219b2ee8SDavid du Colombier
10219b2ee8SDavid du Colombier /*
11219b2ee8SDavid du Colombier * v10 disk inode
12219b2ee8SDavid du Colombier */
13219b2ee8SDavid du Colombier #define VNADDR 13
14219b2ee8SDavid du Colombier #define VFMT 0160000
15219b2ee8SDavid du Colombier #define VIFREG 0100000
16219b2ee8SDavid du Colombier #define VIFDIR 0040000
17219b2ee8SDavid du Colombier #define VIFCHR 0120000
18219b2ee8SDavid du Colombier #define VIFBLK 0160000
19219b2ee8SDavid du Colombier #define VMODE 0777
20219b2ee8SDavid du Colombier #define VSUPERB 1
21219b2ee8SDavid du Colombier #define VROOT 2 /* root inode */
22219b2ee8SDavid du Colombier #define VNAMELEN 14
23219b2ee8SDavid du Colombier #define BLSIZE 4096
24219b2ee8SDavid du Colombier #define LINOPB (BLSIZE/sizeof(struct v10dinode))
25219b2ee8SDavid du Colombier #define LNINDIR (BLSIZE/sizeof(unsigned long))
26219b2ee8SDavid du Colombier
27219b2ee8SDavid du Colombier struct v10dinode {
28219b2ee8SDavid du Colombier unsigned char flags[2];
29219b2ee8SDavid du Colombier unsigned char nlinks[2];
30219b2ee8SDavid du Colombier unsigned char uid[2];
31219b2ee8SDavid du Colombier unsigned char gid[2];
32219b2ee8SDavid du Colombier unsigned char size[4];
33219b2ee8SDavid du Colombier unsigned char addr[40];
34219b2ee8SDavid du Colombier unsigned char atime[4];
35219b2ee8SDavid du Colombier unsigned char mtime[4];
36219b2ee8SDavid du Colombier unsigned char ctime[4];
37219b2ee8SDavid du Colombier };
38219b2ee8SDavid du Colombier
39219b2ee8SDavid du Colombier struct v10dir {
40219b2ee8SDavid du Colombier uchar ino[2];
41219b2ee8SDavid du Colombier char name[VNAMELEN];
42219b2ee8SDavid du Colombier };
43219b2ee8SDavid du Colombier
44219b2ee8SDavid du Colombier int tapefile;
4529b83c63SDavid du Colombier vlong tapelen;
46219b2ee8SDavid du Colombier Fileinf iget(int ino);
47219b2ee8SDavid du Colombier long bmap(Ram *r, long bno);
48219b2ee8SDavid du Colombier void getblk(Ram *r, long bno, char *buf);
49219b2ee8SDavid du Colombier
50219b2ee8SDavid du Colombier void
populate(char * name)51219b2ee8SDavid du Colombier populate(char *name)
52219b2ee8SDavid du Colombier {
53219b2ee8SDavid du Colombier Fileinf f;
5429b83c63SDavid du Colombier Dir *d;
55219b2ee8SDavid du Colombier
56219b2ee8SDavid du Colombier replete = 0;
57219b2ee8SDavid du Colombier tapefile = open(name, OREAD);
58219b2ee8SDavid du Colombier if (tapefile<0)
59219b2ee8SDavid du Colombier error("Can't open argument file");
6029b83c63SDavid du Colombier if ((d=dirfstat(tapefile)) == nil)
6129b83c63SDavid du Colombier error("dirfstat");
6229b83c63SDavid du Colombier tapelen = d->length;
6329b83c63SDavid du Colombier free(d);
64219b2ee8SDavid du Colombier f = iget(VROOT);
65219b2ee8SDavid du Colombier ram->perm = f.mode;
66219b2ee8SDavid du Colombier ram->mtime = f.mdate;
6741fe996aSDavid du Colombier ram->addr = f.addr;
6841fe996aSDavid du Colombier ram->data = f.data;
69219b2ee8SDavid du Colombier ram->ndata = f.size;
70219b2ee8SDavid du Colombier }
71219b2ee8SDavid du Colombier
72219b2ee8SDavid du Colombier void
popdir(Ram * r)73219b2ee8SDavid du Colombier popdir(Ram *r)
74219b2ee8SDavid du Colombier {
75219b2ee8SDavid du Colombier int i, ino;
76219b2ee8SDavid du Colombier char *cp;
77219b2ee8SDavid du Colombier struct v10dir *dp;
78219b2ee8SDavid du Colombier Fileinf f;
79219b2ee8SDavid du Colombier char name[VNAMELEN+1];
80219b2ee8SDavid du Colombier
817dd7cddfSDavid du Colombier cp = 0;
82219b2ee8SDavid du Colombier for (i=0; i<r->ndata; i+=sizeof(struct v10dir)) {
83219b2ee8SDavid du Colombier if (i%BLSIZE==0)
84219b2ee8SDavid du Colombier cp = doread(r, i, BLSIZE);
85219b2ee8SDavid du Colombier dp = (struct v10dir *)(cp+i%BLSIZE);
86219b2ee8SDavid du Colombier ino = g2byte(dp->ino);
87219b2ee8SDavid du Colombier if (strcmp(dp->name, ".")==0 || strcmp(dp->name, "..")==0)
88219b2ee8SDavid du Colombier continue;
89219b2ee8SDavid du Colombier if (ino==0)
90219b2ee8SDavid du Colombier continue;
91219b2ee8SDavid du Colombier f = iget(ino);
92219b2ee8SDavid du Colombier strncpy(name, dp->name, VNAMELEN);
93*9f2726c3SDavid du Colombier name[VNAMELEN] = '\0';
94219b2ee8SDavid du Colombier f.name = name;
95219b2ee8SDavid du Colombier popfile(r, f);
96219b2ee8SDavid du Colombier }
97219b2ee8SDavid du Colombier r->replete = 1;
98219b2ee8SDavid du Colombier }
99219b2ee8SDavid du Colombier
100219b2ee8SDavid du Colombier void
dotrunc(Ram * r)101219b2ee8SDavid du Colombier dotrunc(Ram *r)
102219b2ee8SDavid du Colombier {
103219b2ee8SDavid du Colombier USED(r);
104219b2ee8SDavid du Colombier }
105219b2ee8SDavid du Colombier
106219b2ee8SDavid du Colombier void
docreate(Ram * r)107219b2ee8SDavid du Colombier docreate(Ram *r)
108219b2ee8SDavid du Colombier {
109219b2ee8SDavid du Colombier USED(r);
110219b2ee8SDavid du Colombier }
111219b2ee8SDavid du Colombier
112219b2ee8SDavid du Colombier char *
doread(Ram * r,vlong off,long cnt)11341fe996aSDavid du Colombier doread(Ram *r, vlong off, long cnt)
114219b2ee8SDavid du Colombier {
1159a747e4fSDavid du Colombier static char buf[Maxbuf+BLSIZE];
116219b2ee8SDavid du Colombier int bno, i;
117219b2ee8SDavid du Colombier
118219b2ee8SDavid du Colombier bno = off/BLSIZE;
119219b2ee8SDavid du Colombier off -= bno*BLSIZE;
1209a747e4fSDavid du Colombier if (cnt>Maxbuf)
121219b2ee8SDavid du Colombier error("count too large");
122219b2ee8SDavid du Colombier if (off)
1237dd7cddfSDavid du Colombier cnt += off;
124219b2ee8SDavid du Colombier i = 0;
125219b2ee8SDavid du Colombier while (cnt>0) {
126219b2ee8SDavid du Colombier getblk(r, bno, &buf[i*BLSIZE]);
127219b2ee8SDavid du Colombier cnt -= BLSIZE;
128219b2ee8SDavid du Colombier bno++;
129219b2ee8SDavid du Colombier i++;
130219b2ee8SDavid du Colombier }
131219b2ee8SDavid du Colombier return buf+off;
132219b2ee8SDavid du Colombier }
133219b2ee8SDavid du Colombier
134219b2ee8SDavid du Colombier void
dowrite(Ram * r,char * buf,long off,long cnt)135219b2ee8SDavid du Colombier dowrite(Ram *r, char *buf, long off, long cnt)
136219b2ee8SDavid du Colombier {
137219b2ee8SDavid du Colombier USED(r); USED(buf); USED(off); USED(cnt);
138219b2ee8SDavid du Colombier }
139219b2ee8SDavid du Colombier
140219b2ee8SDavid du Colombier int
dopermw(Ram * r)141219b2ee8SDavid du Colombier dopermw(Ram *r)
142219b2ee8SDavid du Colombier {
143219b2ee8SDavid du Colombier USED(r);
144219b2ee8SDavid du Colombier return 0;
145219b2ee8SDavid du Colombier }
146219b2ee8SDavid du Colombier
147219b2ee8SDavid du Colombier /*
148219b2ee8SDavid du Colombier * fetch an i-node
149219b2ee8SDavid du Colombier * -- no sanity check for now
150219b2ee8SDavid du Colombier * -- magic inode-to-disk-block stuff here
151219b2ee8SDavid du Colombier */
152219b2ee8SDavid du Colombier
153219b2ee8SDavid du Colombier Fileinf
iget(int ino)154219b2ee8SDavid du Colombier iget(int ino)
155219b2ee8SDavid du Colombier {
156219b2ee8SDavid du Colombier char buf[BLSIZE];
157219b2ee8SDavid du Colombier struct v10dinode *dp;
158219b2ee8SDavid du Colombier long flags, i;
159219b2ee8SDavid du Colombier Fileinf f;
160219b2ee8SDavid du Colombier
161219b2ee8SDavid du Colombier seek(tapefile, BLSIZE*((ino-1)/LINOPB + VSUPERB + 1), 0);
162219b2ee8SDavid du Colombier if (read(tapefile, buf, BLSIZE) != BLSIZE)
163219b2ee8SDavid du Colombier error("Can't read inode");
164219b2ee8SDavid du Colombier dp = ((struct v10dinode *)buf) + ((ino-1)%LINOPB);
165219b2ee8SDavid du Colombier flags = g2byte(dp->flags);
166219b2ee8SDavid du Colombier f.size = g4byte(dp->size);
167219b2ee8SDavid du Colombier if ((flags&VFMT)==VIFCHR || (flags&VFMT)==VIFBLK)
168219b2ee8SDavid du Colombier f.size = 0;
16941fe996aSDavid du Colombier f.data = emalloc(VNADDR*sizeof(long));
170219b2ee8SDavid du Colombier for (i = 0; i < VNADDR; i++)
17141fe996aSDavid du Colombier ((long*)f.data)[i] = g3byte(dp->addr+3*i);
172219b2ee8SDavid du Colombier f.mode = flags & VMODE;
173219b2ee8SDavid du Colombier if ((flags&VFMT)==VIFDIR)
1749a747e4fSDavid du Colombier f.mode |= DMDIR;
175219b2ee8SDavid du Colombier f.uid = g2byte(dp->uid);
176219b2ee8SDavid du Colombier f.gid = g2byte(dp->gid);
177219b2ee8SDavid du Colombier f.mdate = g4byte(dp->mtime);
178219b2ee8SDavid du Colombier return f;
179219b2ee8SDavid du Colombier }
180219b2ee8SDavid du Colombier
181219b2ee8SDavid du Colombier void
getblk(Ram * r,long bno,char * buf)182219b2ee8SDavid du Colombier getblk(Ram *r, long bno, char *buf)
183219b2ee8SDavid du Colombier {
184219b2ee8SDavid du Colombier long dbno;
185219b2ee8SDavid du Colombier
186219b2ee8SDavid du Colombier if ((dbno = bmap(r, bno)) == 0) {
187219b2ee8SDavid du Colombier memset(buf, 0, BLSIZE);
188219b2ee8SDavid du Colombier return;
189219b2ee8SDavid du Colombier }
19029b83c63SDavid du Colombier if ((vlong)(dbno+1)*BLSIZE > tapelen) {
19129b83c63SDavid du Colombier fprint(2, "read past end of tape: %lld\n", (vlong)dbno*BLSIZE);
19229b83c63SDavid du Colombier memset(buf, 0, BLSIZE);
19329b83c63SDavid du Colombier return;
19429b83c63SDavid du Colombier }
195219b2ee8SDavid du Colombier seek(tapefile, dbno*BLSIZE, 0);
19629b83c63SDavid du Colombier if (readn(tapefile, buf, BLSIZE) != BLSIZE){
19729b83c63SDavid du Colombier fprint(2, "readn at %lld: %r\n", (vlong)dbno*BLSIZE);
198219b2ee8SDavid du Colombier error("bad read");
199219b2ee8SDavid du Colombier }
20029b83c63SDavid du Colombier }
201219b2ee8SDavid du Colombier
202219b2ee8SDavid du Colombier /*
203219b2ee8SDavid du Colombier * logical to physical block
204219b2ee8SDavid du Colombier * only singly-indirect files for now
205219b2ee8SDavid du Colombier */
206219b2ee8SDavid du Colombier
207219b2ee8SDavid du Colombier long
bmap(Ram * r,long bno)208219b2ee8SDavid du Colombier bmap(Ram *r, long bno)
209219b2ee8SDavid du Colombier {
210219b2ee8SDavid du Colombier unsigned char indbuf[LNINDIR][sizeof(long)];
211219b2ee8SDavid du Colombier
212219b2ee8SDavid du Colombier if (bno < VNADDR-3)
213219b2ee8SDavid du Colombier return ((long*)r->data)[bno];
214219b2ee8SDavid du Colombier if (bno < VNADDR*LNINDIR) {
215219b2ee8SDavid du Colombier seek(tapefile, ((long *)r->data)[(bno-(VNADDR-3))/LNINDIR+(VNADDR-3)]*BLSIZE, 0);
216219b2ee8SDavid du Colombier if (read(tapefile, (char *)indbuf, BLSIZE) != BLSIZE)
217219b2ee8SDavid du Colombier return 0;
218219b2ee8SDavid du Colombier return ((indbuf[(bno-(VNADDR-3))%LNINDIR][2]<<16) + (indbuf[(bno-(VNADDR-3))%LNINDIR][1]<<8)
219219b2ee8SDavid du Colombier + indbuf[(bno-(VNADDR-3))%LNINDIR][0]);
220219b2ee8SDavid du Colombier }
221219b2ee8SDavid du Colombier return 0;
222219b2ee8SDavid du Colombier }
223