| 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 | } |