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