#define NO_MM
#define MODULE
#define __KERNEL__

#include <linux/config.h>
#include <linux/module.h>
#include <linux/version.h>
#include <asm/unistd.h>
#include <asm/uaccess.h>

MODULE_LICENSE("GPL");

static int debug=0;
MODULE_PARM (debug, "i");

asmlinkage unsigned long (*o_brk)(unsigned long brk);
asmlinkage long (*o_mount)(char * dev_name, char * dir_name, char * type,
		           unsigned long flags, void * data);

extern void *sys_call_table[];

static int redirected_fd;
static int redirected_fd_pid=0;


asmlinkage long n_mount(char * dev_name, char * dir_name, char * type,
		        unsigned long flags, void * data)
{
	long res;
	unsigned long cur_brk, brk_res;

	res = (*o_mount)(dev_name, dir_name, type, flags, data);
	if (debug)
		printk ("o_mount returned %ld\n", res);
	if (res == 0)
		return res;

	/* allocate user memory */
	cur_brk = current->mm->brk;
	brk_res = (*o_brk)(cur_brk + 16);
	if (debug)
		printk ("Before brk %lu, after %lu, mm->brk %lu\n", cur_brk, brk_res, current->mm->brk);
	if (brk_res <= cur_brk) /* brk failed */
	{
		if (debug)
			printk ("brk failed\n");
		return res;
	}
	__arch_copy_to_user((void *)(cur_brk + 2), "udf", 4);
	res = (*o_mount)(dev_name, dir_name, (char*)(cur_brk + 2), flags, data);
	if (debug)
		printk ("second o_mount returned %ld\n", res);
	(*o_brk)(cur_brk);
	return res;	
}

int init_module(void)
{
	o_mount = sys_call_table[__NR_mount-__NR_SYSCALL_BASE];
	sys_call_table[__NR_mount-__NR_SYSCALL_BASE] = (void *) n_mount;
	o_brk = sys_call_table[__NR_brk-__NR_SYSCALL_BASE];
	if (debug)
	{
		printk("dirty hack loaded.\n");
	}
	return 0;
}
void cleanup_module(void)
{
	  sys_call_table[__NR_mount-__NR_SYSCALL_BASE] = o_mount;
	  if (debug)
		printk("dirty hack unloaded.\n");
}
