aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/makefs/ffs/mkfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/makefs/ffs/mkfs.c')
-rw-r--r--usr.sbin/makefs/ffs/mkfs.c48
1 files changed, 37 insertions, 11 deletions
diff --git a/usr.sbin/makefs/ffs/mkfs.c b/usr.sbin/makefs/ffs/mkfs.c
index 0f8b040d6997..81e3da5725c8 100644
--- a/usr.sbin/makefs/ffs/mkfs.c
+++ b/usr.sbin/makefs/ffs/mkfs.c
@@ -40,9 +40,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/time.h>
#include <sys/resource.h>
@@ -80,6 +77,23 @@ static int count_digits(int);
#define UMASK 0755
#define POWEROF2(num) (((num) & ((num) - 1)) == 0)
+/*
+ * The definition of "struct cg" used to contain an extra field at the end
+ * to represent the variable-length data that followed the fixed structure.
+ * This had the effect of artificially limiting the number of blocks that
+ * newfs would put in a CG, since newfs thought that the fixed-size header
+ * was bigger than it really was. When we started validating that the CG
+ * header data actually fit into one fs block, the placeholder field caused
+ * a problem because it caused struct cg to be a different size depending on
+ * platform. The placeholder field was later removed, but this caused a
+ * backward compatibility problem with older binaries that still thought
+ * struct cg was larger, and a new file system could fail validation if
+ * viewed by the older binaries. To avoid this compatibility problem, we
+ * now artificially reduce the amount of space that the variable-length data
+ * can use such that new file systems will pass validation by older binaries.
+ */
+#define CGSIZEFUDGE 8
+
static union {
struct fs fs;
char pad[SBLOCKSIZE];
@@ -347,7 +361,8 @@ ffs_mkfs(const char *fsys, const fsinfo_t *fsopts, time_t tstamp)
sblock.fs_fpg = minfpg;
sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
INOPB(&sblock));
- if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize)
+ if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize -
+ CGSIZEFUDGE)
break;
density -= sblock.fs_fsize;
}
@@ -366,9 +381,11 @@ ffs_mkfs(const char *fsys, const fsinfo_t *fsopts, time_t tstamp)
INOPB(&sblock));
if (sblock.fs_size / sblock.fs_fpg < 1)
break;
- if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize)
+ if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize -
+ CGSIZEFUDGE)
continue;
- if (CGSIZE(&sblock) == (unsigned long)sblock.fs_bsize)
+ if (CGSIZE(&sblock) == (unsigned long)sblock.fs_bsize -
+ CGSIZEFUDGE)
break;
sblock.fs_fpg -= sblock.fs_frag;
sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
@@ -529,8 +546,9 @@ ffs_mkfs(const char *fsys, const fsinfo_t *fsopts, time_t tstamp)
initcg(cylno, tstamp, fsopts);
if (cylno % nprintcols == 0)
printf("\n");
- printf(" %*lld,", printcolwidth,
- (long long)fsbtodb(&sblock, cgsblock(&sblock, cylno)));
+ printf(" %*lld%s", printcolwidth,
+ (long long)fsbtodb(&sblock, cgsblock(&sblock, cylno)),
+ cylno == sblock.fs_ncg - 1 ? "" : ",");
fflush(stdout);
}
printf("\n");
@@ -561,13 +579,21 @@ ffs_write_superblock(struct fs *fs, const fsinfo_t *fsopts)
{
int size, blks, i, saveflag;
uint32_t cylno;
- void *space;
+ void *info, *space;
char *wrbuf;
saveflag = fs->fs_flags & FS_INTERNAL;
fs->fs_flags &= ~FS_INTERNAL;
- memcpy(writebuf, &sblock, sbsize);
+ /*
+ * Write out the superblock. Blank out the summary info field, as it's
+ * a random pointer that would make the resulting image unreproducible.
+ */
+ info = fs->fs_si;
+ fs->fs_si = NULL;
+ memcpy(writebuf, fs, sbsize);
+ fs->fs_si = info;
+
if (fsopts->needswap)
ffs_sb_swap(fs, (struct fs*)writebuf);
ffs_wtfs(fs->fs_sblockloc / sectorsize, sbsize, writebuf, fsopts);
@@ -633,7 +659,7 @@ initcg(uint32_t cylno, time_t utime, const fsinfo_t *fsopts)
acg.cg_ndblk = dmax - cbase;
if (sblock.fs_contigsumsize > 0)
acg.cg_nclusterblks = acg.cg_ndblk >> sblock.fs_fragshift;
- start = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield);
+ start = sizeof(acg);
if (Oflag == 2) {
acg.cg_iusedoff = start;
} else {