/*
|
/*
|
* file.c
|
* file.c
|
*
|
*
|
* Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
|
* Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
|
*
|
*
|
*/
|
*/
|
|
|
#include <asm/segment.h>
|
#include <asm/segment.h>
|
#include <asm/system.h>
|
#include <asm/system.h>
|
|
|
#include <linux/sched.h>
|
#include <linux/sched.h>
|
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
#include <linux/errno.h>
|
#include <linux/errno.h>
|
#include <linux/fcntl.h>
|
#include <linux/fcntl.h>
|
#include <linux/stat.h>
|
#include <linux/stat.h>
|
#include <linux/mm.h>
|
#include <linux/mm.h>
|
#include <linux/smb_fs.h>
|
#include <linux/smb_fs.h>
|
#include <linux/malloc.h>
|
#include <linux/malloc.h>
|
|
|
static inline int
|
static inline int
|
min(int a, int b)
|
min(int a, int b)
|
{
|
{
|
return a < b ? a : b;
|
return a < b ? a : b;
|
}
|
}
|
|
|
static int
|
static int
|
smb_fsync(struct inode *inode, struct file *file)
|
smb_fsync(struct inode *inode, struct file *file)
|
{
|
{
|
return 0;
|
return 0;
|
}
|
}
|
|
|
int
|
int
|
smb_make_open(struct inode *i, int right)
|
smb_make_open(struct inode *i, int right)
|
{
|
{
|
struct smb_dirent *dirent;
|
struct smb_dirent *dirent;
|
|
|
if (i == NULL)
|
if (i == NULL)
|
{
|
{
|
printk("smb_make_open: got NULL inode\n");
|
printk("smb_make_open: got NULL inode\n");
|
return -EINVAL;
|
return -EINVAL;
|
}
|
}
|
dirent = &(SMB_INOP(i)->finfo);
|
dirent = &(SMB_INOP(i)->finfo);
|
|
|
DDPRINTK("smb_make_open: dirent->opened = %d\n", dirent->opened);
|
DDPRINTK("smb_make_open: dirent->opened = %d\n", dirent->opened);
|
|
|
if ((dirent->opened) == 0)
|
if ((dirent->opened) == 0)
|
{
|
{
|
/* tries max. rights */
|
/* tries max. rights */
|
int open_result = smb_proc_open(SMB_SERVER(i),
|
int open_result = smb_proc_open(SMB_SERVER(i),
|
SMB_INOP(i)->dir,
|
SMB_INOP(i)->dir,
|
dirent->name, dirent->len,
|
dirent->name, dirent->len,
|
dirent);
|
dirent);
|
if (open_result)
|
if (open_result)
|
{
|
{
|
return open_result;
|
return open_result;
|
}
|
}
|
}
|
}
|
if (((right == O_RDONLY) && ((dirent->access == O_RDONLY)
|
if (((right == O_RDONLY) && ((dirent->access == O_RDONLY)
|
|| (dirent->access == O_RDWR)))
|
|| (dirent->access == O_RDWR)))
|
|| ((right == O_WRONLY) && ((dirent->access == O_WRONLY)
|
|| ((right == O_WRONLY) && ((dirent->access == O_WRONLY)
|
|| (dirent->access == O_RDWR)))
|
|| (dirent->access == O_RDWR)))
|
|| ((right == O_RDWR) && (dirent->access == O_RDWR)))
|
|| ((right == O_RDWR) && (dirent->access == O_RDWR)))
|
return 0;
|
return 0;
|
|
|
return -EACCES;
|
return -EACCES;
|
}
|
}
|
|
|
static int
|
static int
|
smb_file_read(struct inode *inode, struct file *file, char *buf, int count)
|
smb_file_read(struct inode *inode, struct file *file, char *buf, int count)
|
{
|
{
|
int result, bufsize, to_read, already_read;
|
int result, bufsize, to_read, already_read;
|
off_t pos;
|
off_t pos;
|
int errno;
|
int errno;
|
|
|
DPRINTK("smb_file_read: enter %s\n", SMB_FINFO(inode)->name);
|
DPRINTK("smb_file_read: enter %s\n", SMB_FINFO(inode)->name);
|
|
|
if (!inode)
|
if (!inode)
|
{
|
{
|
DPRINTK("smb_file_read: inode = NULL\n");
|
DPRINTK("smb_file_read: inode = NULL\n");
|
return -EINVAL;
|
return -EINVAL;
|
}
|
}
|
if (!S_ISREG(inode->i_mode))
|
if (!S_ISREG(inode->i_mode))
|
{
|
{
|
DPRINTK("smb_file_read: read from non-file, mode %07o\n",
|
DPRINTK("smb_file_read: read from non-file, mode %07o\n",
|
inode->i_mode);
|
inode->i_mode);
|
return -EINVAL;
|
return -EINVAL;
|
}
|
}
|
if ((errno = smb_make_open(inode, O_RDONLY)) != 0)
|
if ((errno = smb_make_open(inode, O_RDONLY)) != 0)
|
return errno;
|
return errno;
|
|
|
pos = file->f_pos;
|
pos = file->f_pos;
|
|
|
if (pos + count > inode->i_size)
|
if (pos + count > inode->i_size)
|
{
|
{
|
count = inode->i_size - pos;
|
count = inode->i_size - pos;
|
}
|
}
|
if (count <= 0)
|
if (count <= 0)
|
{
|
{
|
return 0;
|
return 0;
|
}
|
}
|
bufsize = SMB_SERVER(inode)->max_xmit - SMB_HEADER_LEN - 5 * 2 - 5;
|
bufsize = SMB_SERVER(inode)->max_xmit - SMB_HEADER_LEN - 5 * 2 - 5;
|
|
|
already_read = 0;
|
already_read = 0;
|
|
|
/* First read in as much as possible for each bufsize. */
|
/* First read in as much as possible for each bufsize. */
|
while (already_read < count)
|
while (already_read < count)
|
{
|
{
|
to_read = min(bufsize, count - already_read);
|
to_read = min(bufsize, count - already_read);
|
result = smb_proc_read(SMB_SERVER(inode), SMB_FINFO(inode),
|
result = smb_proc_read(SMB_SERVER(inode), SMB_FINFO(inode),
|
pos, to_read, buf, 1);
|
pos, to_read, buf, 1);
|
if (result < 0)
|
if (result < 0)
|
{
|
{
|
return result;
|
return result;
|
}
|
}
|
pos += result;
|
pos += result;
|
buf += result;
|
buf += result;
|
already_read += result;
|
already_read += result;
|
|
|
if (result < to_read)
|
if (result < to_read)
|
{
|
{
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
file->f_pos = pos;
|
file->f_pos = pos;
|
|
|
if (!IS_RDONLY(inode))
|
if (!IS_RDONLY(inode))
|
inode->i_atime = CURRENT_TIME;
|
inode->i_atime = CURRENT_TIME;
|
inode->i_dirt = 1;
|
inode->i_dirt = 1;
|
|
|
DPRINTK("smb_file_read: exit %s\n", SMB_FINFO(inode)->name);
|
DPRINTK("smb_file_read: exit %s\n", SMB_FINFO(inode)->name);
|
|
|
return already_read;
|
return already_read;
|
}
|
}
|
|
|
static int
|
static int
|
smb_file_write(struct inode *inode, struct file *file, const char *buf,
|
smb_file_write(struct inode *inode, struct file *file, const char *buf,
|
int count)
|
int count)
|
{
|
{
|
int result, bufsize, to_write, already_written;
|
int result, bufsize, to_write, already_written;
|
off_t pos;
|
off_t pos;
|
int errno;
|
int errno;
|
|
|
if (!inode)
|
if (!inode)
|
{
|
{
|
DPRINTK("smb_file_write: inode = NULL\n");
|
DPRINTK("smb_file_write: inode = NULL\n");
|
return -EINVAL;
|
return -EINVAL;
|
}
|
}
|
if (!S_ISREG(inode->i_mode))
|
if (!S_ISREG(inode->i_mode))
|
{
|
{
|
DPRINTK("smb_file_write: write to non-file, mode %07o\n",
|
DPRINTK("smb_file_write: write to non-file, mode %07o\n",
|
inode->i_mode);
|
inode->i_mode);
|
return -EINVAL;
|
return -EINVAL;
|
}
|
}
|
DPRINTK("smb_file_write: enter %s\n", SMB_FINFO(inode)->name);
|
DPRINTK("smb_file_write: enter %s\n", SMB_FINFO(inode)->name);
|
|
|
if (count <= 0)
|
if (count <= 0)
|
{
|
{
|
return 0;
|
return 0;
|
}
|
}
|
if ((errno = smb_make_open(inode, O_RDWR)) != 0)
|
if ((errno = smb_make_open(inode, O_RDWR)) != 0)
|
{
|
{
|
return errno;
|
return errno;
|
}
|
}
|
pos = file->f_pos;
|
pos = file->f_pos;
|
|
|
if (file->f_flags & O_APPEND)
|
if (file->f_flags & O_APPEND)
|
pos = inode->i_size;
|
pos = inode->i_size;
|
|
|
bufsize = SMB_SERVER(inode)->max_xmit - SMB_HEADER_LEN - 5 * 2 - 5;
|
bufsize = SMB_SERVER(inode)->max_xmit - SMB_HEADER_LEN - 5 * 2 - 5;
|
|
|
already_written = 0;
|
already_written = 0;
|
|
|
DPRINTK("smb_write_file: blkmode = %d, blkmode & 2 = %d\n",
|
DPRINTK("smb_write_file: blkmode = %d, blkmode & 2 = %d\n",
|
SMB_SERVER(inode)->blkmode,
|
SMB_SERVER(inode)->blkmode,
|
SMB_SERVER(inode)->blkmode & 2);
|
SMB_SERVER(inode)->blkmode & 2);
|
|
|
while (already_written < count)
|
while (already_written < count)
|
{
|
{
|
to_write = min(bufsize, count - already_written);
|
to_write = min(bufsize, count - already_written);
|
result = smb_proc_write(SMB_SERVER(inode), SMB_FINFO(inode),
|
result = smb_proc_write(SMB_SERVER(inode), SMB_FINFO(inode),
|
pos, to_write, buf);
|
pos, to_write, buf);
|
|
|
if (result < 0)
|
if (result < 0)
|
{
|
{
|
return result;
|
return result;
|
}
|
}
|
pos += result;
|
pos += result;
|
buf += result;
|
buf += result;
|
already_written += result;
|
already_written += result;
|
|
|
if (result < to_write)
|
if (result < to_write)
|
{
|
{
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
|
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
|
inode->i_dirt = 1;
|
inode->i_dirt = 1;
|
|
|
file->f_pos = pos;
|
file->f_pos = pos;
|
|
|
if (pos > inode->i_size)
|
if (pos > inode->i_size)
|
{
|
{
|
inode->i_size = pos;
|
inode->i_size = pos;
|
}
|
}
|
DPRINTK("smb_file_write: exit %s\n", SMB_FINFO(inode)->name);
|
DPRINTK("smb_file_write: exit %s\n", SMB_FINFO(inode)->name);
|
|
|
return already_written;
|
return already_written;
|
}
|
}
|
|
|
static struct file_operations smb_file_operations =
|
static struct file_operations smb_file_operations =
|
{
|
{
|
NULL, /* lseek - default */
|
NULL, /* lseek - default */
|
smb_file_read, /* read */
|
smb_file_read, /* read */
|
smb_file_write, /* write */
|
smb_file_write, /* write */
|
NULL, /* readdir - bad */
|
NULL, /* readdir - bad */
|
NULL, /* select - default */
|
NULL, /* select - default */
|
smb_ioctl, /* ioctl */
|
smb_ioctl, /* ioctl */
|
smb_mmap, /* mmap */
|
smb_mmap, /* mmap */
|
NULL, /* open */
|
NULL, /* open */
|
NULL, /* release */
|
NULL, /* release */
|
smb_fsync, /* fsync */
|
smb_fsync, /* fsync */
|
};
|
};
|
|
|
struct inode_operations smb_file_inode_operations =
|
struct inode_operations smb_file_inode_operations =
|
{
|
{
|
&smb_file_operations, /* default file operations */
|
&smb_file_operations, /* default file operations */
|
NULL, /* create */
|
NULL, /* create */
|
NULL, /* lookup */
|
NULL, /* lookup */
|
NULL, /* link */
|
NULL, /* link */
|
NULL, /* unlink */
|
NULL, /* unlink */
|
NULL, /* symlink */
|
NULL, /* symlink */
|
NULL, /* mkdir */
|
NULL, /* mkdir */
|
NULL, /* rmdir */
|
NULL, /* rmdir */
|
NULL, /* mknod */
|
NULL, /* mknod */
|
NULL, /* rename */
|
NULL, /* rename */
|
NULL, /* readlink */
|
NULL, /* readlink */
|
NULL, /* follow_link */
|
NULL, /* follow_link */
|
NULL, /* readpage */
|
NULL, /* readpage */
|
NULL, /* writepage */
|
NULL, /* writepage */
|
NULL, /* bmap */
|
NULL, /* bmap */
|
NULL /* truncate */
|
NULL /* truncate */
|
};
|
};
|
|
|