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 int min(int a
, 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 nw_file_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;
104 DPRINTK(KERN_DEBUG
"ncp_file_read: enter %s/%s\n",
105 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
109 DPRINTK(KERN_DEBUG
"ncp_file_read: inode = NULL\n");
113 if (!ncp_conn_valid(NCP_SERVER(inode
)))
116 if (!S_ISREG(inode
->i_mode
)) {
117 DPRINTK(KERN_DEBUG
"ncp_file_read: read from non-file, mode %07o\n",
123 if (pos
+ count
> inode
->i_size
) {
124 count
= inode
->i_size
- pos
;
127 if (!count
) /* size_t is never < 0 */
130 error
= ncp_make_open(inode
, O_RDONLY
);
132 printk(KERN_ERR
"ncp_file_read: open failed, error=%d\n", error
);
136 bufsize
= NCP_SERVER(inode
)->buffer_size
;
138 /* First read in as much as possible for each bufsize. */
139 while (already_read
< count
) {
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
);
148 error
= -EIO
; /* This is not exact, i know.. */
151 pos
+= read_this_time
;
152 buf
+= read_this_time
;
153 already_read
+= read_this_time
;
155 if (read_this_time
< to_read
) {
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
);
169 return already_read
? already_read
: error
;
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;
181 DPRINTK(KERN_DEBUG
"ncp_file_write: enter %s/%s\n",
182 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
184 DPRINTK(KERN_DEBUG
"ncp_file_write: inode = NULL\n");
188 if (!ncp_conn_valid(NCP_SERVER(inode
)))
190 if (!S_ISREG(inode
->i_mode
)) {
191 DPRINTK(KERN_DEBUG
"ncp_file_write: write to non-file, mode %07o\n",
199 errno
= ncp_make_open(inode
, O_RDWR
);
201 printk(KERN_ERR
"ncp_file_write: open failed, error=%d\n", errno
);
206 if (file
->f_flags
& O_APPEND
) {
209 bufsize
= NCP_SERVER(inode
)->buffer_size
;
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) {
222 pos
+= written_this_time
;
223 buf
+= written_this_time
;
224 already_written
+= written_this_time
;
226 if (written_this_time
< to_write
) {
231 inode
->i_mtime
= inode
->i_atime
= CURRENT_TIME
;
235 if (pos
> inode
->i_size
) {
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
);
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 */
257 ncp_fsync
, /* fsync */
260 struct inode_operations ncp_file_inode_operations
=
262 &ncp_file_operations
, /* default file operations */