DF-3015 / inopatch.c
/* * inopatch.c — DF-3015/DF-3016 on-disk dinode patcher (runs as root, guest). * * usage: inopatch <image> <ino> get - show dinode summary * inopatch <image> <ino> setsize <hex> - set di_size (64-bit LE) * * Computes the byte offset of inode <ino> using the real FFS macros from * the image's own superblock, self-verifies that the dinode at that offset * has a sane di_gen/di_mode, and patches di_size. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <fcntl.h> #include <unistd.h> #include <sys/types.h> #define _KERNEL_STRUCTURES #define MAXFRAG 8 #include "dinode.h" #include "fs.h" int main(int argc, char **argv) { struct fs fsb; struct ufs1_dinode di; off_t off; int fd; unsigned long ino; if (argc < 4) { fprintf(stderr, "usage: %s img ino get|setsize hexval\n", argv[0]); return (2); } ino = strtoul(argv[2], NULL, 0); fd = open(argv[1], O_RDWR); if (fd < 0) { perror("open"); return (1); } if (pread(fd, &fsb, sizeof(fsb), 8192) != sizeof(fsb)) { perror("pread sb"); return (1); } if (fsb.fs_magic != FS_MAGIC) { fprintf(stderr, "bad magic %x\n", fsb.fs_magic); return (1); } /* byte offset of the inode's dinode (FFS addresses are in fragments) */ off = (off_t)(cgimin(&fsb, ino_to_cg(&fsb, ino)) + (ino % fsb.fs_ipg) / INOPB(&fsb)) * fsb.fs_fsize + ((ino % fsb.fs_ipg) % INOPB(&fsb)) * sizeof(struct ufs1_dinode); if (pread(fd, &di, sizeof(di), off) != sizeof(di)) { perror("pread dinode"); return (1); } printf("ino %lu at byte off %lld: mode=%o nlink=%d size=%llu " "blocks=%d db0=%d gen=%d\n", ino, (long long)off, di.di_mode, di.di_nlink, (unsigned long long)di.di_size, di.di_blocks, di.di_db[0], di.di_gen); if (strcmp(argv[3], "setsize") == 0 && argc > 4) { uint64_t v = strtoull(argv[4], NULL, 0); di.di_size = v; if (pwrite(fd, &di, sizeof(di), off) != sizeof(di)) { perror("pwrite"); return (1); } printf("di_size patched to 0x%llx\n", (unsigned long long)v); } close(fd); return (0); } |