DF-3172 / inopatch.c
/* inopatch.c — patch a ufs1 dinode field directly in a FFS image. * usage: inopatch <img> <ino> <size|uid|gid|mode> <value> * computes the inode's block via the fs.h macros (geometry read from sb). */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <sys/param.h> #include <vfs/ufs/ufs_types.h> #include <vfs/ufs/fs.h> #include <vfs/ufs/dinode.h> #define SBOFF 8192 int main(int argc, char **argv){ if (argc < 5) { fprintf(stderr, "usage: inopatch img ino size|uid|mode val\n"); return 1; } FILE *f = fopen(argv[1], "r+b"); if (!f) { perror("open"); return 1; } struct fs sb; fseek(f, SBOFF, SEEK_SET); if (fread(&sb, sizeof sb, 1, f) != 1) { perror("read sb"); return 1; } ino_t ino = strtoull(argv[2], NULL, 0); /* byte offset of the inode's fragment on the media */ off_t fsboff = (off_t)ino_to_fsba(&sb, ino) * sb.fs_fsize + (off_t)ino_to_fsbo(&sb, ino) * sizeof(struct ufs1_dinode); struct ufs1_dinode di; fseek(f, fsboff, SEEK_SET); if (fread(&di, sizeof di, 1, f) != 1) { perror("read inode"); return 1; } printf("ino %llu at media off %lld: mode=0%o nlink=%d size=%lld blocks=%lld " "ib=[%d,%d,%d] uid=%d\n", (unsigned long long)ino, (long long)fsboff, di.di_mode, di.di_nlink, (long long)di.di_size, (long long)di.di_blocks, (int)di.di_ib[0], (int)di.di_ib[1], (int)di.di_ib[2], di.di_uid); const char *fld = argv[3]; if (!strcmp(fld, "size")) di.di_size = strtoull(argv[4], NULL, 0); else if (!strcmp(fld, "uid")) di.di_uid = (int32_t)strtoul(argv[4], NULL, 0); else if (!strcmp(fld, "gid")) di.di_gid = (int32_t)strtoul(argv[4], NULL, 0); else if (!strcmp(fld, "mode")) di.di_mode = (uint16_t)strtoul(argv[4], NULL, 0); else { fprintf(stderr, "unknown field\n"); return 1; } fseek(f, fsboff, SEEK_SET); fwrite(&di, sizeof di, 1, f); printf("patched %s=%s\n", fld, argv[4]); fclose(f); return 0; } |