1 static char *sccsid = "@(#)mkfs.c 1.5 (Berkeley) 09/19/81"; 2 3 /* 4 * make file system for cylinder-group style file systems 5 * 6 * usage: mkfs fs proto 7 * or: mkfs size [ nsect ntrak cpg ] 8 */ 9 10 #define NDIRECT (BSIZE/sizeof(struct direct)) 11 #define MAXFN 500 12 13 #ifndef STANDALONE 14 #include <stdio.h> 15 #include <a.out.h> 16 #endif 17 18 #include "../h/param.h" 19 #include "../h/inode.h" 20 #include "../h/fs.h" 21 #include "../h/dir.h" 22 23 time_t utime; 24 25 #ifndef STANDALONE 26 FILE *fin; 27 #else 28 int fin; 29 #endif 30 31 int fsi; 32 int fso; 33 char *charp; 34 char buf[BSIZE]; 35 #ifndef STANDALONE 36 struct exec head; 37 #endif 38 char string[50]; 39 40 union { 41 struct fs fs; 42 char pad[BSIZE]; 43 } fsun; 44 #define sblock fsun.fs 45 struct csum *fscs; 46 47 union { 48 struct cg cg; 49 char pad[BSIZE]; 50 } cgun; 51 #define acg cgun.cg 52 53 #define howmany(x, y) (((x)+((y)-1))/(y)) 54 #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) 55 56 char *fsys; 57 char *proto; 58 int error; 59 ino_t ino = ROOTINO - 1; 60 long getnum(); 61 daddr_t alloc(); 62 63 struct dinode zino[MAXIPG]; 64 65 main(argc, argv) 66 char *argv[]; 67 { 68 int f, c; 69 long i,n; 70 71 argc--, argv++; 72 #ifndef STANDALONE 73 time(&utime); 74 if(argc < 2) { 75 printf("usage: mkfs sblock proto/size [ nsect ntrak cpg ]\n"); 76 exit(1); 77 } 78 fsys = argv[0]; 79 proto = argv[1]; 80 #else 81 { 82 static char protos[60]; 83 84 printf("file sys size: "); 85 gets(protos); 86 proto = protos; 87 } 88 #endif 89 #ifdef STANDALONE 90 { 91 char fsbuf[100]; 92 93 do { 94 printf("file system: "); 95 gets(fsbuf); 96 fso = open(fsbuf, 1); 97 fsi = open(fsbuf, 0); 98 } while (fso < 0 || fsi < 0); 99 } 100 fin = NULL; 101 argc = 0; 102 #else 103 fso = creat(fsys, 0666); 104 if(fso < 0) { 105 printf("%s: cannot create\n", fsys); 106 exit(1); 107 } 108 fsi = open(fsys, 0); 109 if(fsi < 0) { 110 printf("%s: cannot open\n", fsys); 111 exit(1); 112 } 113 fin = fopen(proto, "r"); 114 #endif 115 #ifndef STANDALONE 116 if (fin != NULL) { 117 getstr(); 118 f = open(string, 0); 119 if (f < 0) { 120 printf("%s: cannot open init\n", string); 121 goto noinit; 122 } 123 read(f, (char *)&head, sizeof head); 124 c = head.a_text + head.a_data; 125 if (c > BSIZE) 126 printf("%s: too big\n", string); 127 else { 128 read(f, buf, c); 129 wtfs(BBLOCK, BSIZE, buf); 130 } 131 close(f); 132 noinit: 133 n = sblock.fs_size = getnum(); 134 sblock.fs_ntrak = getnum(); 135 sblock.fs_nsect = getnum(); 136 sblock.fs_cpg = getnum(); 137 } else 138 #endif 139 { 140 charp = "d--777 0 0 $ "; 141 n = 0; 142 for (f=0; c=proto[f]; f++) { 143 if (c<'0' || c>'9') { 144 printf("%s: cannot open\n", proto); 145 exit(1); 146 } 147 n = n*10 + (c-'0'); 148 } 149 sblock.fs_size = n; 150 if (argc > 2) 151 sblock.fs_nsect = atoi(argv[2]); 152 else 153 sblock.fs_nsect = 32; 154 if (argc > 3) 155 sblock.fs_ntrak = atoi(argv[3]); 156 else 157 sblock.fs_ntrak = 19; 158 } 159 /* 160 * Now have size for file system and nsect and ntrak. 161 * (And, if coming from prototype, cpg). 162 * Determine number of cylinders occupied by file system. 163 */ 164 if (sblock.fs_ntrak <= 0) 165 printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(1); 166 if (sblock.fs_nsect <= 0) 167 printf("preposterous nsect %d\n", sblock.fs_nsect), exit(1); 168 if (sblock.fs_size <= 0) 169 printf("preposterous size %d\n", sblock.fs_size), exit(1); 170 if (sblock.fs_ntrak * sblock.fs_nsect > MAXBPG * NSPB) { 171 printf("cylinder too large (%d sectors)\n", 172 sblock.fs_ntrak * sblock.fs_nsect); 173 printf("maximum cylinder size: %d sectors\n", 174 MAXBPG * NSPB); 175 exit(1); 176 } 177 sblock.fs_ncyl = n * NSPF / (sblock.fs_nsect * sblock.fs_ntrak); 178 if (n * NSPF > sblock.fs_ncyl * sblock.fs_nsect * sblock.fs_ntrak) { 179 printf("%d sector(s) in last cylinder unused\n", 180 n * NSPF - sblock.fs_ncyl * sblock.fs_nsect * sblock.fs_ntrak); 181 sblock.fs_ncyl++; 182 } 183 sblock.fs_magic = FS_MAGIC; 184 /* 185 * Validate specified/determined cpg. 186 */ 187 #define CGTOOBIG(fs) ((fs).fs_nsect*(fs).fs_ntrak*(fs).fs_cpg/NSPB > MAXBPG) 188 if (argc > 4 || fin) { 189 if (fin == NULL) 190 sblock.fs_cpg = atoi(argv[4]); 191 if (CGTOOBIG(sblock)) { 192 printf("cylinder group too large (%d blocks); ", 193 sblock.fs_cpg * sblock.fs_nsect * sblock.fs_ntrak / NSPB); 194 printf("max: %d blocks\n", MAXBPG); 195 exit(1); 196 } 197 if (sblock.fs_cpg > MAXCPG) { 198 printf("cylinder groups are limited to %d cylinders\n", 199 MAXCPG); 200 exit(1); 201 } 202 } else { 203 sblock.fs_cpg = DESCPG; 204 while (CGTOOBIG(sblock)) 205 --sblock.fs_cpg; 206 } 207 /* 208 * Compute/validate number of cylinder groups. 209 */ 210 sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg; 211 if (sblock.fs_ncyl % sblock.fs_cpg) 212 sblock.fs_ncg++; 213 if ((sblock.fs_nsect*sblock.fs_ntrak*sblock.fs_cpg) % NSPF) { 214 printf("mkfs: nsect %d, ntrak %d, cpg %d is not tolerable\n", 215 sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_cpg); 216 printf("as this would would have cyl groups whose size\n"); 217 printf("is not a multiple of %d; choke!\n", FSIZE); 218 exit(1); 219 } 220 fscs = (struct csum *) 221 calloc(1, roundup(sblock.fs_ncg * sizeof (struct csum), BSIZE)); 222 /* 223 * Compute number of inode blocks per cylinder group. 224 * Start with one inode per NBPI bytes; adjust as necessary. 225 */ 226 n = ((n * BSIZE) / NBPI) / INOPB; 227 if (n <= 0) 228 n = 1; 229 if (n > 65500/INOPB) 230 n = 65500/INOPB; 231 sblock.fs_ipg = ((n / sblock.fs_ncg) + 1) * INOPB; 232 if (sblock.fs_ipg < INOPB) 233 sblock.fs_ipg = INOPB; 234 if (sblock.fs_ipg > MAXIPG) 235 sblock.fs_ipg = MAXIPG; 236 while (sblock.fs_ipg * sblock.fs_ncyl > 65500) 237 sblock.fs_ipg -= INOPB; 238 sblock.fs_spc = sblock.fs_ntrak * sblock.fs_nsect; 239 sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / (FSIZE / 512); 240 if (cgdmin(0,&sblock) >= sblock.fs_fpg) 241 printf("inode blocks/cyl group (%d) >= data blocks (%d)\n", 242 cgdmin(0,&sblock)/FRAG, sblock.fs_fpg/FRAG), exit(1); 243 sblock.fs_nifree = sblock.fs_ipg * sblock.fs_ncg; 244 sblock.fs_cgsize = cgsize(&sblock); 245 sblock.fs_cssize = cssize(&sblock); 246 sblock.fs_sblkno = SBLOCK; 247 sblock.fs_fmod = 0; 248 sblock.fs_ronly = 0; 249 250 /* 251 * Dump out information about file system. 252 */ 253 printf("%s:\t%d sectors in %d cylinders of %d tracks, %d sectors\n", 254 fsys, sblock.fs_size*NSPF, sblock.fs_ncyl, sblock.fs_ntrak, sblock.fs_nsect); 255 printf("\t%.1fMb in %d cyl groups (%d c/g, %.2fMb/g, %d i/g)\n", 256 (float)sblock.fs_size*FSIZE*1e-6, sblock.fs_ncg, sblock.fs_cpg, 257 (float)sblock.fs_fpg*FSIZE*1e-6, sblock.fs_ipg); 258 /* 259 printf("%7d size (%d blocks)\n", sblock.fs_size, sblock.fs_size/FRAG); 260 printf("%7d cylinder groups\n", sblock.fs_ncg); 261 printf("%7d cylinder group block size\n", sblock.fs_cgsize); 262 printf("%7d tracks\n", sblock.fs_ntrak); 263 printf("%7d sectors\n", sblock.fs_nsect); 264 printf("%7d sectors per cylinder\n", sblock.fs_spc); 265 printf("%7d cylinders\n", sblock.fs_ncyl); 266 printf("%7d cylinders per group\n", sblock.fs_cpg); 267 printf("%7d blocks per group\n", sblock.fs_fpg/FRAG); 268 printf("%7d inodes per group\n", sblock.fs_ipg); 269 if (sblock.fs_ncyl % sblock.fs_cpg) { 270 printf("%7d cylinders in last group\n", 271 i = sblock.fs_ncyl % sblock.fs_cpg); 272 printf("%7d blocks in last group\n", 273 i * sblock.fs_spc / NSPB); 274 } 275 */ 276 /* 277 * Now build the cylinders group blocks and 278 * then print out indices of cylinder groups forwarded 279 * past bad blocks or other obstructions. 280 */ 281 sblock.fs_nffree = 0; 282 sblock.fs_nbfree = 0; 283 for (c = 0; c < sblock.fs_ncg; c++) 284 initcg(c); 285 printf("\tsuper-block backups (for fsck -b#) at %d+k*%d (%d .. %d)\n", 286 SBLOCK, sblock.fs_fpg, SBLOCK+sblock.fs_fpg, 287 SBLOCK+(sblock.fs_ncg-1)*sblock.fs_fpg); 288 /* 289 * Now construct the initial file system, and 290 * then write out the super-block. 291 */ 292 cfile((struct inode *)0); 293 sblock.fs_time = utime; 294 wtfs(SBLOCK, BSIZE, (char *)&sblock); 295 for (i = 0; i < cssize(&sblock); i += BSIZE) 296 wtfs(csaddr(&sblock) + i/BSIZE, BSIZE, ((char *)fscs)+i); 297 for (c = 0; c < sblock.fs_ncg; c++) 298 wtfs(cgsblock(c, &sblock), BSIZE, (char *)&sblock); 299 #ifndef STANDALONE 300 exit(error); 301 #endif 302 } 303 304 /* 305 * Initialize a cylinder group. 306 */ 307 initcg(c) 308 int c; 309 { 310 daddr_t cbase, d, dmin, dmax; 311 long i, j, s; 312 register struct csum *cs; 313 314 /* 315 * Determine block bounds for cylinder group. 316 * Allow space for super block summary information in first 317 * cylinder group. 318 */ 319 cbase = cgbase(c,&sblock); 320 dmax = cbase + sblock.fs_fpg; 321 if (dmax > sblock.fs_size) 322 dmax = sblock.fs_size; 323 d = cbase; 324 cs = fscs+c; 325 cs->cs_ndir = 0; 326 acg.cg_time = utime; 327 acg.cg_magic = CG_MAGIC; 328 acg.cg_cgx = c; 329 acg.cg_ncyl = sblock.fs_cpg; 330 acg.cg_niblk = sblock.fs_ipg; 331 acg.cg_ndblk = dmax - cbase; 332 acg.cg_ndir = 0; 333 acg.cg_nffree = 0; 334 acg.cg_nbfree = 0; 335 acg.cg_nifree = 0; 336 acg.cg_rotor = 0; 337 acg.cg_irotor = 0; 338 i = 0; 339 d = cgimin(c,&sblock); 340 while (i < sblock.fs_ipg) { 341 for (j = INOPB; j > 0; j--) { 342 clrbit(acg.cg_iused, i); 343 i++; 344 } 345 acg.cg_nifree += INOPB; 346 d++; 347 } 348 while (i < MAXIPG) { 349 clrbit(acg.cg_iused, i); 350 i++; 351 } 352 lseek(fso, cgimin(c,&sblock)*FSIZE, 0); 353 if (write(fso, (char *)zino, sblock.fs_ipg * sizeof (struct dinode)) != 354 sblock.fs_ipg * sizeof (struct dinode)) 355 printf("write error %D\n", tell(fso) / BSIZE); 356 for (i = 0; i < MAXCPG; i++) 357 for (j = 0; j < NRPOS; j++) 358 acg.cg_b[i][j] = 0; 359 dmin = cgdmin(c,&sblock) - cbase; 360 if (c == 0) { 361 dmin += howmany(cssize(&sblock), BSIZE) * FRAG; 362 } 363 for (d = 0; d < dmin; d += FRAG) 364 clrblock(acg.cg_free, d/FRAG); 365 while ((d+FRAG) <= dmax - cbase) { 366 setblock(acg.cg_free, d/FRAG); 367 acg.cg_nbfree++; 368 s = d * NSPF; 369 acg.cg_b[s/sblock.fs_spc] 370 [s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]++; 371 d += FRAG; 372 } 373 if (d < dmax - cbase) 374 for (; d < dmax - cbase; d++) { 375 setbit(acg.cg_free, d); 376 acg.cg_nffree++; 377 } 378 for (; d < MAXBPG; d++) 379 clrbit(acg.cg_free, d); 380 sblock.fs_nffree += acg.cg_nffree; 381 sblock.fs_nbfree += acg.cg_nbfree; 382 cs->cs_nifree = acg.cg_nifree; 383 cs->cs_nbfree = acg.cg_nbfree; 384 wtfs(cgtod(c, &sblock), BSIZE, (char *)&acg); 385 } 386 387 cfile(par) 388 struct inode *par; 389 { 390 struct inode in; 391 int dbc, ibc; 392 char db[BSIZE]; 393 daddr_t ib[NINDIR]; 394 int i, f, c; 395 396 /* 397 * get mode, uid and gid 398 */ 399 400 getstr(); 401 in.i_mode = gmode(string[0], "-bcd", IFREG, IFBLK, IFCHR, IFDIR); 402 in.i_mode |= gmode(string[1], "-u", 0, ISUID, 0, 0); 403 in.i_mode |= gmode(string[2], "-g", 0, ISGID, 0, 0); 404 for(i=3; i<6; i++) { 405 c = string[i]; 406 if(c<'0' || c>'7') { 407 printf("%c/%s: bad octal mode digit\n", c, string); 408 error = 1; 409 c = 0; 410 } 411 in.i_mode |= (c-'0')<<(15-3*i); 412 } 413 in.i_uid = getnum(); 414 in.i_gid = getnum(); 415 in.i_atime = utime; 416 in.i_mtime = utime; 417 in.i_ctime = utime; 418 419 /* 420 * general initialization prior to 421 * switching on format 422 */ 423 424 ino++; 425 in.i_number = ino; 426 for(i=0; i<BSIZE; i++) 427 db[i] = 0; 428 for(i=0; i<NINDIR; i++) 429 ib[i] = (daddr_t)0; 430 in.i_nlink = 1; 431 in.i_size = 0; 432 for(i=0; i<NDADDR; i++) 433 in.i_db[i] = (daddr_t)0; 434 for(i=0; i<NIADDR; i++) 435 in.i_ib[i] = (daddr_t)0; 436 if(par == (struct inode *)0) { 437 par = ∈ 438 in.i_nlink--; 439 } 440 dbc = 0; 441 ibc = 0; 442 switch(in.i_mode&IFMT) { 443 444 case IFREG: 445 /* 446 * regular file 447 * contents is a file name 448 */ 449 450 getstr(); 451 f = open(string, 0); 452 if(f < 0) { 453 printf("%s: cannot open\n", string); 454 error = 1; 455 break; 456 } 457 while((i=read(f, db, BSIZE)) > 0) { 458 in.i_size += i; 459 newblk(&dbc, db, &ibc, ib, BSIZE); 460 } 461 close(f); 462 break; 463 464 case IFBLK: 465 case IFCHR: 466 /* 467 * special file 468 * content is maj/min types 469 */ 470 471 i = getnum() & 0377; 472 f = getnum() & 0377; 473 in.i_rdev = makedev(i, f); 474 break; 475 476 case IFDIR: 477 /* 478 * directory 479 * put in extra links 480 * call recursively until 481 * name of "$" found 482 */ 483 484 par->i_nlink++; 485 in.i_nlink++; 486 entry(in.i_number, ".", &dbc, db, &ibc, ib); 487 entry(par->i_number, "..", &dbc, db, &ibc, ib); 488 in.i_size = 2*sizeof(struct direct); 489 for(;;) { 490 getstr(); 491 if(string[0]=='$' && string[1]=='\0') 492 break; 493 if (in.i_size >= FSIZE) { 494 printf("can't handle direct of > %d entries\n", 495 NDIRECT/FRAG); 496 exit(1); 497 } 498 entry(ino+1, string, &dbc, db, &ibc, ib); 499 in.i_size += sizeof(struct direct); 500 cfile(&in); 501 } 502 break; 503 } 504 if(dbc != 0) 505 newblk(&dbc, db, &ibc, ib, roundup(dbc,BSIZE)); 506 iput(&in, &ibc, ib); 507 } 508 509 gmode(c, s, m0, m1, m2, m3) 510 char c, *s; 511 { 512 int i; 513 514 for(i=0; s[i]; i++) 515 if(c == s[i]) 516 return((&m0)[i]); 517 printf("%c/%s: bad mode\n", c, string); 518 error = 1; 519 return(0); 520 } 521 522 long 523 getnum() 524 { 525 int i, c; 526 long n; 527 528 getstr(); 529 n = 0; 530 i = 0; 531 for(i=0; c=string[i]; i++) { 532 if(c<'0' || c>'9') { 533 printf("%s: bad number\n", string); 534 error = 1; 535 return((long)0); 536 } 537 n = n*10 + (c-'0'); 538 } 539 return(n); 540 } 541 542 getstr() 543 { 544 int i, c; 545 546 loop: 547 switch(c=getch()) { 548 549 case ' ': 550 case '\t': 551 case '\n': 552 goto loop; 553 554 case '\0': 555 printf("EOF\n"); 556 exit(1); 557 558 case ':': 559 while(getch() != '\n'); 560 goto loop; 561 562 } 563 i = 0; 564 565 do { 566 string[i++] = c; 567 c = getch(); 568 } while(c!=' '&&c!='\t'&&c!='\n'&&c!='\0'); 569 string[i] = '\0'; 570 } 571 572 rdfs(bno, size, bf) 573 daddr_t bno; 574 int size; 575 char *bf; 576 { 577 int n; 578 579 lseek(fsi, bno*FSIZE, 0); 580 n = read(fsi, bf, size); 581 if(n != size) { 582 printf("read error: %ld\n", bno); 583 exit(1); 584 } 585 } 586 587 wtfs(bno, size, bf) 588 daddr_t bno; 589 int size; 590 char *bf; 591 { 592 int n; 593 594 lseek(fso, bno*FSIZE, 0); 595 n = write(fso, bf, size); 596 if(n != size) { 597 printf("write error: %D\n", bno); 598 exit(1); 599 } 600 } 601 602 daddr_t 603 alloc(size) 604 int size; 605 { 606 int c, i, s, frag; 607 daddr_t d; 608 609 c = 0; 610 rdfs(cgtod(0,&sblock), sblock.fs_cgsize, (char *)&acg); 611 if (acg.cg_nbfree == 0) { 612 printf("first cylinder group ran out of space\n"); 613 return (0); 614 } 615 for (d = 0; d < acg.cg_ndblk; d += FRAG) 616 if (isblock(acg.cg_free, d/FRAG)) 617 goto goth; 618 printf("internal error: can't find block in cyl 0\n"); 619 return (0); 620 goth: 621 clrblock(acg.cg_free, d/FRAG); 622 acg.cg_nbfree--; 623 sblock.fs_nbfree--; 624 fscs[0].cs_nbfree--; 625 s = d * NSPF; 626 acg.cg_b[s/sblock.fs_spc][s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]--; 627 if (size != BSIZE) { 628 frag = howmany(size, FSIZE); 629 acg.cg_nffree += FRAG - frag; 630 sblock.fs_nffree += FRAG - frag; 631 for (i = frag; i < FRAG; i++) 632 setbit(acg.cg_free, d+i); 633 } 634 wtfs(cgtod(0,&sblock), sblock.fs_cgsize, (char *)&acg); 635 return (d); 636 } 637 638 entry(inum, str, adbc, db, aibc, ib) 639 ino_t inum; 640 char *str; 641 int *adbc, *aibc; 642 char *db; 643 daddr_t *ib; 644 { 645 struct direct *dp; 646 int i; 647 648 dp = (struct direct *)db; 649 dp += *adbc; 650 (*adbc)++; 651 dp->d_ino = inum; 652 for(i=0; i<DIRSIZ; i++) 653 dp->d_name[i] = 0; 654 for(i=0; i<DIRSIZ; i++) 655 if((dp->d_name[i] = str[i]) == 0) 656 break; 657 if(*adbc >= NDIRECT) 658 newblk(adbc, db, aibc, ib, BSIZE); 659 } 660 661 newblk(adbc, db, aibc, ib, size) 662 int *adbc, *aibc; 663 char *db; 664 daddr_t *ib; 665 int size; 666 { 667 int i; 668 daddr_t bno; 669 670 bno = alloc(size); 671 wtfs(bno, size, db); 672 for(i=0; i<size; i++) 673 db[i] = 0; 674 *adbc = 0; 675 ib[*aibc] = bno; 676 (*aibc)++; 677 if(*aibc >= NINDIR) { 678 printf("indirect block full\n"); 679 error = 1; 680 *aibc = 0; 681 } 682 } 683 684 getch() 685 { 686 687 #ifndef STANDALONE 688 if(charp) 689 #endif 690 return(*charp++); 691 #ifndef STANDALONE 692 return(getc(fin)); 693 #endif 694 } 695 696 iput(ip, aibc, ib) 697 struct inode *ip; 698 int *aibc; 699 daddr_t *ib; 700 { 701 struct dinode *dp; 702 daddr_t d; 703 int i, c = ip->i_number / sblock.fs_ipg; 704 705 rdfs(cgtod(c,&sblock), sblock.fs_cgsize, (char *)&acg); 706 acg.cg_nifree--; 707 setbit(acg.cg_iused, ip->i_number); 708 wtfs(cgtod(c,&sblock), sblock.fs_cgsize, (char *)&acg); 709 sblock.fs_nifree--; 710 fscs[0].cs_nifree--; 711 if(ip->i_number >= sblock.fs_ipg) { 712 printf("mkfs: cant handle more than one cg of inodes (yet)\n"); 713 exit(1); 714 } 715 if(ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) { 716 if(error == 0) 717 printf("ilist too small\n"); 718 error = 1; 719 return; 720 } 721 d = itod(ip->i_number,&sblock); 722 rdfs(d, BSIZE, buf); 723 for(i=0; i<*aibc; i++) { 724 if(i >= NDADDR) 725 break; 726 ip->i_db[i] = ib[i]; 727 } 728 if(*aibc >= NDADDR) { 729 ip->i_ib[0] = alloc(BSIZE); 730 for(i=0; i<NINDIR-NDADDR; i++) { 731 ib[i] = ib[i+NDADDR]; 732 ib[i+NDADDR] = (daddr_t)0; 733 } 734 wtfs(ip->i_ib[0], (char *)ib); 735 } 736 ((struct dinode *)buf+itoo(ip->i_number))->di_ic = ip->i_ic; 737 wtfs(d, BSIZE, buf); 738 } 739