]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/newfs/mkfs.c
This commit was generated by cvs2svn to compensate for changes in r97952,
[FreeBSD/FreeBSD.git] / sbin / newfs / mkfs.c
1 /*
2  * Copyright (c) 1980, 1989, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 #ifndef lint
35 #if 0
36 static char sccsid[] = "@(#)mkfs.c      8.11 (Berkeley) 5/3/95";
37 #endif
38 static const char rcsid[] =
39   "$FreeBSD$";
40 #endif /* not lint */
41
42 #include <err.h>
43 #include <signal.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <stdio.h>
47 #include <unistd.h>
48 #include <sys/param.h>
49 #include <sys/time.h>
50 #include <sys/types.h>
51 #include <sys/wait.h>
52 #include <sys/resource.h>
53 #include <sys/stat.h>
54 #include <ufs/ufs/dinode.h>
55 #include <ufs/ufs/dir.h>
56 #include <ufs/ffs/fs.h>
57 #include <sys/disklabel.h>
58 #include <sys/file.h>
59 #include <sys/mman.h>
60 #include <sys/ioctl.h>
61 #include "newfs.h"
62
63 /*
64  * make filesystem for cylinder-group style filesystems
65  */
66
67 /*
68  * We limit the size of the inode map to be no more than a
69  * third of the cylinder group space, since we must leave at
70  * least an equal amount of space for the block map.
71  *
72  * N.B.: MAXIPG must be a multiple of INOPB(fs).
73  */
74 #define MAXIPG(fs)      roundup((fs)->fs_bsize * NBBY / 3, INOPB(fs))
75
76 #define UMASK           0755
77 #define MAXINOPB        (MAXBSIZE / sizeof(struct dinode))
78 #define POWEROF2(num)   (((num) & ((num) - 1)) == 0)
79
80 static union {
81         struct fs fs;
82         char pad[SBSIZE];
83 } fsun;
84 #define sblock  fsun.fs
85 static struct   csum *fscs;
86
87 static union {
88         struct cg cg;
89         char pad[MAXBSIZE];
90 } cgun;
91 #define acg     cgun.cg
92
93 static struct dinode zino[MAXBSIZE / sizeof(struct dinode)];
94
95 static int randinit;
96 static daddr_t alloc(int size, int mode);
97 static long calcipg(long lcpg, long bpcg, off_t *usedbp);
98 static int charsperline(void);
99 static void clrblock(struct fs *, unsigned char *, int);
100 static void fsinit(time_t);
101 static int ilog2(int);
102 static void initcg(int, time_t);
103 static int isblock(struct fs *, unsigned char *, int);
104 static void iput(struct dinode *, ino_t);
105 static int makedir(struct direct *, int);
106 static void rdfs(daddr_t, int, char *);
107 static void setblock(struct fs *, unsigned char *, int);
108 static void wtfs(daddr_t, int, char *);
109 static void wtfsflush(void);
110
111 void
112 mkfs(struct partition *pp, char *fsys)
113 {
114         long i, mincpc, mincpg, inospercg;
115         long cylno, j, lwarn = 0;
116         long used, mincpgcnt, bpcg;
117         off_t usedb;
118         long mapcramped, inodecramped;
119         time_t utime;
120         quad_t sizepb;
121         int width;
122         char tmpbuf[100];       /* XXX this will break in about 2,500 years */
123
124         if (Rflag)
125                 utime = 1000000000;
126         else 
127                 time(&utime);
128         if (!Rflag && !randinit) {
129                 randinit = 1;
130                 srandomdev();
131         }
132         sblock.fs_inodefmt = FS_44INODEFMT;
133         sblock.fs_maxsymlinklen = MAXSYMLINKLEN;
134         if (Uflag)
135                 sblock.fs_flags |= FS_DOSOFTDEP;
136         /*
137          * Validate the given filesystem size.
138          * Verify that its last block can actually be accessed.
139          */
140         if (fssize <= 0)
141                 printf("preposterous size %d\n", fssize), exit(13);
142         wtfs(fssize - (realsectorsize / DEV_BSIZE), realsectorsize,
143             (char *)&sblock);
144         /*
145          * collect and verify the sector and track info
146          */
147         sblock.fs_nsect = secpercyl;
148         sblock.fs_ntrak = 1;
149         if (sblock.fs_nsect <= 0)
150                 printf("preposterous nsect %d\n", sblock.fs_nsect), exit(15);
151         /*
152          * collect and verify the filesystem density info
153          */
154         sblock.fs_avgfilesize = avgfilesize;
155         sblock.fs_avgfpdir = avgfilesperdir;
156         if (sblock.fs_avgfilesize <= 0)
157                 printf("illegal expected average file size %d\n",
158                     sblock.fs_avgfilesize), exit(14);
159         if (sblock.fs_avgfpdir <= 0)
160                 printf("illegal expected number of files per directory %d\n",
161                     sblock.fs_avgfpdir), exit(15);
162         /*
163          * collect and verify the block and fragment sizes
164          */
165         sblock.fs_bsize = bsize;
166         sblock.fs_fsize = fsize;
167         if (!POWEROF2(sblock.fs_bsize)) {
168                 printf("block size must be a power of 2, not %d\n",
169                     sblock.fs_bsize);
170                 exit(16);
171         }
172         if (!POWEROF2(sblock.fs_fsize)) {
173                 printf("fragment size must be a power of 2, not %d\n",
174                     sblock.fs_fsize);
175                 exit(17);
176         }
177         if (sblock.fs_fsize < sectorsize) {
178                 printf("increasing fragment size from %d to sector size (%d)\n",
179                     sblock.fs_fsize, sectorsize);
180                 sblock.fs_fsize = sectorsize;
181         }
182         if (sblock.fs_bsize < MINBSIZE) {
183                 printf("increasing block size from %d to minimum (%d)\n",
184                     sblock.fs_bsize, MINBSIZE);
185                 sblock.fs_bsize = MINBSIZE;
186         }
187         if (sblock.fs_bsize < sblock.fs_fsize) {
188                 printf("increasing block size from %d to fragment size (%d)\n",
189                     sblock.fs_bsize, sblock.fs_fsize);
190                 sblock.fs_bsize = sblock.fs_fsize;
191         }
192         if (sblock.fs_fsize * MAXFRAG < sblock.fs_bsize) {
193                 printf(
194                 "increasing fragment size from %d to block size / %d (%d)\n",
195                     sblock.fs_fsize, MAXFRAG, sblock.fs_bsize / MAXFRAG);
196                 sblock.fs_fsize = sblock.fs_bsize / MAXFRAG;
197         }
198         sblock.fs_bmask = ~(sblock.fs_bsize - 1);
199         sblock.fs_fmask = ~(sblock.fs_fsize - 1);
200         sblock.fs_qbmask = ~sblock.fs_bmask;
201         sblock.fs_qfmask = ~sblock.fs_fmask;
202         sblock.fs_bshift = ilog2(sblock.fs_bsize);
203         sblock.fs_fshift = ilog2(sblock.fs_fsize);
204         sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize);
205         sblock.fs_fragshift = ilog2(sblock.fs_frag);
206         if (sblock.fs_frag > MAXFRAG) {
207                 printf("fragment size %d is still too small (can't happen)\n",
208                     sblock.fs_bsize / MAXFRAG);
209                 exit(21);
210         }
211         sblock.fs_nrpos = 1;
212         sblock.fs_nindir = sblock.fs_bsize / sizeof(daddr_t);
213         sblock.fs_inopb = sblock.fs_bsize / sizeof(struct dinode);
214         sblock.fs_nspf = sblock.fs_fsize / sectorsize;
215         sblock.fs_fsbtodb = ilog2(NSPF(&sblock));
216         sblock.fs_sblkno =
217             roundup(howmany(BBSIZE + SBSIZE, sblock.fs_fsize), sblock.fs_frag);
218         sblock.fs_cblkno = (daddr_t)(sblock.fs_sblkno +
219             roundup(howmany(SBSIZE, sblock.fs_fsize), sblock.fs_frag));
220         sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag;
221         sblock.fs_cgoffset =
222             roundup(howmany(sblock.fs_nsect, NSPF(&sblock)), sblock.fs_frag);
223         sblock.fs_cgmask = 0xffffffff;
224         sblock.fs_maxfilesize = sblock.fs_bsize * NDADDR - 1;
225         for (sizepb = sblock.fs_bsize, i = 0; i < NIADDR; i++) {
226                 sizepb *= NINDIR(&sblock);
227                 sblock.fs_maxfilesize += sizepb;
228         }
229         /*
230          * Validate specified/determined secpercyl
231          * and calculate minimum cylinders per group.
232          */
233         sblock.fs_spc = secpercyl;
234         for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc;
235              sblock.fs_cpc > 1 && (i & 1) == 0;
236              sblock.fs_cpc >>= 1, i >>= 1)
237                 /* void */;
238         mincpc = sblock.fs_cpc;
239         bpcg = sblock.fs_spc * sectorsize;
240         inospercg = roundup(bpcg / sizeof(struct dinode), INOPB(&sblock));
241         if (inospercg > MAXIPG(&sblock))
242                 inospercg = MAXIPG(&sblock);
243         used = (sblock.fs_iblkno + inospercg / INOPF(&sblock)) * NSPF(&sblock);
244         mincpgcnt = howmany(sblock.fs_cgoffset * (~sblock.fs_cgmask) + used,
245             sblock.fs_spc);
246         mincpg = roundup(mincpgcnt, mincpc);
247         /*
248          * Ensure that cylinder group with mincpg has enough space
249          * for block maps.
250          */
251         sblock.fs_cpg = mincpg;
252         sblock.fs_ipg = inospercg;
253         if (maxcontig > 1)
254                 sblock.fs_contigsumsize = MIN(maxcontig, FS_MAXCONTIG);
255         mapcramped = 0;
256         while (CGSIZE(&sblock) > sblock.fs_bsize) {
257                 mapcramped = 1;
258                 if (sblock.fs_bsize < MAXBSIZE) {
259                         sblock.fs_bsize <<= 1;
260                         if ((i & 1) == 0)
261                                 i >>= 1;
262                         else {
263                                 sblock.fs_cpc <<= 1;
264                                 mincpc <<= 1;
265                                 mincpg = roundup(mincpgcnt, mincpc);
266                                 sblock.fs_cpg = mincpg;
267                         }
268                         sblock.fs_frag <<= 1;
269                         sblock.fs_fragshift += 1;
270                         if (sblock.fs_frag <= MAXFRAG)
271                                 continue;
272                 }
273                 if (sblock.fs_fsize == sblock.fs_bsize) {
274                         printf("There is no block size that");
275                         printf(" can support this disk\n");
276                         exit(22);
277                 }
278                 sblock.fs_frag >>= 1;
279                 sblock.fs_fragshift -= 1;
280                 sblock.fs_fsize <<= 1;
281                 sblock.fs_nspf <<= 1;
282         }
283         /*
284          * Ensure that cylinder group with mincpg has enough space for inodes.
285          */
286         inodecramped = 0;
287         inospercg = calcipg(mincpg, bpcg, &usedb);
288         sblock.fs_ipg = inospercg;
289         while (inospercg > MAXIPG(&sblock)) {
290                 inodecramped = 1;
291                 if (mincpc == 1 || sblock.fs_frag == 1 ||
292                     sblock.fs_bsize == MINBSIZE)
293                         break;
294                 printf("With a block size of %d %s %d\n", sblock.fs_bsize,
295                     "minimum bytes per inode is",
296                     (int)((mincpg * (off_t)bpcg - usedb) /
297                     MAXIPG(&sblock) + 1));
298                 sblock.fs_bsize >>= 1;
299                 sblock.fs_frag >>= 1;
300                 sblock.fs_fragshift -= 1;
301                 mincpc >>= 1;
302                 sblock.fs_cpg = roundup(mincpgcnt, mincpc);
303                 if (CGSIZE(&sblock) > sblock.fs_bsize) {
304                         sblock.fs_bsize <<= 1;
305                         break;
306                 }
307                 mincpg = sblock.fs_cpg;
308                 inospercg = calcipg(mincpg, bpcg, &usedb);
309                 sblock.fs_ipg = inospercg;
310         }
311         if (inodecramped) {
312                 if (inospercg > MAXIPG(&sblock)) {
313                         printf("Minimum bytes per inode is %d\n",
314                             (int)((mincpg * (off_t)bpcg - usedb) /
315                             MAXIPG(&sblock) + 1));
316                 } else if (!mapcramped) {
317                         printf("With %d bytes per inode, ", density);
318                         printf("minimum cylinders per group is %ld\n", mincpg);
319                 }
320         }
321         if (mapcramped) {
322                 printf("With %d sectors per cylinder, ", sblock.fs_spc);
323                 printf("minimum cylinders per group is %ld\n", mincpg);
324         }
325         if (inodecramped || mapcramped) {
326                 if (sblock.fs_bsize != bsize)
327                         printf("%s to be changed from %d to %d\n",
328                             "This requires the block size",
329                             bsize, sblock.fs_bsize);
330                 if (sblock.fs_fsize != fsize)
331                         printf("\t%s to be changed from %d to %d\n",
332                             "and the fragment size", fsize, sblock.fs_fsize);
333                 exit(23);
334         }
335         /*
336          * Calculate the number of cylinders per group
337          */
338         sblock.fs_cpg = cpg;
339         if (sblock.fs_cpg % mincpc != 0) {
340                 printf("%s groups must have a multiple of %ld cylinders\n",
341                     cpgflg ? "Cylinder" : "Warning: cylinder", mincpc);
342                 sblock.fs_cpg = roundup(sblock.fs_cpg, mincpc);
343                 if (!cpgflg)
344                         cpg = sblock.fs_cpg;
345         }
346         /*
347          * Must ensure there is enough space for inodes.
348          */
349         sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb);
350         while (sblock.fs_ipg > MAXIPG(&sblock)) {
351                 inodecramped = 1;
352                 sblock.fs_cpg -= mincpc;
353                 sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb);
354         }
355         /*
356          * Must ensure there is enough space to hold block map.
357          */
358         while (CGSIZE(&sblock) > sblock.fs_bsize) {
359                 mapcramped = 1;
360                 sblock.fs_cpg -= mincpc;
361                 sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb);
362         }
363         sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock);
364         if ((sblock.fs_cpg * sblock.fs_spc) % NSPB(&sblock) != 0) {
365                 printf("panic (fs_cpg * fs_spc) %% NSPF != 0");
366                 exit(24);
367         }
368         if (sblock.fs_cpg < mincpg) {
369                 printf("cylinder groups must have at least %ld cylinders\n",
370                         mincpg);
371                 exit(25);
372         } else if (cpgflg && sblock.fs_cpg != cpg) {
373                 if (!mapcramped && !inodecramped)
374                         exit(26);
375                 if (mapcramped && inodecramped)
376                         printf("Block size and bytes per inode restrict");
377                 else if (mapcramped)
378                         printf("Block size restricts");
379                 else
380                         printf("Bytes per inode restrict");
381                 printf(" cylinders per group to %d.\n", sblock.fs_cpg);
382                 if (cpgflg)
383                         exit(27);
384         }
385         sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock));
386         /*
387          * Now have size for filesystem and nsect and ntrak.
388          * Determine number of cylinders and blocks in the filesystem.
389          */
390         sblock.fs_size = fssize = dbtofsb(&sblock, fssize);
391         sblock.fs_ncyl = fssize * NSPF(&sblock) / sblock.fs_spc;
392         if (fssize * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) {
393                 sblock.fs_ncyl++;
394                 lwarn = 1;
395         }
396         if (sblock.fs_ncyl < 1) {
397                 printf("filesystems must have at least one cylinder\n");
398                 exit(28);
399         }
400         /*
401          * Determine feasability/values of rotational layout tables.
402          *
403          * The size of the rotational layout tables is limited by the
404          * size of the superblock, SBSIZE. The amount of space available
405          * for tables is calculated as (SBSIZE - sizeof (struct fs)).
406          * The size of these tables is inversely proportional to the block
407          * size of the filesystem. The size increases if sectors per track
408          * are not powers of two, because more cylinders must be described
409          * by the tables before the rotational pattern repeats (fs_cpc).
410          */
411         sblock.fs_interleave = 1;
412         sblock.fs_trackskew = 0;
413         sblock.fs_npsect = secpercyl;
414         sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT;
415         sblock.fs_sbsize = fragroundup(&sblock, sizeof(struct fs));
416         if (sblock.fs_sbsize > SBSIZE)
417                 sblock.fs_sbsize = SBSIZE;
418         sblock.fs_cpc = 0;
419         /*
420          * Compute/validate number of cylinder groups.
421          */
422         sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg;
423         if (sblock.fs_ncyl % sblock.fs_cpg)
424                 sblock.fs_ncg++;
425         sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock);
426         i = MIN(~sblock.fs_cgmask, sblock.fs_ncg - 1);
427         if (cgdmin(&sblock, i) - cgbase(&sblock, i) >= sblock.fs_fpg) {
428                 printf("inode blocks/cyl group (%ld) >= data blocks (%ld)\n",
429                     cgdmin(&sblock, i) - cgbase(&sblock, i) / sblock.fs_frag,
430                     (long)(sblock.fs_fpg / sblock.fs_frag));
431                 printf("number of cylinders per cylinder group (%d) %s.\n",
432                     sblock.fs_cpg, "must be increased");
433                 exit(29);
434         }
435         j = sblock.fs_ncg - 1;
436         if ((i = fssize - j * sblock.fs_fpg) < sblock.fs_fpg &&
437             cgdmin(&sblock, j) - cgbase(&sblock, j) > i) {
438                 if (j == 0) {
439                         printf("Filesystem must have at least %d sectors\n",
440                             NSPF(&sblock) *
441                             (cgdmin(&sblock, 0) + 3 * sblock.fs_frag));
442                         exit(30);
443                 }
444                 printf(
445 "Warning: inode blocks/cyl group (%ld) >= data blocks (%ld) in last\n",
446                     (cgdmin(&sblock, j) - cgbase(&sblock, j)) / sblock.fs_frag,
447                     i / sblock.fs_frag);
448                 printf(
449 "    cylinder group. This implies %ld sector(s) cannot be allocated.\n",
450                     i * NSPF(&sblock));
451                 sblock.fs_ncg--;
452                 sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg;
453                 sblock.fs_size = fssize = sblock.fs_ncyl * sblock.fs_spc /
454                     NSPF(&sblock);
455                 lwarn = 0;
456         }
457         if (lwarn) {
458                 printf("Warning: %d sector(s) in last cylinder unallocated\n",
459                     sblock.fs_spc -
460                     (fssize * NSPF(&sblock) - (sblock.fs_ncyl - 1) *
461                     sblock.fs_spc));
462         }
463         /*
464          * fill in remaining fields of the super block
465          */
466         sblock.fs_csaddr = cgdmin(&sblock, 0);
467         sblock.fs_cssize =
468             fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum));
469         /*
470          * The superblock fields 'fs_csmask' and 'fs_csshift' are no
471          * longer used. However, we still initialise them so that the
472          * filesystem remains compatible with old kernels.
473          */
474         i = sblock.fs_bsize / sizeof(struct csum);
475         sblock.fs_csmask = ~(i - 1);
476         sblock.fs_csshift = ilog2(i);
477         fscs = (struct csum *)calloc(1, sblock.fs_cssize);
478         if (fscs == NULL)
479                 errx(31, "calloc failed");
480         sblock.fs_magic = FS_MAGIC;
481         sblock.fs_rotdelay = 0;
482         sblock.fs_minfree = minfree;
483         sblock.fs_maxcontig = maxcontig;
484         sblock.fs_maxbpg = maxbpg;
485         sblock.fs_rps = 60;
486         sblock.fs_optim = opt;
487         sblock.fs_cgrotor = 0;
488         sblock.fs_cstotal.cs_ndir = 0;
489         sblock.fs_cstotal.cs_nbfree = 0;
490         sblock.fs_cstotal.cs_nifree = 0;
491         sblock.fs_cstotal.cs_nffree = 0;
492         sblock.fs_fmod = 0;
493         sblock.fs_ronly = 0;
494         sblock.fs_clean = 1;
495         sblock.fs_id[0] = (long)utime;
496         sblock.fs_id[1] = random();
497
498         /*
499          * Dump out summary information about filesystem.
500          */
501         printf("%s:\t%d sectors in %d %s of %d tracks, %d sectors\n",
502             fsys, sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl,
503             "cylinders", sblock.fs_ntrak, sblock.fs_nsect);
504 #define B2MBFACTOR (1 / (1024.0 * 1024.0))
505         printf("\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)%s\n",
506             (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR,
507             sblock.fs_ncg, sblock.fs_cpg,
508             (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR,
509             sblock.fs_ipg,
510             sblock.fs_flags & FS_DOSOFTDEP ? " SOFTUPDATES" : "");
511 #undef B2MBFACTOR
512         /*
513          * Now build the cylinders group blocks and
514          * then print out indices of cylinder groups.
515          */
516         printf("super-block backups (for fsck -b #) at:\n");
517         i = 0;
518         width = charsperline();
519         for (cylno = 0; cylno < sblock.fs_ncg; cylno++) {
520                 initcg(cylno, utime);
521                 j = snprintf(tmpbuf, sizeof(tmpbuf), " %ld%s",
522                     fsbtodb(&sblock, cgsblock(&sblock, cylno)),
523                     cylno < (sblock.fs_ncg-1) ? "," : "");
524                 if (j < 0)
525                         tmpbuf[j = 0] = '\0';
526                 if (i + j >= width) {
527                         printf("\n");
528                         i = 0;
529                 }
530                 i += j;
531                 printf("%s", tmpbuf);
532                 fflush(stdout);
533         }
534         printf("\n");
535         if (Nflag)
536                 exit(0);
537         /*
538          * Now construct the initial filesystem,
539          * then write out the super-block.
540          */
541         fsinit(utime);
542         sblock.fs_time = utime;
543         wtfs((int)SBOFF / sectorsize, SBSIZE, (char *)&sblock);
544         for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize)
545                 wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)),
546                         sblock.fs_cssize - i < sblock.fs_bsize ?
547                         sblock.fs_cssize - i : sblock.fs_bsize,
548                         ((char *)fscs) + i);
549         /*
550          * Write out the duplicate super blocks
551          */
552         for (cylno = 0; cylno < sblock.fs_ncg; cylno++)
553                 wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)),
554                     SBSIZE, (char *)&sblock);
555         wtfsflush();
556         /*
557          * Update information about this partion in pack
558          * label, to that it may be updated on disk.
559          */
560         if (pp != NULL) {
561                 pp->p_fstype = FS_BSDFFS;
562                 pp->p_fsize = sblock.fs_fsize;
563                 pp->p_frag = sblock.fs_frag;
564                 pp->p_cpg = sblock.fs_cpg;
565         }
566 }
567
568 /*
569  * Initialize a cylinder group.
570  */
571 void
572 initcg(int cylno, time_t utime)
573 {
574         daddr_t cbase, d, dlower, dupper, dmax, blkno;
575         struct csum *cs;
576         long i, j;
577
578         /*
579          * Determine block bounds for cylinder group.
580          * Allow space for super block summary information in first
581          * cylinder group.
582          */
583         cbase = cgbase(&sblock, cylno);
584         dmax = cbase + sblock.fs_fpg;
585         if (dmax > sblock.fs_size)
586                 dmax = sblock.fs_size;
587         dlower = cgsblock(&sblock, cylno) - cbase;
588         dupper = cgdmin(&sblock, cylno) - cbase;
589         if (cylno == 0)
590                 dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
591         cs = fscs + cylno;
592         memset(&acg, 0, sblock.fs_cgsize);
593         acg.cg_time = utime;
594         acg.cg_magic = CG_MAGIC;
595         acg.cg_cgx = cylno;
596         if (cylno == sblock.fs_ncg - 1)
597                 acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg;
598         else
599                 acg.cg_ncyl = sblock.fs_cpg;
600         acg.cg_niblk = sblock.fs_ipg;
601         acg.cg_ndblk = dmax - cbase;
602         if (sblock.fs_contigsumsize > 0)
603                 acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag;
604         acg.cg_btotoff = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield);
605         acg.cg_boff = acg.cg_btotoff + sblock.fs_cpg * sizeof(int32_t);
606         acg.cg_iusedoff = acg.cg_boff +
607                 sblock.fs_cpg * sizeof(u_int16_t);
608         acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY);
609         if (sblock.fs_contigsumsize <= 0) {
610                 acg.cg_nextfreeoff = acg.cg_freeoff +
611                     howmany(sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock),
612                     NBBY);
613         } else {
614                 acg.cg_clustersumoff = acg.cg_freeoff + howmany
615                     (sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY) -
616                     sizeof(u_int32_t);
617                 acg.cg_clustersumoff =
618                     roundup(acg.cg_clustersumoff, sizeof(u_int32_t));
619                 acg.cg_clusteroff = acg.cg_clustersumoff +
620                     (sblock.fs_contigsumsize + 1) * sizeof(u_int32_t);
621                 acg.cg_nextfreeoff = acg.cg_clusteroff + howmany
622                     (sblock.fs_cpg * sblock.fs_spc / NSPB(&sblock), NBBY);
623         }
624         if (acg.cg_nextfreeoff - (long)(&acg.cg_firstfield) >
625             sblock.fs_cgsize) {
626                 printf("Panic: cylinder group too big\n");
627                 exit(37);
628         }
629         acg.cg_cs.cs_nifree += sblock.fs_ipg;
630         if (cylno == 0)
631                 for (i = 0; i < ROOTINO; i++) {
632                         setbit(cg_inosused(&acg), i);
633                         acg.cg_cs.cs_nifree--;
634                 }
635         for (i = 0; i < sblock.fs_ipg / INOPF(&sblock); i += sblock.fs_frag) {
636                 for (j = 0; j < sblock.fs_bsize / sizeof(struct dinode); j++)
637                         zino[j].di_gen = random();
638                 wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i),
639                     sblock.fs_bsize, (char *)zino);
640         }
641         if (cylno > 0) {
642                 /*
643                  * In cylno 0, beginning space is reserved
644                  * for boot and super blocks.
645                  */
646                 for (d = 0; d < dlower; d += sblock.fs_frag) {
647                         blkno = d / sblock.fs_frag;
648                         setblock(&sblock, cg_blksfree(&acg), blkno);
649                         if (sblock.fs_contigsumsize > 0)
650                                 setbit(cg_clustersfree(&acg), blkno);
651                         acg.cg_cs.cs_nbfree++;
652                         cg_blktot(&acg)[cbtocylno(&sblock, d)]++;
653                         cg_blks(&sblock, &acg, cbtocylno(&sblock, d))
654                             [cbtorpos(&sblock, d)]++;
655                 }
656                 sblock.fs_dsize += dlower;
657         }
658         sblock.fs_dsize += acg.cg_ndblk - dupper;
659         if ((i = dupper % sblock.fs_frag)) {
660                 acg.cg_frsum[sblock.fs_frag - i]++;
661                 for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) {
662                         setbit(cg_blksfree(&acg), dupper);
663                         acg.cg_cs.cs_nffree++;
664                 }
665         }
666         for (d = dupper; d + sblock.fs_frag <= dmax - cbase;) {
667                 blkno = d / sblock.fs_frag;
668                 setblock(&sblock, cg_blksfree(&acg), blkno);
669                 if (sblock.fs_contigsumsize > 0)
670                         setbit(cg_clustersfree(&acg), blkno);
671                 acg.cg_cs.cs_nbfree++;
672                 cg_blktot(&acg)[cbtocylno(&sblock, d)]++;
673                 cg_blks(&sblock, &acg, cbtocylno(&sblock, d))
674                     [cbtorpos(&sblock, d)]++;
675                 d += sblock.fs_frag;
676         }
677         if (d < dmax - cbase) {
678                 acg.cg_frsum[dmax - cbase - d]++;
679                 for (; d < dmax - cbase; d++) {
680                         setbit(cg_blksfree(&acg), d);
681                         acg.cg_cs.cs_nffree++;
682                 }
683         }
684         if (sblock.fs_contigsumsize > 0) {
685                 int32_t *sump = cg_clustersum(&acg);
686                 u_char *mapp = cg_clustersfree(&acg);
687                 int map = *mapp++;
688                 int bit = 1;
689                 int run = 0;
690
691                 for (i = 0; i < acg.cg_nclusterblks; i++) {
692                         if ((map & bit) != 0)
693                                 run++;
694                         else if (run != 0) {
695                                 if (run > sblock.fs_contigsumsize)
696                                         run = sblock.fs_contigsumsize;
697                                 sump[run]++;
698                                 run = 0;
699                         }
700                         if ((i & (NBBY - 1)) != NBBY - 1)
701                                 bit <<= 1;
702                         else {
703                                 map = *mapp++;
704                                 bit = 1;
705                         }
706                 }
707                 if (run != 0) {
708                         if (run > sblock.fs_contigsumsize)
709                                 run = sblock.fs_contigsumsize;
710                         sump[run]++;
711                 }
712         }
713         sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir;
714         sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree;
715         sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree;
716         sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree;
717         *cs = acg.cg_cs;
718         wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)),
719                 sblock.fs_bsize, (char *)&acg);
720 }
721
722 /*
723  * initialize the filesystem
724  */
725 struct dinode node;
726
727 #define PREDEFDIR 2
728
729 struct direct root_dir[] = {
730         { ROOTINO, sizeof(struct direct), DT_DIR, 1, "." },
731         { ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." },
732 };
733 struct odirect {
734         u_long  d_ino;
735         u_short d_reclen;
736         u_short d_namlen;
737         u_char  d_name[MAXNAMLEN + 1];
738 } oroot_dir[] = {
739         { ROOTINO, sizeof(struct direct), 1, "." },
740         { ROOTINO, sizeof(struct direct), 2, ".." },
741 };
742 char buf[MAXBSIZE];
743
744 void
745 fsinit(time_t utime)
746 {
747
748         /*
749          * initialize the node
750          */
751         node.di_atime = utime;
752         node.di_mtime = utime;
753         node.di_ctime = utime;
754         /*
755          * create the root directory
756          */
757         node.di_mode = IFDIR | UMASK;
758         node.di_nlink = PREDEFDIR;
759         node.di_size = makedir(root_dir, PREDEFDIR);
760         node.di_db[0] = alloc(sblock.fs_fsize, node.di_mode);
761         node.di_blocks = btodb(fragroundup(&sblock, node.di_size));
762         wtfs(fsbtodb(&sblock, node.di_db[0]), sblock.fs_fsize, buf);
763         iput(&node, ROOTINO);
764 }
765
766 /*
767  * construct a set of directory entries in "buf".
768  * return size of directory.
769  */
770 int
771 makedir(struct direct *protodir, int entries)
772 {
773         char *cp;
774         int i, spcleft;
775
776         spcleft = DIRBLKSIZ;
777         for (cp = buf, i = 0; i < entries - 1; i++) {
778                 protodir[i].d_reclen = DIRSIZ(0, &protodir[i]);
779                 memmove(cp, &protodir[i], protodir[i].d_reclen);
780                 cp += protodir[i].d_reclen;
781                 spcleft -= protodir[i].d_reclen;
782         }
783         protodir[i].d_reclen = spcleft;
784         memmove(cp, &protodir[i], DIRSIZ(0, &protodir[i]));
785         return (DIRBLKSIZ);
786 }
787
788 /*
789  * allocate a block or frag
790  */
791 daddr_t
792 alloc(int size, int mode)
793 {
794         int i, frag;
795         daddr_t d, blkno;
796
797         rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
798             (char *)&acg);
799         if (acg.cg_magic != CG_MAGIC) {
800                 printf("cg 0: bad magic number\n");
801                 return (0);
802         }
803         if (acg.cg_cs.cs_nbfree == 0) {
804                 printf("first cylinder group ran out of space\n");
805                 return (0);
806         }
807         for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag)
808                 if (isblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag))
809                         goto goth;
810         printf("internal error: can't find block in cyl 0\n");
811         return (0);
812 goth:
813         blkno = fragstoblks(&sblock, d);
814         clrblock(&sblock, cg_blksfree(&acg), blkno);
815         if (sblock.fs_contigsumsize > 0)
816                 clrbit(cg_clustersfree(&acg), blkno);
817         acg.cg_cs.cs_nbfree--;
818         sblock.fs_cstotal.cs_nbfree--;
819         fscs[0].cs_nbfree--;
820         if (mode & IFDIR) {
821                 acg.cg_cs.cs_ndir++;
822                 sblock.fs_cstotal.cs_ndir++;
823                 fscs[0].cs_ndir++;
824         }
825         cg_blktot(&acg)[cbtocylno(&sblock, d)]--;
826         cg_blks(&sblock, &acg, cbtocylno(&sblock, d))[cbtorpos(&sblock, d)]--;
827         if (size != sblock.fs_bsize) {
828                 frag = howmany(size, sblock.fs_fsize);
829                 fscs[0].cs_nffree += sblock.fs_frag - frag;
830                 sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag;
831                 acg.cg_cs.cs_nffree += sblock.fs_frag - frag;
832                 acg.cg_frsum[sblock.fs_frag - frag]++;
833                 for (i = frag; i < sblock.fs_frag; i++)
834                         setbit(cg_blksfree(&acg), d + i);
835         }
836         wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
837             (char *)&acg);
838         return (d);
839 }
840
841 /*
842  * Calculate number of inodes per group.
843  */
844 long
845 calcipg(long lcpg, long bpcg, off_t *usedbp)
846 {
847         int i;
848         long ipg, new_ipg, ncg, ncyl;
849         off_t usedb;
850
851         /*
852          * Prepare to scale by fssize / (number of sectors in cylinder groups).
853          * Note that fssize is still in sectors, not filesystem blocks.
854          */
855         ncyl = howmany(fssize, (u_int)secpercyl);
856         ncg = howmany(ncyl, lcpg);
857         /*
858          * Iterate a few times to allow for ipg depending on itself.
859          */
860         ipg = 0;
861         for (i = 0; i < 10; i++) {
862                 usedb = (sblock.fs_iblkno + ipg / INOPF(&sblock)) *
863                     NSPF(&sblock) * (off_t)sectorsize;
864                 new_ipg = (lcpg * (quad_t)bpcg - usedb) / density *
865                     fssize / ncg / secpercyl / lcpg;
866                 new_ipg = roundup(new_ipg, INOPB(&sblock));
867                 if (new_ipg == ipg)
868                         break;
869                 ipg = new_ipg;
870         }
871         *usedbp = usedb;
872         return (ipg);
873 }
874
875 /*
876  * Allocate an inode on the disk
877  */
878 void
879 iput(struct dinode *ip, ino_t ino)
880 {
881         struct dinode lbuf[MAXINOPB];
882         daddr_t d;
883         int c;
884
885         ip->di_gen = random();
886         c = ino_to_cg(&sblock, ino);
887         rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
888             (char *)&acg);
889         if (acg.cg_magic != CG_MAGIC) {
890                 printf("cg 0: bad magic number\n");
891                 exit(31);
892         }
893         acg.cg_cs.cs_nifree--;
894         setbit(cg_inosused(&acg), ino);
895         wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
896             (char *)&acg);
897         sblock.fs_cstotal.cs_nifree--;
898         fscs[0].cs_nifree--;
899         if (ino >= sblock.fs_ipg * sblock.fs_ncg) {
900                 printf("fsinit: inode value out of range (%d).\n", ino);
901                 exit(32);
902         }
903         d = fsbtodb(&sblock, ino_to_fsba(&sblock, ino));
904         rdfs(d, sblock.fs_bsize, (char *)lbuf);
905         lbuf[ino_to_fsbo(&sblock, ino)] = *ip;
906         wtfs(d, sblock.fs_bsize, (char *)lbuf);
907 }
908
909 /*
910  * read a block from the filesystem
911  */
912 void
913 rdfs(daddr_t bno, int size, char *bf)
914 {
915         int n;
916
917         wtfsflush();
918         if (lseek(fso, (off_t)bno * sectorsize, 0) < 0) {
919                 printf("seek error: %ld\n", (long)bno);
920                 err(33, "rdfs");
921         }
922         n = read(fso, bf, size);
923         if (n != size) {
924                 printf("read error: %ld\n", (long)bno);
925                 err(34, "rdfs");
926         }
927 }
928
929 #define WCSIZE (128 * 1024)
930 daddr_t wc_sect;                /* units of sectorsize */
931 int wc_end;                     /* bytes */
932 static char wc[WCSIZE];         /* bytes */
933
934 /*
935  * Flush dirty write behind buffer.
936  */
937 static void
938 wtfsflush()
939 {
940         int n;
941         if (wc_end) {
942                 if (lseek(fso, (off_t)wc_sect * sectorsize, SEEK_SET) < 0) {
943                         printf("seek error: %ld\n", (long)wc_sect);
944                         err(35, "wtfs - writecombine");
945                 }
946                 n = write(fso, wc, wc_end);
947                 if (n != wc_end) {
948                         printf("write error: %ld\n", (long)wc_sect);
949                         err(36, "wtfs - writecombine");
950                 }
951                 wc_end = 0;
952         }
953 }
954
955 /*
956  * write a block to the filesystem
957  */
958 static void
959 wtfs(daddr_t bno, int size, char *bf)
960 {
961         int done, n;
962
963         if (Nflag)
964                 return;
965         done = 0;
966         if (wc_end == 0 && size <= WCSIZE) {
967                 wc_sect = bno;
968                 bcopy(bf, wc, size);
969                 wc_end = size;
970                 if (wc_end < WCSIZE)
971                         return;
972                 done = 1;
973         }
974         if ((off_t)wc_sect * sectorsize + wc_end == (off_t)bno * sectorsize &&
975             wc_end + size <= WCSIZE) {
976                 bcopy(bf, wc + wc_end, size);
977                 wc_end += size;
978                 if (wc_end < WCSIZE)
979                         return;
980                 done = 1;
981         }
982         wtfsflush();
983         if (done)
984                 return;
985         if (lseek(fso, (off_t)bno * sectorsize, SEEK_SET) < 0) {
986                 printf("seek error: %ld\n", (long)bno);
987                 err(35, "wtfs");
988         }
989         n = write(fso, bf, size);
990         if (n != size) {
991                 printf("write error: %ld\n", (long)bno);
992                 err(36, "wtfs");
993         }
994 }
995
996 /*
997  * check if a block is available
998  */
999 static int
1000 isblock(struct fs *fs, unsigned char *cp, int h)
1001 {
1002         unsigned char mask;
1003
1004         switch (fs->fs_frag) {
1005         case 8:
1006                 return (cp[h] == 0xff);
1007         case 4:
1008                 mask = 0x0f << ((h & 0x1) << 2);
1009                 return ((cp[h >> 1] & mask) == mask);
1010         case 2:
1011                 mask = 0x03 << ((h & 0x3) << 1);
1012                 return ((cp[h >> 2] & mask) == mask);
1013         case 1:
1014                 mask = 0x01 << (h & 0x7);
1015                 return ((cp[h >> 3] & mask) == mask);
1016         default:
1017                 fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag);
1018                 return (0);
1019         }
1020 }
1021
1022 /*
1023  * take a block out of the map
1024  */
1025 static void
1026 clrblock(struct fs *fs, unsigned char *cp, int h)
1027 {
1028         switch ((fs)->fs_frag) {
1029         case 8:
1030                 cp[h] = 0;
1031                 return;
1032         case 4:
1033                 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
1034                 return;
1035         case 2:
1036                 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
1037                 return;
1038         case 1:
1039                 cp[h >> 3] &= ~(0x01 << (h & 0x7));
1040                 return;
1041         default:
1042                 fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag);
1043                 return;
1044         }
1045 }
1046
1047 /*
1048  * put a block into the map
1049  */
1050 static void
1051 setblock(struct fs *fs, unsigned char *cp, int h)
1052 {
1053         switch (fs->fs_frag) {
1054         case 8:
1055                 cp[h] = 0xff;
1056                 return;
1057         case 4:
1058                 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
1059                 return;
1060         case 2:
1061                 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
1062                 return;
1063         case 1:
1064                 cp[h >> 3] |= (0x01 << (h & 0x7));
1065                 return;
1066         default:
1067                 fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag);
1068                 return;
1069         }
1070 }
1071
1072 /*
1073  * Determine the number of characters in a
1074  * single line.
1075  */
1076
1077 static int
1078 charsperline(void)
1079 {
1080         int columns;
1081         char *cp;
1082         struct winsize ws;
1083
1084         columns = 0;
1085         if (ioctl(0, TIOCGWINSZ, &ws) != -1)
1086                 columns = ws.ws_col;
1087         if (columns == 0 && (cp = getenv("COLUMNS")))
1088                 columns = atoi(cp);
1089         if (columns == 0)
1090                 columns = 80;   /* last resort */
1091         return (columns);
1092 }
1093
1094 static int
1095 ilog2(int val)
1096 {
1097         u_int n;
1098
1099         for (n = 0; n < sizeof(n) * NBBY; n++)
1100                 if (1 << n == val)
1101                         return (n);
1102         errx(1, "ilog2: %d is not a power of 2\n", val);
1103 }