int main(int argc, char **argv) { puts("Copyright (c) 2001-2010 pinc Software."); if (argc < 2 || !strcmp(argv[1], "--help")) { char *filename = strrchr(argv[0],'/'); fprintf(stderr,"usage: %s [-srib] <device> [allocation_group start]\n" "\t-s\tdump superblock\n" "\t-r\tdump root node\n" " the following options need the allocation_group/start " "parameters:\n" "\t-i\tdump inode\n" "\t-b\tdump b+tree\n" "\t-v\tvalidate b+tree\n" "\t-h\thexdump\n" "\t-o\tshow disk offsets\n", filename ? filename + 1 : argv[0]); return -1; } bool dumpRootNode = false; bool dumpInode = false; bool dumpSuperBlock = false; bool dumpBTree = false; bool validateBTree = false; bool dumpHex = false; bool showOffsets = false; while (*++argv) { char *arg = *argv; if (*arg == '-') { while (*++arg && isalpha(*arg)) { switch (*arg) { case 's': dumpSuperBlock = true; break; case 'r': dumpRootNode = true; break; case 'i': dumpInode = true; break; case 'b': dumpBTree = true; break; case 'v': validateBTree = true; break; case 'h': dumpHex = true; break; case 'o': showOffsets = true; break; } } } else break; } Disk disk(argv[0]); if (disk.InitCheck() < B_OK) { fprintf(stderr, "Could not open device or file: %s\n", strerror(disk.InitCheck())); return -1; } putchar('\n'); if (!dumpSuperBlock && !dumpRootNode && !dumpInode && !dumpBTree && !dumpHex) { printf(" Name:\t\t\t\"%s\"\n", disk.SuperBlock()->name); printf(" (disk is %s)\n\n", disk.ValidateSuperBlock() == B_OK ? "valid" : "invalid!!"); printf(" Block Size:\t\t%" B_PRIu32 " bytes\n", disk.BlockSize()); printf(" Number of Blocks:\t%12" B_PRIdOFF "\t%10g MB\n", disk.NumBlocks(), disk.NumBlocks() * disk.BlockSize() / (1024.0*1024)); if (disk.BlockBitmap() != NULL) { printf(" Used Blocks:\t\t%12" B_PRIdOFF "\t%10g MB\n", disk.BlockBitmap()->UsedBlocks(), disk.BlockBitmap()->UsedBlocks() * disk.BlockSize() / (1024.0*1024)); printf(" Free Blocks:\t\t%12" B_PRIdOFF "\t%10g MB\n", disk.BlockBitmap()->FreeBlocks(), disk.BlockBitmap()->FreeBlocks() * disk.BlockSize() / (1024.0*1024)); } int32 size = (disk.AllocationGroups() * disk.SuperBlock()->blocks_per_ag); printf(" Bitmap Size:\t\t%" B_PRIu32 " bytes (%" B_PRId32 " blocks, %" B_PRId32 " per allocation group)\n", disk.BlockSize() * size, size, disk.SuperBlock()->blocks_per_ag); printf(" Allocation Groups:\t%" B_PRIu32 "\n\n", disk.AllocationGroups()); dump_block_run(" Log:\t\t\t", disk.Log()); printf(" (was %s)\n\n", disk.SuperBlock()->flags == SUPER_BLOCK_CLEAN ? "cleanly unmounted" : "not unmounted cleanly!"); dump_block_run(" Root Directory:\t", disk.Root()); putchar('\n'); } else if (dumpSuperBlock) { dump_super_block(disk.SuperBlock()); putchar('\n'); } if (disk.ValidateSuperBlock() < B_OK) { fprintf(stderr, "The disk's superblock is corrupt (or it's not a BFS " "device)!\n"); return 0; } if (dumpRootNode) { bfs_inode inode; if (disk.ReadAt(disk.ToOffset(disk.Root()), (void *)&inode, sizeof(bfs_inode)) < B_OK) { fprintf(stderr,"Could not read root node from disk!\n"); } else { puts("Root node:\n-----------------------------------------"); dump_inode(NULL, &inode, showOffsets); dump_indirect_stream(disk, &inode, showOffsets); putchar('\n'); } } char buffer[disk.BlockSize()]; bfs_inode* bfsInode = (bfs_inode*)buffer; block_run run; Inode *inode = NULL; if (dumpInode || dumpBTree || dumpHex || validateBTree) { // Set the block_run to the right value (as specified on the command // line) if (!argv[1]) { fprintf(stderr, "The -i/b/f options need the allocation group and " "starting offset (or the block number) of the node to dump!\n"); return -1; } run = parseBlockRun(disk, argv[1], argv[2]); if (disk.ReadAt(disk.ToOffset(run), buffer, disk.BlockSize()) <= 0) { fprintf(stderr,"Could not read node from disk!\n"); return -1; } inode = Inode::Factory(&disk, bfsInode, false); if (inode == NULL || inode->InitCheck() < B_OK) { fprintf(stderr,"Not a valid inode!\n"); delete inode; inode = NULL; } } if (dumpInode) { printf("Inode at block %" B_PRIdOFF ":\n------------------------------" "-----------\n", disk.ToBlock(run)); dump_inode(inode, bfsInode, showOffsets); dump_indirect_stream(disk, bfsInode, showOffsets); dump_double_indirect_stream(disk, bfsInode, showOffsets); dump_small_data(inode); putchar('\n'); } if (dumpBTree && inode != NULL) { printf("B+Tree at block %" B_PRIdOFF ":\n-----------------------------" "------------\n", disk.ToBlock(run)); if (inode->IsDirectory() || inode->IsAttributeDirectory()) { dump_bplustree(disk, (Directory *)inode, inode->Size(), dumpHex); putchar('\n'); } else fprintf(stderr, "Inode is not a directory!\n"); } if (validateBTree && inode != NULL) { printf("Validating B+Tree at block %" B_PRIdOFF ":\n------------------" "-----------------------\n", disk.ToBlock(run)); if (inode->IsDirectory() || inode->IsAttributeDirectory()) { BPlusTree *tree; if (((Directory *)inode)->GetTree(&tree) == B_OK) { if (tree->Validate(true) < B_OK) puts("B+Tree is corrupt!"); else puts("B+Tree seems to be okay."); } } else fprintf(stderr, "Inode is not a directory!\n"); } if (dumpHex) { printf("Hexdump from inode at block %" B_PRIdOFF ":\n-----------------" "------------------------\n", disk.ToBlock(run)); dump_block(buffer, disk.BlockSize()); putchar('\n'); } delete inode; return 0; }
// recover Datafile int recover_file( char* des_dir,char* pathname, char* filename, struct ext2_inode *inode, ext2_ino_t inode_nr, int flag){ int rec_error = 255; char err_string[9]; int retval =-1; int hardlink = 0; char i = 0; char *buf=NULL; struct privat priv; struct stat filestat; char *helpname = NULL; char *recovername = NULL; char *linkname = NULL; char *p1; unsigned long long i_size; struct utimbuf touchtime; mode_t i_mode; int major, minor, type; #ifdef DEBUG printf("RECOVER : INODE=%ld FILENAME=%s/%s\n",inode_nr, pathname,filename); dump_inode(stdout, "",inode_nr, (struct ext2_inode *)inode, 0); #endif if (!(inode->i_mode & LINUX_S_IFMT)) //no type flag - no recover return 1; p1 = pathname; while (*p1 == '/') p1++; helpname = malloc(strlen(des_dir) + 15); recovername = malloc(strlen(des_dir) + strlen(pathname) + strlen(filename) +10); if (helpname && recovername){ strcpy(helpname,des_dir); strcat(helpname,"/"); strcpy(recovername,helpname); strcat(recovername,p1); if (strlen(p1)) strcat(recovername,"/"); strcat(recovername,filename); while (!(stat(recovername, &filestat)) && (i<5)){ strcat(recovername,"#"); i++; } p1 = strchr(helpname,0); sprintf(p1,"#%u#",inode_nr); unlink (helpname); priv.flag = flag; //FIXME: hardlink if (inode->i_links_count > 1){ p1 = check_link_stack(inode_nr, inode->i_generation); if (p1) { //hardlink found if (! stat(p1, &filestat)){ retval = check_dir(recovername); if (retval) fprintf(stderr,"Unknown error at target directory by file: %s\ntrying to continue normal\n", recovername); else { if (! link(p1,recovername)){ if (match_link_stack(inode_nr, inode->i_generation)) rec_error -= CREATE_ERROR ; goto out; } else{ rec_error -= CREATE_ERROR ; } } } } else{ //flag as hardlink hardlink = 1; } } switch (inode->i_mode & LINUX_S_IFMT){ //regular File; case LINUX_S_IFREG : priv.fd = open(helpname, O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, S_IRWXU); if (! priv.fd ){ fprintf(stderr,"Error: open File %s for writing\n",helpname); retval = errno; goto errout; } buf=malloc(current_fs->blocksize); if (buf) { priv.buf = buf; priv.error = 0; // iterate Data Blocks and if not allocated, write to file retval = local_block_iterate3 ( current_fs, *inode, BLOCK_FLAG_DATA_ONLY, NULL, write_block, &priv ); #ifdef DEBUG printf("\n"); #endif if (retval || priv.error){ // error or blocks allocated , we delete the tempfile and goto out close(priv.fd); unlink(helpname); retval = -1; goto errout; } else{ i_size = (unsigned long long)(inode->i_size | ((unsigned long long)inode->i_size_high << 32)); retval = ftruncate(priv.fd,i_size); if (retval){ rec_error -= SEEK_ERROR ; } } } else { fprintf(stderr,"ERROR: can no allocate memory\n"); retval = -1; close(priv.fd); goto errout; } close(priv.fd); break; //symbolic link case LINUX_S_IFLNK : if (ext2fs_inode_data_blocks(current_fs,inode)){ buf = malloc(current_fs->blocksize + 1); if (buf) { memset(buf,0,current_fs->blocksize + 1); priv.buf = buf; priv.error = 0; retval = local_block_iterate3 ( current_fs, *inode, BLOCK_FLAG_DATA_ONLY, NULL, read_syslink_block, &priv ); if (retval || priv.error) goto errout; } else { fprintf(stderr,"ERROR: can no allocate memory\n"); retval = -1; goto errout; } } else { int i; if((! inode->i_size) || (inode->i_size >= 60)) goto errout; buf = malloc(inode->i_size + 1); linkname = (char*) &(inode->i_block[0]); for (i = 0; i < inode->i_size ; i++){ *(buf+i) = (char) *linkname; linkname++; } *(buf+i) = 0; } linkname = buf; retval = symlink(linkname, helpname); if (retval){ rec_error -= (CREATE_ERROR + SEEK_ERROR); } break; //block or char device case LINUX_S_IFBLK : case LINUX_S_IFCHR : type = (LINUX_S_ISBLK(inode->i_mode)) ? S_IFBLK : S_IFCHR ; if (inode->i_block[0]) { major = (inode->i_block[0] >> 8) & 255; minor = inode->i_block[0] & 255; } else {
/* * dump_jbd_metadata() * */ void dump_jbd_metadata(FILE *out, enum ocfs2_block_type type, char *buf, uint64_t blknum) { struct ocfs2_dir_block_trailer *trailer; struct ocfs2_xattr_block *xb; struct ocfs2_xattr_header *xh; struct ocfs2_refcount_block *rb; struct ocfs2_dx_root_block *dx_root; struct ocfs2_dx_leaf *dx_leaf; struct ocfs2_dinode *di; struct ocfs2_extent_block *eb; fprintf(out, "\tBlock %"PRIu64": ", blknum); switch (type) { case OCFS2_BLOCK_INODE: case OCFS2_BLOCK_SUPERBLOCK: fprintf(out, "Inode\n"); di = (struct ocfs2_dinode *)buf; ocfs2_swap_inode_to_cpu(gbls.fs, di); dump_inode(out, di); if (di->i_flags & OCFS2_LOCAL_ALLOC_FL) dump_local_alloc(out, &(di->id2.i_lab)); else if (di->i_flags & OCFS2_CHAIN_FL) dump_chain_list(out, &(di->id2.i_chain)); else if (S_ISLNK(di->i_mode) && !di->i_clusters) dump_fast_symlink(out, (char *)di->id2.i_symlink); else if (di->i_flags & OCFS2_DEALLOC_FL) dump_truncate_log(out, &(di->id2.i_dealloc)); else if (!(di->i_dyn_features & OCFS2_INLINE_DATA_FL)) dump_extent_list(out, &(di->id2.i_list)); fprintf(out, "\n"); break; case OCFS2_BLOCK_EXTENT_BLOCK: fprintf(out, "Extent\n"); eb = (struct ocfs2_extent_block *)buf; ocfs2_swap_extent_block_to_cpu(gbls.fs, eb); dump_extent_block(out, eb); dump_extent_list(out, &(eb->h_list)); fprintf(out, "\n"); break; case OCFS2_BLOCK_GROUP_DESCRIPTOR: fprintf(out, "Group\n"); ocfs2_swap_group_desc_to_cpu(gbls.fs, (struct ocfs2_group_desc *)buf); dump_group_descriptor(out, (struct ocfs2_group_desc *)buf, 0); fprintf(out, "\n"); break; case OCFS2_BLOCK_DIR_BLOCK: fprintf(out, "Dirblock\n"); /* * We know there's a trailer, because that's how it * was detected */ ocfs2_swap_dir_entries_to_cpu(buf, ocfs2_dir_trailer_blk_off(gbls.fs)); trailer = ocfs2_dir_trailer_from_block(gbls.fs, buf); ocfs2_swap_dir_trailer(trailer); dump_dir_block(out, buf); fprintf(out, "\n"); break; case OCFS2_BLOCK_XATTR: fprintf(out, "Xattr\n"); xb = (struct ocfs2_xattr_block *)buf; ocfs2_swap_xattr_block_to_cpu(gbls.fs, xb); if (!(xb->xb_flags & OCFS2_XATTR_INDEXED)) { xh = &xb->xb_attrs.xb_header; dump_xattr(out, xh); } fprintf(out, "\n"); break; case OCFS2_BLOCK_REFCOUNT: fprintf(out, "Refcount\n"); rb = (struct ocfs2_refcount_block *)buf; ocfs2_swap_refcount_block_to_cpu(gbls.fs, rb); dump_refcount_block(out, rb); fprintf(out, "\n"); break; case OCFS2_BLOCK_DXROOT: fprintf(out, "DxRoot\n"); dx_root = (struct ocfs2_dx_root_block *)buf; ocfs2_swap_dx_root_to_cpu(gbls.fs, dx_root); dump_dx_root(out, dx_root); fprintf(out, "\n"); break; case OCFS2_BLOCK_DXLEAF: fprintf(out, "DxLeaf\n"); dx_leaf = (struct ocfs2_dx_leaf *)buf; ocfs2_swap_dx_leaf_to_cpu(dx_leaf); dump_dx_leaf(out, dx_leaf); fprintf(out, "\n"); break; default: fprintf(out, "TODO\n\n"); break; } return ; }