patch-2.1.66 linux/fs/smbfs/file.c
Next file: linux/fs/smbfs/inode.c
Previous file: linux/fs/smbfs/dir.c
Back to the patch index
Back to the overall index
- Lines: 277
- Date:
Mon Nov 24 10:30:40 1997
- Orig file:
v2.1.65/linux/fs/smbfs/file.c
- Orig date:
Sat Oct 25 02:44:18 1997
diff -u --recursive --new-file v2.1.65/linux/fs/smbfs/file.c linux/fs/smbfs/file.c
@@ -12,20 +12,19 @@
#include <linux/fcntl.h>
#include <linux/stat.h>
#include <linux/mm.h>
-#include <linux/smb_fs.h>
#include <linux/malloc.h>
#include <linux/pagemap.h>
#include <asm/uaccess.h>
#include <asm/system.h>
+#include <linux/smbno.h>
+#include <linux/smb_fs.h>
+
#define SMBFS_PARANOIA 1
/* #define SMBFS_DEBUG_VERBOSE 1 */
/* #define pr_debug printk */
-extern int smb_get_rsize(struct smb_sb_info *);
-extern int smb_get_wsize(struct smb_sb_info *);
-
static inline int
min(int a, int b)
{
@@ -75,9 +74,15 @@
printk("smb_readpage_sync: file %s/%s, count=%d@%ld, rsize=%d\n",
dentry->d_parent->d_name.name, dentry->d_name.name, count, offset, rsize);
#endif
- result = smb_open(dentry, O_RDONLY);
+ result = smb_open(dentry, SMB_O_RDONLY);
if (result < 0)
+ {
+#ifdef SMBFS_PARANOIA
+printk("smb_readpage_sync: %s/%s open failed, error=%d\n",
+dentry->d_parent->d_name.name, dentry->d_name.name, result);
+#endif
goto io_error;
+ }
do {
if (count < rsize)
@@ -90,6 +95,7 @@
count -= result;
offset += result;
buffer += result;
+ inode->i_atime = CURRENT_TIME;
if (result < rsize)
break;
} while (count);
@@ -130,7 +136,7 @@
{
u8 *buffer = (u8 *) page_address(page) + offset;
int wsize = smb_get_wsize(SMB_SERVER(inode));
- int result, refresh = 0, written = 0;
+ int result, written = 0;
offset += page->offset;
#ifdef SMBFS_DEBUG_VERBOSE
@@ -145,30 +151,33 @@
result = smb_proc_write(inode, offset, wsize, buffer);
if (result < 0)
- {
- /* Must mark the page invalid after I/O error */
- clear_bit(PG_uptodate, &page->flags);
goto io_error;
- }
/* N.B. what if result < wsize?? */
#ifdef SMBFS_PARANOIA
if (result < wsize)
printk("smb_writepage_sync: short write, wsize=%d, result=%d\n", wsize, result);
#endif
- refresh = 1;
buffer += wsize;
offset += wsize;
written += wsize;
count -= wsize;
+ /*
+ * Update the inode now rather than waiting for a refresh.
+ */
+ inode->i_mtime = inode->i_atime = CURRENT_TIME;
+ if (offset > inode->i_size)
+ inode->i_size = offset;
+ inode->u.smbfs_i.cache_valid |= SMB_F_LOCALWRITE;
} while (count);
-io_error:
-#if 0
- if (refresh)
- smb_refresh_inode(inode);
-#endif
+out:
smb_unlock_page(page);
return written ? written : result;
+
+io_error:
+ /* Must mark the page invalid after I/O error */
+ clear_bit(PG_uptodate, &page->flags);
+ goto out;
}
/*
@@ -230,19 +239,32 @@
static ssize_t
smb_file_read(struct file * file, char * buf, size_t count, loff_t *ppos)
{
+ struct dentry * dentry = file->f_dentry;
+ struct inode * inode = dentry->d_inode;
ssize_t status;
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_file_read: file %s/%s, count=%lu@%lu\n",
-file->f_dentry->d_parent->d_name.name, file->f_dentry->d_name.name,
-count, (unsigned long) *ppos);
+dentry->d_parent->d_name.name, dentry->d_name.name,
+(unsigned long) count, (unsigned long) *ppos);
#endif
- status = smb_revalidate_inode(file->f_dentry->d_inode);
- if (status >= 0)
+ status = smb_revalidate_inode(inode);
+ if (status)
{
- status = generic_file_read(file, buf, count, ppos);
+#ifdef SMBFS_PARANOIA
+printk("smb_file_read: %s/%s validation failed, error=%d\n",
+dentry->d_parent->d_name.name, dentry->d_name.name, status);
+#endif
+ goto out;
}
+
+#ifdef SMBFS_DEBUG_VERBOSE
+printk("smb_file_read: before read, size=%ld, pages=%ld, flags=%x, atime=%ld\n",
+inode->i_size, inode->i_nrpages, inode->i_flags, inode->i_atime);
+#endif
+ status = generic_file_read(file, buf, count, ppos);
+out:
return status;
}
@@ -255,14 +277,21 @@
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_file_mmap: file %s/%s, address %lu - %lu\n",
-file->f_dentry->d_parent->d_name.name, file->f_dentry->d_name.name,
+dentry->d_parent->d_name.name, dentry->d_name.name,
vma->vm_start, vma->vm_end);
#endif
+
status = smb_revalidate_inode(inode);
- if (status >= 0)
+ if (status)
{
- status = generic_file_mmap(file, vma);
+#ifdef SMBFS_PARANOIA
+printk("smb_file_mmap: %s/%s validation failed, error=%d\n",
+dentry->d_parent->d_name.name, dentry->d_name.name, status);
+#endif
+ goto out;
}
+ status = generic_file_mmap(file, vma);
+out:
return status;
}
@@ -272,38 +301,37 @@
static ssize_t
smb_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
+ struct dentry * dentry = file->f_dentry;
+ struct inode * inode = dentry->d_inode;
ssize_t result;
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_file_write: file %s/%s, count=%lu@%lu\n",
-file->f_dentry->d_parent->d_name.name, file->f_dentry->d_name.name,
-count, (unsigned long) *ppos);
+dentry->d_parent->d_name.name, dentry->d_name.name,
+(unsigned long) count, (unsigned long) *ppos);
#endif
-#ifdef SMBFS_PARANOIA
- /* Should be impossible now that inodes can't change mode */
- result = -EINVAL;
- if (!S_ISREG(file->f_dentry->d_inode->i_mode))
+ result = smb_revalidate_inode(inode);
+ if (result)
{
- printk("smb_file_write: write to non-file, mode %07o\n",
- file->f_dentry->d_inode->i_mode);
- goto out;
- }
+#ifdef SMBFS_PARANOIA
+printk("smb_file_write: %s/%s validation failed, error=%d\n",
+dentry->d_parent->d_name.name, dentry->d_name.name, result);
#endif
+ goto out;
+ }
- result = smb_revalidate_inode(file->f_dentry->d_inode);
- if (result)
- goto out;
-
- result = smb_open(file->f_dentry, O_WRONLY);
+ result = smb_open(dentry, SMB_O_WRONLY);
if (result)
goto out;
if (count > 0)
{
result = generic_file_write(file, buf, count, ppos);
- if (result > 0)
- smb_refresh_inode(file->f_dentry->d_inode);
+#ifdef SMBFS_DEBUG_VERBOSE
+printk("smb_file_write: pos=%ld, size=%ld, mtime=%ld, atime=%ld\n",
+(long) file->f_pos, inode->i_size, inode->i_mtime, inode->i_atime);
+#endif
}
out:
return result;
@@ -313,7 +341,9 @@
smb_file_open(struct inode *inode, struct file * file)
{
#ifdef SMBFS_DEBUG_VERBOSE
-printk("smb_file_open: inode=%p, file=%p\n", inode, file);
+printk("smb_file_open: opening %s/%s, d_count=%d\n",
+file->f_dentry->d_parent->d_name.name, file->f_dentry->d_name.name,
+file->f_dentry->d_count);
#endif
return 0;
}
@@ -324,7 +354,7 @@
struct dentry * dentry = file->f_dentry;
#ifdef SMBFS_DEBUG_VERBOSE
-printk("smb_file_release: closing file %s/%s, d_count=%d\n",
+printk("smb_file_release: closing %s/%s, d_count=%d\n",
dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_count);
#endif
@@ -335,6 +365,27 @@
return 0;
}
+/*
+ * Check whether the required access is compatible with
+ * an inode's permission. SMB doesn't recognize superuser
+ * privileges, so we need our own check for this.
+ */
+static int
+smb_file_permission(struct inode *inode, int mask)
+{
+ int mode = inode->i_mode;
+ int error = 0;
+
+#ifdef SMBFS_DEBUG_VERBOSE
+printk("smb_file_permission: mode=%x, mask=%x\n", mode, mask);
+#endif
+ /* Look at user permissions */
+ mode >>= 6;
+ if ((mode & 7 & mask) != mask)
+ error = -EACCES;
+ return error;
+}
+
static struct file_operations smb_file_operations =
{
NULL, /* lseek - default */
@@ -371,7 +422,7 @@
smb_writepage, /* writepage */
NULL, /* bmap */
NULL, /* truncate */
- NULL, /* permission */
+ smb_file_permission, /* permission */
NULL, /* smap */
smb_updatepage, /* updatepage */
smb_revalidate_inode, /* revalidate */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov