1: 2: char *sccsid = "@(#)mkfs.c 2.5"; 3: 4: /* 5: * Make a file system prototype. 6: * usage: mkfs filsys proto/size [ m n ] 7: */ 8: #include <whoami.h> 9: #define NIPB (BSIZE/sizeof(struct dinode)) 10: #define NINDIR (BSIZE/sizeof(daddr_t)) 11: #define NDIRECT (BSIZE/sizeof(struct direct)) 12: #define MAXFN 500 13: #ifndef UCB_NKB 14: #define itoo(x) (int)((x+15)&07) 15: #endif 16: #ifndef STANDALONE 17: #include <stdio.h> 18: #include <a.out.h> 19: #endif 20: #include <sys/param.h> 21: #include <sys/ino.h> 22: #include <sys/inode.h> 23: #include <sys/filsys.h> 24: #include <sys/fblk.h> 25: #include <sys/dir.h> 26: #define LADDR (NADDR-3) 27: time_t utime; 28: #ifndef STANDALONE 29: FILE *fin; 30: #else 31: int fin; 32: char module[] = "Mkfs"; 33: #endif 34: int fsi; 35: int fso; 36: char *charp; 37: char buf[BSIZE]; 38: union { 39: struct fblk fb; 40: char pad1[BSIZE]; 41: } fbuf; 42: #ifndef STANDALONE 43: struct exec head; 44: #endif 45: char string[50]; 46: union { 47: struct filsys fs; 48: char pad2[BSIZE]; 49: } filsys; 50: char *fsys; 51: char *proto; 52: int f_n = 10; 53: int f_m = 5; 54: int error; 55: ino_t ino; 56: long getnum(); 57: daddr_t alloc(); 58: 59: main(argc, argv) 60: char *argv[]; 61: { 62: int f, c; 63: long n; 64: 65: #ifndef STANDALONE 66: time(&utime); 67: if(argc < 3) { 68: printf("usage: mkfs filsys proto/size [ m n ]\n"); 69: exit(1); 70: } 71: fsys = argv[1]; 72: proto = argv[2]; 73: fso = creat(fsys, 0666); 74: if(fso < 0) { 75: printf("%s: cannot create\n", fsys); 76: exit(1); 77: } 78: fsi = open(fsys, 0); 79: if(fsi < 0) { 80: printf("%s: cannot open\n", fsys); 81: exit(1); 82: } 83: fin = fopen(proto, "r"); 84: #else 85: { 86: char buf[100]; 87: static char protos[60]; 88: printf("%s\n",module); 89: 90: do { 91: printf("file system: "); 92: gets(buf); 93: fso = open(buf, 1); 94: fsi = open(buf, 0); 95: } while (fso < 0 || fsi < 0); 96: 97: printf("file sys size: "); 98: gets(protos); 99: proto = protos; 100: printf("interleaving factor (m; %d default): ", f_m); 101: gets(buf); 102: if (buf[0]) 103: f_m = atoi(buf); 104: printf("interleaving modulus (n; %d default): ", f_n); 105: gets(buf); 106: if (buf[0]) 107: f_n = atoi(buf); 108: 109: if(f_n <= 0 || f_n >= MAXFN) 110: f_n = MAXFN; 111: if(f_m <= 0 || f_m > f_n) 112: f_m = 3; 113: } 114: fin = NULL; 115: argc = 0; 116: #endif 117: if(fin == NULL) { 118: n = 0; 119: for(f=0; c=proto[f]; f++) { 120: if(c<'0' || c>'9') { 121: printf("%s: cannot open\n", proto); 122: exit(1); 123: } 124: n = n*10 + (c-'0'); 125: } 126: filsys.s_fsize = n; 127: #ifndef UCB_NKB 128: #define CLSIZE 1 129: #endif 130: /* 131: * Minor hack for standalone root and other 132: * small filesystems: reduce ilist size. 133: */ 134: if (n <= 5000/CLSIZE) 135: n = n/50; 136: else 137: n = n/25; 138: if(n <= 0) 139: n = 1; 140: if(n > 65500/NIPB) 141: n = 65500/NIPB; 142: filsys.s_isize = n + 2; 143: printf("isize = %D\n", n*NIPB); 144: charp = "d--777 0 0 $ "; 145: goto f3; 146: } 147: 148: #ifndef STANDALONE 149: /* 150: * get name of boot load program 151: * and read onto block 0 152: */ 153: 154: getstr(); 155: f = open(string, 0); 156: if(f < 0) { 157: printf("%s: cannot open init\n", string); 158: goto f2; 159: } 160: read(f, (char *)&head, sizeof head); 161: if(head.a_magic != A_MAGIC1) { 162: printf("%s: bad format\n", string); 163: goto f1; 164: } 165: c = head.a_text + head.a_data; 166: if(c > BSIZE) { 167: printf("%s: too big\n", string); 168: goto f1; 169: } 170: read(f, buf, c); 171: wtfs((long)0, buf); 172: 173: f1: 174: close(f); 175: 176: /* 177: * get total disk size 178: * and inode block size 179: */ 180: 181: f2: 182: filsys.s_fsize = getnum(); 183: n = getnum(); 184: n /= NIPB; 185: filsys.s_isize = n + 3; 186: 187: #endif 188: f3: 189: if(argc >= 5) { 190: f_m = atoi(argv[3]); 191: f_n = atoi(argv[4]); 192: if(f_n <= 0 || f_n >= MAXFN) 193: f_n = MAXFN; 194: if(f_m <= 0 || f_m > f_n) 195: f_m = 3; 196: } 197: filsys.s_m = f_m; 198: filsys.s_n = f_n; 199: printf("m/n = %d %d\n", f_m, f_n); 200: if(filsys.s_isize >= filsys.s_fsize) { 201: printf("%ld/%ld: bad ratio\n", filsys.s_fsize, filsys.s_isize-2); 202: exit(1); 203: } 204: filsys.s_tfree = 0; 205: filsys.s_tinode = 0; 206: for(c=0; c<BSIZE; c++) 207: buf[c] = 0; 208: for(n=2; n!=filsys.s_isize; n++) { 209: wtfs(n, buf); 210: filsys.s_tinode += NIPB; 211: } 212: ino = 0; 213: 214: bflist(); 215: 216: cfile((struct inode *)0, 0); 217: 218: filsys.s_time = utime; 219: wtfs((long)1, (char *)&filsys); 220: exit(error); 221: } 222: 223: cfile(par, reclevel) 224: struct inode *par; 225: { 226: struct inode in; 227: int dbc, ibc; 228: char db[BSIZE]; 229: daddr_t ib[NINDIR]; 230: int i, f, c; 231: 232: /* 233: * get mode, uid and gid 234: */ 235: 236: getstr(); 237: in.i_mode = gmode(string[0], "-bcd", IFREG, IFBLK, IFCHR, IFDIR); 238: in.i_mode |= gmode(string[1], "-u", 0, ISUID, 0, 0); 239: in.i_mode |= gmode(string[2], "-g", 0, ISGID, 0, 0); 240: for(i=3; i<6; i++) { 241: c = string[i]; 242: if(c<'0' || c>'7') { 243: printf("%c/%s: bad octal mode digit\n", c, string); 244: error = 1; 245: c = 0; 246: } 247: in.i_mode |= (c-'0')<<(15-3*i); 248: } 249: in.i_uid = getnum(); 250: in.i_gid = getnum(); 251: 252: /* 253: * general initialization prior to 254: * switching on format 255: */ 256: 257: ino++; 258: in.i_number = ino; 259: for(i=0; i<BSIZE; i++) 260: db[i] = 0; 261: for(i=0; i<NINDIR; i++) 262: ib[i] = (daddr_t)0; 263: in.i_nlink = 1; 264: in.i_size = 0; 265: for(i=0; i<NADDR; i++) 266: in.i_un.i_addr[i] = (daddr_t)0; 267: if(par == (struct inode *)0) { 268: par = ∈ 269: in.i_nlink--; 270: } 271: dbc = 0; 272: ibc = 0; 273: switch(in.i_mode&IFMT) { 274: 275: case IFREG: 276: /* 277: * regular file 278: * contents is a file name 279: */ 280: 281: getstr(); 282: f = open(string, 0); 283: if(f < 0) { 284: printf("%s: cannot open\n", string); 285: error = 1; 286: break; 287: } 288: while((i=read(f, db, BSIZE)) > 0) { 289: in.i_size += i; 290: newblk(&dbc, db, &ibc, ib); 291: } 292: close(f); 293: break; 294: 295: case IFBLK: 296: case IFCHR: 297: /* 298: * special file 299: * content is maj/min types 300: */ 301: 302: i = getnum() & 0377; 303: f = getnum() & 0377; 304: in.i_un.i_addr[0] = (i<<8) | f; 305: break; 306: 307: case IFDIR: 308: /* 309: * directory 310: * put in extra links 311: * call recursively until 312: * name of "$" found 313: */ 314: 315: par->i_nlink++; 316: in.i_nlink++; 317: entry(in.i_number, ".", &dbc, db, &ibc, ib); 318: entry(par->i_number, "..", &dbc, db, &ibc, ib); 319: in.i_size = 2*sizeof(struct direct); 320: for(;;) { 321: getstr(); 322: if(string[0]=='$' && string[1]=='\0') 323: break; 324: entry(ino+1, string, &dbc, db, &ibc, ib); 325: in.i_size += sizeof(struct direct); 326: cfile(&in, reclevel + 1); 327: } 328: break; 329: } 330: if (reclevel == 0) { 331: entry(ino+1, "lost+found", &dbc, db, &ibc, ib); 332: in.i_size += sizeof(struct direct); 333: mklost(&in); 334: } 335: if(dbc != 0) 336: newblk(&dbc, db, &ibc, ib); 337: iput(&in, &ibc, ib); 338: } 339: 340: /*ARGSUSED*/ 341: /*VARARGS3*/ 342: gmode(c, s, m0, m1, m2, m3) 343: char c, *s; 344: { 345: int i; 346: 347: for(i=0; s[i]; i++) 348: if(c == s[i]) 349: return((&m0)[i]); 350: printf("%c/%s: bad mode\n", c, string); 351: error = 1; 352: return(0); 353: } 354: 355: long 356: getnum() 357: { 358: int i, c; 359: long n; 360: 361: getstr(); 362: n = 0; 363: i = 0; 364: for(i=0; c=string[i]; i++) { 365: if(c<'0' || c>'9') { 366: printf("%s: bad number\n", string); 367: error = 1; 368: return((long)0); 369: } 370: n = n*10 + (c-'0'); 371: } 372: return(n); 373: } 374: 375: getstr() 376: { 377: int i, c; 378: 379: loop: 380: switch(c=getch()) { 381: 382: case ' ': 383: case '\t': 384: case '\n': 385: goto loop; 386: 387: case '\0': 388: printf("EOF\n"); 389: exit(1); 390: 391: case ':': 392: while(getch() != '\n'); 393: goto loop; 394: 395: } 396: i = 0; 397: 398: do { 399: string[i++] = c; 400: c = getch(); 401: } 402: #ifdef STANDALONE 403: while(c!=' '&&c!='\t'&&c!='\n'&&c!='\0'); 404: #else 405: while(c!=' '&&c!='\t'&&c!='\n'&&c!='\0' && c != EOF); 406: #endif 407: string[i] = '\0'; 408: } 409: 410: rdfs(bno, bf) 411: daddr_t bno; 412: char *bf; 413: { 414: int n; 415: 416: lseek(fsi, bno*BSIZE, 0); 417: n = read(fsi, bf, BSIZE); 418: if(n != BSIZE) { 419: printf("read error: %ld\n", bno); 420: exit(1); 421: } 422: } 423: 424: wtfs(bno, bf) 425: daddr_t bno; 426: char *bf; 427: { 428: int n; 429: 430: lseek(fso, bno*BSIZE, 0); 431: n = write(fso, bf, BSIZE); 432: if(n != BSIZE) { 433: printf("write error: %D\n", bno); 434: exit(1); 435: } 436: } 437: 438: daddr_t 439: alloc() 440: { 441: int i; 442: daddr_t bno; 443: 444: filsys.s_tfree--; 445: bno = filsys.s_free[--filsys.s_nfree]; 446: if(bno == 0) { 447: printf("out of free space\n"); 448: exit(1); 449: } 450: if(filsys.s_nfree <= 0) { 451: rdfs(bno, (char *)&fbuf); 452: filsys.s_nfree = fbuf.df_nfree; 453: for(i=0; i<NICFREE; i++) 454: filsys.s_free[i] = fbuf.df_free[i]; 455: } 456: return(bno); 457: } 458: 459: bfree(bno) 460: daddr_t bno; 461: { 462: int i; 463: 464: if (bno != 0) 465: filsys.s_tfree++; 466: if(filsys.s_nfree >= NICFREE) { 467: fbuf.df_nfree = filsys.s_nfree; 468: for(i=0; i<NICFREE; i++) 469: fbuf.df_free[i] = filsys.s_free[i]; 470: wtfs(bno, (char *)&fbuf); 471: filsys.s_nfree = 0; 472: } 473: filsys.s_free[filsys.s_nfree++] = bno; 474: } 475: 476: entry(inum, str, adbc, db, aibc, ib) 477: ino_t inum; 478: char *str; 479: int *adbc, *aibc; 480: char *db; 481: daddr_t *ib; 482: { 483: struct direct *dp; 484: int i; 485: 486: dp = (struct direct *)db; 487: dp += *adbc; 488: (*adbc)++; 489: dp->d_ino = inum; 490: for(i=0; i<DIRSIZ; i++) 491: dp->d_name[i] = 0; 492: for(i=0; i<DIRSIZ; i++) 493: if((dp->d_name[i] = str[i]) == 0) 494: break; 495: if(*adbc >= NDIRECT) 496: newblk(adbc, db, aibc, ib); 497: } 498: 499: newblk(adbc, db, aibc, ib) 500: int *adbc, *aibc; 501: char *db; 502: daddr_t *ib; 503: { 504: int i; 505: daddr_t bno; 506: 507: bno = alloc(); 508: wtfs(bno, db); 509: for(i=0; i<BSIZE; i++) 510: db[i] = 0; 511: *adbc = 0; 512: ib[*aibc] = bno; 513: (*aibc)++; 514: if(*aibc >= NINDIR) { 515: printf("indirect block full\n"); 516: error = 1; 517: *aibc = 0; 518: } 519: } 520: 521: getch() 522: { 523: 524: #ifndef STANDALONE 525: if(charp) 526: #endif 527: return(*charp++); 528: #ifndef STANDALONE 529: return(getc(fin)); 530: #endif 531: } 532: 533: bflist() 534: { 535: struct inode in; 536: daddr_t ib[NINDIR]; 537: int ibc; 538: char flg[MAXFN]; 539: int adr[MAXFN]; 540: int i, j; 541: daddr_t f, d; 542: 543: for(i=0; i<f_n; i++) 544: flg[i] = 0; 545: i = 0; 546: for(j=0; j<f_n; j++) { 547: while(flg[i]) 548: i = (i+1)%f_n; 549: adr[j] = i+1; 550: flg[i]++; 551: i = (i+f_m)%f_n; 552: } 553: 554: ino++; 555: in.i_number = ino; 556: in.i_mode = IFREG; 557: in.i_uid = 0; 558: in.i_gid = 0; 559: in.i_nlink = 0; 560: in.i_size = 0; 561: for(i=0; i<NADDR; i++) 562: in.i_un.i_addr[i] = (daddr_t)0; 563: 564: for(i=0; i<NINDIR; i++) 565: ib[i] = (daddr_t)0; 566: ibc = 0; 567: bfree((daddr_t)0); 568: d = filsys.s_fsize-1; 569: while(d%f_n) 570: d++; 571: for(; d > 0; d -= f_n) 572: for(i=0; i<f_n; i++) { 573: f = d - adr[i]; 574: if(f < filsys.s_fsize && f >= filsys.s_isize) 575: if(badblk(f)) { 576: if(ibc >= NINDIR) { 577: printf("too many bad blocks\n"); 578: error = 1; 579: ibc = 0; 580: } 581: ib[ibc] = f; 582: ibc++; 583: } else 584: bfree(f); 585: } 586: iput(&in, &ibc, ib); 587: } 588: 589: iput(ip, aibc, ib) 590: struct inode *ip; 591: int *aibc; 592: daddr_t *ib; 593: { 594: struct dinode *dp; 595: daddr_t d; 596: int i; 597: 598: filsys.s_tinode--; 599: d = itod(ip->i_number); 600: if(d >= filsys.s_isize) { 601: if(error == 0) 602: printf("ilist too small\n"); 603: error = 1; 604: return; 605: } 606: rdfs(d, buf); 607: dp = (struct dinode *)buf; 608: dp += itoo(ip->i_number); 609: 610: dp->di_mode = ip->i_mode; 611: dp->di_nlink = ip->i_nlink; 612: dp->di_uid = ip->i_uid; 613: dp->di_gid = ip->i_gid; 614: dp->di_size = ip->i_size; 615: dp->di_atime = utime; 616: dp->di_mtime = utime; 617: dp->di_ctime = utime; 618: 619: switch(ip->i_mode&IFMT) { 620: 621: case IFDIR: 622: case IFREG: 623: for(i=0; i<*aibc; i++) { 624: if(i >= LADDR) 625: break; 626: ip->i_un.i_addr[i] = ib[i]; 627: } 628: if(*aibc >= LADDR) { 629: ip->i_un.i_addr[LADDR] = alloc(); 630: for(i=0; i<NINDIR-LADDR; i++) { 631: ib[i] = ib[i+LADDR]; 632: ib[i+LADDR] = (daddr_t)0; 633: } 634: wtfs(ip->i_un.i_addr[LADDR], (char *)ib); 635: } 636: 637: case IFBLK: 638: case IFCHR: 639: ltol3(dp->di_addr, ip->i_un.i_addr, NADDR); 640: break; 641: 642: default: 643: printf("bad mode %o\n", ip->i_mode); 644: exit(1); 645: } 646: wtfs(d, buf); 647: } 648: 649: /*ARGSUSED*/ 650: badblk(bno) 651: daddr_t bno; 652: { 653: return(0); 654: } 655: 656: mklost(par) 657: struct inode *par; 658: { 659: struct inode in; 660: int dbc, ibc; 661: char db[BSIZE]; 662: daddr_t ib[NINDIR]; 663: int i; 664: 665: in.i_mode = IFDIR | ISVTX | 0777; 666: in.i_uid = 0; 667: in.i_gid = 0; 668: in.i_number = ++ino; 669: for (i = 0; i < BSIZE; i++) 670: db[i] = 0; 671: for (i = 0; i < NINDIR; i++) 672: ib[i] = (daddr_t) 0; 673: for (i = 0; i < NADDR; i++) 674: in.i_un.i_addr[i] = (daddr_t) 0; 675: dbc = 0; 676: ibc = 0; 677: in.i_nlink = 2; 678: /* 679: * blocks 0, ..., NADDR - 4 680: * are direct blocks 681: */ 682: in.i_size = (off_t) (BSIZE * (NADDR - 4 + 1)); 683: par->i_nlink++; 684: entry(in.i_number, ".", &dbc, db, &ibc, ib); 685: entry(par->i_number, "..", &dbc, db, &ibc, ib); 686: for (i = 0; i < NADDR - 4 + 1; i++) 687: newblk(&dbc, db, &ibc, ib); 688: iput(&in, &ibc, ib); 689: }