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