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