4 * Copyright (C) 1995, 1996 by Volker Lendecke
5 * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
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>
18 #include <linux/locks.h>
19 #include <linux/malloc.h>
21 #include <linux/ncp_fs.h>
22 #include "ncplib_kernel.h"
24 static inline unsigned int min(unsigned int a
, unsigned int b
)
29 static int ncp_fsync(struct file
*file
, struct dentry
*dentry
)
35 * Open a file with the specified read/write mode.
37 int ncp_make_open(struct inode
*inode
, int right
)
41 struct ncp_entry_info finfo
;
45 printk(KERN_ERR
"ncp_make_open: got NULL inode\n");
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
);
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
);
65 finfo
.access
= O_RDONLY
;
66 result
= ncp_open_create_file_or_subdir(NCP_SERVER(inode
),
67 NULL
, NULL
, OC_MODE_OPEN
,
71 printk(KERN_DEBUG
"ncp_make_open: failed, result=%d\n", result
);
76 * Update the inode information.
79 ncp_update_inode(inode
, &finfo
);
82 access
= NCP_FINFO(inode
)->access
;
84 printk(KERN_DEBUG
"ncp_make_open: file open, access=%x\n", access
);
86 if (access
== right
|| access
== O_RDWR
)
90 unlock_super(inode
->i_sb
);
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;
107 DPRINTK(KERN_DEBUG
"ncp_file_read: enter %s/%s\n",
108 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
112 DPRINTK(KERN_DEBUG
"ncp_file_read: inode = NULL\n");
116 if (!ncp_conn_valid(NCP_SERVER(inode
)))
119 if (!S_ISREG(inode
->i_mode
)) {
120 DPRINTK(KERN_DEBUG
"ncp_file_read: read from non-file, mode %07o\n",
126 /* leave it out on server ...
127 if (pos + count > inode->i_size) {
128 count = inode->i_size - pos;
132 if (!count
) /* size_t is never < 0 */
135 error
= ncp_make_open(inode
, O_RDONLY
);
137 printk(KERN_ERR
"ncp_file_read: open failed, error=%d\n", error
);
141 bufsize
= NCP_SERVER(inode
)->buffer_size
;
144 freelen
= ncp_read_bounce_size(bufsize
);
145 freepage
= kmalloc(freelen
, GFP_NFS
);
149 /* First read in as much as possible for each bufsize. */
150 while (already_read
< count
) {
152 size_t to_read
= min(bufsize
- (pos
% bufsize
),
153 count
- already_read
);
155 error
= ncp_read_bounce(NCP_SERVER(inode
),
156 NCP_FINFO(inode
)->file_handle
,
157 pos
, to_read
, buf
, &read_this_time
,
161 error
= -EIO
; /* This is not exact, i know.. */
164 pos
+= read_this_time
;
165 buf
+= read_this_time
;
166 already_read
+= read_this_time
;
168 if (read_this_time
!= to_read
) {
176 if (!IS_RDONLY(inode
)) {
177 inode
->i_atime
= CURRENT_TIME
;
180 DPRINTK(KERN_DEBUG
"ncp_file_read: exit %s/%s\n",
181 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
183 return already_read
? already_read
: error
;
187 ncp_file_write(struct file
*file
, const char *buf
, size_t count
, loff_t
*ppos
)
189 struct dentry
*dentry
= file
->f_dentry
;
190 struct inode
*inode
= dentry
->d_inode
;
191 size_t already_written
= 0;
197 DPRINTK(KERN_DEBUG
"ncp_file_write: enter %s/%s\n",
198 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
200 DPRINTK(KERN_DEBUG
"ncp_file_write: inode = NULL\n");
204 if (!ncp_conn_valid(NCP_SERVER(inode
)))
206 if (!S_ISREG(inode
->i_mode
)) {
207 DPRINTK(KERN_DEBUG
"ncp_file_write: write to non-file, mode %07o\n",
215 errno
= ncp_make_open(inode
, O_RDWR
);
217 printk(KERN_ERR
"ncp_file_write: open failed, error=%d\n", errno
);
222 if (file
->f_flags
& O_APPEND
) {
225 bufsize
= NCP_SERVER(inode
)->buffer_size
;
229 bouncebuffer
= kmalloc(bufsize
, GFP_NFS
);
231 return -EIO
; /* -ENOMEM */
232 while (already_written
< count
) {
233 int written_this_time
;
234 size_t to_write
= min(bufsize
- (pos
% bufsize
),
235 count
- already_written
);
237 if (copy_from_user(bouncebuffer
, buf
, to_write
)) {
241 if (ncp_write_kernel(NCP_SERVER(inode
),
242 NCP_FINFO(inode
)->file_handle
,
243 pos
, to_write
, buf
, &written_this_time
) != 0) {
247 pos
+= written_this_time
;
248 buf
+= written_this_time
;
249 already_written
+= written_this_time
;
251 if (written_this_time
!= to_write
) {
256 inode
->i_mtime
= inode
->i_atime
= CURRENT_TIME
;
260 if (pos
> inode
->i_size
) {
263 DPRINTK(KERN_DEBUG
"ncp_file_write: exit %s/%s\n",
264 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
266 return already_written
? already_written
: errno
;
269 static struct file_operations ncp_file_operations
=
271 NULL
, /* lseek - default */
272 ncp_file_read
, /* read */
273 ncp_file_write
, /* write */
274 NULL
, /* readdir - bad */
275 NULL
, /* poll - default */
276 ncp_ioctl
, /* ioctl */
281 ncp_fsync
, /* fsync */
284 struct inode_operations ncp_file_inode_operations
=
286 &ncp_file_operations
, /* default file operations */
297 NULL
, /* follow_link */
298 NULL
, /* get_block */
300 NULL
, /* writepage */
301 NULL
, /* flushpage */
303 NULL
, /* permission */
305 NULL
/* revalidate */