/*
 * Copyright 2008-2017, Axel Dörfler, axeld@pinc-software.de.
 * Distributed under the terms of the MIT License.
 */
 
 
#include "fssh_stdio.h"
#include "syscalls.h"
 
#include "bfs.h"
#include "bfs_control.h"
 
 
namespace FSShell {
 
 
fssh_status_t
command_checkfs(int argc, const char* const* argv)
{
	if (argc == 2 && !strcmp(argv[1], "--help")) {
		fssh_dprintf("Usage: %s [-c]\n"
			"  -c  Check only; don't perform any changes\n", argv[0]);
		return B_OK;
	}
 
	bool checkOnly = false;
	if (argc == 2 && !strcmp(argv[1], "-c"))
		checkOnly = true;
 
	int rootDir = _kern_open_dir(-1, "/myfs");
	if (rootDir < 0)
		return rootDir;
 
	struct check_control result;
	memset(&result, 0, sizeof(result));
	result.magic = BFS_IOCTL_CHECK_MAGIC;
	result.flags = 0;
	if (!checkOnly) {
		result.flags |= BFS_FIX_BITMAP_ERRORS | BFS_REMOVE_WRONG_TYPES
			| BFS_REMOVE_INVALID | BFS_FIX_NAME_MISMATCHES | BFS_FIX_BPLUSTREES;
	}
 
	// start checking
	fssh_status_t status = _kern_ioctl(rootDir, BFS_IOCTL_START_CHECKING,
		&result, sizeof(result));
	if (status != B_OK)
	    return status;
 
	uint64 attributeDirectories = 0, attributes = 0;
	uint64 files = 0, directories = 0, indices = 0;
	uint64 counter = 0;
	uint32 previousPass = result.pass;
 
	// check all files and report errors
	while (_kern_ioctl(rootDir, BFS_IOCTL_CHECK_NEXT_NODE, &result,
			sizeof(result)) == B_OK) {
		if (++counter % 50 == 0) {
			fssh_dprintf("%9" FSSH_B_PRIu64 " nodes processed\x1b[1A\n",
				counter);
		}
 
		if (result.pass == BFS_CHECK_PASS_BITMAP) {
			if (result.errors) {
				fssh_dprintf("%s (inode = %" FSSH_B_PRIdINO ")", result.name,
					result.inode);
				if ((result.errors & BFS_MISSING_BLOCKS) != 0)
					fssh_dprintf(", some blocks weren't allocated");
				if ((result.errors & BFS_BLOCKS_ALREADY_SET) != 0)
					fssh_dprintf(", has blocks already set");
				if ((result.errors & BFS_INVALID_BLOCK_RUN) != 0)
					fssh_dprintf(", has invalid block run(s)");
				if ((result.errors & BFS_COULD_NOT_OPEN) != 0)
					fssh_dprintf(", could not be opened");
				if ((result.errors & BFS_WRONG_TYPE) != 0)
					fssh_dprintf(", has wrong type");
				if ((result.errors & BFS_NAMES_DONT_MATCH) != 0)
					fssh_dprintf(", names don't match");
				if ((result.errors & BFS_INVALID_BPLUSTREE) != 0)
					fssh_dprintf(", invalid b+tree");
				fssh_dprintf("\n");
			}
 
			if ((result.mode & (S_INDEX_DIR | 0777)) == S_INDEX_DIR)
				indices++;
			else if (result.mode & S_ATTR_DIR)
				attributeDirectories++;
			else if (result.mode & S_ATTR)
				attributes++;
			else if (S_ISDIR(result.mode))
				directories++;
			else
				files++;
		} else if (result.pass == BFS_CHECK_PASS_INDEX) {
			if (previousPass != result.pass) {
				fssh_dprintf("Recreating broken index b+trees...\n");
				previousPass = result.pass;
				counter = 0;
			}
		}
	}
 
	// stop checking
	if (_kern_ioctl(rootDir, BFS_IOCTL_STOP_CHECKING, &result, sizeof(result))
			!= B_OK) {
		_kern_close(rootDir);
		return errno;
	}
 
	_kern_close(rootDir);
 
	fssh_dprintf("        %" FSSH_B_PRIu64 " nodes checked,\n\t%" FSSH_B_PRIu64
		" blocks not allocated,\n\t%" FSSH_B_PRIu64 " blocks already set,\n\t%"
		B_PRIu64 " blocks could be freed\n\n", counter, result.stats.missing,
		result.stats.already_set, result.stats.freed);
	fssh_dprintf("\tfiles\t\t%" FSSH_B_PRIu64 "\n\tdirectories\t%"
		FSSH_B_PRIu64 "\n"
		"\tattributes\t%" FSSH_B_PRIu64 "\n\tattr. dirs\t%" FSSH_B_PRIu64 "\n"
		"\tindices\t\t%" FSSH_B_PRIu64 "\n", files, directories, attributes,
		attributeDirectories, indices);
 
	fssh_dprintf("\n\tdirect block runs\t\t%" FSSH_B_PRIu64 " (%" FSSH_B_PRIu64
		")\n", result.stats.direct_block_runs,
		result.stats.blocks_in_direct * result.stats.block_size);
	fssh_dprintf("\tindirect block runs\t\t%" FSSH_B_PRIu64 " (in %"
		FSSH_B_PRIu64 " array blocks, %" FSSH_B_PRIu64 ")\n",
		result.stats.indirect_block_runs, result.stats.indirect_array_blocks,
		result.stats.blocks_in_indirect * result.stats.block_size);
	fssh_dprintf("\tdouble indirect block runs\t%" FSSH_B_PRIu64 " (in %"
		FSSH_B_PRIu64 " array blocks, %" FSSH_B_PRIu64 ")\n",
		result.stats.double_indirect_block_runs,
		result.stats.double_indirect_array_blocks,
		result.stats.blocks_in_double_indirect * result.stats.block_size);
 
	if (result.status == B_ENTRY_NOT_FOUND)
		result.status = B_OK;
 
	return result.status;
}
 
 
}	// namespace FSShell

V576 Incorrect format. Consider checking the third actual argument of the 'fssh_dprintf' function. The memsize type argument is expected.