|
|
1.1 root 1: /*
2: * read a Berkeley `fast file system'
3: * quick, cheap hack
4: */
5:
6: #include <stdio.h>
7: #include <sys/types.h>
8: #include <sys/stat.h> /* for file modes; they happen to match */
9: #include "bsdffs.h"
10:
11: #include "rf.h"
12: #include <errno.h>
13: #include <libc.h>
14:
15: int fserrno;
16: static int devfd;
17: static Rfile *root;
18: static union {
19: char buf[SBSIZE];
20: struct fs super;
21: } super;
22: #define sb (super.super)
23: static long firstblk; /* offset to beginning of filsys */
24: static char *blk;
25:
26: typedef struct Fsfile {
27: long dir[NDADDR];
28: long ind[NIADDR];
29: } Fsfile;
30: #define fsp(f) ((Fsfile *)((f)->fs))
31:
32: /*
33: * init:
34: * open the device
35: */
36:
37: Rfile *
38: fsinit(argc, argv)
39: int argc;
40: char **argv;
41: {
42: register Rfile *f;
43:
44: if (argc <= 1)
45: rfpanic("no device specified\n");
46: if ((devfd = open(argv[1], 0)) < 0)
47: rfpanic("%s: cannot open\n", argv[1]);
48: if (argc > 2)
49: firstblk = atol(argv[2]) * 512;
50: lseek(devfd, firstblk + SBLOCK, 0);
51: if (read(devfd, super.buf, SBSIZE) != SBSIZE)
52: rfpanic("can't read super block\n");
53: if ((blk = malloc(sb.fs_bsize)) == NULL)
54: rfpanic("can't alloc %d for block buf\n", sb.fs_bsize);
55: if ((f = (Rfile *)malloc(sizeof(Rfile))) == NULL)
56: rfpanic("no mem for root\n");
57: if ((f->fs = malloc(sizeof(Fsfile))) == NULL)
58: rfpanic("no mem for root\n");
59: f->ino = ROOTINO;
60: fsstat(f);
61: root = f;
62: return (f);
63: }
64:
65: /*
66: * access a file
67: */
68:
69: Rfile *
70: fswalk(df, name)
71: register Rfile *df;
72: char *name;
73: {
74: register Rfile *f;
75: int ino;
76:
77: if ((ino = dsearch(df, name)) == 0) {
78: fserrno = ENOENT;
79: return (NULL);
80: }
81: if (df == root) { /* "." and ".." magic */
82: if (strcmp(name, ".") == 0)
83: return (df);
84: if (strcmp(name, "..") == 0) {
85: fserrno = 0; /* pseudo-error: popped out of root */
86: return (NULL);
87: }
88: }
89: if ((f = (Rfile *)malloc(sizeof(Rfile))) == NULL) {
90: fserrno = ENOMEM;
91: return (NULL);
92: }
93: if ((f->fs = malloc(sizeof(Fsfile))) == NULL) {
94: free((char *)f);
95: fserrno = ENOMEM;
96: return (NULL);
97: }
98: f->ino = ino;
99: fsstat(f);
100: return (f);
101: }
102:
103: /*
104: * discard a file reference
105: */
106: int
107: fsdone(f)
108: Rfile *f;
109: {
110:
111: free(f->fs);
112: free((char *)f);
113: return (0);
114: }
115:
116: /*
117: * return file status
118: */
119: int
120: fsstat(f)
121: Rfile *f;
122: {
123:
124: getino(f);
125: return (0);
126: }
127:
128: /*
129: * read data
130: */
131: int
132: fsread(f, off, buf, len)
133: register Rfile *f;
134: long off;
135: char *buf;
136: int len;
137: {
138: int rest;
139: long bno;
140:
141: switch (f->mode & S_IFMT) {
142: case S_IFREG:
143: case S_IFDIR:
144: break;
145:
146: default:
147: return (0);
148: }
149: if (off >= f->size)
150: return (0);
151: if (off + len > f->size)
152: len = f->size - off;
153: bno = off / sb.fs_bsize;
154: if (getlblk(f, bno, blk, f->size - bno*sb.fs_bsize) == 0)
155: return (-1);
156: rest = (bno + 1)*sb.fs_bsize - off;
157: if (len > rest)
158: len = rest;
159: memcpy(buf, blk + (off % sb.fs_bsize), len);
160: return (len);
161: }
162:
163: /*
164: * read a piece of a directory
165: */
166: int
167: fsdirread(f, off, buf, len, offp)
168: register Rfile *f;
169: long off;
170: char *buf;
171: int len;
172: long *offp;
173: {
174: int stlen;
175: register struct direct *de;
176: struct direct *endblk;
177: char one[MAXNAMLEN+30];
178: int n;
179:
180: stlen = len;
181: endblk = de = (struct direct *)&blk[sb.fs_bsize];
182: for (; off < f->size; off += de->d_reclen,
183: de = (struct direct *)&blk[off%sb.fs_bsize]) {
184: if (de >= endblk) {
185: if (getlblk(f, off/sb.fs_bsize, blk, f->size - off) == 0)
186: break;
187: de = (struct direct *)&blk[off%sb.fs_bsize];
188: }
189: if (de->d_reclen == 0)
190: break;
191: if (de->d_ino == 0)
192: continue;
193: sprintf(one, "%ld\t%s", de->d_ino, de->d_name);
194: n = strlen(one)+1;
195: if (n > len)
196: break;
197: memcpy(buf, one, n);
198: len -= n;
199: buf += n;
200: }
201: *offp = off;
202: return (stlen - len);
203: }
204:
205: /*
206: * fetch an i-node
207: * -- no sanity check for now
208: * -- magic inode-to-disk-block stuff here
209: */
210:
211: int
212: getino(f)
213: register Rfile *f;
214: {
215: register struct icommon *dp;
216: register int cg;
217: register long ifrag;
218: register long ino;
219:
220: cg = f->ino / sb.fs_ipg;
221: ino = f->ino % sb.fs_ipg;
222: ifrag = cg*sb.fs_fpg + sb.fs_cgoffset*(cg&~sb.fs_cgmask) + sb.fs_iblkno;
223: ifrag += ino / (sb.fs_fsize/sizeof(struct icommon));
224: lseek(devfd, firstblk + ifrag * sb.fs_fsize, 0);
225: if (read(devfd, blk, sb.fs_fsize) != sb.fs_fsize) {
226: /* print error */
227: return (0);
228: }
229: dp = ((struct icommon *)blk) + (ino % (sb.fs_fsize/sizeof(struct icommon)));
230: switch (dp->i_mode & S_IFMT) {
231: case S_IFREG:
232: case S_IFDIR:
233: case S_IFBLK:
234: case S_IFCHR:
235: break;
236:
237: default:
238: return (0); /* unalloc or illegal */
239: }
240: memcpy((char *)fsp(f)->dir, (char *)dp->i_db, NDADDR*sizeof(long));
241: memcpy((char *)fsp(f)->ind, (char *)dp->i_ib, NIADDR*sizeof(long));
242: f->dev = 0;
243: f->rdev = 0; /* well ... */
244: f->mode = dp->i_mode;
245: f->nlink = dp->i_nlink;
246: f->uid = dp->i_uid;
247: f->gid = dp->i_gid;
248: f->size = dp->i_size;
249: f->tm = dp->i_mtime;
250: f->ta = dp->i_atime;
251: f->tc = dp->i_ctime;
252: return (1);
253: }
254:
255: /*
256: * look up a file
257: */
258:
259: int
260: dsearch(f, name)
261: Rfile *f;
262: char *name;
263: {
264: register struct direct *de;
265: register struct direct *endblk;
266: register long b, size;
267:
268: endblk = (struct direct *)(blk + sb.fs_bsize);
269: for (b = 0, size = f->size; size > 0; b++, size -= sb.fs_bsize) {
270: if (getlblk(f, b, blk, size) == 0)
271: continue;
272: for (de = (struct direct *)blk; de < endblk;
273: de = (struct direct *)((char *)de + de->d_reclen)) {
274: if (de->d_reclen == 0) /* safety */
275: break;
276: if (de->d_ino == 0)
277: continue;
278: if (strcmp(de->d_name, name) == 0)
279: return (de->d_ino);
280: }
281: }
282: return (0);
283: }
284:
285: /*
286: * read a block from a file
287: */
288: long bmap();
289:
290: getlblk(f, bno, buf, maxlen)
291: Rfile *f;
292: long bno;
293: char *buf;
294: int maxlen;
295: {
296: long dbno;
297:
298: if (maxlen > sb.fs_bsize)
299: maxlen = sb.fs_bsize;
300: if ((dbno = bmap(f, bno)) == 0) {
301: memset(buf, 0, maxlen);
302: return (1);
303: }
304: lseek(devfd, firstblk + dbno*sb.fs_fsize, 0);
305: if (read(devfd, buf, maxlen) != maxlen) {
306: fserrno = errno;
307: return (0);
308: }
309: return (1);
310: }
311:
312: /*
313: * logical to physical block
314: * only singly-indirect files for now
315: */
316:
317: long
318: bmap(f, bno)
319: register Rfile *f;
320: long bno;
321: {
322:
323: if (bno < NDADDR)
324: return (fsp(f)->dir[bno]);
325: bno -= NDADDR;
326: if (bno >= sb.fs_nindir)
327: return (0);
328: lseek(devfd, firstblk + fsp(f)->ind[0] * sb.fs_fsize, 0);
329: if (read(devfd, blk, sb.fs_bsize) != sb.fs_bsize)
330: return (0);
331: return (((long *)blk)[bno]);
332: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.