Import 2.1.118
[davej-history.git] / fs / ncpfs / file.c
blob50d91a2b290c0e2f3835f7d02c5e134dd42b0f96
1 /*
2 * file.c
4 * Copyright (C) 1995, 1996 by Volker Lendecke
5 * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
7 */
9 #include <asm/uaccess.h>
10 #include <asm/system.h>
12 #include <linux/sched.h>
13 #include <linux/kernel.h>
14 #include <linux/errno.h>
15 #include <linux/fcntl.h>
16 #include <linux/stat.h>
17 #include <linux/mm.h>
18 #include <linux/locks.h>
19 #include <linux/malloc.h>
21 #include <linux/ncp_fs.h>
22 #include "ncplib_kernel.h"
24 static inline int min(int a, int b)
26 return a < b ? a : b;
29 static int ncp_fsync(struct file *file, struct dentry *dentry)
31 return 0;
35 * Open a file with the specified read/write mode.
37 int ncp_make_open(struct inode *inode, int right)
39 int error, result;
40 int access;
41 struct nw_file_info finfo;
43 error = -EINVAL;
44 if (!inode) {
45 printk(KERN_ERR "ncp_make_open: got NULL inode\n");
46 goto out;
49 DPRINTK(KERN_DEBUG "ncp_make_open: opened=%d, volume # %u, dir entry # %u\n",
50 NCP_FINFO(inode)->opened,
51 NCP_FINFO(inode)->volNumber,
52 NCP_FINFO(inode)->dirEntNum);
53 error = -EACCES;
54 lock_super(inode->i_sb);
55 if (!NCP_FINFO(inode)->opened) {
56 finfo.i.dirEntNum = NCP_FINFO(inode)->dirEntNum;
57 finfo.i.volNumber = NCP_FINFO(inode)->volNumber;
58 /* tries max. rights */
59 finfo.access = O_RDWR;
60 result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
61 NULL, NULL, OC_MODE_OPEN,
62 0, AR_READ | AR_WRITE, &finfo);
63 if (!result)
64 goto update;
65 finfo.access = O_RDONLY;
66 result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
67 NULL, NULL, OC_MODE_OPEN,
68 0, AR_READ, &finfo);
69 if (result) {
70 #ifdef NCPFS_PARANOIA
71 printk(KERN_DEBUG "ncp_make_open: failed, result=%d\n", result);
72 #endif
73 goto out_unlock;
76 * Update the inode information.
78 update:
79 ncp_update_inode(inode, &finfo);
82 access = NCP_FINFO(inode)->access;
83 #ifdef NCPFS_PARANOIA
84 printk(KERN_DEBUG "ncp_make_open: file open, access=%x\n", access);
85 #endif
86 if (access == right || access == O_RDWR)
87 error = 0;
89 out_unlock:
90 unlock_super(inode->i_sb);
91 out:
92 return error;
95 static ssize_t
96 ncp_file_read(struct file *file, char *buf, size_t count, loff_t *ppos)
98 struct dentry *dentry = file->f_dentry;
99 struct inode *inode = dentry->d_inode;
100 size_t already_read = 0;
101 off_t pos;
102 int bufsize, error;
104 DPRINTK(KERN_DEBUG "ncp_file_read: enter %s/%s\n",
105 dentry->d_parent->d_name.name, dentry->d_name.name);
107 error = -EINVAL;
108 if (inode == NULL) {
109 DPRINTK(KERN_DEBUG "ncp_file_read: inode = NULL\n");
110 goto out;
112 error = -EIO;
113 if (!ncp_conn_valid(NCP_SERVER(inode)))
114 goto out;
115 error = -EINVAL;
116 if (!S_ISREG(inode->i_mode)) {
117 DPRINTK(KERN_DEBUG "ncp_file_read: read from non-file, mode %07o\n",
118 inode->i_mode);
119 goto out;
122 pos = file->f_pos;
123 if (pos + count > inode->i_size) {
124 count = inode->i_size - pos;
126 error = 0;
127 if (!count) /* size_t is never < 0 */
128 goto out;
130 error = ncp_make_open(inode, O_RDONLY);
131 if (error) {
132 printk(KERN_ERR "ncp_file_read: open failed, error=%d\n", error);
133 goto out;
136 bufsize = NCP_SERVER(inode)->buffer_size;
138 /* First read in as much as possible for each bufsize. */
139 while (already_read < count) {
140 int read_this_time;
141 int to_read = min(bufsize - (pos % bufsize),
142 count - already_read);
144 error = ncp_read(NCP_SERVER(inode),
145 NCP_FINFO(inode)->file_handle,
146 pos, to_read, buf, &read_this_time);
147 if (error) {
148 error = -EIO; /* This is not exact, i know.. */
149 goto out;
151 pos += read_this_time;
152 buf += read_this_time;
153 already_read += read_this_time;
155 if (read_this_time < to_read) {
156 break;
160 file->f_pos = pos;
162 if (!IS_RDONLY(inode)) {
163 inode->i_atime = CURRENT_TIME;
166 DPRINTK(KERN_DEBUG "ncp_file_read: exit %s/%s\n",
167 dentry->d_parent->d_name.name, dentry->d_name.name);
168 out:
169 return already_read ? already_read : error;
172 static ssize_t
173 ncp_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
175 struct dentry *dentry = file->f_dentry;
176 struct inode *inode = dentry->d_inode;
177 size_t already_written = 0;
178 off_t pos;
179 int bufsize, errno;
181 DPRINTK(KERN_DEBUG "ncp_file_write: enter %s/%s\n",
182 dentry->d_parent->d_name.name, dentry->d_name.name);
183 if (inode == NULL) {
184 DPRINTK(KERN_DEBUG "ncp_file_write: inode = NULL\n");
185 return -EINVAL;
187 errno = -EIO;
188 if (!ncp_conn_valid(NCP_SERVER(inode)))
189 goto out;
190 if (!S_ISREG(inode->i_mode)) {
191 DPRINTK(KERN_DEBUG "ncp_file_write: write to non-file, mode %07o\n",
192 inode->i_mode);
193 return -EINVAL;
196 errno = 0;
197 if (!count)
198 goto out;
199 errno = ncp_make_open(inode, O_RDWR);
200 if (errno) {
201 printk(KERN_ERR "ncp_file_write: open failed, error=%d\n", errno);
202 return errno;
204 pos = file->f_pos;
206 if (file->f_flags & O_APPEND) {
207 pos = inode->i_size;
209 bufsize = NCP_SERVER(inode)->buffer_size;
211 already_written = 0;
213 while (already_written < count) {
214 int written_this_time;
215 int to_write = min(bufsize - (pos % bufsize),
216 count - already_written);
218 if (ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
219 pos, to_write, buf, &written_this_time) != 0) {
220 return -EIO;
222 pos += written_this_time;
223 buf += written_this_time;
224 already_written += written_this_time;
226 if (written_this_time < to_write) {
227 break;
231 inode->i_mtime = inode->i_atime = CURRENT_TIME;
233 file->f_pos = pos;
235 if (pos > inode->i_size) {
236 inode->i_size = pos;
237 ncp_invalid_dir_cache(dentry->d_parent->d_inode);
239 DPRINTK(KERN_DEBUG "ncp_file_write: exit %s/%s\n",
240 dentry->d_parent->d_name.name, dentry->d_name.name);
241 out:
242 return already_written ? already_written : errno;
245 static struct file_operations ncp_file_operations =
247 NULL, /* lseek - default */
248 ncp_file_read, /* read */
249 ncp_file_write, /* write */
250 NULL, /* readdir - bad */
251 NULL, /* poll - default */
252 ncp_ioctl, /* ioctl */
253 ncp_mmap, /* mmap */
254 NULL, /* open */
255 NULL, /* flush */
256 NULL, /* release */
257 ncp_fsync, /* fsync */
260 struct inode_operations ncp_file_inode_operations =
262 &ncp_file_operations, /* default file operations */
263 NULL, /* create */
264 NULL, /* lookup */
265 NULL, /* link */
266 NULL, /* unlink */
267 NULL, /* symlink */
268 NULL, /* mkdir */
269 NULL, /* rmdir */
270 NULL, /* mknod */
271 NULL, /* rename */
272 NULL, /* readlink */
273 NULL, /* bmap */
274 NULL /* truncate */