DF-5707 / zerogen.c
/* * zerogen.c (DFly UFS1) - zero di_gen of free inodes on an unmounted image, * simulating the legacy zero-gen condition under which ffs_valloc draws * krandom()/2+1 (ffs_alloc.c:641-642, ffs_vfsops.c:1174-1175). * usage: zerogen <image> <ino> [<ino>...] */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stddef.h> #include <fcntl.h> #include <unistd.h> #include <inttypes.h> #include <sys/types.h> #include <sys/endian.h> #define MAXFRAG 8 #include "inc/ufs/ufs_types.h" #include "inc/ufs/fs.h" #include "inc/ufs/dinode.h" #define SBLOCK_OFF 8192 int main(int argc, char **argv) { if (argc < 3) { fprintf(stderr, "usage: zerogen image ino...\n"); return 2; } int fd = open(argv[1], O_RDWR); if (fd < 0) { perror("open"); return 1; } static char sbbuf[8192]; if (pread(fd, sbbuf, sizeof(sbbuf), SBLOCK_OFF) != (ssize_t)sizeof(sbbuf)) { perror("pread sb"); return 1; } struct fs *fs = (struct fs *)sbbuf; uint32_t magic = le32toh(*(uint32_t *)&fs->fs_magic); /* fs fields on disk are little-endian on x86_64; magic compare directly */ if (fs->fs_magic != FS_MAGIC && bswap32(fs->fs_magic) != FS_MAGIC) { fprintf(stderr, "bad fs magic 0x%x\n", (unsigned)fs->fs_magic); return 1; } int swapped = (fs->fs_magic != FS_MAGIC); (void)swapped; (void)magic; printf("sb ok: bsize=%d fsize=%d ipg=%d inopb=%d iblkno=%d cgoffset=%d\n", fs->fs_bsize, fs->fs_fsize, fs->fs_ipg, fs->fs_inopb, fs->fs_iblkno, fs->fs_cgoffset); for (int i = 2; i < argc; i++) { uint32_t ino = strtoul(argv[i], NULL, 0); off_t base = (off_t)ino_to_fsba(fs, ino) * (off_t)fs->fs_fsize; off_t ioff = base + (off_t)ino_to_fsbo(fs, ino) * (off_t)sizeof(struct ufs1_dinode); off_t goff = ioff + (off_t)offsetof(struct ufs1_dinode, di_gen); uint32_t gen; if (pread(fd, &gen, 4, goff) != 4) { perror("pread gen"); return 1; } printf("ino %u: dinode@%lld di_gen@%lld = 0x%08x -> 0\n", ino, (long long)ioff, (long long)goff, (unsigned)gen); if (getenv("ZG_PRINT") == NULL) { uint32_t z = 0; if (pwrite(fd, &z, 4, goff) != 4) { perror("pwrite gen"); return 1; } } } fsync(fd); close(fd); printf("done\n"); return 0; } |