1 /* $NetBSD: mkfs.c,v 1.100 2006/01/21 12:32:14 simonb 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. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright (c) 2002 Networks Associates Technology, Inc. 34 * All rights reserved. 35 * 36 * This software was developed for the FreeBSD Project by Marshall 37 * Kirk McKusick and Network Associates Laboratories, the Security 38 * Research Division of Network Associates, Inc. under DARPA/SPAWAR 39 * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS 40 * research program 41 * 42 * Redistribution and use in source and binary forms, with or without 43 * modification, are permitted provided that the following conditions 44 * are met: 45 * 1. Redistributions of source code must retain the above copyright 46 * notice, this list of conditions and the following disclaimer. 47 * 2. Redistributions in binary form must reproduce the above copyright 48 * notice, this list of conditions and the following disclaimer in the 49 * documentation and/or other materials provided with the distribution. 50 * 3. All advertising materials mentioning features or use of this software 51 * must display the following acknowledgement: 52 * This product includes software developed by the University of 53 * California, Berkeley and its contributors. 54 * 4. Neither the name of the University nor the names of its contributors 55 * may be used to endorse or promote products derived from this software 56 * without specific prior written permission. 57 * 58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 68 * SUCH DAMAGE. 69 */ 70 71 #include <sys/cdefs.h> 72 #ifndef lint 73 #if 0 74 static char sccsid[] = "@(#)mkfs.c 8.11 (Berkeley) 5/3/95"; 75 #else 76 __RCSID("$NetBSD: mkfs.c,v 1.100 2006/01/21 12:32:14 simonb Exp $"); 77 #endif 78 #endif /* not lint */ 79 80 #include <sys/param.h> 81 #include <sys/mman.h> 82 #include <sys/time.h> 83 #include <sys/resource.h> 84 #include <ufs/ufs/dinode.h> 85 #include <ufs/ufs/dir.h> 86 #include <ufs/ufs/ufs_bswap.h> 87 #include <ufs/ffs/fs.h> 88 #include <ufs/ffs/ffs_extern.h> 89 #include <sys/ioctl.h> 90 #include <sys/disklabel.h> 91 92 #include <err.h> 93 #include <errno.h> 94 #include <string.h> 95 #include <unistd.h> 96 #include <stdlib.h> 97 #include <stddef.h> 98 99 #ifndef STANDALONE 100 #include <stdio.h> 101 #endif 102 103 #include "extern.h" 104 105 union dinode { 106 struct ufs1_dinode dp1; 107 struct ufs2_dinode dp2; 108 }; 109 110 static void initcg(int, const struct timeval *); 111 static int fsinit(const struct timeval *, mode_t, uid_t, gid_t); 112 static int makedir(struct direct *, int); 113 static daddr_t alloc(int, int); 114 static void iput(union dinode *, ino_t); 115 static void rdfs(daddr_t, int, void *); 116 static void wtfs(daddr_t, int, void *); 117 static int isblock(struct fs *, unsigned char *, int); 118 static void clrblock(struct fs *, unsigned char *, int); 119 static void setblock(struct fs *, unsigned char *, int); 120 static int ilog2(int); 121 static void zap_old_sblock(int); 122 #ifdef MFS 123 static void calc_memfree(void); 124 static void *mkfs_malloc(size_t size); 125 #endif 126 127 /* 128 * make file system for cylinder-group style file systems 129 */ 130 #define UMASK 0755 131 #define POWEROF2(num) (((num) & ((num) - 1)) == 0) 132 133 union { 134 struct fs fs; 135 char pad[SBLOCKSIZE]; 136 } fsun; 137 #define sblock fsun.fs 138 139 struct csum *fscs_0; /* first block of cylinder summaries */ 140 struct csum *fscs_next; /* place for next summary */ 141 struct csum *fscs_end; /* end of summary buffer */ 142 struct csum *fscs_reset; /* place for next summary after write */ 143 uint fs_csaddr; /* fragment number to write to */ 144 145 union { 146 struct cg cg; 147 char pad[MAXBSIZE]; 148 } cgun; 149 #define acg cgun.cg 150 151 #define DIP(dp, field) \ 152 ((sblock.fs_magic == FS_UFS1_MAGIC) ? \ 153 (dp)->dp1.di_##field : (dp)->dp2.di_##field) 154 155 char *iobuf; 156 int iobufsize; /* size to end of 2nd inode block */ 157 int iobuf_memsize; /* Actual buffer size */ 158 159 int fsi, fso; 160 161 void 162 mkfs(struct partition *pp, const char *fsys, int fi, int fo, 163 mode_t mfsmode, uid_t mfsuid, gid_t mfsgid) 164 { 165 uint fragsperinodeblk, ncg; 166 uint cgzero; 167 uint64_t inodeblks, cgall; 168 int32_t cylno, i, csfrags; 169 int inodes_per_cg; 170 struct timeval tv; 171 long long sizepb; 172 int len, col, delta, fld_width, max_cols; 173 struct winsize winsize; 174 175 #ifndef STANDALONE 176 gettimeofday(&tv, NULL); 177 #endif 178 #ifdef MFS 179 if (mfs && !Nflag) { 180 calc_memfree(); 181 if (fssize * sectorsize > memleft) 182 fssize = memleft / sectorsize; 183 if ((membase = mkfs_malloc(fssize * sectorsize)) == 0) 184 exit(12); 185 } 186 #endif 187 fsi = fi; 188 fso = fo; 189 if (Oflag == 0) { 190 sblock.fs_old_inodefmt = FS_42INODEFMT; 191 sblock.fs_maxsymlinklen = 0; 192 sblock.fs_old_flags = 0; 193 } else { 194 sblock.fs_old_inodefmt = FS_44INODEFMT; 195 sblock.fs_maxsymlinklen = (Oflag == 1 ? MAXSYMLINKLEN_UFS1 : 196 MAXSYMLINKLEN_UFS2); 197 sblock.fs_old_flags = FS_FLAGS_UPDATED; 198 if (isappleufs) 199 sblock.fs_old_flags = 0; 200 sblock.fs_flags = 0; 201 } 202 203 /* 204 * collect and verify the filesystem density info 205 */ 206 sblock.fs_avgfilesize = avgfilesize; 207 sblock.fs_avgfpdir = avgfpdir; 208 if (sblock.fs_avgfilesize <= 0) { 209 printf("illegal expected average file size %d\n", 210 sblock.fs_avgfilesize); 211 exit(14); 212 } 213 if (sblock.fs_avgfpdir <= 0) { 214 printf("illegal expected number of files per directory %d\n", 215 sblock.fs_avgfpdir); 216 exit(15); 217 } 218 /* 219 * collect and verify the block and fragment sizes 220 */ 221 sblock.fs_bsize = bsize; 222 sblock.fs_fsize = fsize; 223 if (!POWEROF2(sblock.fs_bsize)) { 224 printf("block size must be a power of 2, not %d\n", 225 sblock.fs_bsize); 226 exit(16); 227 } 228 if (!POWEROF2(sblock.fs_fsize)) { 229 printf("fragment size must be a power of 2, not %d\n", 230 sblock.fs_fsize); 231 exit(17); 232 } 233 if (sblock.fs_fsize < sectorsize) { 234 printf("fragment size %d is too small, minimum is %d\n", 235 sblock.fs_fsize, sectorsize); 236 exit(18); 237 } 238 if (sblock.fs_bsize < MINBSIZE) { 239 printf("block size %d is too small, minimum is %d\n", 240 sblock.fs_bsize, MINBSIZE); 241 exit(19); 242 } 243 if (sblock.fs_bsize > MAXBSIZE) { 244 printf("block size %d is too large, maximum is %d\n", 245 sblock.fs_bsize, MAXBSIZE); 246 exit(19); 247 } 248 if (sblock.fs_bsize < sblock.fs_fsize) { 249 printf("block size (%d) cannot be smaller than fragment size (%d)\n", 250 sblock.fs_bsize, sblock.fs_fsize); 251 exit(20); 252 } 253 254 if (maxbsize < bsize || !POWEROF2(maxbsize)) { 255 sblock.fs_maxbsize = sblock.fs_bsize; 256 } else if (sblock.fs_maxbsize > FS_MAXCONTIG * sblock.fs_bsize) { 257 sblock.fs_maxbsize = FS_MAXCONTIG * sblock.fs_bsize; 258 } else { 259 sblock.fs_maxbsize = maxbsize; 260 } 261 sblock.fs_maxcontig = maxcontig; 262 if (sblock.fs_maxcontig < sblock.fs_maxbsize / sblock.fs_bsize) { 263 sblock.fs_maxcontig = sblock.fs_maxbsize / sblock.fs_bsize; 264 if (verbosity > 0) 265 printf("Maxcontig raised to %d\n", sblock.fs_maxbsize); 266 } 267 if (sblock.fs_maxcontig > 1) 268 sblock.fs_contigsumsize = MIN(sblock.fs_maxcontig,FS_MAXCONTIG); 269 270 sblock.fs_bmask = ~(sblock.fs_bsize - 1); 271 sblock.fs_fmask = ~(sblock.fs_fsize - 1); 272 sblock.fs_qbmask = ~sblock.fs_bmask; 273 sblock.fs_qfmask = ~sblock.fs_fmask; 274 for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1) 275 sblock.fs_bshift++; 276 for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1) 277 sblock.fs_fshift++; 278 sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize); 279 for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1) 280 sblock.fs_fragshift++; 281 if (sblock.fs_frag > MAXFRAG) { 282 printf("fragment size %d is too small, " 283 "minimum with block size %d is %d\n", 284 sblock.fs_fsize, sblock.fs_bsize, 285 sblock.fs_bsize / MAXFRAG); 286 exit(21); 287 } 288 sblock.fs_fsbtodb = ilog2(sblock.fs_fsize / sectorsize); 289 sblock.fs_size = dbtofsb(&sblock, fssize); 290 if (Oflag <= 1) { 291 if (sblock.fs_size >= 1ull << 31) { 292 printf("Too many fragments (0x%" PRIx64 293 ") for a UFS1 filesystem\n", sblock.fs_size); 294 exit(22); 295 } 296 sblock.fs_magic = FS_UFS1_MAGIC; 297 sblock.fs_sblockloc = SBLOCK_UFS1; 298 sblock.fs_nindir = sblock.fs_bsize / sizeof(int32_t); 299 sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs1_dinode); 300 sblock.fs_old_cgoffset = 0; 301 sblock.fs_old_cgmask = 0xffffffff; 302 sblock.fs_old_size = sblock.fs_size; 303 sblock.fs_old_rotdelay = 0; 304 sblock.fs_old_rps = 60; 305 sblock.fs_old_nspf = sblock.fs_fsize / sectorsize; 306 sblock.fs_old_cpg = 1; 307 sblock.fs_old_interleave = 1; 308 sblock.fs_old_trackskew = 0; 309 sblock.fs_old_cpc = 0; 310 sblock.fs_old_postblformat = FS_DYNAMICPOSTBLFMT; 311 sblock.fs_old_nrpos = 1; 312 } else { 313 sblock.fs_magic = FS_UFS2_MAGIC; 314 sblock.fs_sblockloc = SBLOCK_UFS2; 315 sblock.fs_nindir = sblock.fs_bsize / sizeof(int64_t); 316 sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs2_dinode); 317 } 318 319 sblock.fs_sblkno = 320 roundup(howmany(sblock.fs_sblockloc + SBLOCKSIZE, sblock.fs_fsize), 321 sblock.fs_frag); 322 sblock.fs_cblkno = (daddr_t)(sblock.fs_sblkno + 323 roundup(howmany(SBLOCKSIZE, sblock.fs_fsize), sblock.fs_frag)); 324 sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag; 325 sblock.fs_maxfilesize = sblock.fs_bsize * NDADDR - 1; 326 for (sizepb = sblock.fs_bsize, i = 0; i < NIADDR; i++) { 327 sizepb *= NINDIR(&sblock); 328 sblock.fs_maxfilesize += sizepb; 329 } 330 331 /* 332 * Calculate the number of blocks to put into each cylinder group. 333 * 334 * The cylinder group size is limited because the data structure 335 * must fit into a single block. 336 * We try to have as few cylinder groups as possible, with a proviso 337 * that we create at least MINCYLGRPS (==4) except for small 338 * filesystems. 339 * 340 * This algorithm works out how many blocks of inodes would be 341 * needed to fill the entire volume at the specified density. 342 * It then looks at how big the 'cylinder block' would have to 343 * be and, assuming that it is linearly related to the number 344 * of inodes and blocks how many cylinder groups are needed to 345 * keep the cylinder block below the filesystem block size. 346 * 347 * The cylinder groups are then all created with the average size. 348 * 349 * Space taken by the red tape on cylinder groups other than the 350 * first is ignored. 351 */ 352 353 /* There must be space for 1 inode block and 2 data blocks */ 354 if (sblock.fs_size < sblock.fs_iblkno + 3 * sblock.fs_frag) { 355 printf("Filesystem size %lld < minimum size of %d\n", 356 (long long)sblock.fs_size, sblock.fs_iblkno + 3 * sblock.fs_frag); 357 exit(23); 358 } 359 if (num_inodes != 0) 360 inodeblks = howmany(num_inodes, INOPB(&sblock)); 361 else { 362 /* 363 * Calculate 'per inode block' so we can allocate less than 364 * 1 fragment per inode - useful for /dev. 365 */ 366 fragsperinodeblk = MAX(numfrags(&sblock, 367 (uint64_t)density * INOPB(&sblock)), 1); 368 inodeblks = (sblock.fs_size - sblock.fs_iblkno) / 369 (sblock.fs_frag + fragsperinodeblk); 370 } 371 if (inodeblks == 0) 372 inodeblks = 1; 373 /* Ensure that there are at least 2 data blocks (or we fail below) */ 374 if (inodeblks > (sblock.fs_size - sblock.fs_iblkno)/sblock.fs_frag - 2) 375 inodeblks = (sblock.fs_size-sblock.fs_iblkno)/sblock.fs_frag-2; 376 /* Even UFS2 limits number of inodes to 2^31 (fs_ipg is int32_t) */ 377 if (inodeblks * INOPB(&sblock) >= 1ull << 31) 378 inodeblks = ((1ull << 31) - NBBY) / INOPB(&sblock); 379 /* 380 * See what would happen if we tried to use 1 cylinder group. 381 * Assume space linear, so work out number of cylinder groups needed. 382 */ 383 cgzero = CGSIZE_IF(&sblock, 0, 0); 384 cgall = CGSIZE_IF(&sblock, inodeblks * INOPB(&sblock), sblock.fs_size); 385 ncg = howmany(cgall - cgzero, sblock.fs_bsize - cgzero); 386 if (ncg < MINCYLGRPS) { 387 /* 388 * We would like to allocate MINCLYGRPS cylinder groups, 389 * but for small file sytems (especially ones with a lot 390 * of inodes) this is not desirable (or possible). 391 */ 392 i = sblock.fs_size / 2 / (sblock.fs_iblkno + 393 inodeblks * sblock.fs_frag); 394 if (i > ncg) 395 ncg = i; 396 if (ncg > MINCYLGRPS) 397 ncg = MINCYLGRPS; 398 if (ncg > inodeblks) 399 ncg = inodeblks; 400 } 401 /* 402 * Put an equal number of blocks in each cylinder group. 403 * Round up so we don't have more fragments in the last CG than 404 * the earlier ones (does that matter?), but kill a block if the 405 * CGSIZE becomes too big (only happens if there are a lot of CGs). 406 */ 407 sblock.fs_fpg = roundup(howmany(sblock.fs_size, ncg), sblock.fs_frag); 408 /* Round up the fragments/group so the bitmap bytes are full */ 409 sblock.fs_fpg = roundup(sblock.fs_fpg, NBBY); 410 inodes_per_cg = ((inodeblks - 1) / ncg + 1) * INOPB(&sblock); 411 412 i = CGSIZE_IF(&sblock, inodes_per_cg, sblock.fs_fpg); 413 if (i > sblock.fs_bsize) { 414 sblock.fs_fpg -= (i - sblock.fs_bsize) * NBBY; 415 /* ... and recalculate how many cylinder groups we now need */ 416 ncg = howmany(sblock.fs_size, sblock.fs_fpg); 417 inodes_per_cg = ((inodeblks - 1) / ncg + 1) * INOPB(&sblock); 418 } 419 sblock.fs_ipg = inodes_per_cg; 420 /* Sanity check on our sums... */ 421 if (CGSIZE(&sblock) > sblock.fs_bsize) { 422 printf("CGSIZE miscalculated %d > %d\n", 423 (int)CGSIZE(&sblock), sblock.fs_bsize); 424 exit(24); 425 } 426 427 sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock); 428 /* Check that the last cylinder group has enough space for the inodes */ 429 i = sblock.fs_size - sblock.fs_fpg * (ncg - 1ull); 430 if (i < sblock.fs_dblkno) { 431 /* 432 * Since we make all the cylinder groups the same size, the 433 * last will only be small if there are a large number of 434 * cylinder groups. If we pull even a fragment from each 435 * of the other groups then the last CG will be overfull. 436 * So we just kill the last CG. 437 */ 438 ncg--; 439 sblock.fs_size -= i; 440 } 441 sblock.fs_ncg = ncg; 442 443 sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock)); 444 if (Oflag <= 1) { 445 sblock.fs_old_spc = sblock.fs_fpg * sblock.fs_old_nspf; 446 sblock.fs_old_nsect = sblock.fs_old_spc; 447 sblock.fs_old_npsect = sblock.fs_old_spc; 448 sblock.fs_old_ncyl = sblock.fs_ncg; 449 } 450 451 /* 452 * Cylinder group summary information for each cylinder is written 453 * into the first cylinder group. 454 * Write this fragment by fragment, but doing the first CG last 455 * (after we've taken stuff off for the structure itself and the 456 * root directory. 457 */ 458 sblock.fs_csaddr = cgdmin(&sblock, 0); 459 sblock.fs_cssize = 460 fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum)); 461 if (512 % sizeof *fscs_0) 462 errx(1, "cylinder group summary doesn't fit in sectors"); 463 fscs_0 = mmap(0, 2 * sblock.fs_fsize, PROT_READ|PROT_WRITE, 464 MAP_ANON|MAP_PRIVATE, -1, 0); 465 if (fscs_0 == NULL) 466 exit(39); 467 memset(fscs_0, 0, 2 * sblock.fs_fsize); 468 fs_csaddr = sblock.fs_csaddr; 469 fscs_next = fscs_0; 470 fscs_end = (void *)((char *)fscs_0 + 2 * sblock.fs_fsize); 471 fscs_reset = (void *)((char *)fscs_0 + sblock.fs_fsize); 472 /* 473 * fill in remaining fields of the super block 474 */ 475 sblock.fs_sbsize = fragroundup(&sblock, sizeof(struct fs)); 476 if (sblock.fs_sbsize > SBLOCKSIZE) 477 sblock.fs_sbsize = SBLOCKSIZE; 478 sblock.fs_minfree = minfree; 479 sblock.fs_maxcontig = maxcontig; 480 sblock.fs_maxbpg = maxbpg; 481 sblock.fs_optim = opt; 482 sblock.fs_cgrotor = 0; 483 sblock.fs_pendingblocks = 0; 484 sblock.fs_pendinginodes = 0; 485 sblock.fs_cstotal.cs_ndir = 0; 486 sblock.fs_cstotal.cs_nbfree = 0; 487 sblock.fs_cstotal.cs_nifree = 0; 488 sblock.fs_cstotal.cs_nffree = 0; 489 sblock.fs_fmod = 0; 490 sblock.fs_ronly = 0; 491 sblock.fs_state = 0; 492 sblock.fs_clean = FS_ISCLEAN; 493 sblock.fs_ronly = 0; 494 sblock.fs_id[0] = (long)tv.tv_sec; /* XXXfvdl huh? */ 495 sblock.fs_id[1] = arc4random() & INT32_MAX; 496 sblock.fs_fsmnt[0] = '\0'; 497 csfrags = howmany(sblock.fs_cssize, sblock.fs_fsize); 498 sblock.fs_dsize = sblock.fs_size - sblock.fs_sblkno - 499 sblock.fs_ncg * (sblock.fs_dblkno - sblock.fs_sblkno); 500 sblock.fs_cstotal.cs_nbfree = 501 fragstoblks(&sblock, sblock.fs_dsize) - 502 howmany(csfrags, sblock.fs_frag); 503 sblock.fs_cstotal.cs_nffree = 504 fragnum(&sblock, sblock.fs_size) + 505 (fragnum(&sblock, csfrags) > 0 ? 506 sblock.fs_frag - fragnum(&sblock, csfrags) : 0); 507 sblock.fs_cstotal.cs_nifree = sblock.fs_ncg * sblock.fs_ipg - ROOTINO; 508 sblock.fs_cstotal.cs_ndir = 0; 509 sblock.fs_dsize -= csfrags; 510 sblock.fs_time = tv.tv_sec; 511 if (Oflag <= 1) { 512 sblock.fs_old_time = tv.tv_sec; 513 sblock.fs_old_dsize = sblock.fs_dsize; 514 sblock.fs_old_csaddr = sblock.fs_csaddr; 515 sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir; 516 sblock.fs_old_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree; 517 sblock.fs_old_cstotal.cs_nifree = sblock.fs_cstotal.cs_nifree; 518 sblock.fs_old_cstotal.cs_nffree = sblock.fs_cstotal.cs_nffree; 519 } 520 /* 521 * Dump out summary information about file system. 522 */ 523 if (verbosity > 0) { 524 #define B2MBFACTOR (1 / (1024.0 * 1024.0)) 525 printf("%s: %.1fMB (%lld sectors) block size %d, " 526 "fragment size %d\n", 527 fsys, (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR, 528 (long long)fsbtodb(&sblock, sblock.fs_size), 529 sblock.fs_bsize, sblock.fs_fsize); 530 printf("\tusing %d cylinder groups of %.2fMB, %d blks, " 531 "%d inodes.\n", 532 sblock.fs_ncg, 533 (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR, 534 sblock.fs_fpg / sblock.fs_frag, sblock.fs_ipg); 535 #undef B2MBFACTOR 536 } 537 538 /* 539 * allocate space for superblock, cylinder group map, and 540 * two sets of inode blocks. 541 */ 542 if (sblock.fs_bsize < SBLOCKSIZE) 543 iobufsize = SBLOCKSIZE + 3 * sblock.fs_bsize; 544 else 545 iobufsize = 4 * sblock.fs_bsize; 546 iobuf_memsize = iobufsize; 547 if (!mfs && sblock.fs_magic == FS_UFS1_MAGIC) { 548 /* A larger buffer so we can write multiple inode blks */ 549 iobuf_memsize += 14 * sblock.fs_bsize; 550 } 551 for (;;) { 552 iobuf = mmap(0, iobuf_memsize, PROT_READ|PROT_WRITE, 553 MAP_ANON|MAP_PRIVATE, -1, 0); 554 if (iobuf != NULL) 555 break; 556 if (iobuf_memsize != iobufsize) { 557 /* Try again with the smaller size */ 558 iobuf_memsize = iobufsize; 559 continue; 560 } 561 printf("Cannot allocate I/O buffer\n"); 562 exit(38); 563 } 564 memset(iobuf, 0, iobuf_memsize); 565 566 /* 567 * We now start writing to the filesystem 568 */ 569 570 if (!Nflag) { 571 /* 572 * Validate the given file system size. 573 * Verify that its last block can actually be accessed. 574 * Convert to file system fragment sized units. 575 */ 576 if (fssize <= 0) { 577 printf("preposterous size %lld\n", (long long)fssize); 578 exit(13); 579 } 580 wtfs(fssize - 1, sectorsize, iobuf); 581 582 /* 583 * Ensure there is nothing that looks like a filesystem 584 * superbock anywhere other than where ours will be. 585 * If fsck finds the wrong one all hell breaks loose! 586 */ 587 for (i = 0; ; i++) { 588 static const int sblocklist[] = SBLOCKSEARCH; 589 int sblkoff = sblocklist[i]; 590 int sz; 591 if (sblkoff == -1) 592 break; 593 /* Remove main superblock */ 594 zap_old_sblock(sblkoff); 595 /* and all possible locations for the first alternate */ 596 sblkoff += SBLOCKSIZE; 597 for (sz = SBLOCKSIZE; sz <= 0x10000; sz <<= 1) 598 zap_old_sblock(roundup(sblkoff, sz)); 599 } 600 601 if (isappleufs) { 602 struct appleufslabel appleufs; 603 ffs_appleufs_set(&appleufs, appleufs_volname, 604 tv.tv_sec, 0); 605 wtfs(APPLEUFS_LABEL_OFFSET/sectorsize, 606 APPLEUFS_LABEL_SIZE, &appleufs); 607 } else { 608 struct appleufslabel appleufs; 609 /* Look for & zap any existing valid apple ufs labels */ 610 rdfs(APPLEUFS_LABEL_OFFSET/sectorsize, 611 APPLEUFS_LABEL_SIZE, &appleufs); 612 if (ffs_appleufs_validate(fsys, &appleufs, NULL) == 0) { 613 memset(&appleufs, 0, sizeof(appleufs)); 614 wtfs(APPLEUFS_LABEL_OFFSET/sectorsize, 615 APPLEUFS_LABEL_SIZE, &appleufs); 616 } 617 } 618 } 619 620 /* 621 * Make a copy of the superblock into the buffer that we will be 622 * writing out in each cylinder group. 623 */ 624 memcpy(iobuf, &sblock, sizeof sblock); 625 if (needswap) 626 ffs_sb_swap(&sblock, (struct fs *)iobuf); 627 if ((sblock.fs_old_flags & FS_FLAGS_UPDATED) == 0) 628 memset(iobuf + offsetof(struct fs, fs_old_postbl_start), 629 0xff, 256); 630 631 if (verbosity >= 3) 632 printf("super-block backups (for fsck_ffs -b #) at:\n"); 633 /* If we are printing more than one line of numbers, line up columns */ 634 fld_width = verbosity < 4 ? 1 : snprintf(NULL, 0, "%" PRIu64, 635 (uint64_t)fsbtodb(&sblock, cgsblock(&sblock, sblock.fs_ncg-1))); 636 /* Get terminal width */ 637 if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) == 0) 638 max_cols = winsize.ws_col; 639 else 640 max_cols = 80; 641 if (Nflag && verbosity == 3) 642 /* Leave space to add " ..." after one row of numbers */ 643 max_cols -= 4; 644 #define BASE 0x10000 /* For some fixed-point maths */ 645 col = 0; 646 delta = verbosity > 2 ? 0 : max_cols * BASE / sblock.fs_ncg; 647 for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { 648 fflush(stdout); 649 initcg(cylno, &tv); 650 if (verbosity < 2) 651 continue; 652 if (delta > 0) { 653 if (Nflag) 654 /* No point doing dots for -N */ 655 break; 656 /* Print dots scaled to end near RH margin */ 657 for (col += delta; col > BASE; col -= BASE) 658 printf("."); 659 continue; 660 } 661 /* Print superblock numbers */ 662 len = printf(" %*" PRIu64 "," + !col, fld_width, 663 (uint64_t)fsbtodb(&sblock, cgsblock(&sblock, cylno))); 664 col += len; 665 if (col + len < max_cols) 666 /* Next number fits */ 667 continue; 668 /* Next number won't fit, need a newline */ 669 if (verbosity <= 3) { 670 /* Print dots for subsequent cylinder groups */ 671 delta = sblock.fs_ncg - cylno - 1; 672 if (delta != 0) { 673 if (Nflag) { 674 printf(" ..."); 675 break; 676 } 677 delta = max_cols * BASE / delta; 678 } 679 } 680 col = 0; 681 printf("\n"); 682 } 683 #undef BASE 684 if (col > 0) 685 printf("\n"); 686 if (Nflag) 687 exit(0); 688 689 /* 690 * Now construct the initial file system, 691 */ 692 if (fsinit(&tv, mfsmode, mfsuid, mfsgid) == 0 && mfs) 693 errx(1, "Error making filesystem"); 694 sblock.fs_time = tv.tv_sec; 695 if (Oflag <= 1) { 696 sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir; 697 sblock.fs_old_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree; 698 sblock.fs_old_cstotal.cs_nifree = sblock.fs_cstotal.cs_nifree; 699 sblock.fs_old_cstotal.cs_nffree = sblock.fs_cstotal.cs_nffree; 700 } 701 /* 702 * Write out the super-block and zeros until the first cg info 703 */ 704 i = cgsblock(&sblock, 0) * sblock.fs_fsize - sblock.fs_sblockloc, 705 memset(iobuf, 0, i); 706 memcpy(iobuf, &sblock, sizeof sblock); 707 if (needswap) 708 ffs_sb_swap(&sblock, (struct fs *)iobuf); 709 if ((sblock.fs_old_flags & FS_FLAGS_UPDATED) == 0) 710 memset(iobuf + offsetof(struct fs, fs_old_postbl_start), 711 0xff, 256); 712 wtfs(sblock.fs_sblockloc / sectorsize, i, iobuf); 713 714 /* Write out first and last cylinder summary sectors */ 715 if (needswap) 716 ffs_csum_swap(fscs_0, fscs_0, sblock.fs_fsize); 717 wtfs(fsbtodb(&sblock, sblock.fs_csaddr), sblock.fs_fsize, fscs_0); 718 719 if (fscs_next > fscs_reset) { 720 if (needswap) 721 ffs_csum_swap(fscs_reset, fscs_reset, sblock.fs_fsize); 722 fs_csaddr++; 723 wtfs(fsbtodb(&sblock, fs_csaddr), sblock.fs_fsize, fscs_reset); 724 } 725 726 /* mfs doesn't need these permanently allocated */ 727 munmap(iobuf, iobuf_memsize); 728 munmap(fscs_0, 2 * sblock.fs_fsize); 729 730 /* 731 * Update information about this partion in pack 732 * label, to that it may be updated on disk. 733 */ 734 if (pp == NULL) 735 return; 736 if (isappleufs) 737 pp->p_fstype = FS_APPLEUFS; 738 else 739 pp->p_fstype = FS_BSDFFS; 740 pp->p_fsize = sblock.fs_fsize; 741 pp->p_frag = sblock.fs_frag; 742 pp->p_cpg = sblock.fs_fpg; 743 } 744 745 /* 746 * Initialize a cylinder group. 747 */ 748 void 749 initcg(int cylno, const struct timeval *tv) 750 { 751 daddr_t cbase, dmax; 752 int32_t i, d, dlower, dupper, blkno; 753 struct ufs1_dinode *dp1; 754 struct ufs2_dinode *dp2; 755 int start; 756 757 /* 758 * Determine block bounds for cylinder group. 759 * Allow space for super block summary information in first 760 * cylinder group. 761 */ 762 cbase = cgbase(&sblock, cylno); 763 dmax = cbase + sblock.fs_fpg; 764 if (dmax > sblock.fs_size) 765 dmax = sblock.fs_size; 766 dlower = cgsblock(&sblock, cylno) - cbase; 767 dupper = cgdmin(&sblock, cylno) - cbase; 768 if (cylno == 0) { 769 dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); 770 if (dupper >= cgstart(&sblock, cylno + 1)) { 771 printf("\rToo many cylinder groups to fit summary " 772 "information into first cylinder group\n"); 773 exit(40); 774 } 775 } 776 memset(&acg, 0, sblock.fs_cgsize); 777 acg.cg_magic = CG_MAGIC; 778 acg.cg_cgx = cylno; 779 acg.cg_ndblk = dmax - cbase; 780 if (sblock.fs_contigsumsize > 0) 781 acg.cg_nclusterblks = acg.cg_ndblk >> sblock.fs_fragshift; 782 start = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield); 783 if (Oflag == 2) { 784 acg.cg_time = tv->tv_sec; 785 acg.cg_niblk = sblock.fs_ipg; 786 acg.cg_initediblk = sblock.fs_ipg < 2 * INOPB(&sblock) ? 787 sblock.fs_ipg : 2 * INOPB(&sblock); 788 acg.cg_iusedoff = start; 789 } else { 790 acg.cg_old_ncyl = sblock.fs_old_cpg; 791 if ((sblock.fs_old_flags & FS_FLAGS_UPDATED) == 0 && 792 (cylno == sblock.fs_ncg - 1)) 793 acg.cg_old_ncyl = 794 sblock.fs_old_ncyl % sblock.fs_old_cpg; 795 acg.cg_old_time = tv->tv_sec; 796 acg.cg_old_niblk = sblock.fs_ipg; 797 acg.cg_old_btotoff = start; 798 acg.cg_old_boff = acg.cg_old_btotoff + 799 sblock.fs_old_cpg * sizeof(int32_t); 800 acg.cg_iusedoff = acg.cg_old_boff + 801 sblock.fs_old_cpg * sizeof(u_int16_t); 802 } 803 acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, CHAR_BIT); 804 if (sblock.fs_contigsumsize <= 0) { 805 acg.cg_nextfreeoff = acg.cg_freeoff + 806 howmany(sblock.fs_fpg, CHAR_BIT); 807 } else { 808 acg.cg_clustersumoff = acg.cg_freeoff + 809 howmany(sblock.fs_fpg, CHAR_BIT) - sizeof(int32_t); 810 if (isappleufs) { 811 /* Apple PR2216969 gives rationale for this change. 812 * I believe they were mistaken, but we need to 813 * duplicate it for compatibility. -- dbj@NetBSD.org 814 */ 815 acg.cg_clustersumoff += sizeof(int32_t); 816 } 817 acg.cg_clustersumoff = 818 roundup(acg.cg_clustersumoff, sizeof(int32_t)); 819 acg.cg_clusteroff = acg.cg_clustersumoff + 820 (sblock.fs_contigsumsize + 1) * sizeof(int32_t); 821 acg.cg_nextfreeoff = acg.cg_clusteroff + 822 howmany(fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT); 823 } 824 if (acg.cg_nextfreeoff > sblock.fs_cgsize) { 825 printf("Panic: cylinder group too big\n"); 826 exit(37); 827 } 828 acg.cg_cs.cs_nifree += sblock.fs_ipg; 829 if (cylno == 0) 830 for (i = 0; i < ROOTINO; i++) { 831 setbit(cg_inosused(&acg, 0), i); 832 acg.cg_cs.cs_nifree--; 833 } 834 if (cylno > 0) { 835 /* 836 * In cylno 0, beginning space is reserved 837 * for boot and super blocks. 838 */ 839 for (d = 0, blkno = 0; d < dlower;) { 840 setblock(&sblock, cg_blksfree(&acg, 0), blkno); 841 if (sblock.fs_contigsumsize > 0) 842 setbit(cg_clustersfree(&acg, 0), blkno); 843 acg.cg_cs.cs_nbfree++; 844 if (Oflag <= 1) { 845 int cn = old_cbtocylno(&sblock, d); 846 old_cg_blktot(&acg, 0)[cn]++; 847 old_cg_blks(&sblock, &acg, 848 cn, 0)[old_cbtorpos(&sblock, d)]++; 849 } 850 d += sblock.fs_frag; 851 blkno++; 852 } 853 } 854 if ((i = (dupper & (sblock.fs_frag - 1))) != 0) { 855 acg.cg_frsum[sblock.fs_frag - i]++; 856 for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) { 857 setbit(cg_blksfree(&acg, 0), dupper); 858 acg.cg_cs.cs_nffree++; 859 } 860 } 861 for (d = dupper, blkno = dupper >> sblock.fs_fragshift; 862 d + sblock.fs_frag <= acg.cg_ndblk; ) { 863 setblock(&sblock, cg_blksfree(&acg, 0), blkno); 864 if (sblock.fs_contigsumsize > 0) 865 setbit(cg_clustersfree(&acg, 0), blkno); 866 acg.cg_cs.cs_nbfree++; 867 if (Oflag <= 1) { 868 int cn = old_cbtocylno(&sblock, d); 869 old_cg_blktot(&acg, 0)[cn]++; 870 old_cg_blks(&sblock, &acg, 871 cn, 0)[old_cbtorpos(&sblock, d)]++; 872 } 873 d += sblock.fs_frag; 874 blkno++; 875 } 876 if (d < acg.cg_ndblk) { 877 acg.cg_frsum[acg.cg_ndblk - d]++; 878 for (; d < acg.cg_ndblk; d++) { 879 setbit(cg_blksfree(&acg, 0), d); 880 acg.cg_cs.cs_nffree++; 881 } 882 } 883 if (sblock.fs_contigsumsize > 0) { 884 int32_t *sump = cg_clustersum(&acg, 0); 885 u_char *mapp = cg_clustersfree(&acg, 0); 886 int map = *mapp++; 887 int bit = 1; 888 int run = 0; 889 890 for (i = 0; i < acg.cg_nclusterblks; i++) { 891 if ((map & bit) != 0) { 892 run++; 893 } else if (run != 0) { 894 if (run > sblock.fs_contigsumsize) 895 run = sblock.fs_contigsumsize; 896 sump[run]++; 897 run = 0; 898 } 899 if ((i & (CHAR_BIT - 1)) != (CHAR_BIT - 1)) { 900 bit <<= 1; 901 } else { 902 map = *mapp++; 903 bit = 1; 904 } 905 } 906 if (run != 0) { 907 if (run > sblock.fs_contigsumsize) 908 run = sblock.fs_contigsumsize; 909 sump[run]++; 910 } 911 } 912 *fscs_next++ = acg.cg_cs; 913 if (fscs_next == fscs_end) { 914 /* write block of cylinder group summary info into cyl 0 */ 915 if (needswap) 916 ffs_csum_swap(fscs_reset, fscs_reset, sblock.fs_fsize); 917 fs_csaddr++; 918 wtfs(fsbtodb(&sblock, fs_csaddr), sblock.fs_fsize, fscs_reset); 919 fscs_next = fscs_reset; 920 memset(fscs_next, 0, sblock.fs_fsize); 921 } 922 /* 923 * Write out the duplicate super block, the cylinder group map 924 * and two blocks worth of inodes in a single write. 925 */ 926 start = sblock.fs_bsize > SBLOCKSIZE ? sblock.fs_bsize : SBLOCKSIZE; 927 memcpy(&iobuf[start], &acg, sblock.fs_cgsize); 928 if (needswap) 929 ffs_cg_swap(&acg, (struct cg*)&iobuf[start], &sblock); 930 start += sblock.fs_bsize; 931 dp1 = (struct ufs1_dinode *)(&iobuf[start]); 932 dp2 = (struct ufs2_dinode *)(&iobuf[start]); 933 for (i = MIN(sblock.fs_ipg, 2) * INOPB(&sblock); i != 0; i--) { 934 if (sblock.fs_magic == FS_UFS1_MAGIC) { 935 /* No need to swap, it'll stay random */ 936 dp1->di_gen = arc4random() & INT32_MAX; 937 dp1++; 938 } else { 939 dp2->di_gen = arc4random() & INT32_MAX; 940 dp2++; 941 } 942 } 943 wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), iobufsize, iobuf); 944 /* 945 * For the old file system, we have to initialize all the inodes. 946 */ 947 if (sblock.fs_magic != FS_UFS1_MAGIC) 948 return; 949 950 /* Write 'd' (usually 16 * fs_frag) file-system fragments at once */ 951 d = (iobuf_memsize - start) / sblock.fs_bsize * sblock.fs_frag; 952 dupper = sblock.fs_ipg / INOPF(&sblock); 953 for (i = 2 * sblock.fs_frag; i < dupper; i += d) { 954 if (d > dupper - i) 955 d = dupper - i; 956 dp1 = (struct ufs1_dinode *)(&iobuf[start]); 957 do 958 dp1->di_gen = arc4random() & INT32_MAX; 959 while ((char *)++dp1 < &iobuf[iobuf_memsize]); 960 wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i), 961 d * sblock.fs_bsize / sblock.fs_frag, &iobuf[start]); 962 } 963 } 964 965 /* 966 * initialize the file system 967 */ 968 969 #ifdef LOSTDIR 970 #define PREDEFDIR 3 971 #else 972 #define PREDEFDIR 2 973 #endif 974 975 struct direct root_dir[] = { 976 { ROOTINO, sizeof(struct direct), DT_DIR, 1, "." }, 977 { ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." }, 978 #ifdef LOSTDIR 979 { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 10, "lost+found" }, 980 #endif 981 }; 982 struct odirect { 983 u_int32_t d_ino; 984 u_int16_t d_reclen; 985 u_int16_t d_namlen; 986 u_char d_name[FFS_MAXNAMLEN + 1]; 987 } oroot_dir[] = { 988 { ROOTINO, sizeof(struct direct), 1, "." }, 989 { ROOTINO, sizeof(struct direct), 2, ".." }, 990 #ifdef LOSTDIR 991 { LOSTFOUNDINO, sizeof(struct direct), 10, "lost+found" }, 992 #endif 993 }; 994 #ifdef LOSTDIR 995 struct direct lost_found_dir[] = { 996 { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 1, "." }, 997 { ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." }, 998 { 0, DIRBLKSIZ, 0, 0, 0 }, 999 }; 1000 struct odirect olost_found_dir[] = { 1001 { LOSTFOUNDINO, sizeof(struct direct), 1, "." }, 1002 { ROOTINO, sizeof(struct direct), 2, ".." }, 1003 { 0, DIRBLKSIZ, 0, 0 }, 1004 }; 1005 #endif 1006 char buf[MAXBSIZE]; 1007 static void copy_dir(struct direct *, struct direct *); 1008 1009 int 1010 fsinit(const struct timeval *tv, mode_t mfsmode, uid_t mfsuid, gid_t mfsgid) 1011 { 1012 union dinode node; 1013 #ifdef LOSTDIR 1014 int i; 1015 int dirblksiz = DIRBLKSIZ; 1016 if (isappleufs) 1017 dirblksiz = APPLEUFS_DIRBLKSIZ; 1018 #endif 1019 1020 /* 1021 * initialize the node 1022 */ 1023 1024 #ifdef LOSTDIR 1025 /* 1026 * create the lost+found directory 1027 */ 1028 memset(&node, 0, sizeof(node)); 1029 if (Oflag == 0) { 1030 (void)makedir((struct direct *)olost_found_dir, 2); 1031 for (i = dirblksiz; i < sblock.fs_bsize; i += dirblksiz) 1032 copy_dir((struct direct*)&olost_found_dir[2], 1033 (struct direct*)&buf[i]); 1034 } else { 1035 (void)makedir(lost_found_dir, 2); 1036 for (i = dirblksiz; i < sblock.fs_bsize; i += dirblksiz) 1037 copy_dir(&lost_found_dir[2], (struct direct*)&buf[i]); 1038 } 1039 if (sblock.fs_magic == FS_UFS1_MAGIC) { 1040 node.dp1.di_atime = tv->tv_sec; 1041 node.dp1.di_atimensec = tv->tv_usec * 1000; 1042 node.dp1.di_mtime = tv->tv_sec; 1043 node.dp1.di_mtimensec = tv->tv_usec * 1000; 1044 node.dp1.di_ctime = tv->tv_sec; 1045 node.dp1.di_ctimensec = tv->tv_usec * 1000; 1046 node.dp1.di_mode = IFDIR | UMASK; 1047 node.dp1.di_nlink = 2; 1048 node.dp1.di_size = sblock.fs_bsize; 1049 node.dp1.di_db[0] = alloc(node.dp1.di_size, node.dp1.di_mode); 1050 if (node.dp1.di_db[0] == 0) 1051 return (0); 1052 node.dp1.di_blocks = btodb(fragroundup(&sblock, 1053 node.dp1.di_size)); 1054 node.dp1.di_uid = geteuid(); 1055 node.dp1.di_gid = getegid(); 1056 wtfs(fsbtodb(&sblock, node.dp1.di_db[0]), node.dp1.di_size, 1057 buf); 1058 } else { 1059 node.dp2.di_atime = tv->tv_sec; 1060 node.dp2.di_atimensec = tv->tv_usec * 1000; 1061 node.dp2.di_mtime = tv->tv_sec; 1062 node.dp2.di_mtimensec = tv->tv_usec * 1000; 1063 node.dp2.di_ctime = tv->tv_sec; 1064 node.dp2.di_ctimensec = tv->tv_usec * 1000; 1065 node.dp2.di_birthtime = tv->tv_sec; 1066 node.dp2.di_birthnsec = tv->tv_usec * 1000; 1067 node.dp2.di_mode = IFDIR | UMASK; 1068 node.dp2.di_nlink = 2; 1069 node.dp2.di_size = sblock.fs_bsize; 1070 node.dp2.di_db[0] = alloc(node.dp2.di_size, node.dp2.di_mode); 1071 if (node.dp2.di_db[0] == 0) 1072 return (0); 1073 node.dp2.di_blocks = btodb(fragroundup(&sblock, 1074 node.dp2.di_size)); 1075 node.dp2.di_uid = geteuid(); 1076 node.dp2.di_gid = getegid(); 1077 wtfs(fsbtodb(&sblock, node.dp2.di_db[0]), node.dp2.di_size, 1078 buf); 1079 } 1080 iput(&node, LOSTFOUNDINO); 1081 #endif 1082 /* 1083 * create the root directory 1084 */ 1085 memset(&node, 0, sizeof(node)); 1086 if (Oflag <= 1) { 1087 if (mfs) { 1088 node.dp1.di_mode = IFDIR | mfsmode; 1089 node.dp1.di_uid = mfsuid; 1090 node.dp1.di_gid = mfsgid; 1091 } else { 1092 node.dp1.di_mode = IFDIR | UMASK; 1093 node.dp1.di_uid = geteuid(); 1094 node.dp1.di_gid = getegid(); 1095 } 1096 node.dp1.di_nlink = PREDEFDIR; 1097 if (Oflag == 0) 1098 node.dp1.di_size = makedir((struct direct *)oroot_dir, 1099 PREDEFDIR); 1100 else 1101 node.dp1.di_size = makedir(root_dir, PREDEFDIR); 1102 node.dp1.di_db[0] = alloc(sblock.fs_fsize, node.dp1.di_mode); 1103 if (node.dp1.di_db[0] == 0) 1104 return (0); 1105 node.dp1.di_blocks = btodb(fragroundup(&sblock, 1106 node.dp1.di_size)); 1107 wtfs(fsbtodb(&sblock, node.dp1.di_db[0]), sblock.fs_fsize, buf); 1108 } else { 1109 if (mfs) { 1110 node.dp2.di_mode = IFDIR | mfsmode; 1111 node.dp2.di_uid = mfsuid; 1112 node.dp2.di_gid = mfsgid; 1113 } else { 1114 node.dp2.di_mode = IFDIR | UMASK; 1115 node.dp2.di_uid = geteuid(); 1116 node.dp2.di_gid = getegid(); 1117 } 1118 node.dp2.di_atime = tv->tv_sec; 1119 node.dp2.di_atimensec = tv->tv_usec * 1000; 1120 node.dp2.di_mtime = tv->tv_sec; 1121 node.dp2.di_mtimensec = tv->tv_usec * 1000; 1122 node.dp2.di_ctime = tv->tv_sec; 1123 node.dp2.di_ctimensec = tv->tv_usec * 1000; 1124 node.dp2.di_birthtime = tv->tv_sec; 1125 node.dp2.di_birthnsec = tv->tv_usec * 1000; 1126 node.dp2.di_nlink = PREDEFDIR; 1127 node.dp2.di_size = makedir(root_dir, PREDEFDIR); 1128 node.dp2.di_db[0] = alloc(sblock.fs_fsize, node.dp2.di_mode); 1129 if (node.dp2.di_db[0] == 0) 1130 return (0); 1131 node.dp2.di_blocks = btodb(fragroundup(&sblock, 1132 node.dp2.di_size)); 1133 wtfs(fsbtodb(&sblock, node.dp2.di_db[0]), sblock.fs_fsize, buf); 1134 } 1135 iput(&node, ROOTINO); 1136 return (1); 1137 } 1138 1139 /* 1140 * construct a set of directory entries in "buf". 1141 * return size of directory. 1142 */ 1143 int 1144 makedir(struct direct *protodir, int entries) 1145 { 1146 char *cp; 1147 int i, spcleft; 1148 int dirblksiz = DIRBLKSIZ; 1149 if (isappleufs) 1150 dirblksiz = APPLEUFS_DIRBLKSIZ; 1151 1152 memset(buf, 0, DIRBLKSIZ); 1153 spcleft = dirblksiz; 1154 for (cp = buf, i = 0; i < entries - 1; i++) { 1155 protodir[i].d_reclen = DIRSIZ(Oflag == 0, &protodir[i], 0); 1156 copy_dir(&protodir[i], (struct direct*)cp); 1157 cp += protodir[i].d_reclen; 1158 spcleft -= protodir[i].d_reclen; 1159 } 1160 protodir[i].d_reclen = spcleft; 1161 copy_dir(&protodir[i], (struct direct*)cp); 1162 return (dirblksiz); 1163 } 1164 1165 /* 1166 * allocate a block or frag 1167 */ 1168 daddr_t 1169 alloc(int size, int mode) 1170 { 1171 int i, frag; 1172 daddr_t d, blkno; 1173 1174 rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, &acg); 1175 /* fs -> host byte order */ 1176 if (needswap) 1177 ffs_cg_swap(&acg, &acg, &sblock); 1178 if (acg.cg_magic != CG_MAGIC) { 1179 printf("cg 0: bad magic number\n"); 1180 return (0); 1181 } 1182 if (acg.cg_cs.cs_nbfree == 0) { 1183 printf("first cylinder group ran out of space\n"); 1184 return (0); 1185 } 1186 for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag) 1187 if (isblock(&sblock, cg_blksfree(&acg, 0), 1188 d >> sblock.fs_fragshift)) 1189 goto goth; 1190 printf("internal error: can't find block in cyl 0\n"); 1191 return (0); 1192 goth: 1193 blkno = fragstoblks(&sblock, d); 1194 clrblock(&sblock, cg_blksfree(&acg, 0), blkno); 1195 if (sblock.fs_contigsumsize > 0) 1196 clrbit(cg_clustersfree(&acg, 0), blkno); 1197 acg.cg_cs.cs_nbfree--; 1198 sblock.fs_cstotal.cs_nbfree--; 1199 fscs_0->cs_nbfree--; 1200 if (mode & IFDIR) { 1201 acg.cg_cs.cs_ndir++; 1202 sblock.fs_cstotal.cs_ndir++; 1203 fscs_0->cs_ndir++; 1204 } 1205 if (Oflag <= 1) { 1206 int cn = old_cbtocylno(&sblock, d); 1207 old_cg_blktot(&acg, 0)[cn]--; 1208 old_cg_blks(&sblock, &acg, 1209 cn, 0)[old_cbtorpos(&sblock, d)]--; 1210 } 1211 if (size != sblock.fs_bsize) { 1212 frag = howmany(size, sblock.fs_fsize); 1213 fscs_0->cs_nffree += sblock.fs_frag - frag; 1214 sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag; 1215 acg.cg_cs.cs_nffree += sblock.fs_frag - frag; 1216 acg.cg_frsum[sblock.fs_frag - frag]++; 1217 for (i = frag; i < sblock.fs_frag; i++) 1218 setbit(cg_blksfree(&acg, 0), d + i); 1219 } 1220 /* host -> fs byte order */ 1221 if (needswap) 1222 ffs_cg_swap(&acg, &acg, &sblock); 1223 wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, &acg); 1224 return (d); 1225 } 1226 1227 /* 1228 * Allocate an inode on the disk 1229 */ 1230 static void 1231 iput(union dinode *ip, ino_t ino) 1232 { 1233 daddr_t d; 1234 int c, i; 1235 struct ufs1_dinode *dp1; 1236 struct ufs2_dinode *dp2; 1237 1238 c = ino_to_cg(&sblock, ino); 1239 rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, &acg); 1240 /* fs -> host byte order */ 1241 if (needswap) 1242 ffs_cg_swap(&acg, &acg, &sblock); 1243 if (acg.cg_magic != CG_MAGIC) { 1244 printf("cg 0: bad magic number\n"); 1245 exit(31); 1246 } 1247 acg.cg_cs.cs_nifree--; 1248 setbit(cg_inosused(&acg, 0), ino); 1249 /* host -> fs byte order */ 1250 if (needswap) 1251 ffs_cg_swap(&acg, &acg, &sblock); 1252 wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, &acg); 1253 sblock.fs_cstotal.cs_nifree--; 1254 fscs_0->cs_nifree--; 1255 if (ino >= sblock.fs_ipg * sblock.fs_ncg) { 1256 printf("fsinit: inode value out of range (%llu).\n", 1257 (unsigned long long)ino); 1258 exit(32); 1259 } 1260 d = fsbtodb(&sblock, ino_to_fsba(&sblock, ino)); 1261 rdfs(d, sblock.fs_bsize, (char *)iobuf); 1262 if (sblock.fs_magic == FS_UFS1_MAGIC) { 1263 dp1 = (struct ufs1_dinode *)iobuf; 1264 dp1 += ino_to_fsbo(&sblock, ino); 1265 if (needswap) { 1266 ffs_dinode1_swap(&ip->dp1, dp1); 1267 /* ffs_dinode1_swap() doesn't swap blocks addrs */ 1268 for (i=0; i<NDADDR + NIADDR; i++) 1269 dp1->di_db[i] = bswap32(ip->dp1.di_db[i]); 1270 } else 1271 *dp1 = ip->dp1; 1272 dp1->di_gen = arc4random() & INT32_MAX; 1273 } else { 1274 dp2 = (struct ufs2_dinode *)iobuf; 1275 dp2 += ino_to_fsbo(&sblock, ino); 1276 if (needswap) { 1277 ffs_dinode2_swap(&ip->dp2, dp2); 1278 for (i=0; i<NDADDR + NIADDR; i++) 1279 dp2->di_db[i] = bswap64(ip->dp2.di_db[i]); 1280 } else 1281 *dp2 = ip->dp2; 1282 dp2->di_gen = arc4random() & INT32_MAX; 1283 } 1284 wtfs(d, sblock.fs_bsize, iobuf); 1285 } 1286 1287 /* 1288 * read a block from the file system 1289 */ 1290 void 1291 rdfs(daddr_t bno, int size, void *bf) 1292 { 1293 int n; 1294 off_t offset; 1295 1296 #ifdef MFS 1297 if (mfs) { 1298 if (Nflag) 1299 memset(bf, 0, size); 1300 else 1301 memmove(bf, membase + bno * sectorsize, size); 1302 return; 1303 } 1304 #endif 1305 offset = bno; 1306 n = pread(fsi, bf, size, offset * sectorsize); 1307 if (n != size) { 1308 printf("rdfs: read error for sector %lld: %s\n", 1309 (long long)bno, strerror(errno)); 1310 exit(34); 1311 } 1312 } 1313 1314 /* 1315 * write a block to the file system 1316 */ 1317 void 1318 wtfs(daddr_t bno, int size, void *bf) 1319 { 1320 int n; 1321 off_t offset; 1322 1323 if (Nflag) 1324 return; 1325 #ifdef MFS 1326 if (mfs) { 1327 memmove(membase + bno * sectorsize, bf, size); 1328 return; 1329 } 1330 #endif 1331 offset = bno; 1332 n = pwrite(fso, bf, size, offset * sectorsize); 1333 if (n != size) { 1334 printf("wtfs: write error for sector %lld: %s\n", 1335 (long long)bno, strerror(errno)); 1336 exit(36); 1337 } 1338 } 1339 1340 /* 1341 * check if a block is available 1342 */ 1343 int 1344 isblock(struct fs *fs, unsigned char *cp, int h) 1345 { 1346 unsigned char mask; 1347 1348 switch (fs->fs_fragshift) { 1349 case 3: 1350 return (cp[h] == 0xff); 1351 case 2: 1352 mask = 0x0f << ((h & 0x1) << 2); 1353 return ((cp[h >> 1] & mask) == mask); 1354 case 1: 1355 mask = 0x03 << ((h & 0x3) << 1); 1356 return ((cp[h >> 2] & mask) == mask); 1357 case 0: 1358 mask = 0x01 << (h & 0x7); 1359 return ((cp[h >> 3] & mask) == mask); 1360 default: 1361 #ifdef STANDALONE 1362 printf("isblock bad fs_fragshift %d\n", fs->fs_fragshift); 1363 #else 1364 fprintf(stderr, "isblock bad fs_fragshift %d\n", 1365 fs->fs_fragshift); 1366 #endif 1367 return (0); 1368 } 1369 } 1370 1371 /* 1372 * take a block out of the map 1373 */ 1374 void 1375 clrblock(struct fs *fs, unsigned char *cp, int h) 1376 { 1377 switch ((fs)->fs_fragshift) { 1378 case 3: 1379 cp[h] = 0; 1380 return; 1381 case 2: 1382 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 1383 return; 1384 case 1: 1385 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 1386 return; 1387 case 0: 1388 cp[h >> 3] &= ~(0x01 << (h & 0x7)); 1389 return; 1390 default: 1391 #ifdef STANDALONE 1392 printf("clrblock bad fs_fragshift %d\n", fs->fs_fragshift); 1393 #else 1394 fprintf(stderr, "clrblock bad fs_fragshift %d\n", 1395 fs->fs_fragshift); 1396 #endif 1397 return; 1398 } 1399 } 1400 1401 /* 1402 * put a block into the map 1403 */ 1404 void 1405 setblock(struct fs *fs, unsigned char *cp, int h) 1406 { 1407 switch (fs->fs_fragshift) { 1408 case 3: 1409 cp[h] = 0xff; 1410 return; 1411 case 2: 1412 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 1413 return; 1414 case 1: 1415 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 1416 return; 1417 case 0: 1418 cp[h >> 3] |= (0x01 << (h & 0x7)); 1419 return; 1420 default: 1421 #ifdef STANDALONE 1422 printf("setblock bad fs_frag %d\n", fs->fs_fragshift); 1423 #else 1424 fprintf(stderr, "setblock bad fs_fragshift %d\n", 1425 fs->fs_fragshift); 1426 #endif 1427 return; 1428 } 1429 } 1430 1431 /* copy a direntry to a buffer, in fs byte order */ 1432 static void 1433 copy_dir(struct direct *dir, struct direct *dbuf) 1434 { 1435 memcpy(dbuf, dir, DIRSIZ(Oflag == 0, dir, 0)); 1436 if (needswap) { 1437 dbuf->d_ino = bswap32(dir->d_ino); 1438 dbuf->d_reclen = bswap16(dir->d_reclen); 1439 if (Oflag == 0) 1440 ((struct odirect*)dbuf)->d_namlen = 1441 bswap16(((struct odirect*)dir)->d_namlen); 1442 } 1443 } 1444 1445 static int 1446 ilog2(int val) 1447 { 1448 u_int n; 1449 1450 for (n = 0; n < sizeof(n) * CHAR_BIT; n++) 1451 if (1 << n == val) 1452 return (n); 1453 errx(1, "ilog2: %d is not a power of 2\n", val); 1454 } 1455 1456 static void 1457 zap_old_sblock(int sblkoff) 1458 { 1459 static int cg0_data; 1460 uint32_t oldfs[SBLOCKSIZE / 4]; 1461 static const struct fsm { 1462 uint32_t offset; 1463 uint32_t magic; 1464 uint32_t mask; 1465 } fs_magics[] = { 1466 {offsetof(struct fs, fs_magic)/4, FS_UFS1_MAGIC, ~0u}, 1467 {offsetof(struct fs, fs_magic)/4, FS_UFS2_MAGIC, ~0u}, 1468 {0, 0x70162, ~0u}, /* LFS_MAGIC */ 1469 {14, 0xef53, 0xffff}, /* EXT2FS (little) */ 1470 {14, 0xef530000, 0xffff0000}, /* EXT2FS (big) */ 1471 {~0u}, 1472 }; 1473 const struct fsm *fsm; 1474 1475 if (Nflag) 1476 return; 1477 1478 if (sblkoff == 0) /* Why did UFS2 add support for this? sigh. */ 1479 return; 1480 1481 if (cg0_data == 0) 1482 /* For FFSv1 this could include all the inodes. */ 1483 cg0_data = cgsblock(&sblock, 0) * sblock.fs_fsize + iobufsize; 1484 1485 /* Ignore anything that is beyond our filesystem */ 1486 if ((sblkoff + SBLOCKSIZE)/sectorsize >= fssize) 1487 return; 1488 /* Zero anything inside our filesystem... */ 1489 if (sblkoff >= sblock.fs_sblockloc) { 1490 /* ...unless we will write that area anyway */ 1491 if (sblkoff >= cg0_data) 1492 wtfs(sblkoff / sectorsize, 1493 roundup(sizeof sblock, sectorsize), iobuf); 1494 return; 1495 } 1496 1497 /* The sector might contain boot code, so we must validate it */ 1498 rdfs(sblkoff/sectorsize, sizeof oldfs, &oldfs); 1499 for (fsm = fs_magics; ; fsm++) { 1500 uint32_t v; 1501 if (fsm->mask == 0) 1502 return; 1503 v = oldfs[fsm->offset]; 1504 if ((v & fsm->mask) == fsm->magic || 1505 (bswap32(v) & fsm->mask) == fsm->magic) 1506 break; 1507 } 1508 1509 /* Just zap the magic number */ 1510 oldfs[fsm->offset] = 0; 1511 wtfs(sblkoff/sectorsize, sizeof oldfs, &oldfs); 1512 } 1513 1514 1515 #ifdef MFS 1516 /* 1517 * XXX! 1518 * Attempt to guess how much more space is available for process data. The 1519 * heuristic we use is 1520 * 1521 * max_data_limit - (sbrk(0) - etext) - 128kB 1522 * 1523 * etext approximates that start address of the data segment, and the 128kB 1524 * allows some slop for both segment gap between text and data, and for other 1525 * (libc) malloc usage. 1526 */ 1527 static void 1528 calc_memfree(void) 1529 { 1530 extern char etext; 1531 struct rlimit rlp; 1532 u_long base; 1533 1534 base = (u_long)sbrk(0) - (u_long)&etext; 1535 if (getrlimit(RLIMIT_DATA, &rlp) < 0) 1536 perror("getrlimit"); 1537 rlp.rlim_cur = rlp.rlim_max; 1538 if (setrlimit(RLIMIT_DATA, &rlp) < 0) 1539 perror("setrlimit"); 1540 memleft = rlp.rlim_max - base - (128 * 1024); 1541 } 1542 1543 /* 1544 * Internal version of malloc that trims the requested size if not enough 1545 * memory is available. 1546 */ 1547 static void * 1548 mkfs_malloc(size_t size) 1549 { 1550 u_long pgsz; 1551 1552 if (size == 0) 1553 return (NULL); 1554 if (memleft == 0) 1555 calc_memfree(); 1556 1557 pgsz = getpagesize() - 1; 1558 size = (size + pgsz) &~ pgsz; 1559 if (size > memleft) 1560 size = memleft; 1561 memleft -= size; 1562 return (mmap(0, size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 1563 -1, 0)); 1564 } 1565 #endif /* MFS */ 1566