|
|
1.1 root 1: /*
2: * Copyright (c) 1983 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: char copyright[] =
9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
10: All rights reserved.\n";
11: #endif not lint
12:
13: #ifndef lint
14: static char sccsid[] = "@(#)mkproto.c 5.4 (Berkeley) 5/31/88";
15: #endif not lint
16:
17: /*
18: * Make a file system prototype.
19: * usage: mkproto filsys proto
20: */
21: #include <stdio.h>
22: #include <sys/param.h>
23: #include <sys/inode.h>
24: #include <sys/fs.h>
25: #include <sys/dir.h>
26:
27: union {
28: struct fs fs;
29: char fsx[SBSIZE];
30: } ufs;
31: #define sblock ufs.fs
32: union {
33: struct cg cg;
34: char cgx[MAXBSIZE];
35: } ucg;
36: #define acg ucg.cg
37: struct fs *fs;
38: struct csum *fscs;
39: int fso, fsi;
40: FILE *proto;
41: char token[BUFSIZ];
42: int errs;
43: long dev_bsize = 1;
44: int ino = 10;
45: long getnum();
46: char *strcpy();
47:
48: main(argc, argv)
49: int argc;
50: char *argv[];
51: {
52: int i;
53: char *calloc();
54:
55: if (argc != 3) {
56: fprintf(stderr, "usage: mkproto filsys proto\n");
57: exit(1);
58: }
59: fso = open(argv[1], 1);
60: fsi = open(argv[1], 0);
61: if (fso < 0 || fsi < 0) {
62: perror(argv[1]);
63: exit(1);
64: }
65: fs = &sblock;
66: rdfs(SBOFF, SBSIZE, (char *)fs);
67: dev_bsize = fs->fs_fsize / fsbtodb(fs, 1);
68: fscs = (struct csum *)calloc(1, (u_int)fs->fs_cssize);
69: for (i = 0; i < fs->fs_cssize; i += fs->fs_bsize)
70: rdfs(fsbtodb(fs, fs->fs_csaddr + numfrags(fs, i)),
71: (int)(fs->fs_cssize - i < fs->fs_bsize ?
72: fs->fs_cssize - i : fs->fs_bsize),
73: ((char *)fscs) + i);
74: proto = fopen(argv[2], "r");
75: descend((struct inode *)0);
76: wtfs(SBOFF / dev_bsize, SBSIZE, (char *)fs);
77: for (i = 0; i < fs->fs_cssize; i += fs->fs_bsize)
78: wtfs(fsbtodb(&sblock, fs->fs_csaddr + numfrags(&sblock, i)),
79: (int)(fs->fs_cssize - i < fs->fs_bsize ?
80: fs->fs_cssize - i : fs->fs_bsize),
81: ((char *)fscs) + i);
82: exit(errs);
83: }
84:
85: descend(par)
86: struct inode *par;
87: {
88: struct inode in;
89: int ibc = 0;
90: int i, f, c;
91: struct dinode *dip, inos[MAXBSIZE / sizeof (struct dinode)];
92: daddr_t ib[MAXBSIZE / sizeof (daddr_t)];
93: char buf[MAXBSIZE];
94:
95: getstr();
96: in.i_mode = gmode(token[0], "-bcd", IFREG, IFBLK, IFCHR, IFDIR);
97: in.i_mode |= gmode(token[1], "-u", 0, ISUID, 0, 0);
98: in.i_mode |= gmode(token[2], "-g", 0, ISGID, 0, 0);
99: for (i = 3; i < 6; i++) {
100: c = token[i];
101: if (c < '0' || c > '7') {
102: printf("%c/%s: bad octal mode digit\n", c, token);
103: errs++;
104: c = 0;
105: }
106: in.i_mode |= (c-'0')<<(15-3*i);
107: }
108: in.i_uid = getnum(); in.i_gid = getnum();
109: for (i = 0; i < fs->fs_bsize; i++)
110: buf[i] = 0;
111: for (i = 0; i < NINDIR(fs); i++)
112: ib[i] = (daddr_t)0;
113: in.i_nlink = 1;
114: in.i_size = 0;
115: for (i = 0; i < NDADDR; i++)
116: in.i_db[i] = (daddr_t)0;
117: for (i = 0; i < NIADDR; i++)
118: in.i_ib[i] = (daddr_t)0;
119: if (par != (struct inode *)0) {
120: ialloc(&in);
121: } else {
122: par = ∈
123: i = itod(fs, ROOTINO);
124: rdfs(fsbtodb(fs, i), fs->fs_bsize, (char *)inos);
125: dip = &inos[ROOTINO % INOPB(fs)];
126: in.i_number = ROOTINO;
127: in.i_nlink = dip->di_nlink;
128: in.i_size = dip->di_size;
129: in.i_db[0] = dip->di_db[0];
130: rdfs(fsbtodb(fs, in.i_db[0]), fs->fs_bsize, buf);
131: }
132:
133: switch (in.i_mode&IFMT) {
134:
135: case IFREG:
136: getstr();
137: f = open(token, 0);
138: if (f < 0) {
139: printf("%s: cannot open\n", token);
140: errs++;
141: break;
142: }
143: while ((i = read(f, buf, (int)fs->fs_bsize)) > 0) {
144: in.i_size += i;
145: newblk(buf, &ibc, ib, (int)blksize(fs, &in, ibc));
146: }
147: close(f);
148: break;
149:
150: case IFBLK:
151: case IFCHR:
152: /*
153: * special file
154: * content is maj/min types
155: */
156:
157: i = getnum() & 0377;
158: f = getnum() & 0377;
159: in.i_rdev = (i << 8) | f;
160: break;
161:
162: case IFDIR:
163: /*
164: * directory
165: * put in extra links
166: * call recursively until
167: * name of "$" found
168: */
169:
170: if (in.i_number != ROOTINO) {
171: par->i_nlink++;
172: in.i_nlink++;
173: entry(&in, in.i_number, ".", buf);
174: entry(&in, par->i_number, "..", buf);
175: }
176: for (;;) {
177: getstr();
178: if (token[0]=='$' && token[1]=='\0')
179: break;
180: entry(&in, (ino_t)(ino+1), token, buf);
181: descend(&in);
182: }
183: if (in.i_number != ROOTINO)
184: newblk(buf, &ibc, ib, (int)blksize(fs, &in, 0));
185: else
186: wtfs(fsbtodb(fs, in.i_db[0]), (int)fs->fs_bsize, buf);
187: break;
188: }
189: iput(&in, &ibc, ib);
190: }
191:
192: /*ARGSUSED*/
193: gmode(c, s, m0, m1, m2, m3)
194: char c, *s;
195: {
196: int i;
197:
198: for (i = 0; s[i]; i++)
199: if (c == s[i])
200: return((&m0)[i]);
201: printf("%c/%s: bad mode\n", c, token);
202: errs++;
203: return(0);
204: }
205:
206: long
207: getnum()
208: {
209: int i, c;
210: long n;
211:
212: getstr();
213: n = 0;
214: i = 0;
215: for (i = 0; c=token[i]; i++) {
216: if (c<'0' || c>'9') {
217: printf("%s: bad number\n", token);
218: errs++;
219: return((long)0);
220: }
221: n = n*10 + (c-'0');
222: }
223: return(n);
224: }
225:
226: getstr()
227: {
228: int i, c;
229:
230: loop:
231: switch (c = getc(proto)) {
232:
233: case ' ':
234: case '\t':
235: case '\n':
236: goto loop;
237:
238: case EOF:
239: printf("Unexpected EOF\n");
240: exit(1);
241:
242: case ':':
243: while (getc(proto) != '\n')
244: ;
245: goto loop;
246:
247: }
248: i = 0;
249: do {
250: token[i++] = c;
251: c = getc(proto);
252: } while (c != ' ' && c != '\t' && c != '\n' && c != '\0');
253: token[i] = 0;
254: }
255:
256: entry(ip, inum, str, buf)
257: struct inode *ip;
258: ino_t inum;
259: char *str;
260: char *buf;
261: {
262: register struct direct *dp, *odp;
263: int oldsize, newsize, spacefree;
264:
265: odp = dp = (struct direct *)buf;
266: while ((int)dp - (int)buf < ip->i_size) {
267: odp = dp;
268: dp = (struct direct *)((int)dp + dp->d_reclen);
269: }
270: if (odp != dp)
271: oldsize = DIRSIZ(odp);
272: else
273: oldsize = 0;
274: spacefree = odp->d_reclen - oldsize;
275: dp = (struct direct *)((int)odp + oldsize);
276: dp->d_ino = inum;
277: dp->d_namlen = strlen(str);
278: newsize = DIRSIZ(dp);
279: if (spacefree >= newsize) {
280: odp->d_reclen = oldsize;
281: dp->d_reclen = spacefree;
282: } else {
283: dp = (struct direct *)((int)odp + odp->d_reclen);
284: if ((int)dp - (int)buf >= fs->fs_bsize) {
285: printf("directory too large\n");
286: exit(1);
287: }
288: dp->d_ino = inum;
289: dp->d_namlen = strlen(str);
290: dp->d_reclen = DIRBLKSIZ;
291: }
292: strcpy(dp->d_name, str);
293: ip->i_size = (int)dp - (int)buf + newsize;
294: }
295:
296: newblk(buf, aibc, ib, size)
297: int *aibc;
298: char *buf;
299: daddr_t *ib;
300: int size;
301: {
302: int i;
303: daddr_t bno, alloc();
304:
305: bno = alloc(size);
306: wtfs(fsbtodb(fs, bno), (int)fs->fs_bsize, buf);
307: for (i = 0; i < fs->fs_bsize; i++)
308: buf[i] = 0;
309: ib[(*aibc)++] = bno;
310: if (*aibc >= NINDIR(fs)) {
311: printf("indirect block full\n");
312: errs++;
313: *aibc = 0;
314: }
315: }
316:
317: iput(ip, aibc, ib)
318: struct inode *ip;
319: int *aibc;
320: daddr_t *ib;
321: {
322: daddr_t d, alloc();
323: int i;
324: struct dinode buf[MAXBSIZE / sizeof (struct dinode)];
325: time_t time();
326:
327: ip->i_atime = ip->i_mtime = ip->i_ctime = time((time_t *)NULL);
328: switch (ip->i_mode&IFMT) {
329:
330: case IFDIR:
331: case IFREG:
332: for (i = 0; i < *aibc; i++) {
333: if (i >= NDADDR)
334: break;
335: ip->i_db[i] = ib[i];
336: }
337: if (*aibc > NDADDR) {
338: ip->i_ib[0] = alloc((int)fs->fs_bsize);
339: for (i = 0; i < NINDIR(fs) - NDADDR; i++) {
340: ib[i] = ib[i+NDADDR];
341: ib[i+NDADDR] = (daddr_t)0;
342: }
343: wtfs(fsbtodb(fs, ip->i_ib[0]),
344: (int)fs->fs_bsize, (char *)ib);
345: }
346: break;
347:
348: case IFBLK:
349: case IFCHR:
350: break;
351:
352: default:
353: printf("bad mode %o\n", ip->i_mode);
354: exit(1);
355: }
356: d = fsbtodb(fs, itod(fs, ip->i_number));
357: rdfs(d, (int)fs->fs_bsize, (char *)buf);
358: buf[itoo(fs, ip->i_number)].di_ic = ip->i_ic;
359: wtfs(d, (int)fs->fs_bsize, (char *)buf);
360: }
361:
362: daddr_t
363: alloc(size)
364: int size;
365: {
366: int i, frag;
367: daddr_t d;
368: static int cg = 0;
369:
370: again:
371: rdfs(fsbtodb(&sblock, cgtod(&sblock, cg)), (int)sblock.fs_cgsize,
372: (char *)&acg);
373: if (!cg_chkmagic(&acg)) {
374: printf("cg %d: bad magic number\n", cg);
375: return (0);
376: }
377: if (acg.cg_cs.cs_nbfree == 0) {
378: cg++;
379: if (cg >= fs->fs_ncg) {
380: printf("ran out of space\n");
381: return (0);
382: }
383: goto again;
384: }
385: for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag)
386: if (isblock(&sblock, (u_char *)cg_blksfree(&acg),
387: d / sblock.fs_frag))
388: goto goth;
389: printf("internal error: can't find block in cyl %d\n", cg);
390: return (0);
391: goth:
392: clrblock(&sblock, (u_char *)cg_blksfree(&acg), d / sblock.fs_frag);
393: acg.cg_cs.cs_nbfree--;
394: sblock.fs_cstotal.cs_nbfree--;
395: fscs[cg].cs_nbfree--;
396: cg_blktot(&acg)[cbtocylno(&sblock, d)]--;
397: cg_blks(&sblock, &acg, cbtocylno(&sblock, d))[cbtorpos(&sblock, d)]--;
398: if (size != sblock.fs_bsize) {
399: frag = howmany(size, sblock.fs_fsize);
400: fscs[cg].cs_nffree += sblock.fs_frag - frag;
401: sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag;
402: acg.cg_cs.cs_nffree += sblock.fs_frag - frag;
403: acg.cg_frsum[sblock.fs_frag - frag]++;
404: for (i = frag; i < sblock.fs_frag; i++)
405: setbit(cg_blksfree(&acg), d + i);
406: }
407: wtfs(fsbtodb(&sblock, cgtod(&sblock, cg)), (int)sblock.fs_cgsize,
408: (char *)&acg);
409: return (acg.cg_cgx * fs->fs_fpg + d);
410: }
411:
412: /*
413: * Allocate an inode on the disk
414: */
415: ialloc(ip)
416: register struct inode *ip;
417: {
418: int c;
419:
420: ip->i_number = ++ino;
421: c = itog(&sblock, ip->i_number);
422: rdfs(fsbtodb(&sblock, cgtod(&sblock, c)), (int)sblock.fs_cgsize,
423: (char *)&acg);
424: if (!cg_chkmagic(&acg)) {
425: printf("cg %d: bad magic number\n", c);
426: exit(1);
427: }
428: if (ip->i_mode & IFDIR) {
429: acg.cg_cs.cs_ndir++;
430: sblock.fs_cstotal.cs_ndir++;
431: fscs[c].cs_ndir++;
432: }
433: acg.cg_cs.cs_nifree--;
434: setbit(cg_inosused(&acg), ip->i_number);
435: wtfs(fsbtodb(&sblock, cgtod(&sblock, c)), (int)sblock.fs_cgsize,
436: (char *)&acg);
437: sblock.fs_cstotal.cs_nifree--;
438: fscs[c].cs_nifree--;
439: if(ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) {
440: printf("fsinit: inode value out of range (%lu).\n",
441: ip->i_number);
442: exit(1);
443: }
444: /* return (ip->i_number); */
445: }
446:
447: /*
448: * read a block from the file system
449: */
450: rdfs(bno, size, bf)
451: int bno, size;
452: char *bf;
453: {
454: int n;
455: off_t lseek();
456:
457: if (lseek(fsi, bno * dev_bsize, 0) < 0) {
458: printf("seek error: %d\n", bno);
459: perror("rdfs");
460: exit(1);
461: }
462: n = read(fsi, bf, size);
463: if(n != size) {
464: printf("read error: %d\n", bno);
465: perror("rdfs");
466: exit(1);
467: }
468: }
469:
470: /*
471: * write a block to the file system
472: */
473: wtfs(bno, size, bf)
474: int bno, size;
475: char *bf;
476: {
477: int n;
478: off_t lseek();
479:
480: if (lseek(fso, bno * dev_bsize, 0) < 0) {
481: printf("seek error: %d\n", bno);
482: perror("wtfs");
483: exit(1);
484: }
485: n = write(fso, bf, size);
486: if(n != size) {
487: printf("write error: %d\n", bno);
488: perror("wtfs");
489: exit(1);
490: }
491: }
492: /*
493: * check if a block is available
494: */
495: isblock(fs, cp, h)
496: struct fs *fs;
497: unsigned char *cp;
498: int h;
499: {
500: unsigned char mask;
501:
502: switch (fs->fs_frag) {
503: case 8:
504: return (cp[h] == 0xff);
505: case 4:
506: mask = 0x0f << ((h & 0x1) << 2);
507: return ((cp[h >> 1] & mask) == mask);
508: case 2:
509: mask = 0x03 << ((h & 0x3) << 1);
510: return ((cp[h >> 2] & mask) == mask);
511: case 1:
512: mask = 0x01 << (h & 0x7);
513: return ((cp[h >> 3] & mask) == mask);
514: default:
515: fprintf(stderr, "isblock bad fs_frag %ld\n", fs->fs_frag);
516: return (0);
517: }
518: /*NOTREACHED*/
519: }
520:
521: /*
522: * take a block out of the map
523: */
524: clrblock(fs, cp, h)
525: struct fs *fs;
526: unsigned char *cp;
527: int h;
528: {
529: switch ((fs)->fs_frag) {
530: case 8:
531: cp[h] = 0;
532: return;
533: case 4:
534: cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
535: return;
536: case 2:
537: cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
538: return;
539: case 1:
540: cp[h >> 3] &= ~(0x01 << (h & 0x7));
541: return;
542: default:
543: fprintf(stderr, "clrblock bad fs_frag %ld\n", fs->fs_frag);
544: return;
545: }
546: }
547:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.