static status_t ext2_get_vnode(fs_volume* _volume, ino_t id, fs_vnode* _node, int* _type, uint32* _flags, bool reenter) { Volume* volume = (Volume*)_volume->private_volume; if (id < 2 || id > volume->NumInodes()) { ERROR("invalid inode id %" B_PRIdINO " requested!\n", id); return B_BAD_VALUE; } Inode* inode = new(std::nothrow) Inode(volume, id); if (inode == NULL) return B_NO_MEMORY; status_t status = inode->InitCheck(); if (status != B_OK) delete inode; if (status == B_OK) { _node->private_node = inode; _node->ops = &gExt2VnodeOps; *_type = inode->Mode(); *_flags = 0; } else ERROR("get_vnode: InitCheck() failed. Error: %s\n", strerror(status)); return status; }
static status_t btrfs_get_vnode(fs_volume* _volume, ino_t id, fs_vnode* _node, int* _type, uint32* _flags, bool reenter) { Volume* volume = (Volume*)_volume->private_volume; Inode* inode = new(std::nothrow) Inode(volume, id); if (inode == NULL) return B_NO_MEMORY; status_t status = inode->InitCheck(); if (status != B_OK) delete inode; if (status == B_OK) { _node->private_node = inode; _node->ops = &gBtrfsVnodeOps; *_type = inode->Mode(); *_flags = 0; } else ERROR("get_vnode: InitCheck() failed. Error: %s\n", strerror(status)); return status; }
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; }
void checkFiles(Disk &disk,BPlusTree &tree,char *attribute) { block_run *runs = (block_run *)malloc(gCount * sizeof(block_run)); if (runs == NULL) { fprintf(stderr," Not enough memory!\n"); return; } // copy hashtable to array block_run *run = NULL; int32 index = 0; gHashtable.Rewind(); while (gHashtable.GetNextEntry((void **)&run) == B_OK) { runs[index++] = *run; } // sort array to speed up disk access qsort(runs,index,sizeof(block_run),(int (*)(const void *,const void *))compareBlockRuns); bool sizeIndex = !strcmp(attribute,"size"); bool nameIndex = !strcmp(attribute,"name"); bool modifiedIndex = !strcmp(attribute,"last_modified"); char key[B_FILE_NAME_LENGTH]; uint16 keyLength = 0; Inode *inode = NULL; for (int32 i = 0;i < index;i++) { if (i % 50 == 0) printf(" %7ld%s1A\n",i,gEscape); delete inode; inode = Inode::Factory(&disk,runs[i]); if (inode == NULL || inode->InitCheck() < B_OK) { fprintf(stderr," inode at (%ld, %d) is corrupt!\n",runs[i].allocation_group,runs[i].start); delete inode; continue; } // check indices not based on standard attributes if (sizeIndex) { if (inode->IsDirectory()) continue; memcpy(key,&inode->InodeBuffer()->data.size,sizeof(off_t)); keyLength = sizeof(off_t); } else if (nameIndex) { strcpy(key,inode->Name()); keyLength = strlen(key); } else if (modifiedIndex) { if (inode->IsDirectory()) continue; memcpy(key,&inode->InodeBuffer()->last_modified_time,sizeof(off_t)); keyLength = sizeof(off_t); } else // iterate through all attributes to find the right one (damn slow, sorry...) { inode->RewindAttributes(); char name[B_FILE_NAME_LENGTH]; uint32 type; void *data; size_t length; bool found = false; while (inode->GetNextAttribute(name,&type,&data,&length) == B_OK) { if (!strcmp(name,attribute)) { strncpy(key,(char *)data,B_FILE_NAME_LENGTH - 1); key[B_FILE_NAME_LENGTH - 1] = '\0'; keyLength = length > B_FILE_NAME_LENGTH ? B_FILE_NAME_LENGTH : length; found = true; break; } } if (!found) continue; } off_t value; if (tree.Find((uint8 *)key,keyLength,&value) < B_OK) { if (*inode->Name()) fprintf(stderr," inode at (%ld, %d) name \"%s\" is not in index!\n",runs[i].allocation_group,runs[i].start,inode->Name()); else { // inode is obviously deleted! block_run parent = inode->Parent(); Directory *directory = (Directory *)Inode::Factory(&disk,parent); if (directory != NULL && directory->InitCheck() == B_OK) { BPlusTree *parentTree; if (directory->GetTree(&parentTree) == B_OK) { char name[B_FILE_NAME_LENGTH]; uint16 length; off_t offset,searchOffset = disk.ToBlock(runs[i]); bool found = false; while (parentTree->GetNextEntry(name,&length,B_FILE_NAME_LENGTH,&offset) == B_OK) { if (offset == searchOffset) { fprintf(stderr," inode at (%ld, %d) name \"%s\" was obviously deleted, but the parent \"%s\" still contains it!\n",runs[i].allocation_group,runs[i].start,name,directory->Name()); found = true; break; } } if (!found) fprintf(stderr," inode at (%ld, %d) was obviously deleted, and the parent \"%s\" obviously doesn't contain it anymore!\n",runs[i].allocation_group,runs[i].start,directory->Name()); } else fprintf(stderr," inode at (%ld, %d) was obviously deleted, but the parent \"%s\" is invalid and still contains it!\n",runs[i].allocation_group,runs[i].start,directory->Name()); } else { // not that this would be really possible... - but who knows fprintf(stderr," inode at (%ld, %d) is not in index and has invalid parent!\n",runs[i].allocation_group,runs[i].start); } delete directory; } } else { if (bplustree_node::LinkType(value) == BPLUSTREE_NODE) { if (disk.ToBlockRun(value) != runs[i]) fprintf(stderr," offset in index and inode offset doesn't match for inode \"%s\" at (%ld, %d)\n",inode->Name(),runs[i].allocation_group,runs[i].start); } else { // search duplicates char name[B_FILE_NAME_LENGTH]; uint16 length; off_t offset; bool found = false,duplicates = false; //puts("++"); tree.Rewind(); while (tree.GetNextEntry(name,&length,B_FILE_NAME_LENGTH,&offset) == B_OK) { //printf("search for = %ld, key = %ld -> value = %Ld (%ld, %d)\n",*(int32 *)&key,*(int32 *)&name,offset,disk.ToBlockRun(offset).allocation_group,disk.ToBlockRun(offset).start); if (keyLength == length && !memcmp(key,name,keyLength)) { duplicates = true; if (disk.ToBlockRun(offset) == runs[i]) { found = true; break; } } //else if (duplicates) // break; } if (!found) { printf(" inode \"%s\" at (%ld, %d) not found in duplicates!\n",inode->Name(),runs[i].allocation_group,runs[i].start); // return; } } } } delete inode; printf(" %7Ld files processed.\n",gCount); }