Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
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);
}