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