#include #include #include #include #include #include #include #ifndef FS_UFS2EA_MAGIC #define FS_UFS2EA_MAGIC 0x19012038 /* UFS2 with extattrs */ #endif #ifndef FS_UFS2EA_MAGIC_SWAPPED #define FS_UFS2EA_MAGIC_SWAPPED 0x38200119 #endif int main(int argc, char **argv) { const char *path; char replybuf[32]; struct fs *fs, *fs2; uint32_t dev_bsize, newmagic; off_t off; char *buf, *buf2; int fd, i; if (argc != 2) { errx(1, "usage: %s ", getprogname()); } path = argv[1]; fd = open(path, O_RDWR); if (fd < 0) { err(1, "open"); } buf = malloc(SBLOCKSIZE); if (buf == NULL) { err(1, "malloc"); } fs = (void *)buf; buf2 = malloc(SBLOCKSIZE); if (buf2 == NULL) { err(1, "malloc2"); } fs2 = (void *)buf2; if (pread(fd, buf, SBLOCKSIZE, SBLOCK_UFS2) != SBLOCKSIZE) { err(1, "pread"); } switch (fs->fs_magic) { case FS_UFS2EA_MAGIC: case FS_UFS2EA_MAGIC_SWAPPED: printf("%s file system is already UFS2ea\n", path); exit(0); break; case FS_UFS2_MAGIC: newmagic = FS_UFS2EA_MAGIC; break; case FS_UFS2_MAGIC_SWAPPED: newmagic = FS_UFS2EA_MAGIC_SWAPPED; break; default: printf("%s does not contain a UFS2 file system\n", path); exit(0); break; } dev_bsize = fs->fs_fsize / FFS_FSBTODB(fs, 1); for (i = 0; i < fs->fs_ncg; i++) { off = (off_t)(FFS_FSBTODB(fs, cgsblock(fs, i))) * dev_bsize; if (pread(fd, buf2, SBLOCKSIZE, off) != SBLOCKSIZE) { err(1, "pread2"); } switch (fs2->fs_magic) { case FS_UFS2EA_MAGIC: case FS_UFS2EA_MAGIC_SWAPPED: case FS_UFS2_MAGIC: case FS_UFS2_MAGIC_SWAPPED: break; default: printf("alt superblock cg %d not recognized\n", i); exit(1); } if (fs2->fs_magic != fs->fs_magic) { errx(1, "primary/alt superblock mismatch cg %d: 0x%08x 0x%08x", i, fs->fs_magic, fs2->fs_magic); } } printf("%s contains an original NetBSD UFS2 file system.\n", path); printf("\n"); printf("This utility converts UFS2 to UFS2ea (UFS2 with extattr support)\n"); printf("WITHOUT deleting possibly corrupted extattr block references.\n"); printf("\n"); printf("In previous releases of NetBSD, UFS2 did not know about extattrs,\n"); printf("so if an inode has non-zero extattr block pointers then an old fsck\n"); printf("may have freed the blocks that these pointers point to.\n"); printf("This utility is intended to be used ONLY by people who have\n"); printf("created extattrs in original NetBSD UFS2 file systems using a kernel\n"); printf("from time period after UFS2 extattr support was added to NetBSD\n"); printf("and before the separate UFS2ea fs type was created.\n"); printf("Using this utility incorrectly may corrupt your file system!\n"); printf("\n"); printf("Proceed with conversion [yes/no] ? "); fflush(stdout); if (fgets(replybuf, sizeof(replybuf), stdin) == NULL || strcmp(replybuf, "yes\n")) { printf("Aborted.\n"); exit(0); } fs->fs_magic = newmagic; fs2->fs_magic = newmagic; for (i = 0; i < fs->fs_ncg; i++) { off = (off_t)(FFS_FSBTODB(fs, cgsblock(fs, i))) * dev_bsize; if (pwrite(fd, buf2, SBLOCKSIZE, off) != SBLOCKSIZE) { err(1, "pwrite alternate sb %d", i); } } if (pwrite(fd, buf, SBLOCKSIZE, SBLOCK_UFS2) != SBLOCKSIZE) { err(1, "pwrite primary sb"); } printf("Conversion successful.\n"); printf("*** RUN \"fsck -fy %s\" TO VERIFY THIS FILE SYSTEM ***\n", path); exit(0); }