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