1 /* $NetBSD: mkfs.c,v 1.61 2002/01/18 08:59:18 lukem 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.61 2002/01/18 08:59:18 lukem 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_frag; 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) - cgbase(&sblock, i) / sblock.fs_frag, 509 sblock.fs_fpg / sblock.fs_frag); 510 printf("number of cylinders per cylinder group (%d) %s.\n", 511 sblock.fs_cpg, "must be increased"); 512 exit(29); 513 } 514 j = sblock.fs_ncg - 1; 515 if ((i = fssize - j * sblock.fs_fpg) < sblock.fs_fpg && 516 cgdmin(&sblock, j) - cgbase(&sblock, j) > i) { 517 if (j == 0) { 518 printf("File system must have at least %d sectors\n", 519 NSPF(&sblock) * 520 (cgdmin(&sblock, 0) + 3 * sblock.fs_frag)); 521 exit(30); 522 } 523 printf("Warning: inode blocks/cyl group (%d) >= " 524 "data blocks (%d) in last\n", 525 (cgdmin(&sblock, j) - cgbase(&sblock, j)) / sblock.fs_frag, 526 i / sblock.fs_frag); 527 printf(" cylinder group. This implies %d sector(s) " 528 "cannot be allocated.\n", 529 i * NSPF(&sblock)); 530 sblock.fs_ncg--; 531 sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg; 532 sblock.fs_size = fssize = sblock.fs_ncyl * sblock.fs_spc / 533 NSPF(&sblock); 534 warning = 0; 535 } 536 if (warning && !mfs) { 537 printf("Warning: %d sector(s) in last cylinder unallocated\n", 538 sblock.fs_spc - 539 (fssize * NSPF(&sblock) - (sblock.fs_ncyl - 1) 540 * sblock.fs_spc)); 541 } 542 /* 543 * fill in remaining fields of the super block 544 */ 545 sblock.fs_csaddr = cgdmin(&sblock, 0); 546 sblock.fs_cssize = 547 fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum)); 548 /* 549 * The superblock fields 'fs_csmask' and 'fs_csshift' are no 550 * longer used. However, we still initialise them so that the 551 * filesystem remains compatible with old kernels. 552 */ 553 i = sblock.fs_bsize / sizeof(struct csum); 554 sblock.fs_csmask = ~(i - 1); 555 for (sblock.fs_csshift = 0; i > 1; i >>= 1) 556 sblock.fs_csshift++; 557 fscs = (struct csum *)calloc(1, sblock.fs_cssize); 558 if (fscs == NULL) 559 exit(39); 560 sblock.fs_magic = FS_MAGIC; 561 sblock.fs_rotdelay = rotdelay; 562 sblock.fs_minfree = minfree; 563 sblock.fs_maxcontig = maxcontig; 564 sblock.fs_maxbpg = maxbpg; 565 sblock.fs_rps = rpm / 60; 566 sblock.fs_optim = opt; 567 sblock.fs_cgrotor = 0; 568 sblock.fs_cstotal.cs_ndir = 0; 569 sblock.fs_cstotal.cs_nbfree = 0; 570 sblock.fs_cstotal.cs_nifree = 0; 571 sblock.fs_cstotal.cs_nffree = 0; 572 sblock.fs_fmod = 0; 573 sblock.fs_clean = FS_ISCLEAN; 574 sblock.fs_ronly = 0; 575 /* 576 * Dump out summary information about file system. 577 */ 578 if (!mfs) { 579 printf("%s:\t%d sectors in %d %s of %d tracks, %d sectors\n", 580 fsys, sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl, 581 "cylinders", sblock.fs_ntrak, sblock.fs_nsect); 582 #define B2MBFACTOR (1 / (1024.0 * 1024.0)) 583 printf("\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)\n", 584 (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR, 585 sblock.fs_ncg, sblock.fs_cpg, 586 (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR, 587 sblock.fs_ipg); 588 #undef B2MBFACTOR 589 } 590 /* 591 * Now determine how wide each column will be, and calculate how 592 * many columns will fit in a 76 char line. 76 is the width of the 593 * subwindows in sysinst. 594 */ 595 printcolwidth = count_digits( 596 fsbtodb(&sblock, cgsblock(&sblock, sblock.fs_ncg -1))); 597 nprintcols = 76 / (printcolwidth + 2); 598 /* 599 * Now build the cylinders group blocks and 600 * then print out indices of cylinder groups. 601 */ 602 if (!mfs) 603 printf("super-block backups (for fsck -b #) at:"); 604 for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { 605 initcg(cylno, utime); 606 if (mfs) 607 continue; 608 if (cylno % nprintcols == 0) 609 printf("\n"); 610 printf(" %*d,", printcolwidth, 611 fsbtodb(&sblock, cgsblock(&sblock, cylno))); 612 fflush(stdout); 613 } 614 if (!mfs) 615 printf("\n"); 616 if (Nflag && !mfs) 617 exit(0); 618 /* 619 * Now construct the initial file system, 620 * then write out the super-block. 621 */ 622 if (fsinit(utime, mfsmode, mfsuid, mfsgid) == 0 && mfs) 623 errx(1, "Error making filesystem"); 624 sblock.fs_time = utime; 625 memcpy(writebuf, &sblock, sbsize); 626 if (needswap) 627 ffs_sb_swap(&sblock, (struct fs*)writebuf); 628 wtfs((int)SBOFF / sectorsize, sbsize, writebuf); 629 /* 630 * Write out the duplicate super blocks 631 */ 632 for (cylno = 0; cylno < sblock.fs_ncg; cylno++) 633 wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), 634 sbsize, writebuf); 635 636 /* 637 * if we need to swap, create a buffer for the cylinder summaries 638 * to get swapped to. 639 */ 640 if (needswap) { 641 if ((writebuf2 = malloc(sblock.fs_cssize)) == NULL) 642 exit(12); 643 ffs_csum_swap(fscs, (struct csum*)writebuf2, sblock.fs_cssize); 644 } else 645 writebuf2 = (char *)fscs; 646 647 for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) 648 wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)), 649 sblock.fs_cssize - i < sblock.fs_bsize ? 650 sblock.fs_cssize - i : sblock.fs_bsize, 651 ((char *)writebuf2) + i); 652 if (writebuf2 != (char *)fscs) 653 free(writebuf2); 654 655 /* 656 * Update information about this partion in pack 657 * label, to that it may be updated on disk. 658 */ 659 pp->p_fstype = FS_BSDFFS; 660 pp->p_fsize = sblock.fs_fsize; 661 pp->p_frag = sblock.fs_frag; 662 pp->p_cpg = sblock.fs_cpg; 663 } 664 665 /* 666 * Initialize a cylinder group. 667 */ 668 void 669 initcg(int cylno, time_t utime) 670 { 671 daddr_t cbase, d, dlower, dupper, dmax, blkno; 672 int32_t i; 673 struct csum *cs; 674 675 /* 676 * Determine block bounds for cylinder group. 677 * Allow space for super block summary information in first 678 * cylinder group. 679 */ 680 cbase = cgbase(&sblock, cylno); 681 dmax = cbase + sblock.fs_fpg; 682 if (dmax > sblock.fs_size) 683 dmax = sblock.fs_size; 684 dlower = cgsblock(&sblock, cylno) - cbase; 685 dupper = cgdmin(&sblock, cylno) - cbase; 686 if (cylno == 0) 687 dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); 688 cs = fscs + cylno; 689 memset(&acg, 0, sblock.fs_cgsize); 690 acg.cg_time = utime; 691 acg.cg_magic = CG_MAGIC; 692 acg.cg_cgx = cylno; 693 if (cylno == sblock.fs_ncg - 1) 694 acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg; 695 else 696 acg.cg_ncyl = sblock.fs_cpg; 697 acg.cg_niblk = sblock.fs_ipg; 698 acg.cg_ndblk = dmax - cbase; 699 if (sblock.fs_contigsumsize > 0) 700 acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag; 701 acg.cg_btotoff = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield); 702 acg.cg_boff = acg.cg_btotoff + sblock.fs_cpg * sizeof(int32_t); 703 acg.cg_iusedoff = acg.cg_boff + 704 sblock.fs_cpg * sblock.fs_nrpos * sizeof(int16_t); 705 acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY); 706 if (sblock.fs_contigsumsize <= 0) { 707 acg.cg_nextfreeoff = acg.cg_freeoff + 708 howmany(sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY); 709 } else { 710 acg.cg_clustersumoff = acg.cg_freeoff + howmany 711 (sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY) - 712 sizeof(int32_t); 713 acg.cg_clustersumoff = 714 roundup(acg.cg_clustersumoff, sizeof(int32_t)); 715 acg.cg_clusteroff = acg.cg_clustersumoff + 716 (sblock.fs_contigsumsize + 1) * sizeof(int32_t); 717 acg.cg_nextfreeoff = acg.cg_clusteroff + howmany 718 (sblock.fs_cpg * sblock.fs_spc / NSPB(&sblock), NBBY); 719 } 720 if (acg.cg_nextfreeoff > sblock.fs_cgsize) { 721 printf("Panic: cylinder group too big\n"); 722 exit(37); 723 } 724 acg.cg_cs.cs_nifree += sblock.fs_ipg; 725 if (cylno == 0) 726 for (i = 0; i < ROOTINO; i++) { 727 setbit(cg_inosused(&acg, 0), i); 728 acg.cg_cs.cs_nifree--; 729 } 730 for (i = 0; i < sblock.fs_ipg / INOPF(&sblock); i += sblock.fs_frag) 731 wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i), 732 sblock.fs_bsize, (char *)zino); 733 if (cylno > 0) { 734 /* 735 * In cylno 0, beginning space is reserved 736 * for boot and super blocks. 737 */ 738 for (d = 0; d < dlower; d += sblock.fs_frag) { 739 blkno = d / sblock.fs_frag; 740 setblock(&sblock, cg_blksfree(&acg, 0), blkno); 741 if (sblock.fs_contigsumsize > 0) 742 setbit(cg_clustersfree(&acg, 0), blkno); 743 acg.cg_cs.cs_nbfree++; 744 cg_blktot(&acg, 0)[cbtocylno(&sblock, d)]++; 745 cg_blks(&sblock, &acg, cbtocylno(&sblock, d), 0) 746 [cbtorpos(&sblock, d)]++; 747 } 748 sblock.fs_dsize += dlower; 749 } 750 sblock.fs_dsize += acg.cg_ndblk - dupper; 751 if ((i = (dupper % sblock.fs_frag)) != 0) { 752 acg.cg_frsum[sblock.fs_frag - i]++; 753 for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) { 754 setbit(cg_blksfree(&acg, 0), dupper); 755 acg.cg_cs.cs_nffree++; 756 } 757 } 758 for (d = dupper; d + sblock.fs_frag <= dmax - cbase; ) { 759 blkno = d / sblock.fs_frag; 760 setblock(&sblock, cg_blksfree(&acg, 0), blkno); 761 if (sblock.fs_contigsumsize > 0) 762 setbit(cg_clustersfree(&acg, 0), blkno); 763 acg.cg_cs.cs_nbfree++; 764 cg_blktot(&acg, 0)[cbtocylno(&sblock, d)]++; 765 cg_blks(&sblock, &acg, cbtocylno(&sblock, d), 0) 766 [cbtorpos(&sblock, d)]++; 767 d += sblock.fs_frag; 768 } 769 if (d < dmax - cbase) { 770 acg.cg_frsum[dmax - cbase - d]++; 771 for (; d < dmax - cbase; d++) { 772 setbit(cg_blksfree(&acg, 0), d); 773 acg.cg_cs.cs_nffree++; 774 } 775 } 776 if (sblock.fs_contigsumsize > 0) { 777 int32_t *sump = cg_clustersum(&acg, 0); 778 u_char *mapp = cg_clustersfree(&acg, 0); 779 int map = *mapp++; 780 int bit = 1; 781 int run = 0; 782 783 for (i = 0; i < acg.cg_nclusterblks; i++) { 784 if ((map & bit) != 0) { 785 run++; 786 } else if (run != 0) { 787 if (run > sblock.fs_contigsumsize) 788 run = sblock.fs_contigsumsize; 789 sump[run]++; 790 run = 0; 791 } 792 if ((i & (NBBY - 1)) != (NBBY - 1)) { 793 bit <<= 1; 794 } else { 795 map = *mapp++; 796 bit = 1; 797 } 798 } 799 if (run != 0) { 800 if (run > sblock.fs_contigsumsize) 801 run = sblock.fs_contigsumsize; 802 sump[run]++; 803 } 804 } 805 sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir; 806 sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree; 807 sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree; 808 sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree; 809 *cs = acg.cg_cs; 810 memcpy(writebuf, &acg, sblock.fs_bsize); 811 if (needswap) 812 swap_cg(&acg, (struct cg*)writebuf); 813 wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), 814 sblock.fs_bsize, writebuf); 815 } 816 817 /* 818 * initialize the file system 819 */ 820 struct dinode node; 821 822 #ifdef LOSTDIR 823 #define PREDEFDIR 3 824 #else 825 #define PREDEFDIR 2 826 #endif 827 828 struct direct root_dir[] = { 829 { ROOTINO, sizeof(struct direct), DT_DIR, 1, "." }, 830 { ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." }, 831 #ifdef LOSTDIR 832 { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 10, "lost+found" }, 833 #endif 834 }; 835 struct odirect { 836 u_int32_t d_ino; 837 u_int16_t d_reclen; 838 u_int16_t d_namlen; 839 u_char d_name[MAXNAMLEN + 1]; 840 } oroot_dir[] = { 841 { ROOTINO, sizeof(struct direct), 1, "." }, 842 { ROOTINO, sizeof(struct direct), 2, ".." }, 843 #ifdef LOSTDIR 844 { LOSTFOUNDINO, sizeof(struct direct), 10, "lost+found" }, 845 #endif 846 }; 847 #ifdef LOSTDIR 848 struct direct lost_found_dir[] = { 849 { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 1, "." }, 850 { ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." }, 851 { 0, DIRBLKSIZ, 0, 0, 0 }, 852 }; 853 struct odirect olost_found_dir[] = { 854 { LOSTFOUNDINO, sizeof(struct direct), 1, "." }, 855 { ROOTINO, sizeof(struct direct), 2, ".." }, 856 { 0, DIRBLKSIZ, 0, 0 }, 857 }; 858 #endif 859 char buf[MAXBSIZE]; 860 static void copy_dir(struct direct *, struct direct *); 861 862 int 863 fsinit(time_t utime, mode_t mfsmode, uid_t mfsuid, gid_t mfsgid) 864 { 865 #ifdef LOSTDIR 866 int i; 867 #endif 868 869 /* 870 * initialize the node 871 */ 872 memset(&node, 0, sizeof(node)); 873 node.di_atime = utime; 874 node.di_mtime = utime; 875 node.di_ctime = utime; 876 877 #ifdef LOSTDIR 878 /* 879 * create the lost+found directory 880 */ 881 if (Oflag) { 882 (void)makedir((struct direct *)olost_found_dir, 2); 883 for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ) 884 copy_dir((struct direct*)&olost_found_dir[2], 885 (struct direct*)&buf[i]); 886 } else { 887 (void)makedir(lost_found_dir, 2); 888 for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ) 889 copy_dir(&lost_found_dir[2], (struct direct*)&buf[i]); 890 } 891 node.di_mode = IFDIR | UMASK; 892 node.di_nlink = 2; 893 node.di_size = sblock.fs_bsize; 894 node.di_db[0] = alloc(node.di_size, node.di_mode); 895 node.di_blocks = btodb(fragroundup(&sblock, node.di_size)); 896 node.di_uid = geteuid(); 897 node.di_gid = getegid(); 898 wtfs(fsbtodb(&sblock, node.di_db[0]), node.di_size, buf); 899 iput(&node, LOSTFOUNDINO); 900 #endif 901 /* 902 * create the root directory 903 */ 904 if (mfs) { 905 node.di_mode = IFDIR | mfsmode; 906 node.di_uid = mfsuid; 907 node.di_gid = mfsgid; 908 } else { 909 node.di_mode = IFDIR | UMASK; 910 node.di_uid = geteuid(); 911 node.di_gid = getegid(); 912 } 913 node.di_nlink = PREDEFDIR; 914 if (Oflag) 915 node.di_size = makedir((struct direct *)oroot_dir, PREDEFDIR); 916 else 917 node.di_size = makedir(root_dir, PREDEFDIR); 918 node.di_db[0] = alloc(sblock.fs_fsize, node.di_mode); 919 if (node.di_db[0] == 0) 920 return (0); 921 node.di_blocks = btodb(fragroundup(&sblock, node.di_size)); 922 wtfs(fsbtodb(&sblock, node.di_db[0]), sblock.fs_fsize, buf); 923 iput(&node, ROOTINO); 924 return (1); 925 } 926 927 /* 928 * construct a set of directory entries in "buf". 929 * return size of directory. 930 */ 931 int 932 makedir(struct direct *protodir, int entries) 933 { 934 char *cp; 935 int i, spcleft; 936 937 spcleft = DIRBLKSIZ; 938 for (cp = buf, i = 0; i < entries - 1; i++) { 939 protodir[i].d_reclen = DIRSIZ(Oflag, &protodir[i], 0); 940 copy_dir(&protodir[i], (struct direct*)cp); 941 cp += protodir[i].d_reclen; 942 spcleft -= protodir[i].d_reclen; 943 } 944 protodir[i].d_reclen = spcleft; 945 copy_dir(&protodir[i], (struct direct*)cp); 946 return (DIRBLKSIZ); 947 } 948 949 /* 950 * allocate a block or frag 951 */ 952 daddr_t 953 alloc(int size, int mode) 954 { 955 int i, frag; 956 daddr_t d, blkno; 957 958 rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, &acg); 959 /* fs -> host byte order */ 960 if (needswap) 961 swap_cg(&acg, &acg); 962 if (acg.cg_magic != CG_MAGIC) { 963 printf("cg 0: bad magic number\n"); 964 return (0); 965 } 966 if (acg.cg_cs.cs_nbfree == 0) { 967 printf("first cylinder group ran out of space\n"); 968 return (0); 969 } 970 for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag) 971 if (isblock(&sblock, cg_blksfree(&acg, 0), d / sblock.fs_frag)) 972 goto goth; 973 printf("internal error: can't find block in cyl 0\n"); 974 return (0); 975 goth: 976 blkno = fragstoblks(&sblock, d); 977 clrblock(&sblock, cg_blksfree(&acg, 0), blkno); 978 if (sblock.fs_contigsumsize > 0) 979 clrbit(cg_clustersfree(&acg, 0), blkno); 980 acg.cg_cs.cs_nbfree--; 981 sblock.fs_cstotal.cs_nbfree--; 982 fscs[0].cs_nbfree--; 983 if (mode & IFDIR) { 984 acg.cg_cs.cs_ndir++; 985 sblock.fs_cstotal.cs_ndir++; 986 fscs[0].cs_ndir++; 987 } 988 cg_blktot(&acg, 0)[cbtocylno(&sblock, d)]--; 989 cg_blks(&sblock, &acg, cbtocylno(&sblock, d), 0)[cbtorpos(&sblock, d)]--; 990 if (size != sblock.fs_bsize) { 991 frag = howmany(size, sblock.fs_fsize); 992 fscs[0].cs_nffree += sblock.fs_frag - frag; 993 sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag; 994 acg.cg_cs.cs_nffree += sblock.fs_frag - frag; 995 acg.cg_frsum[sblock.fs_frag - frag]++; 996 for (i = frag; i < sblock.fs_frag; i++) 997 setbit(cg_blksfree(&acg, 0), d + i); 998 } 999 /* host -> fs byte order */ 1000 if (needswap) 1001 swap_cg(&acg, &acg); 1002 wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 1003 (char *)&acg); 1004 return (d); 1005 } 1006 1007 /* 1008 * Calculate number of inodes per group. 1009 */ 1010 int32_t 1011 calcipg(int32_t cylpg, int32_t bpcg, off_t *usedbp) 1012 { 1013 int i; 1014 int32_t ipg, new_ipg, ncg, ncyl; 1015 off_t usedb; 1016 1017 /* 1018 * Prepare to scale by fssize / (number of sectors in cylinder groups). 1019 * Note that fssize is still in sectors, not file system blocks. 1020 */ 1021 ncyl = howmany(fssize, secpercyl); 1022 ncg = howmany(ncyl, cylpg); 1023 /* 1024 * Iterate a few times to allow for ipg depending on itself. 1025 */ 1026 ipg = 0; 1027 for (i = 0; i < 10; i++) { 1028 usedb = (sblock.fs_iblkno + ipg / INOPF(&sblock)) 1029 * NSPF(&sblock) * (off_t)sectorsize; 1030 new_ipg = (cylpg * (long long)bpcg - usedb) / 1031 (long long)density * fssize / (ncg * secpercyl * cylpg); 1032 if (new_ipg <= 0) 1033 new_ipg = 1; /* ensure ipg > 0 */ 1034 new_ipg = roundup(new_ipg, INOPB(&sblock)); 1035 if (new_ipg == ipg) 1036 break; 1037 ipg = new_ipg; 1038 } 1039 *usedbp = usedb; 1040 return (ipg); 1041 } 1042 1043 /* 1044 * Allocate an inode on the disk 1045 */ 1046 static void 1047 iput(struct dinode *ip, ino_t ino) 1048 { 1049 struct dinode ibuf[MAXINOPB]; 1050 daddr_t d; 1051 int c, i; 1052 1053 c = ino_to_cg(&sblock, ino); 1054 rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, &acg); 1055 /* fs -> host byte order */ 1056 if (needswap) 1057 swap_cg(&acg, &acg); 1058 if (acg.cg_magic != CG_MAGIC) { 1059 printf("cg 0: bad magic number\n"); 1060 exit(31); 1061 } 1062 acg.cg_cs.cs_nifree--; 1063 setbit(cg_inosused(&acg, 0), ino); 1064 /* host -> fs byte order */ 1065 if (needswap) 1066 swap_cg(&acg, &acg); 1067 wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 1068 (char *)&acg); 1069 sblock.fs_cstotal.cs_nifree--; 1070 fscs[0].cs_nifree--; 1071 if (ino >= sblock.fs_ipg * sblock.fs_ncg) { 1072 printf("fsinit: inode value out of range (%d).\n", ino); 1073 exit(32); 1074 } 1075 d = fsbtodb(&sblock, ino_to_fsba(&sblock, ino)); 1076 rdfs(d, sblock.fs_bsize, ibuf); 1077 if (needswap) { 1078 ffs_dinode_swap(ip, &ibuf[ino_to_fsbo(&sblock, ino)]); 1079 /* ffs_dinode_swap() doesn't swap blocks addrs */ 1080 for (i=0; i<NDADDR + NIADDR; i++) 1081 (&ibuf[ino_to_fsbo(&sblock, ino)])->di_db[i] = 1082 bswap32(ip->di_db[i]); 1083 } else 1084 ibuf[ino_to_fsbo(&sblock, ino)] = *ip; 1085 wtfs(d, sblock.fs_bsize, ibuf); 1086 } 1087 1088 /* 1089 * read a block from the file system 1090 */ 1091 void 1092 rdfs(daddr_t bno, int size, void *bf) 1093 { 1094 int n; 1095 off_t offset; 1096 1097 #ifdef MFS 1098 if (mfs) { 1099 memmove(bf, membase + bno * sectorsize, size); 1100 return; 1101 } 1102 #endif 1103 offset = bno; 1104 offset *= sectorsize; 1105 if (lseek(fsi, offset, SEEK_SET) < 0) { 1106 printf("rdfs: seek error for sector %d: %s\n", 1107 bno, strerror(errno)); 1108 exit(33); 1109 } 1110 n = read(fsi, bf, size); 1111 if (n != size) { 1112 printf("rdfs: read error for sector %d: %s\n", 1113 bno, strerror(errno)); 1114 exit(34); 1115 } 1116 } 1117 1118 /* 1119 * write a block to the file system 1120 */ 1121 void 1122 wtfs(daddr_t bno, int size, void *bf) 1123 { 1124 int n; 1125 off_t offset; 1126 1127 #ifdef MFS 1128 if (mfs) { 1129 memmove(membase + bno * sectorsize, bf, size); 1130 return; 1131 } 1132 #endif 1133 if (Nflag) 1134 return; 1135 offset = bno; 1136 offset *= sectorsize; 1137 if (lseek(fso, offset, SEEK_SET) < 0) { 1138 printf("wtfs: seek error for sector %d: %s\n", 1139 bno, strerror(errno)); 1140 exit(35); 1141 } 1142 n = write(fso, bf, size); 1143 if (n != size) { 1144 printf("wtfs: write error for sector %d: %s\n", 1145 bno, strerror(errno)); 1146 exit(36); 1147 } 1148 } 1149 1150 /* 1151 * check if a block is available 1152 */ 1153 int 1154 isblock(struct fs *fs, unsigned char *cp, int h) 1155 { 1156 unsigned char mask; 1157 1158 switch (fs->fs_frag) { 1159 case 8: 1160 return (cp[h] == 0xff); 1161 case 4: 1162 mask = 0x0f << ((h & 0x1) << 2); 1163 return ((cp[h >> 1] & mask) == mask); 1164 case 2: 1165 mask = 0x03 << ((h & 0x3) << 1); 1166 return ((cp[h >> 2] & mask) == mask); 1167 case 1: 1168 mask = 0x01 << (h & 0x7); 1169 return ((cp[h >> 3] & mask) == mask); 1170 default: 1171 #ifdef STANDALONE 1172 printf("isblock bad fs_frag %d\n", fs->fs_frag); 1173 #else 1174 fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); 1175 #endif 1176 return (0); 1177 } 1178 } 1179 1180 /* 1181 * take a block out of the map 1182 */ 1183 void 1184 clrblock(struct fs *fs, unsigned char *cp, int h) 1185 { 1186 switch ((fs)->fs_frag) { 1187 case 8: 1188 cp[h] = 0; 1189 return; 1190 case 4: 1191 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 1192 return; 1193 case 2: 1194 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 1195 return; 1196 case 1: 1197 cp[h >> 3] &= ~(0x01 << (h & 0x7)); 1198 return; 1199 default: 1200 #ifdef STANDALONE 1201 printf("clrblock bad fs_frag %d\n", fs->fs_frag); 1202 #else 1203 fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag); 1204 #endif 1205 return; 1206 } 1207 } 1208 1209 /* 1210 * put a block into the map 1211 */ 1212 void 1213 setblock(struct fs *fs, unsigned char *cp, int h) 1214 { 1215 switch (fs->fs_frag) { 1216 case 8: 1217 cp[h] = 0xff; 1218 return; 1219 case 4: 1220 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 1221 return; 1222 case 2: 1223 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 1224 return; 1225 case 1: 1226 cp[h >> 3] |= (0x01 << (h & 0x7)); 1227 return; 1228 default: 1229 #ifdef STANDALONE 1230 printf("setblock bad fs_frag %d\n", fs->fs_frag); 1231 #else 1232 fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag); 1233 #endif 1234 return; 1235 } 1236 } 1237 1238 /* swap byte order of cylinder group */ 1239 static void 1240 swap_cg(struct cg *o, struct cg *n) 1241 { 1242 int i, btotsize, fbsize; 1243 u_int32_t *n32, *o32; 1244 u_int16_t *n16, *o16; 1245 1246 n->cg_firstfield = bswap32(o->cg_firstfield); 1247 n->cg_magic = bswap32(o->cg_magic); 1248 n->cg_time = bswap32(o->cg_time); 1249 n->cg_cgx = bswap32(o->cg_cgx); 1250 n->cg_ncyl = bswap16(o->cg_ncyl); 1251 n->cg_niblk = bswap16(o->cg_niblk); 1252 n->cg_ndblk = bswap32(o->cg_ndblk); 1253 n->cg_cs.cs_ndir = bswap32(o->cg_cs.cs_ndir); 1254 n->cg_cs.cs_nbfree = bswap32(o->cg_cs.cs_nbfree); 1255 n->cg_cs.cs_nifree = bswap32(o->cg_cs.cs_nifree); 1256 n->cg_cs.cs_nffree = bswap32(o->cg_cs.cs_nffree); 1257 n->cg_rotor = bswap32(o->cg_rotor); 1258 n->cg_frotor = bswap32(o->cg_frotor); 1259 n->cg_irotor = bswap32(o->cg_irotor); 1260 n->cg_btotoff = bswap32(o->cg_btotoff); 1261 n->cg_boff = bswap32(o->cg_boff); 1262 n->cg_iusedoff = bswap32(o->cg_iusedoff); 1263 n->cg_freeoff = bswap32(o->cg_freeoff); 1264 n->cg_nextfreeoff = bswap32(o->cg_nextfreeoff); 1265 n->cg_clustersumoff = bswap32(o->cg_clustersumoff); 1266 n->cg_clusteroff = bswap32(o->cg_clusteroff); 1267 n->cg_nclusterblks = bswap32(o->cg_nclusterblks); 1268 for (i=0; i < MAXFRAG; i++) 1269 n->cg_frsum[i] = bswap32(o->cg_frsum[i]); 1270 1271 /* alays new format */ 1272 if (n->cg_magic == CG_MAGIC) { 1273 btotsize = n->cg_boff - n->cg_btotoff; 1274 fbsize = n->cg_iusedoff - n->cg_boff; 1275 n32 = (u_int32_t*)((u_int8_t*)n + n->cg_btotoff); 1276 o32 = (u_int32_t*)((u_int8_t*)o + n->cg_btotoff); 1277 n16 = (u_int16_t*)((u_int8_t*)n + n->cg_boff); 1278 o16 = (u_int16_t*)((u_int8_t*)o + n->cg_boff); 1279 } else { 1280 btotsize = bswap32(n->cg_boff) - bswap32(n->cg_btotoff); 1281 fbsize = bswap32(n->cg_iusedoff) - bswap32(n->cg_boff); 1282 n32 = (u_int32_t*)((u_int8_t*)n + bswap32(n->cg_btotoff)); 1283 o32 = (u_int32_t*)((u_int8_t*)o + bswap32(n->cg_btotoff)); 1284 n16 = (u_int16_t*)((u_int8_t*)n + bswap32(n->cg_boff)); 1285 o16 = (u_int16_t*)((u_int8_t*)o + bswap32(n->cg_boff)); 1286 } 1287 for (i=0; i < btotsize / sizeof(u_int32_t); i++) 1288 n32[i] = bswap32(o32[i]); 1289 1290 for (i=0; i < fbsize/sizeof(u_int16_t); i++) 1291 n16[i] = bswap16(o16[i]); 1292 1293 if (n->cg_magic == CG_MAGIC) { 1294 n32 = (u_int32_t*)((u_int8_t*)n + n->cg_clustersumoff); 1295 o32 = (u_int32_t*)((u_int8_t*)o + n->cg_clustersumoff); 1296 } else { 1297 n32 = (u_int32_t*)((u_int8_t*)n + bswap32(n->cg_clustersumoff)); 1298 o32 = (u_int32_t*)((u_int8_t*)o + bswap32(n->cg_clustersumoff)); 1299 } 1300 for (i = 1; i < sblock.fs_contigsumsize + 1; i++) 1301 n32[i] = bswap32(o32[i]); 1302 } 1303 1304 /* copy a direntry to a buffer, in fs byte order */ 1305 static void 1306 copy_dir(struct direct *dir, struct direct *dbuf) 1307 { 1308 memcpy(dbuf, dir, DIRSIZ(Oflag, dir, 0)); 1309 if (needswap) { 1310 dbuf->d_ino = bswap32(dir->d_ino); 1311 dbuf->d_reclen = bswap16(dir->d_reclen); 1312 if (Oflag) 1313 ((struct odirect*)dbuf)->d_namlen = 1314 bswap16(((struct odirect*)dir)->d_namlen); 1315 } 1316 } 1317 1318 /* Determine how many digits are needed to print a given integer */ 1319 static int 1320 count_digits(int num) 1321 { 1322 int ndig; 1323 1324 for(ndig = 1; num > 9; num /=10, ndig++); 1325 1326 return (ndig); 1327 } 1328 1329 #ifdef MFS 1330 /* 1331 * XXX! 1332 * Attempt to guess how much more space is available for process data. The 1333 * heuristic we use is 1334 * 1335 * max_data_limit - (sbrk(0) - etext) - 128kB 1336 * 1337 * etext approximates that start address of the data segment, and the 128kB 1338 * allows some slop for both segment gap between text and data, and for other 1339 * (libc) malloc usage. 1340 */ 1341 static void 1342 calc_memfree(void) 1343 { 1344 extern char etext; 1345 struct rlimit rlp; 1346 u_long base; 1347 1348 base = (u_long)sbrk(0) - (u_long)&etext; 1349 if (getrlimit(RLIMIT_DATA, &rlp) < 0) 1350 perror("getrlimit"); 1351 rlp.rlim_cur = rlp.rlim_max; 1352 if (setrlimit(RLIMIT_DATA, &rlp) < 0) 1353 perror("setrlimit"); 1354 memleft = rlp.rlim_max - base - (128 * 1024); 1355 } 1356 1357 /* 1358 * Internal version of malloc that trims the requested size if not enough 1359 * memory is available. 1360 */ 1361 static void * 1362 mkfs_malloc(size_t size) 1363 { 1364 u_long pgsz; 1365 1366 if (size == 0) 1367 return (NULL); 1368 if (memleft == 0) 1369 calc_memfree(); 1370 1371 pgsz = getpagesize() - 1; 1372 size = (size + pgsz) &~ pgsz; 1373 if (size > memleft) 1374 size = memleft; 1375 memleft -= size; 1376 return (mmap(0, size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 1377 -1, 0)); 1378 } 1379 #endif /* MFS */ 1380