📄 genext2fs.c
字号:
fs->sb.s_magic = EXT2_MAGIC_NUMBER; // set up groupdescriptors fs->sb.s_free_blocks_count -= 5 + fs->sb.s_inodes_count * sizeof(inode) / BLOCKSIZE; fs->gd.bg_free_blocks_count = fs->sb.s_free_blocks_count; fs->gd.bg_free_inodes_count = fs->sb.s_free_inodes_count; fs->gd.bg_used_dirs_count = 1; fs->gd.bg_block_bitmap = 3; fs->gd.bg_inode_bitmap = 4; fs->gd.bg_inode_table = 5; // mark non-filesystem blocks and inodes as allocated for(i = fs->sb.s_blocks_count; i <= BLOCKSIZE * 8; i++) allocate(fs->bbm, i); for(i = fs->sb.s_inodes_count + 1; i <= BLOCKSIZE * 8; i++) allocate(fs->ibm, i); // mark system blocsk and inodes as allocated for(i = 1; i <= 4 + fs->sb.s_inodes_count * sizeof(inode) / BLOCKSIZE; i++) allocate(fs->bbm, i); for(i = 1; i < EXT2_FIRST_INO; i++) allocate(fs->ibm, i); // make root inode and directory fs->itab[EXT2_ROOT_INO-1].i_mode = FM_IFDIR | FM_IRWXU | FM_IRWXG | FM_IRWXO; fs->itab[EXT2_ROOT_INO-1].i_size = BLOCKSIZE; fs->itab[EXT2_ROOT_INO-1].i_links_count = 2; b = get_workblk(); d = (directory*)b; d->d_inode = EXT2_ROOT_INO; d->d_rec_len = sizeof(directory)+4; d->d_name_len = 1; strcpy(d->d_name, "."); d = (directory*)(b + d->d_rec_len); d->d_inode = EXT2_ROOT_INO; d->d_rec_len = BLOCKSIZE - (sizeof(directory)+4); d->d_name_len = 2; strcpy(d->d_name, ".."); extend_blk(fs, EXT2_ROOT_INO, b, 1); // make lost+found directory and reserve blocks if(fs->sb.s_r_blocks_count) { nod = mkdir_fs(fs, EXT2_ROOT_INO, "lost+found", FM_IRWXU | FM_IRWXG | FM_IRWXO); memset(b, 0, BLOCKSIZE); ((directory*)b)->d_rec_len = BLOCKSIZE; for(i = 1; i < fs->sb.s_r_blocks_count; i++) extend_blk(fs, nod, b, 1); get_nod(fs, nod)->i_size = fs->sb.s_r_blocks_count * BLOCKSIZE; } free_workblk(b); // administrative info fs->sb.s_state = 1; fs->sb.s_max_mnt_count = 20; // options for me if(holes) fs->sb.s_reserved[200] |= OP_HOLES; return fs;}// loads a filesystem from diskfilesystem * load_fs(FILE * fh, int swapit){ size_t fssize; filesystem *fs; if((fseek(fh, 0, SEEK_END) < 0) || ((fssize = ftell(fh)) < 0)) pexit("input filesystem image"); rewind(fh); fssize = (fssize + BLOCKSIZE - 1) / BLOCKSIZE; if(fssize < 16) // totally arbitrary errexit("too small filesystem"); if(fssize > BLOCKS_PER_GROUP) // I build only one group errexit("too big filesystem"); if(!(fs = (filesystem*)calloc(fssize, BLOCKSIZE))) errexit("not enough memory for filesystem"); if(fread(fs, BLOCKSIZE, fssize, fh) != fssize) pexit("input filesystem image"); if(swapit) swap_badfs(fs); if(fs->sb.s_rev_level || (fs->sb.s_magic != EXT2_MAGIC_NUMBER)) errexit("not a suitable ext2 filesystem"); return fs;}void free_fs(filesystem *fs){ free(fs);}// just walk through blocks listvoid flist_blocks(filesystem *fs, uint32 nod, FILE *fh){ blockwalker bw; uint32 bk; init_bw(fs, nod, &bw); while((bk = walk_bw(fs, nod, &bw, 0, 0)) != WALK_END) fprintf(fh, " %d", bk); fprintf(fh, "\n");}// walk through blocks listvoid list_blocks(filesystem *fs, uint32 nod){ int bn = 0; blockwalker bw; uint32 bk; init_bw(fs, nod, &bw); printf("blocks in inode %d:", nod); while((bk = walk_bw(fs, nod, &bw, 0, 0)) != WALK_END) printf(" %d", bk), bn++; printf("\n%d blocks (%d bytes)\n", bn, bn * BLOCKSIZE);}// saves blocks to FILE*void write_blocks(filesystem *fs, uint32 nod, FILE* f){ blockwalker bw; uint32 bk; int32 fsize = get_nod(fs, nod)->i_size; init_bw(fs, nod, &bw); while((bk = walk_bw(fs, nod, &bw, 0, 0)) != WALK_END) { if(fsize <= 0) errexit("wrong size while saving inode %d", nod); if(fwrite(get_blk(fs, bk), (fsize > BLOCKSIZE) ? BLOCKSIZE : fsize, 1, f) != 1) errexit("error while saving inode %d", nod); fsize -= BLOCKSIZE; }}// hexdumps blocks to a FILE*void hexdump_blocks(filesystem *fs, uint32 nod, FILE* f){ blockwalker bw; uint32 bk; uint8 *b; int32 fsize = get_nod(fs, nod)->i_size; init_bw(fs, nod, &bw); printf("block: offset: data: ascii:\n"); while((bk = walk_bw(fs, nod, &bw, 0, 0)) != WALK_END) { int i, j; if(fsize <= 0) errexit("wrong size while saving inode %d", nod); b = get_blk(fs, bk); for(i = 0; i < 64; i++) { int dmp = 0; for(j = 0; j < 4; j++) if(*(int32*)&b[i * 16 + j * 4]) dmp = 1; if(!dmp) continue; printf("%5d: %03X:", bk, i * 16); for(j = 0; j < 4; j++) printf(" %08x", *(int32*)&b[i * 16 + j * 4]); printf(" "); for(j = 0; j < 16; j++) printf("%c", (b[i * 16 + j] >= ' ' && b[i * 16 + j] < 127) ? b[i * 16 + j] : ' '); printf("\n"); } fsize -= BLOCKSIZE; }}// print block/char device minor and majorvoid print_dev(filesystem *fs, uint32 nod){ int minor, major; minor = ((uint8*)get_nod(fs, nod)->i_block)[0]; major = ((uint8*)get_nod(fs, nod)->i_block)[1]; printf("major: %d, minor: %d\n", major, minor);}// print an inode as a directoryvoid print_dir(filesystem *fs, uint32 nod){ blockwalker bw; uint32 bk; init_bw(fs, nod, &bw); printf("directory for inode %d:\n", nod); while((bk = walk_bw(fs, nod, &bw, 0, 0)) != WALK_END) { directory *d; uint8 *b; b = get_blk(fs, bk); for(d = (directory*)b; (int8*)d + sizeof(*d) < (int8*)b + BLOCKSIZE; d = (directory*)((int8*)d + d->d_rec_len)) if(d->d_inode) { int i; printf("entry '"); for(i = 0; i < d->d_name_len; i++) putchar(d->d_name[i]); printf("' (inode %d): rec_len: %d (name_len: %d)\n", d->d_inode, d->d_rec_len, d->d_name_len); } }}// print a symbolic linkvoid print_link(filesystem *fs, uint32 nod){ if(!get_nod(fs, nod)->i_blocks) printf("links to '%s'\n", (char*)get_nod(fs, nod)->i_block); else { printf("links to '"); write_blocks(fs, nod, stdout); printf("'\n"); }}// make a ls-like printout of permissionsvoid make_perms(uint32 mode, char perms[11]){ strcpy(perms, "----------"); if(mode & FM_IRUSR) perms[1] = 'r'; if(mode & FM_IWUSR) perms[2] = 'w'; if(mode & FM_IXUSR) perms[3] = 'x'; if(mode & FM_IRGRP) perms[4] = 'r'; if(mode & FM_IWGRP) perms[5] = 'w'; if(mode & FM_IXGRP) perms[6] = 'x'; if(mode & FM_IROTH) perms[7] = 'r'; if(mode & FM_IWOTH) perms[8] = 'w'; if(mode & FM_IXOTH) perms[9] = 'x'; if(mode & FM_ISUID) perms[3] = 's'; if(mode & FM_ISGID) perms[6] = 's'; if(mode & FM_ISVTX) perms[9] = 't'; switch(mode & FM_IFMT) { case 0: *perms = '0'; break; case FM_IFSOCK: *perms = 's'; break; case FM_IFLNK: *perms = 'l'; break; case FM_IFREG: *perms = '-'; break; case FM_IFBLK: *perms = 'b'; break; case FM_IFDIR: *perms = 'd'; break; case FM_IFCHR: *perms = 'c'; break; case FM_IFIFO: *perms = 'p'; break; default: *perms = '?'; }}// print an inodevoid print_inode(filesystem *fs, uint32 nod){ char *s; char perms[11]; if(!get_nod(fs, nod)->i_mode) return; switch(nod) { case EXT2_BAD_INO: s = "bad blocks"; break; case EXT2_ROOT_INO: s = "root"; break; case EXT2_ACL_IDX_INO: case EXT2_ACL_DATA_INO: s = "ACL"; break; case EXT2_BOOT_LOADER_INO: s = "boot loader"; break; case EXT2_UNDEL_DIR_INO: s = "undelete directory"; break; default: s = (nod >= EXT2_FIRST_INO) ? "normal" : "unknown reserved"; } printf("inode %d (%s, %d links): ", nod, s, get_nod(fs, nod)->i_links_count); if(!allocated(fs->ibm, nod)) { printf("unallocated\n"); return; } make_perms(get_nod(fs, nod)->i_mode, perms); printf("%s, size: %d byte%s (%d block%s)\n", perms, plural(get_nod(fs, nod)->i_size), plural(get_nod(fs, nod)->i_blocks / INOBLK)); switch(get_nod(fs, nod)->i_mode & FM_IFMT) { case FM_IFSOCK: list_blocks(fs, nod); break; case FM_IFLNK: print_link(fs, nod); break; case FM_IFREG: list_blocks(fs, nod); break; case FM_IFBLK: print_dev(fs, nod); break; case FM_IFDIR: list_blocks(fs, nod); print_dir(fs, nod); break; case FM_IFCHR: print_dev(fs, nod); break; case FM_IFIFO: list_blocks(fs, nod); break; default: list_blocks(fs, nod); }}// describes various fields in a filesystemvoid print_fs(filesystem *fs){ int i; printf("%d blocks (%d free, %d reserved), first data block: %d\n", fs->sb.s_blocks_count, fs->sb.s_free_blocks_count, fs->sb.s_r_blocks_count, fs->sb.s_first_data_block); printf("%d inodes (%d free)\n", fs->sb.s_inodes_count, fs->sb.s_free_inodes_count); printf("block size = %d, frag size = %d\n", fs->sb.s_log_block_size ? (fs->sb.s_log_block_size << 11) : 1024, fs->sb.s_log_frag_size ? (fs->sb.s_log_frag_size << 11) : 1024); printf("%d blocks per group, %d frags per group, %d inodes per group\n", fs->sb.s_blocks_per_group, fs->sb.s_frags_per_group, fs->sb.s_inodes_per_group); printf("block bitmap: block %d, inode bitmap: block %d, inode table: block %d\n", fs->gd.bg_block_bitmap, fs->gd.bg_inode_bitmap, fs->gd.bg_inode_table); printf("block bitmap allocation:\n"); print_bm(fs->bbm, fs->sb.s_blocks_count); printf("inode bitmap allocation:\n"); print_bm(fs->ibm, fs->sb.s_inodes_count); for(i=1; i<=fs->sb.s_inodes_count; i++) if(allocated(fs->ibm, i)) print_inode(fs, i);}void dump_fs(filesystem *fs, FILE * fh, int swapit){ int nbblocks = fs->sb.s_blocks_count; fs->sb.s_reserved[200] = 0; if(swapit) swap_goodfs(fs); if(fwrite(fs, BLOCKSIZE, nbblocks, fh) < nbblocks) pexit("output filesystem image"); if(swapit) swap_badfs(fs);}void showhelp(void){ fprintf(stderr, "Usage: %s [options] image\n" "Create an ext2 filesystem image from directories/files\n\n" " -x image Use this image as a starting point\n" " -d directory Add this directory as source\n" " -f file Add nodes (e.g. devices) from this spec file\n" " -b blocks Size in blocks\n" " -i inodes Number of inodes\n" " -r reserved Number of reserved blocks\n" " -g path Generate a block map file for this path\n" " -e value Fill unallocated blocks with value\n" " -z Make files with holes\n" " -v Print resulting filesystem structure\n" " -h Show this help\n\n" "Example of spec file:\n" "drwx /dev\n" "crw- 10,190 /dev/lcd\n" "brw- 1,0 /dev/ram0\n\n" "Report bugs to xavier.bestel@free.fr\n", argv0);}#define MAX_DOPT 128#define MAX_GOPT 128#define MAX_FILENAME 255extern char* optarg;extern int optind, opterr, optopt;int main(int argc, char **argv){ int nbblocks = -1; int nbinodes = -1; int nbresrvd = -1; char * fsout = "-"; char * fsin = 0; char * dopt[MAX_DOPT]; int didx = 0; char * gopt[MAX_GOPT]; int gidx = 0; int verbose = 0; int holes = 0; int emptyval = 0; uint16 endian = 1; int bigendian = !*(char*)&endian; filesystem *fs; int i; int c; argv0 = argv[0]; if(argc <= 1) { showhelp(); exit(1); } while((c = getopt(argc, argv, "x:f:d:b:i:r:g:e:zvh")) != EOF) switch(c) { case 'x': fsin = optarg; break; case 'd': case 'f': dopt[didx++] = optarg; break; case 'b': nbblocks = atoi(optarg); break; case 'i': nbinodes = atoi(optarg); break; case 'r': nbresrvd = atoi(optarg); break; case 'g': gopt[gidx++] = optarg; break; case 'e': emptyval = atoi(optarg); break; case 'z': holes = 1; break; case 'v': verbose = 1; break; case 'h': showhelp(); exit(0); default: exit(1); } if(optind < (argc - 1)) errexit("too many arguments"); if(optind == (argc - 1)) fsout = argv[optind]; if(fsin) { if(strcmp(fsin, "-")) { FILE * fh = fopen(fsin, "r"); if(!fh) pexit(fsin); fs = load_fs(fh, bigendian); fclose(fh); } else fs = load_fs(stdin, bigendian); } else { if(nbblocks == -1) errexit("filesystem size unspecified"); if(nbinodes == -1) nbinodes = nbblocks * BLOCKSIZE / rndup(BYTES_PER_INODE, BLOCKSIZE); if(nbresrvd == -1) nbresrvd = nbblocks * RESERVED_INODES; fs = init_fs(nbblocks, nbinodes, nbresrvd, holes); } for(i = 0; i < didx; i++) { struct stat st; FILE *fh; char *pdir; stat(dopt[i], &st); switch(st.st_mode & S_IFMT) { case S_IFREG: if(!(fh = fopen(dopt[i], "r"))) pexit(dopt[i]); add2fs_from_file(fs, EXT2_ROOT_INO, fh); fclose(fh); break; case S_IFDIR: if(!(pdir = getcwd(0, GETCWD_SIZE))) pexit(dopt[i]); if(chdir(dopt[i]) < 0) pexit(dopt[i]); add2fs_from_dir(fs, EXT2_ROOT_INO); if(chdir(pdir) < 0) pexit(pdir); free(pdir); break; default: errexit("%s in neither a file nor a directory", dopt[i]); } } if(emptyval) for(i = 1; i < fs->sb.s_blocks_count; i++) if(!allocated(fs->bbm, i)) memset(get_blk(fs, i), emptyval, BLOCKSIZE); if(verbose) print_fs(fs); for(i = 0; i < gidx; i++) { uint32 nod; char fname[MAX_FILENAME]; char *p; FILE *fh; if(!(nod = find_path(fs, EXT2_ROOT_INO, gopt[i]))) errexit("path %s not found in filesystem", gopt[i]); while((p = strchr(gopt[i], '/'))) *p = '_'; snprintf(fname, MAX_FILENAME-1, "%s.blk", gopt[i]); if(!(fh = fopen(fname, "w"))) pexit(fname); fprintf(fh, "%d:", get_nod(fs, nod)->i_size); flist_blocks(fs, nod, fh); fclose(fh); } if(strcmp(fsout, "-")) { FILE * fh = fopen(fsout, "w"); if(!fh) pexit(fsout); dump_fs(fs, fh, bigendian); fclose(fh); } else dump_fs(fs, stdout, bigendian); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -