1 /* $NetBSD: mkfs.c,v 1.64 2002/04/10 17:28:13 mycroft Exp $ */ 2 3 /* 4 * Copyright (c) 1980, 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <sys/cdefs.h> 37 #ifndef lint 38 #if 0 39 static char sccsid[] = "@(#)mkfs.c 8.11 (Berkeley) 5/3/95"; 40 #else 41 __RCSID("$NetBSD: mkfs.c,v 1.64 2002/04/10 17:28:13 mycroft Exp $"); 42 #endif 43 #endif /* not lint */ 44 45 #include <sys/param.h> 46 #include <sys/mman.h> 47 #include <sys/time.h> 48 #include <sys/resource.h> 49 #include <ufs/ufs/dinode.h> 50 #include <ufs/ufs/dir.h> 51 #include <ufs/ufs/ufs_bswap.h> 52 #include <ufs/ffs/fs.h> 53 #include <ufs/ffs/ffs_extern.h> 54 #include <sys/disklabel.h> 55 56 #include <err.h> 57 #include <errno.h> 58 #include <string.h> 59 #include <unistd.h> 60 #include <stdlib.h> 61 62 #ifndef STANDALONE 63 #include <stdio.h> 64 #endif 65 66 #include "extern.h" 67 68 static void initcg(int, time_t); 69 static int fsinit(time_t, mode_t, uid_t, gid_t); 70 static int makedir(struct direct *, int); 71 static daddr_t alloc(int, int); 72 static void iput(struct dinode *, ino_t); 73 static void rdfs(daddr_t, int, void *); 74 static void wtfs(daddr_t, int, void *); 75 static int isblock(struct fs *, unsigned char *, int); 76 static void clrblock(struct fs *, unsigned char *, int); 77 static void setblock(struct fs *, unsigned char *, int); 78 static int32_t calcipg(int32_t, int32_t, off_t *); 79 static void swap_cg(struct cg *, struct cg *); 80 #ifdef MFS 81 static void calc_memfree(void); 82 static void *mkfs_malloc(size_t size); 83 #endif 84 85 static int count_digits(int); 86 87 /* 88 * make file system for cylinder-group style file systems 89 */ 90 91 /* 92 * We limit the size of the inode map to be no more than a 93 * third of the cylinder group space, since we must leave at 94 * least an equal amount of space for the block map. 95 * 96 * N.B.: MAXIPG must be a multiple of INOPB(fs). 97 */ 98 #define MAXIPG(fs) roundup((fs)->fs_bsize * NBBY / 3, INOPB(fs)) 99 100 #define UMASK 0755 101 #define MAXINOPB (MAXBSIZE / DINODE_SIZE) 102 #define POWEROF2(num) (((num) & ((num) - 1)) == 0) 103 104 union { 105 struct fs fs; 106 char pad[SBSIZE]; 107 } fsun; 108 #define sblock fsun.fs 109 struct csum *fscs; 110 111 union { 112 struct cg cg; 113 char pad[MAXBSIZE]; 114 } cgun; 115 #define acg cgun.cg 116 117 struct dinode zino[MAXBSIZE / DINODE_SIZE]; 118 119 char writebuf[MAXBSIZE]; 120 121 int fsi, fso; 122 123 void 124 mkfs(struct partition *pp, const char *fsys, int fi, int fo, 125 mode_t mfsmode, uid_t mfsuid, gid_t mfsgid) 126 { 127 int32_t i, mincpc, mincpg, inospercg; 128 int32_t cylno, rpos, blk, j, warning = 0; 129 int32_t used, mincpgcnt, bpcg; 130 off_t usedb; 131 int32_t mapcramped, inodecramped; 132 int32_t postblsize, rotblsize, totalsbsize; 133 time_t utime; 134 long long sizepb; 135 char *writebuf2; /* dynamic buffer */ 136 int nprintcols, printcolwidth; 137 138 #ifndef STANDALONE 139 time(&utime); 140 #endif 141 #ifdef MFS 142 if (mfs) { 143 calc_memfree(); 144 if (fssize * sectorsize > memleft) 145 fssize = memleft / sectorsize; 146 if ((membase = mkfs_malloc(fssize * sectorsize)) == 0) 147 exit(12); 148 } 149 #endif 150 fsi = fi; 151 fso = fo; 152 if (Oflag) { 153 sblock.fs_inodefmt = FS_42INODEFMT; 154 sblock.fs_maxsymlinklen = 0; 155 } else { 156 sblock.fs_inodefmt = FS_44INODEFMT; 157 sblock.fs_maxsymlinklen = MAXSYMLINKLEN; 158 } 159 /* 160 * Validate the given file system size. 161 * Verify that its last block can actually be accessed. 162 */ 163 if (fssize <= 0) 164 printf("preposterous size %d\n", fssize), exit(13); 165 wtfs(fssize - 1, sectorsize, (char *)&sblock); 166 167 /* 168 * collect and verify the sector and track info 169 */ 170 sblock.fs_nsect = nsectors; 171 sblock.fs_ntrak = ntracks; 172 if (sblock.fs_ntrak <= 0) 173 printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(14); 174 if (sblock.fs_nsect <= 0) 175 printf("preposterous nsect %d\n", sblock.fs_nsect), exit(15); 176 /* 177 * collect and verify the filesystem density info 178 */ 179 sblock.fs_avgfilesize = avgfilesize; 180 sblock.fs_avgfpdir = avgfpdir; 181 if (sblock.fs_avgfilesize <= 0) 182 printf("illegal expected average file size %d\n", 183 sblock.fs_avgfilesize), exit(14); 184 if (sblock.fs_avgfpdir <= 0) 185 printf("illegal expected number of files per directory %d\n", 186 sblock.fs_avgfpdir), exit(15); 187 /* 188 * collect and verify the block and fragment sizes 189 */ 190 sblock.fs_bsize = bsize; 191 sblock.fs_fsize = fsize; 192 if (!POWEROF2(sblock.fs_bsize)) { 193 printf("block size must be a power of 2, not %d\n", 194 sblock.fs_bsize); 195 exit(16); 196 } 197 if (!POWEROF2(sblock.fs_fsize)) { 198 printf("fragment size must be a power of 2, not %d\n", 199 sblock.fs_fsize); 200 exit(17); 201 } 202 if (sblock.fs_fsize < sectorsize) { 203 printf("fragment size %d is too small, minimum is %d\n", 204 sblock.fs_fsize, sectorsize); 205 exit(18); 206 } 207 if (sblock.fs_bsize < MINBSIZE) { 208 printf("block size %d is too small, minimum is %d\n", 209 sblock.fs_bsize, MINBSIZE); 210 exit(19); 211 } 212 if (sblock.fs_bsize > MAXBSIZE) { 213 printf("block size %d is too large, maximum is %d\n", 214 sblock.fs_bsize, MAXBSIZE); 215 exit(19); 216 } 217 if (sblock.fs_bsize < sblock.fs_fsize) { 218 printf("block size (%d) cannot be smaller than fragment size (%d)\n", 219 sblock.fs_bsize, sblock.fs_fsize); 220 exit(20); 221 } 222 sblock.fs_bmask = ~(sblock.fs_bsize - 1); 223 sblock.fs_fmask = ~(sblock.fs_fsize - 1); 224 sblock.fs_qbmask = ~sblock.fs_bmask; 225 sblock.fs_qfmask = ~sblock.fs_fmask; 226 for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1) 227 sblock.fs_bshift++; 228 for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1) 229 sblock.fs_fshift++; 230 sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize); 231 for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1) 232 sblock.fs_fragshift++; 233 if (sblock.fs_frag > MAXFRAG) { 234 printf("fragment size %d is too small, " 235 "minimum with block size %d is %d\n", 236 sblock.fs_fsize, sblock.fs_bsize, 237 sblock.fs_bsize / MAXFRAG); 238 exit(21); 239 } 240 sblock.fs_nrpos = nrpos; 241 sblock.fs_nindir = sblock.fs_bsize / sizeof(daddr_t); 242 sblock.fs_inopb = sblock.fs_bsize / DINODE_SIZE; 243 sblock.fs_nspf = sblock.fs_fsize / sectorsize; 244 for (sblock.fs_fsbtodb = 0, i = NSPF(&sblock); i > 1; i >>= 1) 245 sblock.fs_fsbtodb++; 246 sblock.fs_sblkno = 247 roundup(howmany(bbsize + sbsize, sblock.fs_fsize), sblock.fs_frag); 248 sblock.fs_cblkno = (daddr_t)(sblock.fs_sblkno + 249 roundup(howmany(sbsize, sblock.fs_fsize), sblock.fs_frag)); 250 sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag; 251 sblock.fs_cgoffset = roundup( 252 howmany(sblock.fs_nsect, NSPF(&sblock)), sblock.fs_frag); 253 for (sblock.fs_cgmask = 0xffffffff, i = sblock.fs_ntrak; i > 1; i >>= 1) 254 sblock.fs_cgmask <<= 1; 255 if (!POWEROF2(sblock.fs_ntrak)) 256 sblock.fs_cgmask <<= 1; 257 sblock.fs_maxfilesize = sblock.fs_bsize * NDADDR - 1; 258 for (sizepb = sblock.fs_bsize, i = 0; i < NIADDR; i++) { 259 sizepb *= NINDIR(&sblock); 260 sblock.fs_maxfilesize += sizepb; 261 } 262 /* 263 * Validate specified/determined secpercyl 264 * and calculate minimum cylinders per group. 265 */ 266 sblock.fs_spc = secpercyl; 267 for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc; 268 sblock.fs_cpc > 1 && (i & 1) == 0; 269 sblock.fs_cpc >>= 1, i >>= 1) 270 /* void */; 271 mincpc = sblock.fs_cpc; 272 bpcg = sblock.fs_spc * sectorsize; 273 inospercg = roundup(bpcg / DINODE_SIZE, INOPB(&sblock)); 274 if (inospercg > MAXIPG(&sblock)) 275 inospercg = MAXIPG(&sblock); 276 used = (sblock.fs_iblkno + inospercg / INOPF(&sblock)) * NSPF(&sblock); 277 mincpgcnt = howmany(sblock.fs_cgoffset * (~sblock.fs_cgmask) + used, 278 sblock.fs_spc); 279 mincpg = roundup(mincpgcnt, mincpc); 280 /* 281 * Ensure that cylinder group with mincpg has enough space 282 * for block maps. 283 */ 284 sblock.fs_cpg = mincpg; 285 sblock.fs_ipg = inospercg; 286 if (maxcontig > 1) 287 sblock.fs_contigsumsize = MIN(maxcontig, FS_MAXCONTIG); 288 mapcramped = 0; 289 while (CGSIZE(&sblock) > sblock.fs_bsize) { 290 mapcramped = 1; 291 if (sblock.fs_bsize < MAXBSIZE) { 292 sblock.fs_bsize <<= 1; 293 if ((i & 1) == 0) { 294 i >>= 1; 295 } else { 296 sblock.fs_cpc <<= 1; 297 mincpc <<= 1; 298 mincpg = roundup(mincpgcnt, mincpc); 299 sblock.fs_cpg = mincpg; 300 } 301 sblock.fs_frag <<= 1; 302 sblock.fs_fragshift += 1; 303 if (sblock.fs_frag <= MAXFRAG) 304 continue; 305 } 306 if (sblock.fs_fsize == sblock.fs_bsize) { 307 printf("There is no block size that"); 308 printf(" can support this disk\n"); 309 exit(22); 310 } 311 sblock.fs_frag >>= 1; 312 sblock.fs_fragshift -= 1; 313 sblock.fs_fsize <<= 1; 314 sblock.fs_nspf <<= 1; 315 } 316 /* 317 * Ensure that cylinder group with mincpg has enough space for inodes. 318 */ 319 inodecramped = 0; 320 inospercg = calcipg(mincpg, bpcg, &usedb); 321 sblock.fs_ipg = inospercg; 322 while (inospercg > MAXIPG(&sblock)) { 323 inodecramped = 1; 324 if (mincpc == 1 || sblock.fs_frag == 1 || 325 sblock.fs_bsize == MINBSIZE) 326 break; 327 printf("With a block size of %d %s %d\n", sblock.fs_bsize, 328 "minimum bytes per inode is", 329 (int)((mincpg * (off_t)bpcg - usedb) 330 / MAXIPG(&sblock) + 1)); 331 sblock.fs_bsize >>= 1; 332 sblock.fs_frag >>= 1; 333 sblock.fs_fragshift -= 1; 334 mincpc >>= 1; 335 sblock.fs_cpg = roundup(mincpgcnt, mincpc); 336 if (CGSIZE(&sblock) > sblock.fs_bsize) { 337 sblock.fs_bsize <<= 1; 338 break; 339 } 340 mincpg = sblock.fs_cpg; 341 inospercg = calcipg(mincpg, bpcg, &usedb); 342 sblock.fs_ipg = inospercg; 343 } 344 if (inodecramped) { 345 if (inospercg > MAXIPG(&sblock)) { 346 printf("Minimum bytes per inode is %d\n", 347 (int)((mincpg * (off_t)bpcg - usedb) 348 / MAXIPG(&sblock) + 1)); 349 } else if (!mapcramped) { 350 printf("With %d bytes per inode, ", density); 351 printf("minimum cylinders per group is %d\n", mincpg); 352 } 353 } 354 if (mapcramped) { 355 printf("With %d sectors per cylinder, ", sblock.fs_spc); 356 printf("minimum cylinders per group is %d\n", mincpg); 357 } 358 if (inodecramped || mapcramped) { 359 if (sblock.fs_bsize != bsize) 360 printf("%s to be changed from %d to %d\n", 361 "This requires the block size", 362 bsize, sblock.fs_bsize); 363 if (sblock.fs_fsize != fsize) 364 printf("\t%s to be changed from %d to %d\n", 365 "and the fragment size", 366 fsize, sblock.fs_fsize); 367 exit(23); 368 } 369 /* 370 * Calculate the number of cylinders per group 371 */ 372 sblock.fs_cpg = cpg; 373 if (sblock.fs_cpg % mincpc != 0) { 374 printf("%s groups must have a multiple of %d cylinders\n", 375 cpgflg ? "Cylinder" : "Warning: cylinder", mincpc); 376 sblock.fs_cpg = roundup(sblock.fs_cpg, mincpc); 377 if (!cpgflg) 378 cpg = sblock.fs_cpg; 379 } 380 /* 381 * Must ensure there is enough space for inodes. 382 */ 383 sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb); 384 while (sblock.fs_ipg > MAXIPG(&sblock)) { 385 inodecramped = 1; 386 sblock.fs_cpg -= mincpc; 387 sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb); 388 } 389 /* 390 * Must ensure there is enough space to hold block map. 391 */ 392 while (CGSIZE(&sblock) > sblock.fs_bsize) { 393 mapcramped = 1; 394 sblock.fs_cpg -= mincpc; 395 sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb); 396 } 397 sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock); 398 if ((sblock.fs_cpg * sblock.fs_spc) % NSPB(&sblock) != 0) { 399 printf("panic (fs_cpg * fs_spc) %% NSPF != 0"); 400 exit(24); 401 } 402 if (sblock.fs_cpg < mincpg) { 403 printf("cylinder groups must have at least %d cylinders\n", 404 mincpg); 405 exit(25); 406 } else if (sblock.fs_cpg != cpg && cpgflg) { 407 if (!mapcramped && !inodecramped) 408 exit(26); 409 if (mapcramped && inodecramped) 410 printf("Block size and bytes per inode restrict"); 411 else if (mapcramped) 412 printf("Block size restricts"); 413 else 414 printf("Bytes per inode restrict"); 415 printf(" cylinders per group to %d.\n", sblock.fs_cpg); 416 exit(27); 417 } 418 sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock)); 419 /* 420 * Now have size for file system and nsect and ntrak. 421 * Determine number of cylinders and blocks in the file system. 422 */ 423 sblock.fs_size = fssize = dbtofsb(&sblock, fssize); 424 sblock.fs_ncyl = fssize * NSPF(&sblock) / sblock.fs_spc; 425 if (fssize * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) { 426 sblock.fs_ncyl++; 427 warning = 1; 428 } 429 if (sblock.fs_ncyl < 1) { 430 printf("file systems must have at least one cylinder\n"); 431 exit(28); 432 } 433 /* 434 * Determine feasability/values of rotational layout tables. 435 * 436 * The size of the rotational layout tables is limited by the 437 * size of the superblock, SBSIZE. The amount of space available 438 * for tables is calculated as (SBSIZE - sizeof (struct fs)). 439 * The size of these tables is inversely proportional to the block 440 * size of the file system. The size increases if sectors per track 441 * are not powers of two, because more cylinders must be described 442 * by the tables before the rotational pattern repeats (fs_cpc). 443 */ 444 sblock.fs_interleave = interleave; 445 sblock.fs_trackskew = trackskew; 446 sblock.fs_npsect = nphyssectors; 447 sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT; 448 sblock.fs_sbsize = fragroundup(&sblock, sizeof(struct fs)); 449 if (sblock.fs_ntrak == 1) { 450 sblock.fs_cpc = 0; 451 goto next; 452 } 453 postblsize = sblock.fs_nrpos * sblock.fs_cpc * sizeof(int16_t); 454 rotblsize = sblock.fs_cpc * sblock.fs_spc / NSPB(&sblock); 455 totalsbsize = sizeof(struct fs) + rotblsize; 456 if (sblock.fs_nrpos == 8 && sblock.fs_cpc <= 16) { 457 /* use old static table space */ 458 sblock.fs_postbloff = (char *)(&sblock.fs_opostbl[0][0]) - 459 (char *)(&sblock.fs_firstfield); 460 sblock.fs_rotbloff = &sblock.fs_space[0] - 461 (u_char *)(&sblock.fs_firstfield); 462 } else { 463 /* use dynamic table space */ 464 sblock.fs_postbloff = &sblock.fs_space[0] - 465 (u_char *)(&sblock.fs_firstfield); 466 sblock.fs_rotbloff = sblock.fs_postbloff + postblsize; 467 totalsbsize += postblsize; 468 } 469 if (totalsbsize > SBSIZE || 470 sblock.fs_nsect > (1 << NBBY) * NSPB(&sblock)) { 471 printf("%s %s %d %s %d.%s", 472 "Warning: insufficient space in super block for\n", 473 "rotational layout tables with nsect", sblock.fs_nsect, 474 "and ntrak", sblock.fs_ntrak, 475 "\nFile system performance may be impaired.\n"); 476 sblock.fs_cpc = 0; 477 goto next; 478 } 479 sblock.fs_sbsize = fragroundup(&sblock, totalsbsize); 480 /* 481 * calculate the available blocks for each rotational position 482 */ 483 for (cylno = 0; cylno < sblock.fs_cpc; cylno++) 484 for (rpos = 0; rpos < sblock.fs_nrpos; rpos++) 485 fs_postbl(&sblock, cylno)[rpos] = -1; 486 for (i = (rotblsize - 1) << sblock.fs_fragshift; 487 i >= 0; i -= sblock.fs_frag) { 488 cylno = cbtocylno(&sblock, i); 489 rpos = cbtorpos(&sblock, i); 490 blk = fragstoblks(&sblock, i); 491 if (fs_postbl(&sblock, cylno)[rpos] == -1) 492 fs_rotbl(&sblock)[blk] = 0; 493 else 494 fs_rotbl(&sblock)[blk] = fs_postbl(&sblock, cylno)[rpos] - blk; 495 fs_postbl(&sblock, cylno)[rpos] = blk; 496 } 497 next: 498 /* 499 * Compute/validate number of cylinder groups. 500 */ 501 sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg; 502 if (sblock.fs_ncyl % sblock.fs_cpg) 503 sblock.fs_ncg++; 504 sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock); 505 i = MIN(~sblock.fs_cgmask, sblock.fs_ncg - 1); 506 if (cgdmin(&sblock, i) - cgbase(&sblock, i) >= sblock.fs_fpg) { 507 printf("inode blocks/cyl group (%d) >= data blocks (%d)\n", 508 cgdmin(&sblock, i) - 509 (cgbase(&sblock, i) >> sblock.fs_fragshift), 510 sblock.fs_fpg >> sblock.fs_fragshift); 511 printf("number of cylinders per cylinder group (%d) %s.\n", 512 sblock.fs_cpg, "must be increased"); 513 exit(29); 514 } 515 j = sblock.fs_ncg - 1; 516 if ((i = fssize - j * sblock.fs_fpg) < sblock.fs_fpg && 517 cgdmin(&sblock, j) - cgbase(&sblock, j) > i) { 518 if (j == 0) { 519 printf("File system must have at least %d sectors\n", 520 NSPF(&sblock) * 521 (cgdmin(&sblock, 0) + (3 << sblock.fs_fragshift))); 522 exit(30); 523 } 524 printf("Warning: inode blocks/cyl group (%d) >= " 525 "data blocks (%d) in last\n", 526 (cgdmin(&sblock, j) - 527 cgbase(&sblock, j)) >> sblock.fs_fragshift, 528 i >> sblock.fs_fragshift); 529 printf(" cylinder group. This implies %d sector(s) " 530 "cannot be allocated.\n", 531 i * NSPF(&sblock)); 532 sblock.fs_ncg--; 533 sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg; 534 sblock.fs_size = fssize = sblock.fs_ncyl * sblock.fs_spc / 535 NSPF(&sblock); 536 warning = 0; 537 } 538 if (warning && !mfs) { 539 printf("Warning: %d sector(s) in last cylinder unallocated\n", 540 sblock.fs_spc - 541 (fssize * NSPF(&sblock) - (sblock.fs_ncyl - 1) 542 * sblock.fs_spc)); 543 } 544 /* 545 * fill in remaining fields of the super block 546 */ 547 sblock.fs_csaddr = cgdmin(&sblock, 0); 548 sblock.fs_cssize = 549 fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum)); 550 /* 551 * The superblock fields 'fs_csmask' and 'fs_csshift' are no 552 * longer used. However, we still initialise them so that the 553 * filesystem remains compatible with old kernels. 554 */ 555 i = sblock.fs_bsize / sizeof(struct csum); 556 sblock.fs_csmask = ~(i - 1); 557 for (sblock.fs_csshift = 0; i > 1; i >>= 1) 558 sblock.fs_csshift++; 559 fscs = (struct csum *)calloc(1, sblock.fs_cssize); 560 if (fscs == NULL) 561 exit(39); 562 sblock.fs_magic = FS_MAGIC; 563 sblock.fs_rotdelay = rotdelay; 564 sblock.fs_minfree = minfree; 565 sblock.fs_maxcontig = maxcontig; 566 sblock.fs_maxbpg = maxbpg; 567 sblock.fs_rps = rpm / 60; 568 sblock.fs_optim = opt; 569 sblock.fs_cgrotor = 0; 570 sblock.fs_cstotal.cs_ndir = 0; 571 sblock.fs_cstotal.cs_nbfree = 0; 572 sblock.fs_cstotal.cs_nifree = 0; 573 sblock.fs_cstotal.cs_nffree = 0; 574 sblock.fs_fmod = 0; 575 sblock.fs_clean = FS_ISCLEAN; 576 sblock.fs_ronly = 0; 577 /* 578 * Dump out summary information about file system. 579 */ 580 if (!mfs) { 581 printf("%s:\t%d sectors in %d %s of %d tracks, %d sectors\n", 582 fsys, sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl, 583 "cylinders", sblock.fs_ntrak, sblock.fs_nsect); 584 #define B2MBFACTOR (1 / (1024.0 * 1024.0)) 585 printf("\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)\n", 586 (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR, 587 sblock.fs_ncg, sblock.fs_cpg, 588 (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR, 589 sblock.fs_ipg); 590 #undef B2MBFACTOR 591 } 592 /* 593 * Now determine how wide each column will be, and calculate how 594 * many columns will fit in a 76 char line. 76 is the width of the 595 * subwindows in sysinst. 596 */ 597 printcolwidth = count_digits( 598 fsbtodb(&sblock, cgsblock(&sblock, sblock.fs_ncg -1))); 599 nprintcols = 76 / (printcolwidth + 2); 600 /* 601 * Now build the cylinders group blocks and 602 * then print out indices of cylinder groups. 603 */ 604 if (!mfs) 605 printf("super-block backups (for fsck -b #) at:"); 606 for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { 607 initcg(cylno, utime); 608 if (mfs) 609 continue; 610 if (cylno % nprintcols == 0) 611 printf("\n"); 612 printf(" %*d,", printcolwidth, 613 fsbtodb(&sblock, cgsblock(&sblock, cylno))); 614 fflush(stdout); 615 } 616 if (!mfs) 617 printf("\n"); 618 if (Nflag && !mfs) 619 exit(0); 620 /* 621 * Now construct the initial file system, 622 * then write out the super-block. 623 */ 624 if (fsinit(utime, mfsmode, mfsuid, mfsgid) == 0 && mfs) 625 errx(1, "Error making filesystem"); 626 sblock.fs_time = utime; 627 memcpy(writebuf, &sblock, sbsize); 628 if (needswap) 629 ffs_sb_swap(&sblock, (struct fs*)writebuf); 630 wtfs((int)SBOFF / sectorsize, sbsize, writebuf); 631 /* 632 * Write out the duplicate super blocks 633 */ 634 for (cylno = 0; cylno < sblock.fs_ncg; cylno++) 635 wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), 636 sbsize, writebuf); 637 638 /* 639 * if we need to swap, create a buffer for the cylinder summaries 640 * to get swapped to. 641 */ 642 if (needswap) { 643 if ((writebuf2 = malloc(sblock.fs_cssize)) == NULL) 644 exit(12); 645 ffs_csum_swap(fscs, (struct csum*)writebuf2, sblock.fs_cssize); 646 } else 647 writebuf2 = (char *)fscs; 648 649 for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) 650 wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)), 651 sblock.fs_cssize - i < sblock.fs_bsize ? 652 sblock.fs_cssize - i : sblock.fs_bsize, 653 ((char *)writebuf2) + i); 654 if (writebuf2 != (char *)fscs) 655 free(writebuf2); 656 657 /* 658 * Update information about this partion in pack 659 * label, to that it may be updated on disk. 660 */ 661 pp->p_fstype = FS_BSDFFS; 662 pp->p_fsize = sblock.fs_fsize; 663 pp->p_frag = sblock.fs_frag; 664 pp->p_cpg = sblock.fs_cpg; 665 } 666 667 /* 668 * Initialize a cylinder group. 669 */ 670 void 671 initcg(int cylno, time_t utime) 672 { 673 daddr_t cbase, d, dlower, dupper, dmax, blkno; 674 int32_t i; 675 struct csum *cs; 676 int cn; 677 678 /* 679 * Determine block bounds for cylinder group. 680 * Allow space for super block summary information in first 681 * cylinder group. 682 */ 683 cbase = cgbase(&sblock, cylno); 684 dmax = cbase + sblock.fs_fpg; 685 if (dmax > sblock.fs_size) 686 dmax = sblock.fs_size; 687 dlower = cgsblock(&sblock, cylno) - cbase; 688 dupper = cgdmin(&sblock, cylno) - cbase; 689 if (cylno == 0) 690 dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); 691 cs = fscs + cylno; 692 memset(&acg, 0, sblock.fs_cgsize); 693 acg.cg_time = utime; 694 acg.cg_magic = CG_MAGIC; 695 acg.cg_cgx = cylno; 696 if (cylno == sblock.fs_ncg - 1) 697 acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg; 698 else 699 acg.cg_ncyl = sblock.fs_cpg; 700 acg.cg_niblk = sblock.fs_ipg; 701 acg.cg_ndblk = dmax - cbase; 702 if (sblock.fs_contigsumsize > 0) 703 acg.cg_nclusterblks = acg.cg_ndblk >> sblock.fs_fragshift; 704 acg.cg_btotoff = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield); 705 acg.cg_boff = acg.cg_btotoff + sblock.fs_cpg * sizeof(int32_t); 706 acg.cg_iusedoff = acg.cg_boff + 707 sblock.fs_cpg * sblock.fs_nrpos * sizeof(int16_t); 708 acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY); 709 if (sblock.fs_contigsumsize <= 0) { 710 acg.cg_nextfreeoff = acg.cg_freeoff + 711 howmany(sblock.fs_fpg, NBBY); 712 } else { 713 acg.cg_clustersumoff = acg.cg_freeoff + 714 howmany(sblock.fs_fpg, NBBY) - sizeof(int32_t); 715 acg.cg_clustersumoff = 716 roundup(acg.cg_clustersumoff, sizeof(int32_t)); 717 acg.cg_clusteroff = acg.cg_clustersumoff + 718 (sblock.fs_contigsumsize + 1) * sizeof(int32_t); 719 acg.cg_nextfreeoff = acg.cg_clusteroff + 720 howmany(fragstoblks(&sblock, sblock.fs_fpg), NBBY); 721 } 722 if (acg.cg_nextfreeoff > sblock.fs_cgsize) { 723 printf("Panic: cylinder group too big\n"); 724 exit(37); 725 } 726 acg.cg_cs.cs_nifree += sblock.fs_ipg; 727 if (cylno == 0) 728 for (i = 0; i < ROOTINO; i++) { 729 setbit(cg_inosused(&acg, 0), i); 730 acg.cg_cs.cs_nifree--; 731 } 732 for (i = 0; i < sblock.fs_ipg / INOPF(&sblock); i += sblock.fs_frag) 733 wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i), 734 sblock.fs_bsize, (char *)zino); 735 if (cylno > 0) { 736 /* 737 * In cylno 0, beginning space is reserved 738 * for boot and super blocks. 739 */ 740 for (d = 0, blkno = 0; d < dlower; ) { 741 setblock(&sblock, cg_blksfree(&acg, 0), blkno); 742 if (sblock.fs_contigsumsize > 0) 743 setbit(cg_clustersfree(&acg, 0), blkno); 744 acg.cg_cs.cs_nbfree++; 745 cn = cbtocylno(&sblock, d); 746 cg_blktot(&acg, 0)[cn]++; 747 cg_blks(&sblock, &acg, cn, 0)[cbtorpos(&sblock, d)]++; 748 d += sblock.fs_frag; 749 blkno++; 750 } 751 sblock.fs_dsize += dlower; 752 } 753 sblock.fs_dsize += acg.cg_ndblk - dupper; 754 if ((i = (dupper & (sblock.fs_frag - 1))) != 0) { 755 acg.cg_frsum[sblock.fs_frag - i]++; 756 for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) { 757 setbit(cg_blksfree(&acg, 0), dupper); 758 acg.cg_cs.cs_nffree++; 759 } 760 } 761 for (d = dupper, blkno = dupper >> sblock.fs_fragshift; 762 d + sblock.fs_frag <= dmax - cbase; ) { 763 setblock(&sblock, cg_blksfree(&acg, 0), blkno); 764 if (sblock.fs_contigsumsize > 0) 765 setbit(cg_clustersfree(&acg, 0), blkno); 766 acg.cg_cs.cs_nbfree++; 767 cn = cbtocylno(&sblock, d); 768 cg_blktot(&acg, 0)[cn]++; 769 cg_blks(&sblock, &acg, cn, 0)[cbtorpos(&sblock, d)]++; 770 d += sblock.fs_frag; 771 blkno++; 772 } 773 if (d < dmax - cbase) { 774 acg.cg_frsum[dmax - cbase - d]++; 775 for (; d < dmax - cbase; d++) { 776 setbit(cg_blksfree(&acg, 0), d); 777 acg.cg_cs.cs_nffree++; 778 } 779 } 780 if (sblock.fs_contigsumsize > 0) { 781 int32_t *sump = cg_clustersum(&acg, 0); 782 u_char *mapp = cg_clustersfree(&acg, 0); 783 int map = *mapp++; 784 int bit = 1; 785 int run = 0; 786 787 for (i = 0; i < acg.cg_nclusterblks; i++) { 788 if ((map & bit) != 0) { 789 run++; 790 } else if (run != 0) { 791 if (run > sblock.fs_contigsumsize) 792 run = sblock.fs_contigsumsize; 793 sump[run]++; 794 run = 0; 795 } 796 if ((i & (NBBY - 1)) != (NBBY - 1)) { 797 bit <<= 1; 798 } else { 799 map = *mapp++; 800 bit = 1; 801 } 802 } 803 if (run != 0) { 804 if (run > sblock.fs_contigsumsize) 805 run = sblock.fs_contigsumsize; 806 sump[run]++; 807 } 808 } 809 sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir; 810 sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree; 811 sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree; 812 sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree; 813 *cs = acg.cg_cs; 814 memcpy(writebuf, &acg, sblock.fs_bsize); 815 if (needswap) 816 swap_cg(&acg, (struct cg*)writebuf); 817 wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), 818 sblock.fs_bsize, writebuf); 819 } 820 821 /* 822 * initialize the file system 823 */ 824 struct dinode node; 825 826 #ifdef LOSTDIR 827 #define PREDEFDIR 3 828 #else 829 #define PREDEFDIR 2 830 #endif 831 832 struct direct root_dir[] = { 833 { ROOTINO, sizeof(struct direct), DT_DIR, 1, "." }, 834 { ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." }, 835 #ifdef LOSTDIR 836 { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 10, "lost+found" }, 837 #endif 838 }; 839 struct odirect { 840 u_int32_t d_ino; 841 u_int16_t d_reclen; 842 u_int16_t d_namlen; 843 u_char d_name[MAXNAMLEN + 1]; 844 } oroot_dir[] = { 845 { ROOTINO, sizeof(struct direct), 1, "." }, 846 { ROOTINO, sizeof(struct direct), 2, ".." }, 847 #ifdef LOSTDIR 848 { LOSTFOUNDINO, sizeof(struct direct), 10, "lost+found" }, 849 #endif 850 }; 851 #ifdef LOSTDIR 852 struct direct lost_found_dir[] = { 853 { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 1, "." }, 854 { ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." }, 855 { 0, DIRBLKSIZ, 0, 0, 0 }, 856 }; 857 struct odirect olost_found_dir[] = { 858 { LOSTFOUNDINO, sizeof(struct direct), 1, "." }, 859 { ROOTINO, sizeof(struct direct), 2, ".." }, 860 { 0, DIRBLKSIZ, 0, 0 }, 861 }; 862 #endif 863 char buf[MAXBSIZE]; 864 static void copy_dir(struct direct *, struct direct *); 865 866 int 867 fsinit(time_t utime, mode_t mfsmode, uid_t mfsuid, gid_t mfsgid) 868 { 869 #ifdef LOSTDIR 870 int i; 871 #endif 872 873 /* 874 * initialize the node 875 */ 876 memset(&node, 0, sizeof(node)); 877 node.di_atime = utime; 878 node.di_mtime = utime; 879 node.di_ctime = utime; 880 881 #ifdef LOSTDIR 882 /* 883 * create the lost+found directory 884 */ 885 if (Oflag) { 886 (void)makedir((struct direct *)olost_found_dir, 2); 887 for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ) 888 copy_dir((struct direct*)&olost_found_dir[2], 889 (struct direct*)&buf[i]); 890 } else { 891 (void)makedir(lost_found_dir, 2); 892 for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ) 893 copy_dir(&lost_found_dir[2], (struct direct*)&buf[i]); 894 } 895 node.di_mode = IFDIR | UMASK; 896 node.di_nlink = 2; 897 node.di_size = sblock.fs_bsize; 898 node.di_db[0] = alloc(node.di_size, node.di_mode); 899 node.di_blocks = btodb(fragroundup(&sblock, node.di_size)); 900 node.di_uid = geteuid(); 901 node.di_gid = getegid(); 902 wtfs(fsbtodb(&sblock, node.di_db[0]), node.di_size, buf); 903 iput(&node, LOSTFOUNDINO); 904 #endif 905 /* 906 * create the root directory 907 */ 908 if (mfs) { 909 node.di_mode = IFDIR | mfsmode; 910 node.di_uid = mfsuid; 911 node.di_gid = mfsgid; 912 } else { 913 node.di_mode = IFDIR | UMASK; 914 node.di_uid = geteuid(); 915 node.di_gid = getegid(); 916 } 917 node.di_nlink = PREDEFDIR; 918 if (Oflag) 919 node.di_size = makedir((struct direct *)oroot_dir, PREDEFDIR); 920 else 921 node.di_size = makedir(root_dir, PREDEFDIR); 922 node.di_db[0] = alloc(sblock.fs_fsize, node.di_mode); 923 if (node.di_db[0] == 0) 924 return (0); 925 node.di_blocks = btodb(fragroundup(&sblock, node.di_size)); 926 wtfs(fsbtodb(&sblock, node.di_db[0]), sblock.fs_fsize, buf); 927 iput(&node, ROOTINO); 928 return (1); 929 } 930 931 /* 932 * construct a set of directory entries in "buf". 933 * return size of directory. 934 */ 935 int 936 makedir(struct direct *protodir, int entries) 937 { 938 char *cp; 939 int i, spcleft; 940 941 spcleft = DIRBLKSIZ; 942 for (cp = buf, i = 0; i < entries - 1; i++) { 943 protodir[i].d_reclen = DIRSIZ(Oflag, &protodir[i], 0); 944 copy_dir(&protodir[i], (struct direct*)cp); 945 cp += protodir[i].d_reclen; 946 spcleft -= protodir[i].d_reclen; 947 } 948 protodir[i].d_reclen = spcleft; 949 copy_dir(&protodir[i], (struct direct*)cp); 950 return (DIRBLKSIZ); 951 } 952 953 /* 954 * allocate a block or frag 955 */ 956 daddr_t 957 alloc(int size, int mode) 958 { 959 int i, frag; 960 daddr_t d, blkno; 961 962 rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, &acg); 963 /* fs -> host byte order */ 964 if (needswap) 965 swap_cg(&acg, &acg); 966 if (acg.cg_magic != CG_MAGIC) { 967 printf("cg 0: bad magic number\n"); 968 return (0); 969 } 970 if (acg.cg_cs.cs_nbfree == 0) { 971 printf("first cylinder group ran out of space\n"); 972 return (0); 973 } 974 for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag) 975 if (isblock(&sblock, cg_blksfree(&acg, 0), 976 d >> sblock.fs_fragshift)) 977 goto goth; 978 printf("internal error: can't find block in cyl 0\n"); 979 return (0); 980 goth: 981 blkno = fragstoblks(&sblock, d); 982 clrblock(&sblock, cg_blksfree(&acg, 0), blkno); 983 if (sblock.fs_contigsumsize > 0) 984 clrbit(cg_clustersfree(&acg, 0), blkno); 985 acg.cg_cs.cs_nbfree--; 986 sblock.fs_cstotal.cs_nbfree--; 987 fscs[0].cs_nbfree--; 988 if (mode & IFDIR) { 989 acg.cg_cs.cs_ndir++; 990 sblock.fs_cstotal.cs_ndir++; 991 fscs[0].cs_ndir++; 992 } 993 cg_blktot(&acg, 0)[cbtocylno(&sblock, d)]--; 994 cg_blks(&sblock, &acg, cbtocylno(&sblock, d), 0)[cbtorpos(&sblock, d)]--; 995 if (size != sblock.fs_bsize) { 996 frag = howmany(size, sblock.fs_fsize); 997 fscs[0].cs_nffree += sblock.fs_frag - frag; 998 sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag; 999 acg.cg_cs.cs_nffree += sblock.fs_frag - frag; 1000 acg.cg_frsum[sblock.fs_frag - frag]++; 1001 for (i = frag; i < sblock.fs_frag; i++) 1002 setbit(cg_blksfree(&acg, 0), d + i); 1003 } 1004 /* host -> fs byte order */ 1005 if (needswap) 1006 swap_cg(&acg, &acg); 1007 wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 1008 (char *)&acg); 1009 return (d); 1010 } 1011 1012 /* 1013 * Calculate number of inodes per group. 1014 */ 1015 int32_t 1016 calcipg(int32_t cylpg, int32_t bpcg, off_t *usedbp) 1017 { 1018 int i; 1019 int32_t ipg, new_ipg, ncg, ncyl; 1020 off_t usedb; 1021 1022 /* 1023 * Prepare to scale by fssize / (number of sectors in cylinder groups). 1024 * Note that fssize is still in sectors, not file system blocks. 1025 */ 1026 ncyl = howmany(fssize, secpercyl); 1027 ncg = howmany(ncyl, cylpg); 1028 /* 1029 * Iterate a few times to allow for ipg depending on itself. 1030 */ 1031 ipg = 0; 1032 for (i = 0; i < 10; i++) { 1033 usedb = (sblock.fs_iblkno + ipg / INOPF(&sblock)) 1034 * NSPF(&sblock) * (off_t)sectorsize; 1035 new_ipg = (cylpg * (long long)bpcg - usedb) / 1036 (long long)density * fssize / (ncg * secpercyl * cylpg); 1037 if (new_ipg <= 0) 1038 new_ipg = 1; /* ensure ipg > 0 */ 1039 new_ipg = roundup(new_ipg, INOPB(&sblock)); 1040 if (new_ipg == ipg) 1041 break; 1042 ipg = new_ipg; 1043 } 1044 *usedbp = usedb; 1045 return (ipg); 1046 } 1047 1048 /* 1049 * Allocate an inode on the disk 1050 */ 1051 static void 1052 iput(struct dinode *ip, ino_t ino) 1053 { 1054 struct dinode ibuf[MAXINOPB]; 1055 daddr_t d; 1056 int c, i; 1057 1058 c = ino_to_cg(&sblock, ino); 1059 rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, &acg); 1060 /* fs -> host byte order */ 1061 if (needswap) 1062 swap_cg(&acg, &acg); 1063 if (acg.cg_magic != CG_MAGIC) { 1064 printf("cg 0: bad magic number\n"); 1065 exit(31); 1066 } 1067 acg.cg_cs.cs_nifree--; 1068 setbit(cg_inosused(&acg, 0), ino); 1069 /* host -> fs byte order */ 1070 if (needswap) 1071 swap_cg(&acg, &acg); 1072 wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 1073 (char *)&acg); 1074 sblock.fs_cstotal.cs_nifree--; 1075 fscs[0].cs_nifree--; 1076 if (ino >= sblock.fs_ipg * sblock.fs_ncg) { 1077 printf("fsinit: inode value out of range (%d).\n", ino); 1078 exit(32); 1079 } 1080 d = fsbtodb(&sblock, ino_to_fsba(&sblock, ino)); 1081 rdfs(d, sblock.fs_bsize, ibuf); 1082 if (needswap) { 1083 ffs_dinode_swap(ip, &ibuf[ino_to_fsbo(&sblock, ino)]); 1084 /* ffs_dinode_swap() doesn't swap blocks addrs */ 1085 for (i=0; i<NDADDR + NIADDR; i++) 1086 (&ibuf[ino_to_fsbo(&sblock, ino)])->di_db[i] = 1087 bswap32(ip->di_db[i]); 1088 } else 1089 ibuf[ino_to_fsbo(&sblock, ino)] = *ip; 1090 wtfs(d, sblock.fs_bsize, ibuf); 1091 } 1092 1093 /* 1094 * read a block from the file system 1095 */ 1096 void 1097 rdfs(daddr_t bno, int size, void *bf) 1098 { 1099 int n; 1100 off_t offset; 1101 1102 #ifdef MFS 1103 if (mfs) { 1104 memmove(bf, membase + bno * sectorsize, size); 1105 return; 1106 } 1107 #endif 1108 offset = bno; 1109 offset *= sectorsize; 1110 if (lseek(fsi, offset, SEEK_SET) < 0) { 1111 printf("rdfs: seek error for sector %d: %s\n", 1112 bno, strerror(errno)); 1113 exit(33); 1114 } 1115 n = read(fsi, bf, size); 1116 if (n != size) { 1117 printf("rdfs: read error for sector %d: %s\n", 1118 bno, strerror(errno)); 1119 exit(34); 1120 } 1121 } 1122 1123 /* 1124 * write a block to the file system 1125 */ 1126 void 1127 wtfs(daddr_t bno, int size, void *bf) 1128 { 1129 int n; 1130 off_t offset; 1131 1132 #ifdef MFS 1133 if (mfs) { 1134 memmove(membase + bno * sectorsize, bf, size); 1135 return; 1136 } 1137 #endif 1138 if (Nflag) 1139 return; 1140 offset = bno; 1141 offset *= sectorsize; 1142 if (lseek(fso, offset, SEEK_SET) < 0) { 1143 printf("wtfs: seek error for sector %d: %s\n", 1144 bno, strerror(errno)); 1145 exit(35); 1146 } 1147 n = write(fso, bf, size); 1148 if (n != size) { 1149 printf("wtfs: write error for sector %d: %s\n", 1150 bno, strerror(errno)); 1151 exit(36); 1152 } 1153 } 1154 1155 /* 1156 * check if a block is available 1157 */ 1158 int 1159 isblock(struct fs *fs, unsigned char *cp, int h) 1160 { 1161 unsigned char mask; 1162 1163 switch (fs->fs_fragshift) { 1164 case 3: 1165 return (cp[h] == 0xff); 1166 case 2: 1167 mask = 0x0f << ((h & 0x1) << 2); 1168 return ((cp[h >> 1] & mask) == mask); 1169 case 1: 1170 mask = 0x03 << ((h & 0x3) << 1); 1171 return ((cp[h >> 2] & mask) == mask); 1172 case 0: 1173 mask = 0x01 << (h & 0x7); 1174 return ((cp[h >> 3] & mask) == mask); 1175 default: 1176 #ifdef STANDALONE 1177 printf("isblock bad fs_fragshift %d\n", fs->fs_fragshift); 1178 #else 1179 fprintf(stderr, "isblock bad fs_fragshift %d\n", 1180 fs->fs_fragshift); 1181 #endif 1182 return (0); 1183 } 1184 } 1185 1186 /* 1187 * take a block out of the map 1188 */ 1189 void 1190 clrblock(struct fs *fs, unsigned char *cp, int h) 1191 { 1192 switch ((fs)->fs_fragshift) { 1193 case 3: 1194 cp[h] = 0; 1195 return; 1196 case 2: 1197 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 1198 return; 1199 case 1: 1200 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 1201 return; 1202 case 0: 1203 cp[h >> 3] &= ~(0x01 << (h & 0x7)); 1204 return; 1205 default: 1206 #ifdef STANDALONE 1207 printf("clrblock bad fs_fragshift %d\n", fs->fs_fragshift); 1208 #else 1209 fprintf(stderr, "clrblock bad fs_fragshift %d\n", 1210 fs->fs_fragshift); 1211 #endif 1212 return; 1213 } 1214 } 1215 1216 /* 1217 * put a block into the map 1218 */ 1219 void 1220 setblock(struct fs *fs, unsigned char *cp, int h) 1221 { 1222 switch (fs->fs_fragshift) { 1223 case 3: 1224 cp[h] = 0xff; 1225 return; 1226 case 2: 1227 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 1228 return; 1229 case 1: 1230 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 1231 return; 1232 case 0: 1233 cp[h >> 3] |= (0x01 << (h & 0x7)); 1234 return; 1235 default: 1236 #ifdef STANDALONE 1237 printf("setblock bad fs_frag %d\n", fs->fs_fragshift); 1238 #else 1239 fprintf(stderr, "setblock bad fs_fragshift %d\n", 1240 fs->fs_fragshift); 1241 #endif 1242 return; 1243 } 1244 } 1245 1246 /* swap byte order of cylinder group */ 1247 static void 1248 swap_cg(struct cg *o, struct cg *n) 1249 { 1250 int i, btotsize, fbsize; 1251 u_int32_t *n32, *o32; 1252 u_int16_t *n16, *o16; 1253 1254 n->cg_firstfield = bswap32(o->cg_firstfield); 1255 n->cg_magic = bswap32(o->cg_magic); 1256 n->cg_time = bswap32(o->cg_time); 1257 n->cg_cgx = bswap32(o->cg_cgx); 1258 n->cg_ncyl = bswap16(o->cg_ncyl); 1259 n->cg_niblk = bswap16(o->cg_niblk); 1260 n->cg_ndblk = bswap32(o->cg_ndblk); 1261 n->cg_cs.cs_ndir = bswap32(o->cg_cs.cs_ndir); 1262 n->cg_cs.cs_nbfree = bswap32(o->cg_cs.cs_nbfree); 1263 n->cg_cs.cs_nifree = bswap32(o->cg_cs.cs_nifree); 1264 n->cg_cs.cs_nffree = bswap32(o->cg_cs.cs_nffree); 1265 n->cg_rotor = bswap32(o->cg_rotor); 1266 n->cg_frotor = bswap32(o->cg_frotor); 1267 n->cg_irotor = bswap32(o->cg_irotor); 1268 n->cg_btotoff = bswap32(o->cg_btotoff); 1269 n->cg_boff = bswap32(o->cg_boff); 1270 n->cg_iusedoff = bswap32(o->cg_iusedoff); 1271 n->cg_freeoff = bswap32(o->cg_freeoff); 1272 n->cg_nextfreeoff = bswap32(o->cg_nextfreeoff); 1273 n->cg_clustersumoff = bswap32(o->cg_clustersumoff); 1274 n->cg_clusteroff = bswap32(o->cg_clusteroff); 1275 n->cg_nclusterblks = bswap32(o->cg_nclusterblks); 1276 for (i=0; i < MAXFRAG; i++) 1277 n->cg_frsum[i] = bswap32(o->cg_frsum[i]); 1278 1279 /* alays new format */ 1280 if (n->cg_magic == CG_MAGIC) { 1281 btotsize = n->cg_boff - n->cg_btotoff; 1282 fbsize = n->cg_iusedoff - n->cg_boff; 1283 n32 = (u_int32_t*)((u_int8_t*)n + n->cg_btotoff); 1284 o32 = (u_int32_t*)((u_int8_t*)o + n->cg_btotoff); 1285 n16 = (u_int16_t*)((u_int8_t*)n + n->cg_boff); 1286 o16 = (u_int16_t*)((u_int8_t*)o + n->cg_boff); 1287 } else { 1288 btotsize = bswap32(n->cg_boff) - bswap32(n->cg_btotoff); 1289 fbsize = bswap32(n->cg_iusedoff) - bswap32(n->cg_boff); 1290 n32 = (u_int32_t*)((u_int8_t*)n + bswap32(n->cg_btotoff)); 1291 o32 = (u_int32_t*)((u_int8_t*)o + bswap32(n->cg_btotoff)); 1292 n16 = (u_int16_t*)((u_int8_t*)n + bswap32(n->cg_boff)); 1293 o16 = (u_int16_t*)((u_int8_t*)o + bswap32(n->cg_boff)); 1294 } 1295 for (i=0; i < btotsize / sizeof(u_int32_t); i++) 1296 n32[i] = bswap32(o32[i]); 1297 1298 for (i=0; i < fbsize/sizeof(u_int16_t); i++) 1299 n16[i] = bswap16(o16[i]); 1300 1301 if (n->cg_magic == CG_MAGIC) { 1302 n32 = (u_int32_t*)((u_int8_t*)n + n->cg_clustersumoff); 1303 o32 = (u_int32_t*)((u_int8_t*)o + n->cg_clustersumoff); 1304 } else { 1305 n32 = (u_int32_t*)((u_int8_t*)n + bswap32(n->cg_clustersumoff)); 1306 o32 = (u_int32_t*)((u_int8_t*)o + bswap32(n->cg_clustersumoff)); 1307 } 1308 for (i = 1; i < sblock.fs_contigsumsize + 1; i++) 1309 n32[i] = bswap32(o32[i]); 1310 } 1311 1312 /* copy a direntry to a buffer, in fs byte order */ 1313 static void 1314 copy_dir(struct direct *dir, struct direct *dbuf) 1315 { 1316 memcpy(dbuf, dir, DIRSIZ(Oflag, dir, 0)); 1317 if (needswap) { 1318 dbuf->d_ino = bswap32(dir->d_ino); 1319 dbuf->d_reclen = bswap16(dir->d_reclen); 1320 if (Oflag) 1321 ((struct odirect*)dbuf)->d_namlen = 1322 bswap16(((struct odirect*)dir)->d_namlen); 1323 } 1324 } 1325 1326 /* Determine how many digits are needed to print a given integer */ 1327 static int 1328 count_digits(int num) 1329 { 1330 int ndig; 1331 1332 for(ndig = 1; num > 9; num /=10, ndig++); 1333 1334 return (ndig); 1335 } 1336 1337 #ifdef MFS 1338 /* 1339 * XXX! 1340 * Attempt to guess how much more space is available for process data. The 1341 * heuristic we use is 1342 * 1343 * max_data_limit - (sbrk(0) - etext) - 128kB 1344 * 1345 * etext approximates that start address of the data segment, and the 128kB 1346 * allows some slop for both segment gap between text and data, and for other 1347 * (libc) malloc usage. 1348 */ 1349 static void 1350 calc_memfree(void) 1351 { 1352 extern char etext; 1353 struct rlimit rlp; 1354 u_long base; 1355 1356 base = (u_long)sbrk(0) - (u_long)&etext; 1357 if (getrlimit(RLIMIT_DATA, &rlp) < 0) 1358 perror("getrlimit"); 1359 rlp.rlim_cur = rlp.rlim_max; 1360 if (setrlimit(RLIMIT_DATA, &rlp) < 0) 1361 perror("setrlimit"); 1362 memleft = rlp.rlim_max - base - (128 * 1024); 1363 } 1364 1365 /* 1366 * Internal version of malloc that trims the requested size if not enough 1367 * memory is available. 1368 */ 1369 static void * 1370 mkfs_malloc(size_t size) 1371 { 1372 u_long pgsz; 1373 1374 if (size == 0) 1375 return (NULL); 1376 if (memleft == 0) 1377 calc_memfree(); 1378 1379 pgsz = getpagesize() - 1; 1380 size = (size + pgsz) &~ pgsz; 1381 if (size > memleft) 1382 size = memleft; 1383 memleft -= size; 1384 return (mmap(0, size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 1385 -1, 0)); 1386 } 1387 #endif /* MFS */ 1388