#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/module.h>

#include "ftpfs.h"
#include "ftpfs_proc.h"


static int
ftp_readlink(struct dentry *dentry, char *buffer, int bufflen){
	struct inode *inode = dentry->d_inode;
	struct super_block *sb = inode->i_sb;
	struct ftp_sb_info *info = sb->u.generic_sbp;
	
	char buf[FTP_MAXPATHLEN];
	struct ftp_directory *dir;
	struct ftp_dirlist_node *file;
	char *real_name;
	int res;
	
	ftp_get_name(dentry->d_parent, buf);

	ftp_lock(info);
	res = ftp_cache_get(info, buf, &dir);
	ftp_unlock(info);
	if(res < 0){
		VERBOSE(" ftp_cache_get failed!\n");
		return res;
	}

	for(file = dir->head; file != NULL; file = file->next)
		if(strcmp(file->entry.name, dentry->d_name.name) == 0)
			break;
	if(!file){
		VERBOSE(" file not found in cache!!?!\n");
		return -1;
	}

	real_name = file->entry.name + strlen(file->entry.name) + 4;

	return vfs_readlink(dentry, buffer, bufflen, real_name);
}

static int
ftp_follow_link(struct dentry *dentry, struct nameidata *nd){
	struct inode *inode = dentry->d_inode;
	struct super_block *sb = inode->i_sb;
	struct ftp_sb_info *info = sb->u.generic_sbp;
	
	char buf[FTP_MAXPATHLEN];
	struct ftp_directory *dir;
	struct ftp_dirlist_node *file;
	char *real_name;
	int res;
	
	ftp_get_name(dentry->d_parent, buf);
	DEBUG(" %s\n", buf);

	ftp_lock(info);
	res = ftp_cache_get(info, buf, &dir);
	ftp_unlock(info);
	
	if(res < 0){
		VERBOSE(" ftp_cache_get failed!\n");
		return res;
	}

	for(file = dir->head; file != NULL; file = file->next)
		if(strcmp(file->entry.name, dentry->d_name.name) == 0)
			break;
	if(!file){
		VERBOSE(" file not found in cache!!?!\n");
		return -1;
	}

	real_name = file->entry.name + strlen(file->entry.name) + 4;

	return  vfs_follow_link(nd, real_name);
}

struct inode_operations ftp_symlink_inode_operations = {
	readlink:	ftp_readlink,
	follow_link:	ftp_follow_link,
};

