/*
 * Copyright (C) 2003 ASANO Masahiro
 */

#include <unistd.h>
#include "crash.h"

PRIVATE addr_t nfs_page();
const commandtable_t command_nfs_page =
	{"nfs_page", nfs_page, "address", "print nfs_page table"};
extern void prhead_nfs_page();
extern addr_t print_nfs_page();

PRIVATE addr_t nfs_inode();
const commandtable_t command_nfs_inode =
	{"nfs_inode", nfs_inode, "[-f] {address | -i inode-address}", "print nfs_inode table"};
extern void prhead_nfs_inode();
extern addr_t print_nfs_inode();

PRIVATE addr_t nfs_server();
const commandtable_t command_nfs_server =
	{"nfs_server", nfs_server, "[-f] [address]", "print nfs_server table"};
extern void prhead_nfs_server();
extern addr_t print_nfs_server();
extern addr_t print_superblock_union();

extern addr_t super_blocks_addr;
addr_t nfs_fs_type_addr;

PRIVATE addr_t
nfs_page()
{
	int c;
	int full = 0;

	while ((c = getopt(argcnt, args, "f")) != EOF) {
		switch (c) {
		case 'f':
			full = 1;
			break;
		default:
			THROW(usage);
		}
	}

	if (argcnt == optind) {
		THROW(usage);
	}

	prhead_nfs_page();
	while (args[optind]) {
		print_nfs_page(getvalue(args[optind]), full);
		optind++;
	}
	return 0;
}

PRIVATE addr_t
nfs_inode()
{
	int c;
	int full = 0;
	int iflag = 0;

	while ((c = getopt(argcnt, args, "fi")) != EOF) {
		switch (c) {
		case 'f':
			full = 1;
			break;
		case 'i':
			iflag = 1;
			break;
		default:
			THROW(usage);
		}
	}

	if (argcnt == optind) {
		THROW(usage);
	}

	prhead_nfs_inode();
	while (args[optind]) {
		print_nfs_inode(getvalue(args[optind]), full, iflag);
		optind++;
	}
	return 0;
}

PRIVATE addr_t
nfs_server()
{
	int c;
	int full = 0;

	while ((c = getopt(argcnt, args, "f")) != EOF) {
		switch (c) {
		case 'f':
			full = 1;
			break;
		default:
			THROW(usage);
		}
	}

	if (argcnt == optind) {
		addr_t addr;
		struct list_head super_blocks;

		GETADDR(super_blocks);
		memread(super_blocks_addr, sizeof(super_blocks), &super_blocks,
			"super_blocks");
		GETADDR(nfs_fs_type);

		prhead_nfs_server();
		for (addr = (addr_t)super_blocks.next; addr && addr != super_blocks_addr;) {
			addr = print_superblock_union(addr, nfs_fs_type_addr, print_nfs_server, full);
		}

	} else {
		if (!full) prhead_nfs_server();
		while (args[optind]) {
			if (full) prhead_nfs_server();
			print_nfs_server(0, getvalue(args[optind]), full);
			optind++;
		}
	}

	return 0;
}
