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