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

#include <sys/stat.h>
#include <unistd.h>
#include "crash.h"

PRIVATE addr_t dentry();
const commandtable_t command_dentry =
	{"dentry", dentry, "[-s] [-p] [-u] [address]", "dump dentry table"};

extern addr_t print_dentry();
addr_t dentry_unused_addr;
addr_t dentry_hashtable_addr;
addr_t d_hash_mask_addr;

PRIVATE addr_t
dentry()
{
	int i, c;
	int subdir = 0, parent = 0, uflag = 0;
	addr_t addr = 0;
	static unsigned int d_hash_mask;
	addr_t dh_array;
	extern void prhead_dentry();

	while ((c = getopt(argcnt, args, "spu")) != EOF) {
		switch (c) {
		case 's':
			subdir = 1;
			break;
		case 'p':
			parent = 1;
			break;
		case 'u':
			uflag = 1;
			break;
		default:
			THROW(usage);
		}
	}
	if (subdir + parent > 1) {
		THROW(usage);
	}

	if (argcnt > optind) {
		prhead_dentry();
		for (i = optind; i < argcnt; i++) {
			addr = getaddr(args[i]);
			addr = print_dentry(addr, 0, subdir, parent);
		}
		return addr;
	}

	GETADDR(dentry_hashtable);
	GETADDR(dentry_unused);
	GETADDR(d_hash_mask);

	if (uflag) {
		memread(dentry_unused_addr, sizeof(addr), &addr, "dentry_unused");
		prhead_dentry();
		while (addr && addr != dentry_unused_addr) {
			addr = print_dentry(addr, 2, subdir, parent);
		}
		return addr;
	}

	if (d_hash_mask == 0) {
		memread(d_hash_mask_addr, sizeof(d_hash_mask), &d_hash_mask, "d_hash_mask");
		if (d_hash_mask == 0) {
			THROW("invalid valud: d_hash_mask");
		}
	}

	mprintf("HASH MASK %d\n", d_hash_mask);
	prhead_dentry();
	memread(dentry_hashtable_addr, sizeof(dh_array), &dh_array, "dentry_hashtable");
	for (i = 0; i <= d_hash_mask; i++) {
		memread(dh_array + sizeof(addr) * i, sizeof(addr), &addr, "dentry_hashtable");
		while (addr) {
			addr = print_dentry(addr, 1, subdir, parent);
		}
	}
	return addr;
}
