/* * This program fixes a bug introduced in ffs filesystems whose * superblock was updated by a netbsd-current kernel in sept 2003. * For more information see mail to tech-kern@netbsd.org * Message ID: <200309282220.h8SMKUN03670@marcela.zlz.net> * Archive URL: * http://mail-index.netbsd.org/tech-kern/2003/09/28/0003.html * * THIS PROGRAM MODIFIES YOUR FILESYSTEM SUPERBLOCK. RUN WITH CARE * * To compile: * cc -o fixufsflags fixufsflags.c -lutil * * Example invocation: * fixufsflags wd0a * * Darrin B. Jewell 2003-10-03 * */ #include #include #include #include #include #include #include #include /* For opendisk. compile this with -lutil */ #include #include #include int fixfs(struct fs *fs); int main(int argc, char *argv[]) { char devfname[MAXPATHLEN] = "unknown"; u_int8_t sbbuf[SBLOCKSIZE] = { 0 }; int r; int fd; off_t off; ssize_t sz; int ret; setprogname(argv[0]); if (argc != 2) errx(EXIT_FAILURE,"usage: %s device",getprogname()); fd = opendisk(argv[1],O_RDWR|O_SYNC|O_RSYNC,devfname,MAXPATHLEN,0); if (fd == -1) err(EXIT_FAILURE,"Unable to open disk %s as %s",argv[1],devfname); off = lseek(fd, SBLOCK_UFS1, SEEK_SET); if (off == -1) err(EXIT_FAILURE,"unable to seek to offset %d",SBLOCK_UFS1); assert(off == SBLOCK_UFS1); sz = read(fd, sbbuf, SBLOCKSIZE); if (sz == -1) err(EXIT_FAILURE,"unable to read %d bytes at offset %d",SBLOCKSIZE,SBLOCK_UFS1); if (sz != SBLOCKSIZE) warnx("unable to read superblock, only read %d bytes at offset %d",sz,SBLOCK_UFS1); printf("Successfully read %"PRIdMAX" bytes at offset %"PRIdMAX" from %s\n", (intmax_t)sz,(intmax_t)off,devfname); ret = fixfs((struct fs *)sbbuf); if ((ret == 1) && (sz == SBLOCKSIZE)) { off = lseek(fd, SBLOCK_UFS1, SEEK_SET); if (off == -1) err(EXIT_FAILURE,"unable to seek to offset %d",SBLOCK_UFS1); assert(off == SBLOCK_UFS1); sz = write(fd, sbbuf, SBLOCKSIZE); if (sz == -1) err(EXIT_FAILURE,"unable to write %d bytes at offset %d",SBLOCKSIZE,SBLOCK_UFS1); if (sz != SBLOCKSIZE) warnx("unable to write superblock, only wrote %d bytes at offset %d",sz,SBLOCK_UFS1); printf("Successfully wrote %"PRIdMAX" bytes at offset %"PRIdMAX" from %s\n", (intmax_t)sz,(intmax_t)off,devfname); printf("Superblock updated\n"); } r = close(fd); if (r == -1) err(EXIT_FAILURE,"close"); assert(r == 0); if (ret == -1) return EXIT_FAILURE; return EXIT_SUCCESS; } int fixfs(struct fs *fs) { int swapped; swapped = fs->fs_magic == FS_UFS1_MAGIC_SWAPPED; if (!swapped && fs->fs_magic != FS_UFS1_MAGIC) { warnx("Magic number does not indicate ffs filesystem"); return -1; } if (swapped) { warnx("Swapped ffs filesystems not supported"); return -1; } if (fs->fs_bsize != fs->fs_maxbsize) { warnx("Does not appear to be upgraded ffs filesystem"); return -1; } if (fs->fs_flags & 0xffffff00) { printf("Unknown bits set in fs_flags: 0x%08x\n",fs->fs_flags); if ((fs->fs_flags & 0x7fffff00) == 0x7fffff00) { printf("Stripping incorrect bits from fs_flags\n"); fs->fs_flags &= 0x7f; return 1; } } else { printf("fs_flags bits appear to be clean\n"); } return 0; }