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