/*
 *  linux/fs/msdos/file.c
 *
 *  Written 1992,1993 by Werner Almesberger
 *
 *  MS-DOS regular file handling primitives
 */

#include <asm/segment.h>
#include <asm/system.h>

#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/msdos_fs.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/stat.h>

#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#define MAX(a,b) (((a) > (b)) ? (a) : (b))

static int msdos_file_read(struct inode *inode,struct file *filp,char *buf,
    int count);
static int msdos_file_write(struct inode *inode,struct file *filp,char *buf,
    int count);


static struct file_operations msdos_file_operations = {
	NULL,			/* lseek - default */
	msdos_file_read,	/* read */
	msdos_file_write,	/* write */
	NULL,			/* readdir - bad */
	NULL,			/* select - default */
	NULL,			/* ioctl - default */
	NULL,			/* mmap */
	NULL,			/* no special open is needed */
	NULL,			/* release */
	file_fsync		/* fsync */
};

struct inode_operations msdos_file_inode_operations = {
	&msdos_file_operations,	/* default file operations */
	NULL,			/* create */
	NULL,			/* lookup */
	NULL,			/* link */
	NULL,			/* unlink */
	NULL,			/* symlink */
	NULL,			/* mkdir */
	NULL,			/* rmdir */
	NULL,			/* mknod */
	NULL,			/* rename */
	NULL,			/* readlink */
	NULL,			/* follow_link */
	msdos_bmap,		/* bmap */
	msdos_truncate,		/* truncate */
	NULL			/* permission */
};

/* No bmap for MS-DOS FS' that don't align data at kByte boundaries. */

struct inode_operations msdos_file_inode_operations_no_bmap = {
	&msdos_file_operations,	/* default file operations */
	NULL,			/* create */
	NULL,			/* lookup */
	NULL,			/* link */
	NULL,			/* unlink */
	NULL,			/* symlink */
	NULL,			/* mkdir */
	NULL,			/* rmdir */
	NULL,			/* mknod */
	NULL,			/* rename */
	NULL,			/* readlink */
	NULL,			/* follow_link */
	NULL,			/* bmap */
	msdos_truncate,		/* truncate */
	NULL			/* permission */
};


static int msdos_file_read(struct inode *inode,struct file *filp,char *buf,
    int count)
{
	char *start;
	int left,offset,size,sector,cnt;
	char ch;
	struct buffer_head *bh;
	void *data;

/* printk("msdos_file_read\n"); */
	if (!inode) {
		printk("msdos_file_read: inode = NULL\n");
		return -EINVAL;
	}
	if (!S_ISREG(inode->i_mode)) {
		printk("msdos_file_read: mode = %07o\n",inode->i_mode);
		return -EINVAL;
	}
	if (filp->f_pos >= inode->i_size || count <= 0) return 0;
	start = buf;
	while ((left = MIN(inode->i_size-filp->f_pos,count-(buf-start))) > 0){
		if (!(sector = msdos_smap(inode,filp->f_pos >> SECTOR_BITS)))
			break;
		offset = filp->f_pos & (SECTOR_SIZE-1);
		if (!(bh = msdos_sread(inode->i_dev,sector,&data))) break;
		filp->f_pos += (size = MIN(SECTOR_SIZE-offset,left));
		if (MSDOS_I(inode)->i_binary) {
			memcpy_tofs(buf,data+offset,size);
			buf += size;
		}
		else for (cnt = size; cnt; cnt--) {
				if ((ch = *((char *) data+offset++)) == '\r')
					size--;
				else {
					if (ch != 26) put_fs_byte(ch,buf++);
					else {
						filp->f_pos = inode->i_size;
						brelse(bh);
						return buf-start;
					}
				}
			}
		brelse(bh);
	}
	if (start == buf) return -EIO;
	return buf-start;
}


static int msdos_file_write(struct inode *inode,struct file *filp,char *buf,
    int count)
{
	int sector,offset,size,left,written;
	int error,carry;
	char *start,*to,ch;
	struct buffer_head *bh;
	void *data;

	if (!inode) {
		printk("msdos_file_write: inode = NULL\n");
		return -EINVAL;
	}
	if (!S_ISREG(inode->i_mode)) {
		printk("msdos_file_write: mode = %07o\n",inode->i_mode);
		return -EINVAL;
	}
/*
 * ok, append may not work when many processes are writing at the same time
 * but so what. That way leads to madness anyway.
 */
	if (filp->f_flags & O_APPEND) filp->f_pos = inode->i_size;
	if (count <= 0) return 0;
	error = carry = 0;
	for (start = buf; count || carry; count -= size) {
		while (!(sector = msdos_smap(inode,filp->f_pos >> SECTOR_BITS)))
			if ((error = msdos_add_cluster(inode)) < 0) break;
		if (error) {
			msdos_truncate(inode);
			break;
		}
		offset = filp->f_pos & (SECTOR_SIZE-1);
		size = MIN(SECTOR_SIZE-offset,MAX(carry,count));
		if (!(bh = msdos_sread(inode->i_dev,sector,&data))) {
			error = -EIO;
			break;
		}
		if (MSDOS_I(inode)->i_binary) {
			memcpy_fromfs(data+(filp->f_pos & (SECTOR_SIZE-1)),
			    buf,written = size);
			buf += size;
		}
		else {
			written = left = SECTOR_SIZE-offset;
			to = (char *) data+(filp->f_pos & (SECTOR_SIZE-1));
			if (carry) {
				*to++ = '\n';
				left--;
				carry = 0;
			}
			for (size = 0; size < count && left; size++) {
				if ((ch = get_fs_byte(buf++)) == '\n') {
					*to++ = '\r';
					left--;
				}
				if (!left) carry = 1;
				else {
					*to++ = ch;
					left--;
				}
			}
			written -= left;
		}
		filp->f_pos += written;
		if (filp->f_pos > inode->i_size) {
			inode->i_size = filp->f_pos;
			inode->i_dirt = 1;
		}
		bh->b_dirt = 1;
		brelse(bh);
	}
	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
	MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
	inode->i_dirt = 1;
	return start == buf ? error : buf-start;
}


void msdos_truncate(struct inode *inode)
{
	int cluster;

	cluster = SECTOR_SIZE*MSDOS_SB(inode->i_sb)->cluster_size;
	(void) fat_free(inode,(inode->i_size+(cluster-1))/cluster);
	MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
	inode->i_dirt = 1;
}
