Commit 92e5baef8578a03335059a3dec933955c361edc1

Authored by Josef Sipek
Committed by Linus Torvalds
1 parent 17506041de

[PATCH] struct path: convert ncpfs

Signed-off-by: Josef Sipek <jsipek@fsl.cs.sunysb.edu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 5 changed files with 14 additions and 14 deletions Inline Diff

1 /* 1 /*
2 * dir.c 2 * dir.c
3 * 3 *
4 * Copyright (C) 1995, 1996 by Volker Lendecke 4 * Copyright (C) 1995, 1996 by Volker Lendecke
5 * Modified for big endian by J.F. Chadima and David S. Miller 5 * Modified for big endian by J.F. Chadima and David S. Miller
6 * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache 6 * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
7 * Modified 1998, 1999 Wolfram Pienkoss for NLS 7 * Modified 1998, 1999 Wolfram Pienkoss for NLS
8 * Modified 1999 Wolfram Pienkoss for directory caching 8 * Modified 1999 Wolfram Pienkoss for directory caching
9 * Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info 9 * Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
10 * 10 *
11 */ 11 */
12 12
13 13
14 #include <linux/time.h> 14 #include <linux/time.h>
15 #include <linux/errno.h> 15 #include <linux/errno.h>
16 #include <linux/stat.h> 16 #include <linux/stat.h>
17 #include <linux/kernel.h> 17 #include <linux/kernel.h>
18 #include <linux/slab.h> 18 #include <linux/slab.h>
19 #include <linux/vmalloc.h> 19 #include <linux/vmalloc.h>
20 #include <linux/mm.h> 20 #include <linux/mm.h>
21 #include <asm/uaccess.h> 21 #include <asm/uaccess.h>
22 #include <asm/byteorder.h> 22 #include <asm/byteorder.h>
23 #include <linux/smp_lock.h> 23 #include <linux/smp_lock.h>
24 24
25 #include <linux/ncp_fs.h> 25 #include <linux/ncp_fs.h>
26 26
27 #include "ncplib_kernel.h" 27 #include "ncplib_kernel.h"
28 28
29 static void ncp_read_volume_list(struct file *, void *, filldir_t, 29 static void ncp_read_volume_list(struct file *, void *, filldir_t,
30 struct ncp_cache_control *); 30 struct ncp_cache_control *);
31 static void ncp_do_readdir(struct file *, void *, filldir_t, 31 static void ncp_do_readdir(struct file *, void *, filldir_t,
32 struct ncp_cache_control *); 32 struct ncp_cache_control *);
33 33
34 static int ncp_readdir(struct file *, void *, filldir_t); 34 static int ncp_readdir(struct file *, void *, filldir_t);
35 35
36 static int ncp_create(struct inode *, struct dentry *, int, struct nameidata *); 36 static int ncp_create(struct inode *, struct dentry *, int, struct nameidata *);
37 static struct dentry *ncp_lookup(struct inode *, struct dentry *, struct nameidata *); 37 static struct dentry *ncp_lookup(struct inode *, struct dentry *, struct nameidata *);
38 static int ncp_unlink(struct inode *, struct dentry *); 38 static int ncp_unlink(struct inode *, struct dentry *);
39 static int ncp_mkdir(struct inode *, struct dentry *, int); 39 static int ncp_mkdir(struct inode *, struct dentry *, int);
40 static int ncp_rmdir(struct inode *, struct dentry *); 40 static int ncp_rmdir(struct inode *, struct dentry *);
41 static int ncp_rename(struct inode *, struct dentry *, 41 static int ncp_rename(struct inode *, struct dentry *,
42 struct inode *, struct dentry *); 42 struct inode *, struct dentry *);
43 static int ncp_mknod(struct inode * dir, struct dentry *dentry, 43 static int ncp_mknod(struct inode * dir, struct dentry *dentry,
44 int mode, dev_t rdev); 44 int mode, dev_t rdev);
45 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) 45 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
46 extern int ncp_symlink(struct inode *, struct dentry *, const char *); 46 extern int ncp_symlink(struct inode *, struct dentry *, const char *);
47 #else 47 #else
48 #define ncp_symlink NULL 48 #define ncp_symlink NULL
49 #endif 49 #endif
50 50
51 const struct file_operations ncp_dir_operations = 51 const struct file_operations ncp_dir_operations =
52 { 52 {
53 .read = generic_read_dir, 53 .read = generic_read_dir,
54 .readdir = ncp_readdir, 54 .readdir = ncp_readdir,
55 .ioctl = ncp_ioctl, 55 .ioctl = ncp_ioctl,
56 #ifdef CONFIG_COMPAT 56 #ifdef CONFIG_COMPAT
57 .compat_ioctl = ncp_compat_ioctl, 57 .compat_ioctl = ncp_compat_ioctl,
58 #endif 58 #endif
59 }; 59 };
60 60
61 struct inode_operations ncp_dir_inode_operations = 61 struct inode_operations ncp_dir_inode_operations =
62 { 62 {
63 .create = ncp_create, 63 .create = ncp_create,
64 .lookup = ncp_lookup, 64 .lookup = ncp_lookup,
65 .unlink = ncp_unlink, 65 .unlink = ncp_unlink,
66 .symlink = ncp_symlink, 66 .symlink = ncp_symlink,
67 .mkdir = ncp_mkdir, 67 .mkdir = ncp_mkdir,
68 .rmdir = ncp_rmdir, 68 .rmdir = ncp_rmdir,
69 .mknod = ncp_mknod, 69 .mknod = ncp_mknod,
70 .rename = ncp_rename, 70 .rename = ncp_rename,
71 .setattr = ncp_notify_change, 71 .setattr = ncp_notify_change,
72 }; 72 };
73 73
74 /* 74 /*
75 * Dentry operations routines 75 * Dentry operations routines
76 */ 76 */
77 static int ncp_lookup_validate(struct dentry *, struct nameidata *); 77 static int ncp_lookup_validate(struct dentry *, struct nameidata *);
78 static int ncp_hash_dentry(struct dentry *, struct qstr *); 78 static int ncp_hash_dentry(struct dentry *, struct qstr *);
79 static int ncp_compare_dentry (struct dentry *, struct qstr *, struct qstr *); 79 static int ncp_compare_dentry (struct dentry *, struct qstr *, struct qstr *);
80 static int ncp_delete_dentry(struct dentry *); 80 static int ncp_delete_dentry(struct dentry *);
81 81
82 static struct dentry_operations ncp_dentry_operations = 82 static struct dentry_operations ncp_dentry_operations =
83 { 83 {
84 .d_revalidate = ncp_lookup_validate, 84 .d_revalidate = ncp_lookup_validate,
85 .d_hash = ncp_hash_dentry, 85 .d_hash = ncp_hash_dentry,
86 .d_compare = ncp_compare_dentry, 86 .d_compare = ncp_compare_dentry,
87 .d_delete = ncp_delete_dentry, 87 .d_delete = ncp_delete_dentry,
88 }; 88 };
89 89
90 struct dentry_operations ncp_root_dentry_operations = 90 struct dentry_operations ncp_root_dentry_operations =
91 { 91 {
92 .d_hash = ncp_hash_dentry, 92 .d_hash = ncp_hash_dentry,
93 .d_compare = ncp_compare_dentry, 93 .d_compare = ncp_compare_dentry,
94 .d_delete = ncp_delete_dentry, 94 .d_delete = ncp_delete_dentry,
95 }; 95 };
96 96
97 97
98 /* 98 /*
99 * Note: leave the hash unchanged if the directory 99 * Note: leave the hash unchanged if the directory
100 * is case-sensitive. 100 * is case-sensitive.
101 */ 101 */
102 static int 102 static int
103 ncp_hash_dentry(struct dentry *dentry, struct qstr *this) 103 ncp_hash_dentry(struct dentry *dentry, struct qstr *this)
104 { 104 {
105 struct nls_table *t; 105 struct nls_table *t;
106 unsigned long hash; 106 unsigned long hash;
107 int i; 107 int i;
108 108
109 t = NCP_IO_TABLE(dentry); 109 t = NCP_IO_TABLE(dentry);
110 110
111 if (!ncp_case_sensitive(dentry->d_inode)) { 111 if (!ncp_case_sensitive(dentry->d_inode)) {
112 hash = init_name_hash(); 112 hash = init_name_hash();
113 for (i=0; i<this->len ; i++) 113 for (i=0; i<this->len ; i++)
114 hash = partial_name_hash(ncp_tolower(t, this->name[i]), 114 hash = partial_name_hash(ncp_tolower(t, this->name[i]),
115 hash); 115 hash);
116 this->hash = end_name_hash(hash); 116 this->hash = end_name_hash(hash);
117 } 117 }
118 return 0; 118 return 0;
119 } 119 }
120 120
121 static int 121 static int
122 ncp_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b) 122 ncp_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b)
123 { 123 {
124 if (a->len != b->len) 124 if (a->len != b->len)
125 return 1; 125 return 1;
126 126
127 if (ncp_case_sensitive(dentry->d_inode)) 127 if (ncp_case_sensitive(dentry->d_inode))
128 return strncmp(a->name, b->name, a->len); 128 return strncmp(a->name, b->name, a->len);
129 129
130 return ncp_strnicmp(NCP_IO_TABLE(dentry), a->name, b->name, a->len); 130 return ncp_strnicmp(NCP_IO_TABLE(dentry), a->name, b->name, a->len);
131 } 131 }
132 132
133 /* 133 /*
134 * This is the callback from dput() when d_count is going to 0. 134 * This is the callback from dput() when d_count is going to 0.
135 * We use this to unhash dentries with bad inodes. 135 * We use this to unhash dentries with bad inodes.
136 * Closing files can be safely postponed until iput() - it's done there anyway. 136 * Closing files can be safely postponed until iput() - it's done there anyway.
137 */ 137 */
138 static int 138 static int
139 ncp_delete_dentry(struct dentry * dentry) 139 ncp_delete_dentry(struct dentry * dentry)
140 { 140 {
141 struct inode *inode = dentry->d_inode; 141 struct inode *inode = dentry->d_inode;
142 142
143 if (inode) { 143 if (inode) {
144 if (is_bad_inode(inode)) 144 if (is_bad_inode(inode))
145 return 1; 145 return 1;
146 } else 146 } else
147 { 147 {
148 /* N.B. Unhash negative dentries? */ 148 /* N.B. Unhash negative dentries? */
149 } 149 }
150 return 0; 150 return 0;
151 } 151 }
152 152
153 static inline int 153 static inline int
154 ncp_single_volume(struct ncp_server *server) 154 ncp_single_volume(struct ncp_server *server)
155 { 155 {
156 return (server->m.mounted_vol[0] != '\0'); 156 return (server->m.mounted_vol[0] != '\0');
157 } 157 }
158 158
159 static inline int ncp_is_server_root(struct inode *inode) 159 static inline int ncp_is_server_root(struct inode *inode)
160 { 160 {
161 return (!ncp_single_volume(NCP_SERVER(inode)) && 161 return (!ncp_single_volume(NCP_SERVER(inode)) &&
162 inode == inode->i_sb->s_root->d_inode); 162 inode == inode->i_sb->s_root->d_inode);
163 } 163 }
164 164
165 165
166 /* 166 /*
167 * This is the callback when the dcache has a lookup hit. 167 * This is the callback when the dcache has a lookup hit.
168 */ 168 */
169 169
170 170
171 #ifdef CONFIG_NCPFS_STRONG 171 #ifdef CONFIG_NCPFS_STRONG
172 /* try to delete a readonly file (NW R bit set) */ 172 /* try to delete a readonly file (NW R bit set) */
173 173
174 static int 174 static int
175 ncp_force_unlink(struct inode *dir, struct dentry* dentry) 175 ncp_force_unlink(struct inode *dir, struct dentry* dentry)
176 { 176 {
177 int res=0x9c,res2; 177 int res=0x9c,res2;
178 struct nw_modify_dos_info info; 178 struct nw_modify_dos_info info;
179 __le32 old_nwattr; 179 __le32 old_nwattr;
180 struct inode *inode; 180 struct inode *inode;
181 181
182 memset(&info, 0, sizeof(info)); 182 memset(&info, 0, sizeof(info));
183 183
184 /* remove the Read-Only flag on the NW server */ 184 /* remove the Read-Only flag on the NW server */
185 inode = dentry->d_inode; 185 inode = dentry->d_inode;
186 186
187 old_nwattr = NCP_FINFO(inode)->nwattr; 187 old_nwattr = NCP_FINFO(inode)->nwattr;
188 info.attributes = old_nwattr & ~(aRONLY|aDELETEINHIBIT|aRENAMEINHIBIT); 188 info.attributes = old_nwattr & ~(aRONLY|aDELETEINHIBIT|aRENAMEINHIBIT);
189 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info); 189 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
190 if (res2) 190 if (res2)
191 goto leave_me; 191 goto leave_me;
192 192
193 /* now try again the delete operation */ 193 /* now try again the delete operation */
194 res = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry); 194 res = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry);
195 195
196 if (res) /* delete failed, set R bit again */ 196 if (res) /* delete failed, set R bit again */
197 { 197 {
198 info.attributes = old_nwattr; 198 info.attributes = old_nwattr;
199 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info); 199 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
200 if (res2) 200 if (res2)
201 goto leave_me; 201 goto leave_me;
202 } 202 }
203 leave_me: 203 leave_me:
204 return(res); 204 return(res);
205 } 205 }
206 #endif /* CONFIG_NCPFS_STRONG */ 206 #endif /* CONFIG_NCPFS_STRONG */
207 207
208 #ifdef CONFIG_NCPFS_STRONG 208 #ifdef CONFIG_NCPFS_STRONG
209 static int 209 static int
210 ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_name, 210 ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_name,
211 struct inode *new_dir, struct dentry* new_dentry, char *_new_name) 211 struct inode *new_dir, struct dentry* new_dentry, char *_new_name)
212 { 212 {
213 struct nw_modify_dos_info info; 213 struct nw_modify_dos_info info;
214 int res=0x90,res2; 214 int res=0x90,res2;
215 struct inode *old_inode = old_dentry->d_inode; 215 struct inode *old_inode = old_dentry->d_inode;
216 __le32 old_nwattr = NCP_FINFO(old_inode)->nwattr; 216 __le32 old_nwattr = NCP_FINFO(old_inode)->nwattr;
217 __le32 new_nwattr = 0; /* shut compiler warning */ 217 __le32 new_nwattr = 0; /* shut compiler warning */
218 int old_nwattr_changed = 0; 218 int old_nwattr_changed = 0;
219 int new_nwattr_changed = 0; 219 int new_nwattr_changed = 0;
220 220
221 memset(&info, 0, sizeof(info)); 221 memset(&info, 0, sizeof(info));
222 222
223 /* remove the Read-Only flag on the NW server */ 223 /* remove the Read-Only flag on the NW server */
224 224
225 info.attributes = old_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); 225 info.attributes = old_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
226 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info); 226 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
227 if (!res2) 227 if (!res2)
228 old_nwattr_changed = 1; 228 old_nwattr_changed = 1;
229 if (new_dentry && new_dentry->d_inode) { 229 if (new_dentry && new_dentry->d_inode) {
230 new_nwattr = NCP_FINFO(new_dentry->d_inode)->nwattr; 230 new_nwattr = NCP_FINFO(new_dentry->d_inode)->nwattr;
231 info.attributes = new_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); 231 info.attributes = new_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
232 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info); 232 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
233 if (!res2) 233 if (!res2)
234 new_nwattr_changed = 1; 234 new_nwattr_changed = 1;
235 } 235 }
236 /* now try again the rename operation */ 236 /* now try again the rename operation */
237 /* but only if something really happened */ 237 /* but only if something really happened */
238 if (new_nwattr_changed || old_nwattr_changed) { 238 if (new_nwattr_changed || old_nwattr_changed) {
239 res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir), 239 res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
240 old_dir, _old_name, 240 old_dir, _old_name,
241 new_dir, _new_name); 241 new_dir, _new_name);
242 } 242 }
243 if (res) 243 if (res)
244 goto leave_me; 244 goto leave_me;
245 /* file was successfully renamed, so: 245 /* file was successfully renamed, so:
246 do not set attributes on old file - it no longer exists 246 do not set attributes on old file - it no longer exists
247 copy attributes from old file to new */ 247 copy attributes from old file to new */
248 new_nwattr_changed = old_nwattr_changed; 248 new_nwattr_changed = old_nwattr_changed;
249 new_nwattr = old_nwattr; 249 new_nwattr = old_nwattr;
250 old_nwattr_changed = 0; 250 old_nwattr_changed = 0;
251 251
252 leave_me:; 252 leave_me:;
253 if (old_nwattr_changed) { 253 if (old_nwattr_changed) {
254 info.attributes = old_nwattr; 254 info.attributes = old_nwattr;
255 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info); 255 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
256 /* ignore errors */ 256 /* ignore errors */
257 } 257 }
258 if (new_nwattr_changed) { 258 if (new_nwattr_changed) {
259 info.attributes = new_nwattr; 259 info.attributes = new_nwattr;
260 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info); 260 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
261 /* ignore errors */ 261 /* ignore errors */
262 } 262 }
263 return(res); 263 return(res);
264 } 264 }
265 #endif /* CONFIG_NCPFS_STRONG */ 265 #endif /* CONFIG_NCPFS_STRONG */
266 266
267 267
268 static int 268 static int
269 __ncp_lookup_validate(struct dentry * dentry, struct nameidata *nd) 269 __ncp_lookup_validate(struct dentry * dentry, struct nameidata *nd)
270 { 270 {
271 struct ncp_server *server; 271 struct ncp_server *server;
272 struct dentry *parent; 272 struct dentry *parent;
273 struct inode *dir; 273 struct inode *dir;
274 struct ncp_entry_info finfo; 274 struct ncp_entry_info finfo;
275 int res, val = 0, len; 275 int res, val = 0, len;
276 __u8 __name[NCP_MAXPATHLEN + 1]; 276 __u8 __name[NCP_MAXPATHLEN + 1];
277 277
278 parent = dget_parent(dentry); 278 parent = dget_parent(dentry);
279 dir = parent->d_inode; 279 dir = parent->d_inode;
280 280
281 if (!dentry->d_inode) 281 if (!dentry->d_inode)
282 goto finished; 282 goto finished;
283 283
284 server = NCP_SERVER(dir); 284 server = NCP_SERVER(dir);
285 285
286 if (!ncp_conn_valid(server)) 286 if (!ncp_conn_valid(server))
287 goto finished; 287 goto finished;
288 288
289 /* 289 /*
290 * Inspired by smbfs: 290 * Inspired by smbfs:
291 * The default validation is based on dentry age: 291 * The default validation is based on dentry age:
292 * We set the max age at mount time. (But each 292 * We set the max age at mount time. (But each
293 * successful server lookup renews the timestamp.) 293 * successful server lookup renews the timestamp.)
294 */ 294 */
295 val = NCP_TEST_AGE(server, dentry); 295 val = NCP_TEST_AGE(server, dentry);
296 if (val) 296 if (val)
297 goto finished; 297 goto finished;
298 298
299 DDPRINTK("ncp_lookup_validate: %s/%s not valid, age=%ld, server lookup\n", 299 DDPRINTK("ncp_lookup_validate: %s/%s not valid, age=%ld, server lookup\n",
300 dentry->d_parent->d_name.name, dentry->d_name.name, 300 dentry->d_parent->d_name.name, dentry->d_name.name,
301 NCP_GET_AGE(dentry)); 301 NCP_GET_AGE(dentry));
302 302
303 len = sizeof(__name); 303 len = sizeof(__name);
304 if (ncp_is_server_root(dir)) { 304 if (ncp_is_server_root(dir)) {
305 res = ncp_io2vol(server, __name, &len, dentry->d_name.name, 305 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
306 dentry->d_name.len, 1); 306 dentry->d_name.len, 1);
307 if (!res) 307 if (!res)
308 res = ncp_lookup_volume(server, __name, &(finfo.i)); 308 res = ncp_lookup_volume(server, __name, &(finfo.i));
309 } else { 309 } else {
310 res = ncp_io2vol(server, __name, &len, dentry->d_name.name, 310 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
311 dentry->d_name.len, !ncp_preserve_case(dir)); 311 dentry->d_name.len, !ncp_preserve_case(dir));
312 if (!res) 312 if (!res)
313 res = ncp_obtain_info(server, dir, __name, &(finfo.i)); 313 res = ncp_obtain_info(server, dir, __name, &(finfo.i));
314 } 314 }
315 finfo.volume = finfo.i.volNumber; 315 finfo.volume = finfo.i.volNumber;
316 DDPRINTK("ncp_lookup_validate: looked for %s/%s, res=%d\n", 316 DDPRINTK("ncp_lookup_validate: looked for %s/%s, res=%d\n",
317 dentry->d_parent->d_name.name, __name, res); 317 dentry->d_parent->d_name.name, __name, res);
318 /* 318 /*
319 * If we didn't find it, or if it has a different dirEntNum to 319 * If we didn't find it, or if it has a different dirEntNum to
320 * what we remember, it's not valid any more. 320 * what we remember, it's not valid any more.
321 */ 321 */
322 if (!res) { 322 if (!res) {
323 if (finfo.i.dirEntNum == NCP_FINFO(dentry->d_inode)->dirEntNum) { 323 if (finfo.i.dirEntNum == NCP_FINFO(dentry->d_inode)->dirEntNum) {
324 ncp_new_dentry(dentry); 324 ncp_new_dentry(dentry);
325 val=1; 325 val=1;
326 } else 326 } else
327 DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n"); 327 DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");
328 328
329 ncp_update_inode2(dentry->d_inode, &finfo); 329 ncp_update_inode2(dentry->d_inode, &finfo);
330 } 330 }
331 331
332 finished: 332 finished:
333 DDPRINTK("ncp_lookup_validate: result=%d\n", val); 333 DDPRINTK("ncp_lookup_validate: result=%d\n", val);
334 dput(parent); 334 dput(parent);
335 return val; 335 return val;
336 } 336 }
337 337
338 static int 338 static int
339 ncp_lookup_validate(struct dentry * dentry, struct nameidata *nd) 339 ncp_lookup_validate(struct dentry * dentry, struct nameidata *nd)
340 { 340 {
341 int res; 341 int res;
342 lock_kernel(); 342 lock_kernel();
343 res = __ncp_lookup_validate(dentry, nd); 343 res = __ncp_lookup_validate(dentry, nd);
344 unlock_kernel(); 344 unlock_kernel();
345 return res; 345 return res;
346 } 346 }
347 347
348 static struct dentry * 348 static struct dentry *
349 ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos) 349 ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
350 { 350 {
351 struct dentry *dent = dentry; 351 struct dentry *dent = dentry;
352 struct list_head *next; 352 struct list_head *next;
353 353
354 if (d_validate(dent, parent)) { 354 if (d_validate(dent, parent)) {
355 if (dent->d_name.len <= NCP_MAXPATHLEN && 355 if (dent->d_name.len <= NCP_MAXPATHLEN &&
356 (unsigned long)dent->d_fsdata == fpos) { 356 (unsigned long)dent->d_fsdata == fpos) {
357 if (!dent->d_inode) { 357 if (!dent->d_inode) {
358 dput(dent); 358 dput(dent);
359 dent = NULL; 359 dent = NULL;
360 } 360 }
361 return dent; 361 return dent;
362 } 362 }
363 dput(dent); 363 dput(dent);
364 } 364 }
365 365
366 /* If a pointer is invalid, we search the dentry. */ 366 /* If a pointer is invalid, we search the dentry. */
367 spin_lock(&dcache_lock); 367 spin_lock(&dcache_lock);
368 next = parent->d_subdirs.next; 368 next = parent->d_subdirs.next;
369 while (next != &parent->d_subdirs) { 369 while (next != &parent->d_subdirs) {
370 dent = list_entry(next, struct dentry, d_u.d_child); 370 dent = list_entry(next, struct dentry, d_u.d_child);
371 if ((unsigned long)dent->d_fsdata == fpos) { 371 if ((unsigned long)dent->d_fsdata == fpos) {
372 if (dent->d_inode) 372 if (dent->d_inode)
373 dget_locked(dent); 373 dget_locked(dent);
374 else 374 else
375 dent = NULL; 375 dent = NULL;
376 spin_unlock(&dcache_lock); 376 spin_unlock(&dcache_lock);
377 goto out; 377 goto out;
378 } 378 }
379 next = next->next; 379 next = next->next;
380 } 380 }
381 spin_unlock(&dcache_lock); 381 spin_unlock(&dcache_lock);
382 return NULL; 382 return NULL;
383 383
384 out: 384 out:
385 return dent; 385 return dent;
386 } 386 }
387 387
388 static time_t ncp_obtain_mtime(struct dentry *dentry) 388 static time_t ncp_obtain_mtime(struct dentry *dentry)
389 { 389 {
390 struct inode *inode = dentry->d_inode; 390 struct inode *inode = dentry->d_inode;
391 struct ncp_server *server = NCP_SERVER(inode); 391 struct ncp_server *server = NCP_SERVER(inode);
392 struct nw_info_struct i; 392 struct nw_info_struct i;
393 393
394 if (!ncp_conn_valid(server) || ncp_is_server_root(inode)) 394 if (!ncp_conn_valid(server) || ncp_is_server_root(inode))
395 return 0; 395 return 0;
396 396
397 if (ncp_obtain_info(server, inode, NULL, &i)) 397 if (ncp_obtain_info(server, inode, NULL, &i))
398 return 0; 398 return 0;
399 399
400 return ncp_date_dos2unix(i.modifyTime, i.modifyDate); 400 return ncp_date_dos2unix(i.modifyTime, i.modifyDate);
401 } 401 }
402 402
403 static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir) 403 static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
404 { 404 {
405 struct dentry *dentry = filp->f_dentry; 405 struct dentry *dentry = filp->f_path.dentry;
406 struct inode *inode = dentry->d_inode; 406 struct inode *inode = dentry->d_inode;
407 struct page *page = NULL; 407 struct page *page = NULL;
408 struct ncp_server *server = NCP_SERVER(inode); 408 struct ncp_server *server = NCP_SERVER(inode);
409 union ncp_dir_cache *cache = NULL; 409 union ncp_dir_cache *cache = NULL;
410 struct ncp_cache_control ctl; 410 struct ncp_cache_control ctl;
411 int result, mtime_valid = 0; 411 int result, mtime_valid = 0;
412 time_t mtime = 0; 412 time_t mtime = 0;
413 413
414 lock_kernel(); 414 lock_kernel();
415 415
416 ctl.page = NULL; 416 ctl.page = NULL;
417 ctl.cache = NULL; 417 ctl.cache = NULL;
418 418
419 DDPRINTK("ncp_readdir: reading %s/%s, pos=%d\n", 419 DDPRINTK("ncp_readdir: reading %s/%s, pos=%d\n",
420 dentry->d_parent->d_name.name, dentry->d_name.name, 420 dentry->d_parent->d_name.name, dentry->d_name.name,
421 (int) filp->f_pos); 421 (int) filp->f_pos);
422 422
423 result = -EIO; 423 result = -EIO;
424 if (!ncp_conn_valid(server)) 424 if (!ncp_conn_valid(server))
425 goto out; 425 goto out;
426 426
427 result = 0; 427 result = 0;
428 if (filp->f_pos == 0) { 428 if (filp->f_pos == 0) {
429 if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR)) 429 if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR))
430 goto out; 430 goto out;
431 filp->f_pos = 1; 431 filp->f_pos = 1;
432 } 432 }
433 if (filp->f_pos == 1) { 433 if (filp->f_pos == 1) {
434 if (filldir(dirent, "..", 2, 1, parent_ino(dentry), DT_DIR)) 434 if (filldir(dirent, "..", 2, 1, parent_ino(dentry), DT_DIR))
435 goto out; 435 goto out;
436 filp->f_pos = 2; 436 filp->f_pos = 2;
437 } 437 }
438 438
439 page = grab_cache_page(&inode->i_data, 0); 439 page = grab_cache_page(&inode->i_data, 0);
440 if (!page) 440 if (!page)
441 goto read_really; 441 goto read_really;
442 442
443 ctl.cache = cache = kmap(page); 443 ctl.cache = cache = kmap(page);
444 ctl.head = cache->head; 444 ctl.head = cache->head;
445 445
446 if (!PageUptodate(page) || !ctl.head.eof) 446 if (!PageUptodate(page) || !ctl.head.eof)
447 goto init_cache; 447 goto init_cache;
448 448
449 if (filp->f_pos == 2) { 449 if (filp->f_pos == 2) {
450 if (jiffies - ctl.head.time >= NCP_MAX_AGE(server)) 450 if (jiffies - ctl.head.time >= NCP_MAX_AGE(server))
451 goto init_cache; 451 goto init_cache;
452 452
453 mtime = ncp_obtain_mtime(dentry); 453 mtime = ncp_obtain_mtime(dentry);
454 mtime_valid = 1; 454 mtime_valid = 1;
455 if ((!mtime) || (mtime != ctl.head.mtime)) 455 if ((!mtime) || (mtime != ctl.head.mtime))
456 goto init_cache; 456 goto init_cache;
457 } 457 }
458 458
459 if (filp->f_pos > ctl.head.end) 459 if (filp->f_pos > ctl.head.end)
460 goto finished; 460 goto finished;
461 461
462 ctl.fpos = filp->f_pos + (NCP_DIRCACHE_START - 2); 462 ctl.fpos = filp->f_pos + (NCP_DIRCACHE_START - 2);
463 ctl.ofs = ctl.fpos / NCP_DIRCACHE_SIZE; 463 ctl.ofs = ctl.fpos / NCP_DIRCACHE_SIZE;
464 ctl.idx = ctl.fpos % NCP_DIRCACHE_SIZE; 464 ctl.idx = ctl.fpos % NCP_DIRCACHE_SIZE;
465 465
466 for (;;) { 466 for (;;) {
467 if (ctl.ofs != 0) { 467 if (ctl.ofs != 0) {
468 ctl.page = find_lock_page(&inode->i_data, ctl.ofs); 468 ctl.page = find_lock_page(&inode->i_data, ctl.ofs);
469 if (!ctl.page) 469 if (!ctl.page)
470 goto invalid_cache; 470 goto invalid_cache;
471 ctl.cache = kmap(ctl.page); 471 ctl.cache = kmap(ctl.page);
472 if (!PageUptodate(ctl.page)) 472 if (!PageUptodate(ctl.page))
473 goto invalid_cache; 473 goto invalid_cache;
474 } 474 }
475 while (ctl.idx < NCP_DIRCACHE_SIZE) { 475 while (ctl.idx < NCP_DIRCACHE_SIZE) {
476 struct dentry *dent; 476 struct dentry *dent;
477 int res; 477 int res;
478 478
479 dent = ncp_dget_fpos(ctl.cache->dentry[ctl.idx], 479 dent = ncp_dget_fpos(ctl.cache->dentry[ctl.idx],
480 dentry, filp->f_pos); 480 dentry, filp->f_pos);
481 if (!dent) 481 if (!dent)
482 goto invalid_cache; 482 goto invalid_cache;
483 res = filldir(dirent, dent->d_name.name, 483 res = filldir(dirent, dent->d_name.name,
484 dent->d_name.len, filp->f_pos, 484 dent->d_name.len, filp->f_pos,
485 dent->d_inode->i_ino, DT_UNKNOWN); 485 dent->d_inode->i_ino, DT_UNKNOWN);
486 dput(dent); 486 dput(dent);
487 if (res) 487 if (res)
488 goto finished; 488 goto finished;
489 filp->f_pos += 1; 489 filp->f_pos += 1;
490 ctl.idx += 1; 490 ctl.idx += 1;
491 if (filp->f_pos > ctl.head.end) 491 if (filp->f_pos > ctl.head.end)
492 goto finished; 492 goto finished;
493 } 493 }
494 if (ctl.page) { 494 if (ctl.page) {
495 kunmap(ctl.page); 495 kunmap(ctl.page);
496 SetPageUptodate(ctl.page); 496 SetPageUptodate(ctl.page);
497 unlock_page(ctl.page); 497 unlock_page(ctl.page);
498 page_cache_release(ctl.page); 498 page_cache_release(ctl.page);
499 ctl.page = NULL; 499 ctl.page = NULL;
500 } 500 }
501 ctl.idx = 0; 501 ctl.idx = 0;
502 ctl.ofs += 1; 502 ctl.ofs += 1;
503 } 503 }
504 invalid_cache: 504 invalid_cache:
505 if (ctl.page) { 505 if (ctl.page) {
506 kunmap(ctl.page); 506 kunmap(ctl.page);
507 unlock_page(ctl.page); 507 unlock_page(ctl.page);
508 page_cache_release(ctl.page); 508 page_cache_release(ctl.page);
509 ctl.page = NULL; 509 ctl.page = NULL;
510 } 510 }
511 ctl.cache = cache; 511 ctl.cache = cache;
512 init_cache: 512 init_cache:
513 ncp_invalidate_dircache_entries(dentry); 513 ncp_invalidate_dircache_entries(dentry);
514 if (!mtime_valid) { 514 if (!mtime_valid) {
515 mtime = ncp_obtain_mtime(dentry); 515 mtime = ncp_obtain_mtime(dentry);
516 mtime_valid = 1; 516 mtime_valid = 1;
517 } 517 }
518 ctl.head.mtime = mtime; 518 ctl.head.mtime = mtime;
519 ctl.head.time = jiffies; 519 ctl.head.time = jiffies;
520 ctl.head.eof = 0; 520 ctl.head.eof = 0;
521 ctl.fpos = 2; 521 ctl.fpos = 2;
522 ctl.ofs = 0; 522 ctl.ofs = 0;
523 ctl.idx = NCP_DIRCACHE_START; 523 ctl.idx = NCP_DIRCACHE_START;
524 ctl.filled = 0; 524 ctl.filled = 0;
525 ctl.valid = 1; 525 ctl.valid = 1;
526 read_really: 526 read_really:
527 if (ncp_is_server_root(inode)) { 527 if (ncp_is_server_root(inode)) {
528 ncp_read_volume_list(filp, dirent, filldir, &ctl); 528 ncp_read_volume_list(filp, dirent, filldir, &ctl);
529 } else { 529 } else {
530 ncp_do_readdir(filp, dirent, filldir, &ctl); 530 ncp_do_readdir(filp, dirent, filldir, &ctl);
531 } 531 }
532 ctl.head.end = ctl.fpos - 1; 532 ctl.head.end = ctl.fpos - 1;
533 ctl.head.eof = ctl.valid; 533 ctl.head.eof = ctl.valid;
534 finished: 534 finished:
535 if (page) { 535 if (page) {
536 cache->head = ctl.head; 536 cache->head = ctl.head;
537 kunmap(page); 537 kunmap(page);
538 SetPageUptodate(page); 538 SetPageUptodate(page);
539 unlock_page(page); 539 unlock_page(page);
540 page_cache_release(page); 540 page_cache_release(page);
541 } 541 }
542 if (ctl.page) { 542 if (ctl.page) {
543 kunmap(ctl.page); 543 kunmap(ctl.page);
544 SetPageUptodate(ctl.page); 544 SetPageUptodate(ctl.page);
545 unlock_page(ctl.page); 545 unlock_page(ctl.page);
546 page_cache_release(ctl.page); 546 page_cache_release(ctl.page);
547 } 547 }
548 out: 548 out:
549 unlock_kernel(); 549 unlock_kernel();
550 return result; 550 return result;
551 } 551 }
552 552
553 static int 553 static int
554 ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, 554 ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
555 struct ncp_cache_control *ctrl, struct ncp_entry_info *entry) 555 struct ncp_cache_control *ctrl, struct ncp_entry_info *entry)
556 { 556 {
557 struct dentry *newdent, *dentry = filp->f_dentry; 557 struct dentry *newdent, *dentry = filp->f_path.dentry;
558 struct inode *newino, *inode = dentry->d_inode; 558 struct inode *newino, *inode = dentry->d_inode;
559 struct ncp_cache_control ctl = *ctrl; 559 struct ncp_cache_control ctl = *ctrl;
560 struct qstr qname; 560 struct qstr qname;
561 int valid = 0; 561 int valid = 0;
562 int hashed = 0; 562 int hashed = 0;
563 ino_t ino = 0; 563 ino_t ino = 0;
564 __u8 __name[NCP_MAXPATHLEN + 1]; 564 __u8 __name[NCP_MAXPATHLEN + 1];
565 565
566 qname.len = sizeof(__name); 566 qname.len = sizeof(__name);
567 if (ncp_vol2io(NCP_SERVER(inode), __name, &qname.len, 567 if (ncp_vol2io(NCP_SERVER(inode), __name, &qname.len,
568 entry->i.entryName, entry->i.nameLen, 568 entry->i.entryName, entry->i.nameLen,
569 !ncp_preserve_entry_case(inode, entry->i.NSCreator))) 569 !ncp_preserve_entry_case(inode, entry->i.NSCreator)))
570 return 1; /* I'm not sure */ 570 return 1; /* I'm not sure */
571 571
572 qname.name = __name; 572 qname.name = __name;
573 qname.hash = full_name_hash(qname.name, qname.len); 573 qname.hash = full_name_hash(qname.name, qname.len);
574 574
575 if (dentry->d_op && dentry->d_op->d_hash) 575 if (dentry->d_op && dentry->d_op->d_hash)
576 if (dentry->d_op->d_hash(dentry, &qname) != 0) 576 if (dentry->d_op->d_hash(dentry, &qname) != 0)
577 goto end_advance; 577 goto end_advance;
578 578
579 newdent = d_lookup(dentry, &qname); 579 newdent = d_lookup(dentry, &qname);
580 580
581 if (!newdent) { 581 if (!newdent) {
582 newdent = d_alloc(dentry, &qname); 582 newdent = d_alloc(dentry, &qname);
583 if (!newdent) 583 if (!newdent)
584 goto end_advance; 584 goto end_advance;
585 } else { 585 } else {
586 hashed = 1; 586 hashed = 1;
587 memcpy((char *) newdent->d_name.name, qname.name, 587 memcpy((char *) newdent->d_name.name, qname.name,
588 newdent->d_name.len); 588 newdent->d_name.len);
589 } 589 }
590 590
591 if (!newdent->d_inode) { 591 if (!newdent->d_inode) {
592 entry->opened = 0; 592 entry->opened = 0;
593 entry->ino = iunique(inode->i_sb, 2); 593 entry->ino = iunique(inode->i_sb, 2);
594 newino = ncp_iget(inode->i_sb, entry); 594 newino = ncp_iget(inode->i_sb, entry);
595 if (newino) { 595 if (newino) {
596 newdent->d_op = &ncp_dentry_operations; 596 newdent->d_op = &ncp_dentry_operations;
597 d_instantiate(newdent, newino); 597 d_instantiate(newdent, newino);
598 if (!hashed) 598 if (!hashed)
599 d_rehash(newdent); 599 d_rehash(newdent);
600 } 600 }
601 } else 601 } else
602 ncp_update_inode2(newdent->d_inode, entry); 602 ncp_update_inode2(newdent->d_inode, entry);
603 603
604 if (newdent->d_inode) { 604 if (newdent->d_inode) {
605 ino = newdent->d_inode->i_ino; 605 ino = newdent->d_inode->i_ino;
606 newdent->d_fsdata = (void *) ctl.fpos; 606 newdent->d_fsdata = (void *) ctl.fpos;
607 ncp_new_dentry(newdent); 607 ncp_new_dentry(newdent);
608 } 608 }
609 609
610 if (ctl.idx >= NCP_DIRCACHE_SIZE) { 610 if (ctl.idx >= NCP_DIRCACHE_SIZE) {
611 if (ctl.page) { 611 if (ctl.page) {
612 kunmap(ctl.page); 612 kunmap(ctl.page);
613 SetPageUptodate(ctl.page); 613 SetPageUptodate(ctl.page);
614 unlock_page(ctl.page); 614 unlock_page(ctl.page);
615 page_cache_release(ctl.page); 615 page_cache_release(ctl.page);
616 } 616 }
617 ctl.cache = NULL; 617 ctl.cache = NULL;
618 ctl.idx -= NCP_DIRCACHE_SIZE; 618 ctl.idx -= NCP_DIRCACHE_SIZE;
619 ctl.ofs += 1; 619 ctl.ofs += 1;
620 ctl.page = grab_cache_page(&inode->i_data, ctl.ofs); 620 ctl.page = grab_cache_page(&inode->i_data, ctl.ofs);
621 if (ctl.page) 621 if (ctl.page)
622 ctl.cache = kmap(ctl.page); 622 ctl.cache = kmap(ctl.page);
623 } 623 }
624 if (ctl.cache) { 624 if (ctl.cache) {
625 ctl.cache->dentry[ctl.idx] = newdent; 625 ctl.cache->dentry[ctl.idx] = newdent;
626 valid = 1; 626 valid = 1;
627 } 627 }
628 dput(newdent); 628 dput(newdent);
629 end_advance: 629 end_advance:
630 if (!valid) 630 if (!valid)
631 ctl.valid = 0; 631 ctl.valid = 0;
632 if (!ctl.filled && (ctl.fpos == filp->f_pos)) { 632 if (!ctl.filled && (ctl.fpos == filp->f_pos)) {
633 if (!ino) 633 if (!ino)
634 ino = find_inode_number(dentry, &qname); 634 ino = find_inode_number(dentry, &qname);
635 if (!ino) 635 if (!ino)
636 ino = iunique(inode->i_sb, 2); 636 ino = iunique(inode->i_sb, 2);
637 ctl.filled = filldir(dirent, qname.name, qname.len, 637 ctl.filled = filldir(dirent, qname.name, qname.len,
638 filp->f_pos, ino, DT_UNKNOWN); 638 filp->f_pos, ino, DT_UNKNOWN);
639 if (!ctl.filled) 639 if (!ctl.filled)
640 filp->f_pos += 1; 640 filp->f_pos += 1;
641 } 641 }
642 ctl.fpos += 1; 642 ctl.fpos += 1;
643 ctl.idx += 1; 643 ctl.idx += 1;
644 *ctrl = ctl; 644 *ctrl = ctl;
645 return (ctl.valid || !ctl.filled); 645 return (ctl.valid || !ctl.filled);
646 } 646 }
647 647
648 static void 648 static void
649 ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir, 649 ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir,
650 struct ncp_cache_control *ctl) 650 struct ncp_cache_control *ctl)
651 { 651 {
652 struct dentry *dentry = filp->f_dentry; 652 struct dentry *dentry = filp->f_path.dentry;
653 struct inode *inode = dentry->d_inode; 653 struct inode *inode = dentry->d_inode;
654 struct ncp_server *server = NCP_SERVER(inode); 654 struct ncp_server *server = NCP_SERVER(inode);
655 struct ncp_volume_info info; 655 struct ncp_volume_info info;
656 struct ncp_entry_info entry; 656 struct ncp_entry_info entry;
657 int i; 657 int i;
658 658
659 DPRINTK("ncp_read_volume_list: pos=%ld\n", 659 DPRINTK("ncp_read_volume_list: pos=%ld\n",
660 (unsigned long) filp->f_pos); 660 (unsigned long) filp->f_pos);
661 661
662 for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) { 662 for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) {
663 663
664 if (ncp_get_volume_info_with_number(server, i, &info) != 0) 664 if (ncp_get_volume_info_with_number(server, i, &info) != 0)
665 return; 665 return;
666 if (!strlen(info.volume_name)) 666 if (!strlen(info.volume_name))
667 continue; 667 continue;
668 668
669 DPRINTK("ncp_read_volume_list: found vol: %s\n", 669 DPRINTK("ncp_read_volume_list: found vol: %s\n",
670 info.volume_name); 670 info.volume_name);
671 671
672 if (ncp_lookup_volume(server, info.volume_name, 672 if (ncp_lookup_volume(server, info.volume_name,
673 &entry.i)) { 673 &entry.i)) {
674 DPRINTK("ncpfs: could not lookup vol %s\n", 674 DPRINTK("ncpfs: could not lookup vol %s\n",
675 info.volume_name); 675 info.volume_name);
676 continue; 676 continue;
677 } 677 }
678 entry.volume = entry.i.volNumber; 678 entry.volume = entry.i.volNumber;
679 if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry)) 679 if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))
680 return; 680 return;
681 } 681 }
682 } 682 }
683 683
684 static void 684 static void
685 ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir, 685 ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
686 struct ncp_cache_control *ctl) 686 struct ncp_cache_control *ctl)
687 { 687 {
688 struct dentry *dentry = filp->f_dentry; 688 struct dentry *dentry = filp->f_path.dentry;
689 struct inode *dir = dentry->d_inode; 689 struct inode *dir = dentry->d_inode;
690 struct ncp_server *server = NCP_SERVER(dir); 690 struct ncp_server *server = NCP_SERVER(dir);
691 struct nw_search_sequence seq; 691 struct nw_search_sequence seq;
692 struct ncp_entry_info entry; 692 struct ncp_entry_info entry;
693 int err; 693 int err;
694 void* buf; 694 void* buf;
695 int more; 695 int more;
696 size_t bufsize; 696 size_t bufsize;
697 697
698 DPRINTK("ncp_do_readdir: %s/%s, fpos=%ld\n", 698 DPRINTK("ncp_do_readdir: %s/%s, fpos=%ld\n",
699 dentry->d_parent->d_name.name, dentry->d_name.name, 699 dentry->d_parent->d_name.name, dentry->d_name.name,
700 (unsigned long) filp->f_pos); 700 (unsigned long) filp->f_pos);
701 PPRINTK("ncp_do_readdir: init %s, volnum=%d, dirent=%u\n", 701 PPRINTK("ncp_do_readdir: init %s, volnum=%d, dirent=%u\n",
702 dentry->d_name.name, NCP_FINFO(dir)->volNumber, 702 dentry->d_name.name, NCP_FINFO(dir)->volNumber,
703 NCP_FINFO(dir)->dirEntNum); 703 NCP_FINFO(dir)->dirEntNum);
704 704
705 err = ncp_initialize_search(server, dir, &seq); 705 err = ncp_initialize_search(server, dir, &seq);
706 if (err) { 706 if (err) {
707 DPRINTK("ncp_do_readdir: init failed, err=%d\n", err); 707 DPRINTK("ncp_do_readdir: init failed, err=%d\n", err);
708 return; 708 return;
709 } 709 }
710 /* We MUST NOT use server->buffer_size handshaked with server if we are 710 /* We MUST NOT use server->buffer_size handshaked with server if we are
711 using UDP, as for UDP server uses max. buffer size determined by 711 using UDP, as for UDP server uses max. buffer size determined by
712 MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes). 712 MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes).
713 So we use 128KB, just to be sure, as there is no way how to know 713 So we use 128KB, just to be sure, as there is no way how to know
714 this value in advance. */ 714 this value in advance. */
715 bufsize = 131072; 715 bufsize = 131072;
716 buf = vmalloc(bufsize); 716 buf = vmalloc(bufsize);
717 if (!buf) 717 if (!buf)
718 return; 718 return;
719 do { 719 do {
720 int cnt; 720 int cnt;
721 char* rpl; 721 char* rpl;
722 size_t rpls; 722 size_t rpls;
723 723
724 err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls); 724 err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls);
725 if (err) /* Error */ 725 if (err) /* Error */
726 break; 726 break;
727 if (!cnt) /* prevent endless loop */ 727 if (!cnt) /* prevent endless loop */
728 break; 728 break;
729 while (cnt--) { 729 while (cnt--) {
730 size_t onerpl; 730 size_t onerpl;
731 731
732 if (rpls < offsetof(struct nw_info_struct, entryName)) 732 if (rpls < offsetof(struct nw_info_struct, entryName))
733 break; /* short packet */ 733 break; /* short packet */
734 ncp_extract_file_info(rpl, &entry.i); 734 ncp_extract_file_info(rpl, &entry.i);
735 onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen; 735 onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen;
736 if (rpls < onerpl) 736 if (rpls < onerpl)
737 break; /* short packet */ 737 break; /* short packet */
738 (void)ncp_obtain_nfs_info(server, &entry.i); 738 (void)ncp_obtain_nfs_info(server, &entry.i);
739 rpl += onerpl; 739 rpl += onerpl;
740 rpls -= onerpl; 740 rpls -= onerpl;
741 entry.volume = entry.i.volNumber; 741 entry.volume = entry.i.volNumber;
742 if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry)) 742 if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))
743 break; 743 break;
744 } 744 }
745 } while (more); 745 } while (more);
746 vfree(buf); 746 vfree(buf);
747 return; 747 return;
748 } 748 }
749 749
750 int ncp_conn_logged_in(struct super_block *sb) 750 int ncp_conn_logged_in(struct super_block *sb)
751 { 751 {
752 struct ncp_server* server = NCP_SBP(sb); 752 struct ncp_server* server = NCP_SBP(sb);
753 int result; 753 int result;
754 754
755 if (ncp_single_volume(server)) { 755 if (ncp_single_volume(server)) {
756 int len; 756 int len;
757 struct dentry* dent; 757 struct dentry* dent;
758 __u32 volNumber; 758 __u32 volNumber;
759 __le32 dirEntNum; 759 __le32 dirEntNum;
760 __le32 DosDirNum; 760 __le32 DosDirNum;
761 __u8 __name[NCP_MAXPATHLEN + 1]; 761 __u8 __name[NCP_MAXPATHLEN + 1];
762 762
763 len = sizeof(__name); 763 len = sizeof(__name);
764 result = ncp_io2vol(server, __name, &len, server->m.mounted_vol, 764 result = ncp_io2vol(server, __name, &len, server->m.mounted_vol,
765 strlen(server->m.mounted_vol), 1); 765 strlen(server->m.mounted_vol), 1);
766 if (result) 766 if (result)
767 goto out; 767 goto out;
768 result = -ENOENT; 768 result = -ENOENT;
769 if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) { 769 if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) {
770 PPRINTK("ncp_conn_logged_in: %s not found\n", 770 PPRINTK("ncp_conn_logged_in: %s not found\n",
771 server->m.mounted_vol); 771 server->m.mounted_vol);
772 goto out; 772 goto out;
773 } 773 }
774 dent = sb->s_root; 774 dent = sb->s_root;
775 if (dent) { 775 if (dent) {
776 struct inode* ino = dent->d_inode; 776 struct inode* ino = dent->d_inode;
777 if (ino) { 777 if (ino) {
778 NCP_FINFO(ino)->volNumber = volNumber; 778 NCP_FINFO(ino)->volNumber = volNumber;
779 NCP_FINFO(ino)->dirEntNum = dirEntNum; 779 NCP_FINFO(ino)->dirEntNum = dirEntNum;
780 NCP_FINFO(ino)->DosDirNum = DosDirNum; 780 NCP_FINFO(ino)->DosDirNum = DosDirNum;
781 } else { 781 } else {
782 DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n"); 782 DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n");
783 } 783 }
784 } else { 784 } else {
785 DPRINTK("ncpfs: sb->s_root == NULL!\n"); 785 DPRINTK("ncpfs: sb->s_root == NULL!\n");
786 } 786 }
787 } 787 }
788 result = 0; 788 result = 0;
789 789
790 out: 790 out:
791 return result; 791 return result;
792 } 792 }
793 793
794 static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) 794 static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
795 { 795 {
796 struct ncp_server *server = NCP_SERVER(dir); 796 struct ncp_server *server = NCP_SERVER(dir);
797 struct inode *inode = NULL; 797 struct inode *inode = NULL;
798 struct ncp_entry_info finfo; 798 struct ncp_entry_info finfo;
799 int error, res, len; 799 int error, res, len;
800 __u8 __name[NCP_MAXPATHLEN + 1]; 800 __u8 __name[NCP_MAXPATHLEN + 1];
801 801
802 lock_kernel(); 802 lock_kernel();
803 error = -EIO; 803 error = -EIO;
804 if (!ncp_conn_valid(server)) 804 if (!ncp_conn_valid(server))
805 goto finished; 805 goto finished;
806 806
807 PPRINTK("ncp_lookup: server lookup for %s/%s\n", 807 PPRINTK("ncp_lookup: server lookup for %s/%s\n",
808 dentry->d_parent->d_name.name, dentry->d_name.name); 808 dentry->d_parent->d_name.name, dentry->d_name.name);
809 809
810 len = sizeof(__name); 810 len = sizeof(__name);
811 if (ncp_is_server_root(dir)) { 811 if (ncp_is_server_root(dir)) {
812 res = ncp_io2vol(server, __name, &len, dentry->d_name.name, 812 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
813 dentry->d_name.len, 1); 813 dentry->d_name.len, 1);
814 if (!res) 814 if (!res)
815 res = ncp_lookup_volume(server, __name, &(finfo.i)); 815 res = ncp_lookup_volume(server, __name, &(finfo.i));
816 } else { 816 } else {
817 res = ncp_io2vol(server, __name, &len, dentry->d_name.name, 817 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
818 dentry->d_name.len, !ncp_preserve_case(dir)); 818 dentry->d_name.len, !ncp_preserve_case(dir));
819 if (!res) 819 if (!res)
820 res = ncp_obtain_info(server, dir, __name, &(finfo.i)); 820 res = ncp_obtain_info(server, dir, __name, &(finfo.i));
821 } 821 }
822 PPRINTK("ncp_lookup: looked for %s/%s, res=%d\n", 822 PPRINTK("ncp_lookup: looked for %s/%s, res=%d\n",
823 dentry->d_parent->d_name.name, __name, res); 823 dentry->d_parent->d_name.name, __name, res);
824 /* 824 /*
825 * If we didn't find an entry, make a negative dentry. 825 * If we didn't find an entry, make a negative dentry.
826 */ 826 */
827 if (res) 827 if (res)
828 goto add_entry; 828 goto add_entry;
829 829
830 /* 830 /*
831 * Create an inode for the entry. 831 * Create an inode for the entry.
832 */ 832 */
833 finfo.opened = 0; 833 finfo.opened = 0;
834 finfo.ino = iunique(dir->i_sb, 2); 834 finfo.ino = iunique(dir->i_sb, 2);
835 finfo.volume = finfo.i.volNumber; 835 finfo.volume = finfo.i.volNumber;
836 error = -EACCES; 836 error = -EACCES;
837 inode = ncp_iget(dir->i_sb, &finfo); 837 inode = ncp_iget(dir->i_sb, &finfo);
838 838
839 if (inode) { 839 if (inode) {
840 ncp_new_dentry(dentry); 840 ncp_new_dentry(dentry);
841 add_entry: 841 add_entry:
842 dentry->d_op = &ncp_dentry_operations; 842 dentry->d_op = &ncp_dentry_operations;
843 d_add(dentry, inode); 843 d_add(dentry, inode);
844 error = 0; 844 error = 0;
845 } 845 }
846 846
847 finished: 847 finished:
848 PPRINTK("ncp_lookup: result=%d\n", error); 848 PPRINTK("ncp_lookup: result=%d\n", error);
849 unlock_kernel(); 849 unlock_kernel();
850 return ERR_PTR(error); 850 return ERR_PTR(error);
851 } 851 }
852 852
853 /* 853 /*
854 * This code is common to create, mkdir, and mknod. 854 * This code is common to create, mkdir, and mknod.
855 */ 855 */
856 static int ncp_instantiate(struct inode *dir, struct dentry *dentry, 856 static int ncp_instantiate(struct inode *dir, struct dentry *dentry,
857 struct ncp_entry_info *finfo) 857 struct ncp_entry_info *finfo)
858 { 858 {
859 struct inode *inode; 859 struct inode *inode;
860 int error = -EINVAL; 860 int error = -EINVAL;
861 861
862 finfo->ino = iunique(dir->i_sb, 2); 862 finfo->ino = iunique(dir->i_sb, 2);
863 inode = ncp_iget(dir->i_sb, finfo); 863 inode = ncp_iget(dir->i_sb, finfo);
864 if (!inode) 864 if (!inode)
865 goto out_close; 865 goto out_close;
866 d_instantiate(dentry,inode); 866 d_instantiate(dentry,inode);
867 error = 0; 867 error = 0;
868 out: 868 out:
869 return error; 869 return error;
870 870
871 out_close: 871 out_close:
872 PPRINTK("ncp_instantiate: %s/%s failed, closing file\n", 872 PPRINTK("ncp_instantiate: %s/%s failed, closing file\n",
873 dentry->d_parent->d_name.name, dentry->d_name.name); 873 dentry->d_parent->d_name.name, dentry->d_name.name);
874 ncp_close_file(NCP_SERVER(dir), finfo->file_handle); 874 ncp_close_file(NCP_SERVER(dir), finfo->file_handle);
875 goto out; 875 goto out;
876 } 876 }
877 877
878 int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode, 878 int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
879 dev_t rdev, __le32 attributes) 879 dev_t rdev, __le32 attributes)
880 { 880 {
881 struct ncp_server *server = NCP_SERVER(dir); 881 struct ncp_server *server = NCP_SERVER(dir);
882 struct ncp_entry_info finfo; 882 struct ncp_entry_info finfo;
883 int error, result, len; 883 int error, result, len;
884 int opmode; 884 int opmode;
885 __u8 __name[NCP_MAXPATHLEN + 1]; 885 __u8 __name[NCP_MAXPATHLEN + 1];
886 886
887 PPRINTK("ncp_create_new: creating %s/%s, mode=%x\n", 887 PPRINTK("ncp_create_new: creating %s/%s, mode=%x\n",
888 dentry->d_parent->d_name.name, dentry->d_name.name, mode); 888 dentry->d_parent->d_name.name, dentry->d_name.name, mode);
889 889
890 error = -EIO; 890 error = -EIO;
891 lock_kernel(); 891 lock_kernel();
892 if (!ncp_conn_valid(server)) 892 if (!ncp_conn_valid(server))
893 goto out; 893 goto out;
894 894
895 ncp_age_dentry(server, dentry); 895 ncp_age_dentry(server, dentry);
896 len = sizeof(__name); 896 len = sizeof(__name);
897 error = ncp_io2vol(server, __name, &len, dentry->d_name.name, 897 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
898 dentry->d_name.len, !ncp_preserve_case(dir)); 898 dentry->d_name.len, !ncp_preserve_case(dir));
899 if (error) 899 if (error)
900 goto out; 900 goto out;
901 901
902 error = -EACCES; 902 error = -EACCES;
903 903
904 if (S_ISREG(mode) && 904 if (S_ISREG(mode) &&
905 (server->m.flags & NCP_MOUNT_EXTRAS) && 905 (server->m.flags & NCP_MOUNT_EXTRAS) &&
906 (mode & S_IXUGO)) 906 (mode & S_IXUGO))
907 attributes |= aSYSTEM | aSHARED; 907 attributes |= aSYSTEM | aSHARED;
908 908
909 result = ncp_open_create_file_or_subdir(server, dir, __name, 909 result = ncp_open_create_file_or_subdir(server, dir, __name,
910 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE, 910 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
911 attributes, AR_READ | AR_WRITE, &finfo); 911 attributes, AR_READ | AR_WRITE, &finfo);
912 opmode = O_RDWR; 912 opmode = O_RDWR;
913 if (result) { 913 if (result) {
914 result = ncp_open_create_file_or_subdir(server, dir, __name, 914 result = ncp_open_create_file_or_subdir(server, dir, __name,
915 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE, 915 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
916 attributes, AR_WRITE, &finfo); 916 attributes, AR_WRITE, &finfo);
917 if (result) { 917 if (result) {
918 if (result == 0x87) 918 if (result == 0x87)
919 error = -ENAMETOOLONG; 919 error = -ENAMETOOLONG;
920 DPRINTK("ncp_create: %s/%s failed\n", 920 DPRINTK("ncp_create: %s/%s failed\n",
921 dentry->d_parent->d_name.name, dentry->d_name.name); 921 dentry->d_parent->d_name.name, dentry->d_name.name);
922 goto out; 922 goto out;
923 } 923 }
924 opmode = O_WRONLY; 924 opmode = O_WRONLY;
925 } 925 }
926 finfo.access = opmode; 926 finfo.access = opmode;
927 if (ncp_is_nfs_extras(server, finfo.volume)) { 927 if (ncp_is_nfs_extras(server, finfo.volume)) {
928 finfo.i.nfs.mode = mode; 928 finfo.i.nfs.mode = mode;
929 finfo.i.nfs.rdev = new_encode_dev(rdev); 929 finfo.i.nfs.rdev = new_encode_dev(rdev);
930 if (ncp_modify_nfs_info(server, finfo.volume, 930 if (ncp_modify_nfs_info(server, finfo.volume,
931 finfo.i.dirEntNum, 931 finfo.i.dirEntNum,
932 mode, new_encode_dev(rdev)) != 0) 932 mode, new_encode_dev(rdev)) != 0)
933 goto out; 933 goto out;
934 } 934 }
935 935
936 error = ncp_instantiate(dir, dentry, &finfo); 936 error = ncp_instantiate(dir, dentry, &finfo);
937 out: 937 out:
938 unlock_kernel(); 938 unlock_kernel();
939 return error; 939 return error;
940 } 940 }
941 941
942 static int ncp_create(struct inode *dir, struct dentry *dentry, int mode, 942 static int ncp_create(struct inode *dir, struct dentry *dentry, int mode,
943 struct nameidata *nd) 943 struct nameidata *nd)
944 { 944 {
945 return ncp_create_new(dir, dentry, mode, 0, 0); 945 return ncp_create_new(dir, dentry, mode, 0, 0);
946 } 946 }
947 947
948 static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode) 948 static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode)
949 { 949 {
950 struct ncp_entry_info finfo; 950 struct ncp_entry_info finfo;
951 struct ncp_server *server = NCP_SERVER(dir); 951 struct ncp_server *server = NCP_SERVER(dir);
952 int error, len; 952 int error, len;
953 __u8 __name[NCP_MAXPATHLEN + 1]; 953 __u8 __name[NCP_MAXPATHLEN + 1];
954 954
955 DPRINTK("ncp_mkdir: making %s/%s\n", 955 DPRINTK("ncp_mkdir: making %s/%s\n",
956 dentry->d_parent->d_name.name, dentry->d_name.name); 956 dentry->d_parent->d_name.name, dentry->d_name.name);
957 957
958 error = -EIO; 958 error = -EIO;
959 lock_kernel(); 959 lock_kernel();
960 if (!ncp_conn_valid(server)) 960 if (!ncp_conn_valid(server))
961 goto out; 961 goto out;
962 962
963 ncp_age_dentry(server, dentry); 963 ncp_age_dentry(server, dentry);
964 len = sizeof(__name); 964 len = sizeof(__name);
965 error = ncp_io2vol(server, __name, &len, dentry->d_name.name, 965 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
966 dentry->d_name.len, !ncp_preserve_case(dir)); 966 dentry->d_name.len, !ncp_preserve_case(dir));
967 if (error) 967 if (error)
968 goto out; 968 goto out;
969 969
970 error = -EACCES; 970 error = -EACCES;
971 if (ncp_open_create_file_or_subdir(server, dir, __name, 971 if (ncp_open_create_file_or_subdir(server, dir, __name,
972 OC_MODE_CREATE, aDIR, 972 OC_MODE_CREATE, aDIR,
973 cpu_to_le16(0xffff), 973 cpu_to_le16(0xffff),
974 &finfo) == 0) 974 &finfo) == 0)
975 { 975 {
976 if (ncp_is_nfs_extras(server, finfo.volume)) { 976 if (ncp_is_nfs_extras(server, finfo.volume)) {
977 mode |= S_IFDIR; 977 mode |= S_IFDIR;
978 finfo.i.nfs.mode = mode; 978 finfo.i.nfs.mode = mode;
979 if (ncp_modify_nfs_info(server, 979 if (ncp_modify_nfs_info(server,
980 finfo.volume, 980 finfo.volume,
981 finfo.i.dirEntNum, 981 finfo.i.dirEntNum,
982 mode, 0) != 0) 982 mode, 0) != 0)
983 goto out; 983 goto out;
984 } 984 }
985 error = ncp_instantiate(dir, dentry, &finfo); 985 error = ncp_instantiate(dir, dentry, &finfo);
986 } 986 }
987 out: 987 out:
988 unlock_kernel(); 988 unlock_kernel();
989 return error; 989 return error;
990 } 990 }
991 991
992 static int ncp_rmdir(struct inode *dir, struct dentry *dentry) 992 static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
993 { 993 {
994 struct ncp_server *server = NCP_SERVER(dir); 994 struct ncp_server *server = NCP_SERVER(dir);
995 int error, result, len; 995 int error, result, len;
996 __u8 __name[NCP_MAXPATHLEN + 1]; 996 __u8 __name[NCP_MAXPATHLEN + 1];
997 997
998 DPRINTK("ncp_rmdir: removing %s/%s\n", 998 DPRINTK("ncp_rmdir: removing %s/%s\n",
999 dentry->d_parent->d_name.name, dentry->d_name.name); 999 dentry->d_parent->d_name.name, dentry->d_name.name);
1000 1000
1001 error = -EIO; 1001 error = -EIO;
1002 lock_kernel(); 1002 lock_kernel();
1003 if (!ncp_conn_valid(server)) 1003 if (!ncp_conn_valid(server))
1004 goto out; 1004 goto out;
1005 1005
1006 error = -EBUSY; 1006 error = -EBUSY;
1007 if (!d_unhashed(dentry)) 1007 if (!d_unhashed(dentry))
1008 goto out; 1008 goto out;
1009 1009
1010 len = sizeof(__name); 1010 len = sizeof(__name);
1011 error = ncp_io2vol(server, __name, &len, dentry->d_name.name, 1011 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
1012 dentry->d_name.len, !ncp_preserve_case(dir)); 1012 dentry->d_name.len, !ncp_preserve_case(dir));
1013 if (error) 1013 if (error)
1014 goto out; 1014 goto out;
1015 1015
1016 result = ncp_del_file_or_subdir(server, dir, __name); 1016 result = ncp_del_file_or_subdir(server, dir, __name);
1017 switch (result) { 1017 switch (result) {
1018 case 0x00: 1018 case 0x00:
1019 error = 0; 1019 error = 0;
1020 break; 1020 break;
1021 case 0x85: /* unauthorized to delete file */ 1021 case 0x85: /* unauthorized to delete file */
1022 case 0x8A: /* unauthorized to delete file */ 1022 case 0x8A: /* unauthorized to delete file */
1023 error = -EACCES; 1023 error = -EACCES;
1024 break; 1024 break;
1025 case 0x8F: 1025 case 0x8F:
1026 case 0x90: /* read only */ 1026 case 0x90: /* read only */
1027 error = -EPERM; 1027 error = -EPERM;
1028 break; 1028 break;
1029 case 0x9F: /* in use by another client */ 1029 case 0x9F: /* in use by another client */
1030 error = -EBUSY; 1030 error = -EBUSY;
1031 break; 1031 break;
1032 case 0xA0: /* directory not empty */ 1032 case 0xA0: /* directory not empty */
1033 error = -ENOTEMPTY; 1033 error = -ENOTEMPTY;
1034 break; 1034 break;
1035 case 0xFF: /* someone deleted file */ 1035 case 0xFF: /* someone deleted file */
1036 error = -ENOENT; 1036 error = -ENOENT;
1037 break; 1037 break;
1038 default: 1038 default:
1039 error = -EACCES; 1039 error = -EACCES;
1040 break; 1040 break;
1041 } 1041 }
1042 out: 1042 out:
1043 unlock_kernel(); 1043 unlock_kernel();
1044 return error; 1044 return error;
1045 } 1045 }
1046 1046
1047 static int ncp_unlink(struct inode *dir, struct dentry *dentry) 1047 static int ncp_unlink(struct inode *dir, struct dentry *dentry)
1048 { 1048 {
1049 struct inode *inode = dentry->d_inode; 1049 struct inode *inode = dentry->d_inode;
1050 struct ncp_server *server; 1050 struct ncp_server *server;
1051 int error; 1051 int error;
1052 1052
1053 lock_kernel(); 1053 lock_kernel();
1054 server = NCP_SERVER(dir); 1054 server = NCP_SERVER(dir);
1055 DPRINTK("ncp_unlink: unlinking %s/%s\n", 1055 DPRINTK("ncp_unlink: unlinking %s/%s\n",
1056 dentry->d_parent->d_name.name, dentry->d_name.name); 1056 dentry->d_parent->d_name.name, dentry->d_name.name);
1057 1057
1058 error = -EIO; 1058 error = -EIO;
1059 if (!ncp_conn_valid(server)) 1059 if (!ncp_conn_valid(server))
1060 goto out; 1060 goto out;
1061 1061
1062 /* 1062 /*
1063 * Check whether to close the file ... 1063 * Check whether to close the file ...
1064 */ 1064 */
1065 if (inode) { 1065 if (inode) {
1066 PPRINTK("ncp_unlink: closing file\n"); 1066 PPRINTK("ncp_unlink: closing file\n");
1067 ncp_make_closed(inode); 1067 ncp_make_closed(inode);
1068 } 1068 }
1069 1069
1070 error = ncp_del_file_or_subdir2(server, dentry); 1070 error = ncp_del_file_or_subdir2(server, dentry);
1071 #ifdef CONFIG_NCPFS_STRONG 1071 #ifdef CONFIG_NCPFS_STRONG
1072 /* 9C is Invalid path.. It should be 8F, 90 - read only, but 1072 /* 9C is Invalid path.. It should be 8F, 90 - read only, but
1073 it is not :-( */ 1073 it is not :-( */
1074 if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */ 1074 if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */
1075 error = ncp_force_unlink(dir, dentry); 1075 error = ncp_force_unlink(dir, dentry);
1076 } 1076 }
1077 #endif 1077 #endif
1078 switch (error) { 1078 switch (error) {
1079 case 0x00: 1079 case 0x00:
1080 DPRINTK("ncp: removed %s/%s\n", 1080 DPRINTK("ncp: removed %s/%s\n",
1081 dentry->d_parent->d_name.name, dentry->d_name.name); 1081 dentry->d_parent->d_name.name, dentry->d_name.name);
1082 break; 1082 break;
1083 case 0x85: 1083 case 0x85:
1084 case 0x8A: 1084 case 0x8A:
1085 error = -EACCES; 1085 error = -EACCES;
1086 break; 1086 break;
1087 case 0x8D: /* some files in use */ 1087 case 0x8D: /* some files in use */
1088 case 0x8E: /* all files in use */ 1088 case 0x8E: /* all files in use */
1089 error = -EBUSY; 1089 error = -EBUSY;
1090 break; 1090 break;
1091 case 0x8F: /* some read only */ 1091 case 0x8F: /* some read only */
1092 case 0x90: /* all read only */ 1092 case 0x90: /* all read only */
1093 case 0x9C: /* !!! returned when in-use or read-only by NW4 */ 1093 case 0x9C: /* !!! returned when in-use or read-only by NW4 */
1094 error = -EPERM; 1094 error = -EPERM;
1095 break; 1095 break;
1096 case 0xFF: 1096 case 0xFF:
1097 error = -ENOENT; 1097 error = -ENOENT;
1098 break; 1098 break;
1099 default: 1099 default:
1100 error = -EACCES; 1100 error = -EACCES;
1101 break; 1101 break;
1102 } 1102 }
1103 1103
1104 out: 1104 out:
1105 unlock_kernel(); 1105 unlock_kernel();
1106 return error; 1106 return error;
1107 } 1107 }
1108 1108
1109 static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry, 1109 static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
1110 struct inode *new_dir, struct dentry *new_dentry) 1110 struct inode *new_dir, struct dentry *new_dentry)
1111 { 1111 {
1112 struct ncp_server *server = NCP_SERVER(old_dir); 1112 struct ncp_server *server = NCP_SERVER(old_dir);
1113 int error; 1113 int error;
1114 int old_len, new_len; 1114 int old_len, new_len;
1115 __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1]; 1115 __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1];
1116 1116
1117 DPRINTK("ncp_rename: %s/%s to %s/%s\n", 1117 DPRINTK("ncp_rename: %s/%s to %s/%s\n",
1118 old_dentry->d_parent->d_name.name, old_dentry->d_name.name, 1118 old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
1119 new_dentry->d_parent->d_name.name, new_dentry->d_name.name); 1119 new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
1120 1120
1121 error = -EIO; 1121 error = -EIO;
1122 lock_kernel(); 1122 lock_kernel();
1123 if (!ncp_conn_valid(server)) 1123 if (!ncp_conn_valid(server))
1124 goto out; 1124 goto out;
1125 1125
1126 ncp_age_dentry(server, old_dentry); 1126 ncp_age_dentry(server, old_dentry);
1127 ncp_age_dentry(server, new_dentry); 1127 ncp_age_dentry(server, new_dentry);
1128 1128
1129 old_len = sizeof(__old_name); 1129 old_len = sizeof(__old_name);
1130 error = ncp_io2vol(server, __old_name, &old_len, 1130 error = ncp_io2vol(server, __old_name, &old_len,
1131 old_dentry->d_name.name, old_dentry->d_name.len, 1131 old_dentry->d_name.name, old_dentry->d_name.len,
1132 !ncp_preserve_case(old_dir)); 1132 !ncp_preserve_case(old_dir));
1133 if (error) 1133 if (error)
1134 goto out; 1134 goto out;
1135 1135
1136 new_len = sizeof(__new_name); 1136 new_len = sizeof(__new_name);
1137 error = ncp_io2vol(server, __new_name, &new_len, 1137 error = ncp_io2vol(server, __new_name, &new_len,
1138 new_dentry->d_name.name, new_dentry->d_name.len, 1138 new_dentry->d_name.name, new_dentry->d_name.len,
1139 !ncp_preserve_case(new_dir)); 1139 !ncp_preserve_case(new_dir));
1140 if (error) 1140 if (error)
1141 goto out; 1141 goto out;
1142 1142
1143 error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name, 1143 error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name,
1144 new_dir, __new_name); 1144 new_dir, __new_name);
1145 #ifdef CONFIG_NCPFS_STRONG 1145 #ifdef CONFIG_NCPFS_STRONG
1146 if ((error == 0x90 || error == 0x8B || error == -EACCES) && 1146 if ((error == 0x90 || error == 0x8B || error == -EACCES) &&
1147 server->m.flags & NCP_MOUNT_STRONG) { /* RO */ 1147 server->m.flags & NCP_MOUNT_STRONG) { /* RO */
1148 error = ncp_force_rename(old_dir, old_dentry, __old_name, 1148 error = ncp_force_rename(old_dir, old_dentry, __old_name,
1149 new_dir, new_dentry, __new_name); 1149 new_dir, new_dentry, __new_name);
1150 } 1150 }
1151 #endif 1151 #endif
1152 switch (error) { 1152 switch (error) {
1153 case 0x00: 1153 case 0x00:
1154 DPRINTK("ncp renamed %s -> %s.\n", 1154 DPRINTK("ncp renamed %s -> %s.\n",
1155 old_dentry->d_name.name,new_dentry->d_name.name); 1155 old_dentry->d_name.name,new_dentry->d_name.name);
1156 break; 1156 break;
1157 case 0x9E: 1157 case 0x9E:
1158 error = -ENAMETOOLONG; 1158 error = -ENAMETOOLONG;
1159 break; 1159 break;
1160 case 0xFF: 1160 case 0xFF:
1161 error = -ENOENT; 1161 error = -ENOENT;
1162 break; 1162 break;
1163 default: 1163 default:
1164 error = -EACCES; 1164 error = -EACCES;
1165 break; 1165 break;
1166 } 1166 }
1167 out: 1167 out:
1168 unlock_kernel(); 1168 unlock_kernel();
1169 return error; 1169 return error;
1170 } 1170 }
1171 1171
1172 static int ncp_mknod(struct inode * dir, struct dentry *dentry, 1172 static int ncp_mknod(struct inode * dir, struct dentry *dentry,
1173 int mode, dev_t rdev) 1173 int mode, dev_t rdev)
1174 { 1174 {
1175 if (!new_valid_dev(rdev)) 1175 if (!new_valid_dev(rdev))
1176 return -EINVAL; 1176 return -EINVAL;
1177 if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) { 1177 if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) {
1178 DPRINTK(KERN_DEBUG "ncp_mknod: mode = 0%o\n", mode); 1178 DPRINTK(KERN_DEBUG "ncp_mknod: mode = 0%o\n", mode);
1179 return ncp_create_new(dir, dentry, mode, rdev, 0); 1179 return ncp_create_new(dir, dentry, mode, rdev, 0);
1180 } 1180 }
1181 return -EPERM; /* Strange, but true */ 1181 return -EPERM; /* Strange, but true */
1182 } 1182 }
1183 1183
1184 /* The following routines are taken directly from msdos-fs */ 1184 /* The following routines are taken directly from msdos-fs */
1185 1185
1186 /* Linear day numbers of the respective 1sts in non-leap years. */ 1186 /* Linear day numbers of the respective 1sts in non-leap years. */
1187 1187
1188 static int day_n[] = 1188 static int day_n[] =
1189 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0}; 1189 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
1190 /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */ 1190 /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
1191 1191
1192 1192
1193 extern struct timezone sys_tz; 1193 extern struct timezone sys_tz;
1194 1194
1195 static int utc2local(int time) 1195 static int utc2local(int time)
1196 { 1196 {
1197 return time - sys_tz.tz_minuteswest * 60; 1197 return time - sys_tz.tz_minuteswest * 60;
1198 } 1198 }
1199 1199
1200 static int local2utc(int time) 1200 static int local2utc(int time)
1201 { 1201 {
1202 return time + sys_tz.tz_minuteswest * 60; 1202 return time + sys_tz.tz_minuteswest * 60;
1203 } 1203 }
1204 1204
1205 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */ 1205 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
1206 int 1206 int
1207 ncp_date_dos2unix(__le16 t, __le16 d) 1207 ncp_date_dos2unix(__le16 t, __le16 d)
1208 { 1208 {
1209 unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d); 1209 unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d);
1210 int month, year, secs; 1210 int month, year, secs;
1211 1211
1212 /* first subtract and mask after that... Otherwise, if 1212 /* first subtract and mask after that... Otherwise, if
1213 date == 0, bad things happen */ 1213 date == 0, bad things happen */
1214 month = ((date >> 5) - 1) & 15; 1214 month = ((date >> 5) - 1) & 15;
1215 year = date >> 9; 1215 year = date >> 9;
1216 secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 + 1216 secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
1217 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) + 1217 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) +
1218 year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653); 1218 year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653);
1219 /* days since 1.1.70 plus 80's leap day */ 1219 /* days since 1.1.70 plus 80's leap day */
1220 return local2utc(secs); 1220 return local2utc(secs);
1221 } 1221 }
1222 1222
1223 1223
1224 /* Convert linear UNIX date to a MS-DOS time/date pair. */ 1224 /* Convert linear UNIX date to a MS-DOS time/date pair. */
1225 void 1225 void
1226 ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date) 1226 ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
1227 { 1227 {
1228 int day, year, nl_day, month; 1228 int day, year, nl_day, month;
1229 1229
1230 unix_date = utc2local(unix_date); 1230 unix_date = utc2local(unix_date);
1231 *time = cpu_to_le16( 1231 *time = cpu_to_le16(
1232 (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) + 1232 (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
1233 (((unix_date / 3600) % 24) << 11)); 1233 (((unix_date / 3600) % 24) << 11));
1234 day = unix_date / 86400 - 3652; 1234 day = unix_date / 86400 - 3652;
1235 year = day / 365; 1235 year = day / 365;
1236 if ((year + 3) / 4 + 365 * year > day) 1236 if ((year + 3) / 4 + 365 * year > day)
1237 year--; 1237 year--;
1238 day -= (year + 3) / 4 + 365 * year; 1238 day -= (year + 3) / 4 + 365 * year;
1239 if (day == 59 && !(year & 3)) { 1239 if (day == 59 && !(year & 3)) {
1240 nl_day = day; 1240 nl_day = day;
1241 month = 2; 1241 month = 2;
1242 } else { 1242 } else {
1243 nl_day = (year & 3) || day <= 59 ? day : day - 1; 1243 nl_day = (year & 3) || day <= 59 ? day : day - 1;
1244 for (month = 0; month < 12; month++) 1244 for (month = 0; month < 12; month++)
1245 if (day_n[month] > nl_day) 1245 if (day_n[month] > nl_day)
1246 break; 1246 break;
1247 } 1247 }
1248 *date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9)); 1248 *date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));
1249 } 1249 }
1250 1250
1 /* 1 /*
2 * file.c 2 * file.c
3 * 3 *
4 * Copyright (C) 1995, 1996 by Volker Lendecke 4 * Copyright (C) 1995, 1996 by Volker Lendecke
5 * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache 5 * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
6 * 6 *
7 */ 7 */
8 8
9 #include <asm/uaccess.h> 9 #include <asm/uaccess.h>
10 #include <asm/system.h> 10 #include <asm/system.h>
11 11
12 #include <linux/time.h> 12 #include <linux/time.h>
13 #include <linux/kernel.h> 13 #include <linux/kernel.h>
14 #include <linux/errno.h> 14 #include <linux/errno.h>
15 #include <linux/fcntl.h> 15 #include <linux/fcntl.h>
16 #include <linux/stat.h> 16 #include <linux/stat.h>
17 #include <linux/mm.h> 17 #include <linux/mm.h>
18 #include <linux/slab.h> 18 #include <linux/slab.h>
19 #include <linux/vmalloc.h> 19 #include <linux/vmalloc.h>
20 #include <linux/smp_lock.h> 20 #include <linux/smp_lock.h>
21 21
22 #include <linux/ncp_fs.h> 22 #include <linux/ncp_fs.h>
23 #include "ncplib_kernel.h" 23 #include "ncplib_kernel.h"
24 24
25 static int ncp_fsync(struct file *file, struct dentry *dentry, int datasync) 25 static int ncp_fsync(struct file *file, struct dentry *dentry, int datasync)
26 { 26 {
27 return 0; 27 return 0;
28 } 28 }
29 29
30 /* 30 /*
31 * Open a file with the specified read/write mode. 31 * Open a file with the specified read/write mode.
32 */ 32 */
33 int ncp_make_open(struct inode *inode, int right) 33 int ncp_make_open(struct inode *inode, int right)
34 { 34 {
35 int error; 35 int error;
36 int access; 36 int access;
37 37
38 error = -EINVAL; 38 error = -EINVAL;
39 if (!inode) { 39 if (!inode) {
40 printk(KERN_ERR "ncp_make_open: got NULL inode\n"); 40 printk(KERN_ERR "ncp_make_open: got NULL inode\n");
41 goto out; 41 goto out;
42 } 42 }
43 43
44 DPRINTK("ncp_make_open: opened=%d, volume # %u, dir entry # %u\n", 44 DPRINTK("ncp_make_open: opened=%d, volume # %u, dir entry # %u\n",
45 atomic_read(&NCP_FINFO(inode)->opened), 45 atomic_read(&NCP_FINFO(inode)->opened),
46 NCP_FINFO(inode)->volNumber, 46 NCP_FINFO(inode)->volNumber,
47 NCP_FINFO(inode)->dirEntNum); 47 NCP_FINFO(inode)->dirEntNum);
48 error = -EACCES; 48 error = -EACCES;
49 mutex_lock(&NCP_FINFO(inode)->open_mutex); 49 mutex_lock(&NCP_FINFO(inode)->open_mutex);
50 if (!atomic_read(&NCP_FINFO(inode)->opened)) { 50 if (!atomic_read(&NCP_FINFO(inode)->opened)) {
51 struct ncp_entry_info finfo; 51 struct ncp_entry_info finfo;
52 int result; 52 int result;
53 53
54 /* tries max. rights */ 54 /* tries max. rights */
55 finfo.access = O_RDWR; 55 finfo.access = O_RDWR;
56 result = ncp_open_create_file_or_subdir(NCP_SERVER(inode), 56 result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
57 inode, NULL, OC_MODE_OPEN, 57 inode, NULL, OC_MODE_OPEN,
58 0, AR_READ | AR_WRITE, &finfo); 58 0, AR_READ | AR_WRITE, &finfo);
59 if (!result) 59 if (!result)
60 goto update; 60 goto update;
61 /* RDWR did not succeeded, try readonly or writeonly as requested */ 61 /* RDWR did not succeeded, try readonly or writeonly as requested */
62 switch (right) { 62 switch (right) {
63 case O_RDONLY: 63 case O_RDONLY:
64 finfo.access = O_RDONLY; 64 finfo.access = O_RDONLY;
65 result = ncp_open_create_file_or_subdir(NCP_SERVER(inode), 65 result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
66 inode, NULL, OC_MODE_OPEN, 66 inode, NULL, OC_MODE_OPEN,
67 0, AR_READ, &finfo); 67 0, AR_READ, &finfo);
68 break; 68 break;
69 case O_WRONLY: 69 case O_WRONLY:
70 finfo.access = O_WRONLY; 70 finfo.access = O_WRONLY;
71 result = ncp_open_create_file_or_subdir(NCP_SERVER(inode), 71 result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
72 inode, NULL, OC_MODE_OPEN, 72 inode, NULL, OC_MODE_OPEN,
73 0, AR_WRITE, &finfo); 73 0, AR_WRITE, &finfo);
74 break; 74 break;
75 } 75 }
76 if (result) { 76 if (result) {
77 PPRINTK("ncp_make_open: failed, result=%d\n", result); 77 PPRINTK("ncp_make_open: failed, result=%d\n", result);
78 goto out_unlock; 78 goto out_unlock;
79 } 79 }
80 /* 80 /*
81 * Update the inode information. 81 * Update the inode information.
82 */ 82 */
83 update: 83 update:
84 ncp_update_inode(inode, &finfo); 84 ncp_update_inode(inode, &finfo);
85 atomic_set(&NCP_FINFO(inode)->opened, 1); 85 atomic_set(&NCP_FINFO(inode)->opened, 1);
86 } 86 }
87 87
88 access = NCP_FINFO(inode)->access; 88 access = NCP_FINFO(inode)->access;
89 PPRINTK("ncp_make_open: file open, access=%x\n", access); 89 PPRINTK("ncp_make_open: file open, access=%x\n", access);
90 if (access == right || access == O_RDWR) { 90 if (access == right || access == O_RDWR) {
91 atomic_inc(&NCP_FINFO(inode)->opened); 91 atomic_inc(&NCP_FINFO(inode)->opened);
92 error = 0; 92 error = 0;
93 } 93 }
94 94
95 out_unlock: 95 out_unlock:
96 mutex_unlock(&NCP_FINFO(inode)->open_mutex); 96 mutex_unlock(&NCP_FINFO(inode)->open_mutex);
97 out: 97 out:
98 return error; 98 return error;
99 } 99 }
100 100
101 static ssize_t 101 static ssize_t
102 ncp_file_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) 102 ncp_file_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
103 { 103 {
104 struct dentry *dentry = file->f_dentry; 104 struct dentry *dentry = file->f_path.dentry;
105 struct inode *inode = dentry->d_inode; 105 struct inode *inode = dentry->d_inode;
106 size_t already_read = 0; 106 size_t already_read = 0;
107 off_t pos; 107 off_t pos;
108 size_t bufsize; 108 size_t bufsize;
109 int error; 109 int error;
110 void* freepage; 110 void* freepage;
111 size_t freelen; 111 size_t freelen;
112 112
113 DPRINTK("ncp_file_read: enter %s/%s\n", 113 DPRINTK("ncp_file_read: enter %s/%s\n",
114 dentry->d_parent->d_name.name, dentry->d_name.name); 114 dentry->d_parent->d_name.name, dentry->d_name.name);
115 115
116 if (!ncp_conn_valid(NCP_SERVER(inode))) 116 if (!ncp_conn_valid(NCP_SERVER(inode)))
117 return -EIO; 117 return -EIO;
118 118
119 pos = *ppos; 119 pos = *ppos;
120 120
121 if ((ssize_t) count < 0) { 121 if ((ssize_t) count < 0) {
122 return -EINVAL; 122 return -EINVAL;
123 } 123 }
124 if (!count) 124 if (!count)
125 return 0; 125 return 0;
126 if (pos > inode->i_sb->s_maxbytes) 126 if (pos > inode->i_sb->s_maxbytes)
127 return 0; 127 return 0;
128 if (pos + count > inode->i_sb->s_maxbytes) { 128 if (pos + count > inode->i_sb->s_maxbytes) {
129 count = inode->i_sb->s_maxbytes - pos; 129 count = inode->i_sb->s_maxbytes - pos;
130 } 130 }
131 131
132 error = ncp_make_open(inode, O_RDONLY); 132 error = ncp_make_open(inode, O_RDONLY);
133 if (error) { 133 if (error) {
134 DPRINTK(KERN_ERR "ncp_file_read: open failed, error=%d\n", error); 134 DPRINTK(KERN_ERR "ncp_file_read: open failed, error=%d\n", error);
135 return error; 135 return error;
136 } 136 }
137 137
138 bufsize = NCP_SERVER(inode)->buffer_size; 138 bufsize = NCP_SERVER(inode)->buffer_size;
139 139
140 error = -EIO; 140 error = -EIO;
141 freelen = ncp_read_bounce_size(bufsize); 141 freelen = ncp_read_bounce_size(bufsize);
142 freepage = vmalloc(freelen); 142 freepage = vmalloc(freelen);
143 if (!freepage) 143 if (!freepage)
144 goto outrel; 144 goto outrel;
145 error = 0; 145 error = 0;
146 /* First read in as much as possible for each bufsize. */ 146 /* First read in as much as possible for each bufsize. */
147 while (already_read < count) { 147 while (already_read < count) {
148 int read_this_time; 148 int read_this_time;
149 size_t to_read = min_t(unsigned int, 149 size_t to_read = min_t(unsigned int,
150 bufsize - (pos % bufsize), 150 bufsize - (pos % bufsize),
151 count - already_read); 151 count - already_read);
152 152
153 error = ncp_read_bounce(NCP_SERVER(inode), 153 error = ncp_read_bounce(NCP_SERVER(inode),
154 NCP_FINFO(inode)->file_handle, 154 NCP_FINFO(inode)->file_handle,
155 pos, to_read, buf, &read_this_time, 155 pos, to_read, buf, &read_this_time,
156 freepage, freelen); 156 freepage, freelen);
157 if (error) { 157 if (error) {
158 error = -EIO; /* NW errno -> Linux errno */ 158 error = -EIO; /* NW errno -> Linux errno */
159 break; 159 break;
160 } 160 }
161 pos += read_this_time; 161 pos += read_this_time;
162 buf += read_this_time; 162 buf += read_this_time;
163 already_read += read_this_time; 163 already_read += read_this_time;
164 164
165 if (read_this_time != to_read) { 165 if (read_this_time != to_read) {
166 break; 166 break;
167 } 167 }
168 } 168 }
169 vfree(freepage); 169 vfree(freepage);
170 170
171 *ppos = pos; 171 *ppos = pos;
172 172
173 file_accessed(file); 173 file_accessed(file);
174 174
175 DPRINTK("ncp_file_read: exit %s/%s\n", 175 DPRINTK("ncp_file_read: exit %s/%s\n",
176 dentry->d_parent->d_name.name, dentry->d_name.name); 176 dentry->d_parent->d_name.name, dentry->d_name.name);
177 outrel: 177 outrel:
178 ncp_inode_close(inode); 178 ncp_inode_close(inode);
179 return already_read ? already_read : error; 179 return already_read ? already_read : error;
180 } 180 }
181 181
182 static ssize_t 182 static ssize_t
183 ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) 183 ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
184 { 184 {
185 struct dentry *dentry = file->f_dentry; 185 struct dentry *dentry = file->f_path.dentry;
186 struct inode *inode = dentry->d_inode; 186 struct inode *inode = dentry->d_inode;
187 size_t already_written = 0; 187 size_t already_written = 0;
188 off_t pos; 188 off_t pos;
189 size_t bufsize; 189 size_t bufsize;
190 int errno; 190 int errno;
191 void* bouncebuffer; 191 void* bouncebuffer;
192 192
193 DPRINTK("ncp_file_write: enter %s/%s\n", 193 DPRINTK("ncp_file_write: enter %s/%s\n",
194 dentry->d_parent->d_name.name, dentry->d_name.name); 194 dentry->d_parent->d_name.name, dentry->d_name.name);
195 if (!ncp_conn_valid(NCP_SERVER(inode))) 195 if (!ncp_conn_valid(NCP_SERVER(inode)))
196 return -EIO; 196 return -EIO;
197 if ((ssize_t) count < 0) 197 if ((ssize_t) count < 0)
198 return -EINVAL; 198 return -EINVAL;
199 pos = *ppos; 199 pos = *ppos;
200 if (file->f_flags & O_APPEND) { 200 if (file->f_flags & O_APPEND) {
201 pos = inode->i_size; 201 pos = inode->i_size;
202 } 202 }
203 203
204 if (pos + count > MAX_NON_LFS && !(file->f_flags&O_LARGEFILE)) { 204 if (pos + count > MAX_NON_LFS && !(file->f_flags&O_LARGEFILE)) {
205 if (pos >= MAX_NON_LFS) { 205 if (pos >= MAX_NON_LFS) {
206 send_sig(SIGXFSZ, current, 0); 206 send_sig(SIGXFSZ, current, 0);
207 return -EFBIG; 207 return -EFBIG;
208 } 208 }
209 if (count > MAX_NON_LFS - (u32)pos) { 209 if (count > MAX_NON_LFS - (u32)pos) {
210 count = MAX_NON_LFS - (u32)pos; 210 count = MAX_NON_LFS - (u32)pos;
211 } 211 }
212 } 212 }
213 if (pos >= inode->i_sb->s_maxbytes) { 213 if (pos >= inode->i_sb->s_maxbytes) {
214 if (count || pos > inode->i_sb->s_maxbytes) { 214 if (count || pos > inode->i_sb->s_maxbytes) {
215 send_sig(SIGXFSZ, current, 0); 215 send_sig(SIGXFSZ, current, 0);
216 return -EFBIG; 216 return -EFBIG;
217 } 217 }
218 } 218 }
219 if (pos + count > inode->i_sb->s_maxbytes) { 219 if (pos + count > inode->i_sb->s_maxbytes) {
220 count = inode->i_sb->s_maxbytes - pos; 220 count = inode->i_sb->s_maxbytes - pos;
221 } 221 }
222 222
223 if (!count) 223 if (!count)
224 return 0; 224 return 0;
225 errno = ncp_make_open(inode, O_WRONLY); 225 errno = ncp_make_open(inode, O_WRONLY);
226 if (errno) { 226 if (errno) {
227 DPRINTK(KERN_ERR "ncp_file_write: open failed, error=%d\n", errno); 227 DPRINTK(KERN_ERR "ncp_file_write: open failed, error=%d\n", errno);
228 return errno; 228 return errno;
229 } 229 }
230 bufsize = NCP_SERVER(inode)->buffer_size; 230 bufsize = NCP_SERVER(inode)->buffer_size;
231 231
232 already_written = 0; 232 already_written = 0;
233 233
234 bouncebuffer = vmalloc(bufsize); 234 bouncebuffer = vmalloc(bufsize);
235 if (!bouncebuffer) { 235 if (!bouncebuffer) {
236 errno = -EIO; /* -ENOMEM */ 236 errno = -EIO; /* -ENOMEM */
237 goto outrel; 237 goto outrel;
238 } 238 }
239 while (already_written < count) { 239 while (already_written < count) {
240 int written_this_time; 240 int written_this_time;
241 size_t to_write = min_t(unsigned int, 241 size_t to_write = min_t(unsigned int,
242 bufsize - (pos % bufsize), 242 bufsize - (pos % bufsize),
243 count - already_written); 243 count - already_written);
244 244
245 if (copy_from_user(bouncebuffer, buf, to_write)) { 245 if (copy_from_user(bouncebuffer, buf, to_write)) {
246 errno = -EFAULT; 246 errno = -EFAULT;
247 break; 247 break;
248 } 248 }
249 if (ncp_write_kernel(NCP_SERVER(inode), 249 if (ncp_write_kernel(NCP_SERVER(inode),
250 NCP_FINFO(inode)->file_handle, 250 NCP_FINFO(inode)->file_handle,
251 pos, to_write, bouncebuffer, &written_this_time) != 0) { 251 pos, to_write, bouncebuffer, &written_this_time) != 0) {
252 errno = -EIO; 252 errno = -EIO;
253 break; 253 break;
254 } 254 }
255 pos += written_this_time; 255 pos += written_this_time;
256 buf += written_this_time; 256 buf += written_this_time;
257 already_written += written_this_time; 257 already_written += written_this_time;
258 258
259 if (written_this_time != to_write) { 259 if (written_this_time != to_write) {
260 break; 260 break;
261 } 261 }
262 } 262 }
263 vfree(bouncebuffer); 263 vfree(bouncebuffer);
264 264
265 file_update_time(file); 265 file_update_time(file);
266 266
267 *ppos = pos; 267 *ppos = pos;
268 268
269 if (pos > inode->i_size) { 269 if (pos > inode->i_size) {
270 inode->i_size = pos; 270 inode->i_size = pos;
271 } 271 }
272 DPRINTK("ncp_file_write: exit %s/%s\n", 272 DPRINTK("ncp_file_write: exit %s/%s\n",
273 dentry->d_parent->d_name.name, dentry->d_name.name); 273 dentry->d_parent->d_name.name, dentry->d_name.name);
274 outrel: 274 outrel:
275 ncp_inode_close(inode); 275 ncp_inode_close(inode);
276 return already_written ? already_written : errno; 276 return already_written ? already_written : errno;
277 } 277 }
278 278
279 static int ncp_release(struct inode *inode, struct file *file) { 279 static int ncp_release(struct inode *inode, struct file *file) {
280 if (ncp_make_closed(inode)) { 280 if (ncp_make_closed(inode)) {
281 DPRINTK("ncp_release: failed to close\n"); 281 DPRINTK("ncp_release: failed to close\n");
282 } 282 }
283 return 0; 283 return 0;
284 } 284 }
285 285
286 const struct file_operations ncp_file_operations = 286 const struct file_operations ncp_file_operations =
287 { 287 {
288 .llseek = remote_llseek, 288 .llseek = remote_llseek,
289 .read = ncp_file_read, 289 .read = ncp_file_read,
290 .write = ncp_file_write, 290 .write = ncp_file_write,
291 .ioctl = ncp_ioctl, 291 .ioctl = ncp_ioctl,
292 #ifdef CONFIG_COMPAT 292 #ifdef CONFIG_COMPAT
293 .compat_ioctl = ncp_compat_ioctl, 293 .compat_ioctl = ncp_compat_ioctl,
294 #endif 294 #endif
295 .mmap = ncp_mmap, 295 .mmap = ncp_mmap,
296 .release = ncp_release, 296 .release = ncp_release,
297 .fsync = ncp_fsync, 297 .fsync = ncp_fsync,
298 }; 298 };
299 299
300 struct inode_operations ncp_file_inode_operations = 300 struct inode_operations ncp_file_inode_operations =
301 { 301 {
302 .setattr = ncp_notify_change, 302 .setattr = ncp_notify_change,
303 }; 303 };
304 304
1 /* 1 /*
2 * inode.c 2 * inode.c
3 * 3 *
4 * Copyright (C) 1995, 1996 by Volker Lendecke 4 * Copyright (C) 1995, 1996 by Volker Lendecke
5 * Modified for big endian by J.F. Chadima and David S. Miller 5 * Modified for big endian by J.F. Chadima and David S. Miller
6 * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache 6 * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
7 * Modified 1998 Wolfram Pienkoss for NLS 7 * Modified 1998 Wolfram Pienkoss for NLS
8 * Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info 8 * Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
9 * 9 *
10 */ 10 */
11 11
12 #include <linux/module.h> 12 #include <linux/module.h>
13 13
14 #include <asm/system.h> 14 #include <asm/system.h>
15 #include <asm/uaccess.h> 15 #include <asm/uaccess.h>
16 #include <asm/byteorder.h> 16 #include <asm/byteorder.h>
17 17
18 #include <linux/time.h> 18 #include <linux/time.h>
19 #include <linux/kernel.h> 19 #include <linux/kernel.h>
20 #include <linux/mm.h> 20 #include <linux/mm.h>
21 #include <linux/string.h> 21 #include <linux/string.h>
22 #include <linux/stat.h> 22 #include <linux/stat.h>
23 #include <linux/errno.h> 23 #include <linux/errno.h>
24 #include <linux/file.h> 24 #include <linux/file.h>
25 #include <linux/fcntl.h> 25 #include <linux/fcntl.h>
26 #include <linux/slab.h> 26 #include <linux/slab.h>
27 #include <linux/vmalloc.h> 27 #include <linux/vmalloc.h>
28 #include <linux/init.h> 28 #include <linux/init.h>
29 #include <linux/smp_lock.h> 29 #include <linux/smp_lock.h>
30 #include <linux/vfs.h> 30 #include <linux/vfs.h>
31 31
32 #include <linux/ncp_fs.h> 32 #include <linux/ncp_fs.h>
33 33
34 #include <net/sock.h> 34 #include <net/sock.h>
35 35
36 #include "ncplib_kernel.h" 36 #include "ncplib_kernel.h"
37 #include "getopt.h" 37 #include "getopt.h"
38 38
39 static void ncp_delete_inode(struct inode *); 39 static void ncp_delete_inode(struct inode *);
40 static void ncp_put_super(struct super_block *); 40 static void ncp_put_super(struct super_block *);
41 static int ncp_statfs(struct dentry *, struct kstatfs *); 41 static int ncp_statfs(struct dentry *, struct kstatfs *);
42 42
43 static struct kmem_cache * ncp_inode_cachep; 43 static struct kmem_cache * ncp_inode_cachep;
44 44
45 static struct inode *ncp_alloc_inode(struct super_block *sb) 45 static struct inode *ncp_alloc_inode(struct super_block *sb)
46 { 46 {
47 struct ncp_inode_info *ei; 47 struct ncp_inode_info *ei;
48 ei = (struct ncp_inode_info *)kmem_cache_alloc(ncp_inode_cachep, GFP_KERNEL); 48 ei = (struct ncp_inode_info *)kmem_cache_alloc(ncp_inode_cachep, GFP_KERNEL);
49 if (!ei) 49 if (!ei)
50 return NULL; 50 return NULL;
51 return &ei->vfs_inode; 51 return &ei->vfs_inode;
52 } 52 }
53 53
54 static void ncp_destroy_inode(struct inode *inode) 54 static void ncp_destroy_inode(struct inode *inode)
55 { 55 {
56 kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode)); 56 kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode));
57 } 57 }
58 58
59 static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) 59 static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
60 { 60 {
61 struct ncp_inode_info *ei = (struct ncp_inode_info *) foo; 61 struct ncp_inode_info *ei = (struct ncp_inode_info *) foo;
62 62
63 if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == 63 if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
64 SLAB_CTOR_CONSTRUCTOR) { 64 SLAB_CTOR_CONSTRUCTOR) {
65 mutex_init(&ei->open_mutex); 65 mutex_init(&ei->open_mutex);
66 inode_init_once(&ei->vfs_inode); 66 inode_init_once(&ei->vfs_inode);
67 } 67 }
68 } 68 }
69 69
70 static int init_inodecache(void) 70 static int init_inodecache(void)
71 { 71 {
72 ncp_inode_cachep = kmem_cache_create("ncp_inode_cache", 72 ncp_inode_cachep = kmem_cache_create("ncp_inode_cache",
73 sizeof(struct ncp_inode_info), 73 sizeof(struct ncp_inode_info),
74 0, (SLAB_RECLAIM_ACCOUNT| 74 0, (SLAB_RECLAIM_ACCOUNT|
75 SLAB_MEM_SPREAD), 75 SLAB_MEM_SPREAD),
76 init_once, NULL); 76 init_once, NULL);
77 if (ncp_inode_cachep == NULL) 77 if (ncp_inode_cachep == NULL)
78 return -ENOMEM; 78 return -ENOMEM;
79 return 0; 79 return 0;
80 } 80 }
81 81
82 static void destroy_inodecache(void) 82 static void destroy_inodecache(void)
83 { 83 {
84 kmem_cache_destroy(ncp_inode_cachep); 84 kmem_cache_destroy(ncp_inode_cachep);
85 } 85 }
86 86
87 static int ncp_remount(struct super_block *sb, int *flags, char* data) 87 static int ncp_remount(struct super_block *sb, int *flags, char* data)
88 { 88 {
89 *flags |= MS_NODIRATIME; 89 *flags |= MS_NODIRATIME;
90 return 0; 90 return 0;
91 } 91 }
92 92
93 static struct super_operations ncp_sops = 93 static struct super_operations ncp_sops =
94 { 94 {
95 .alloc_inode = ncp_alloc_inode, 95 .alloc_inode = ncp_alloc_inode,
96 .destroy_inode = ncp_destroy_inode, 96 .destroy_inode = ncp_destroy_inode,
97 .drop_inode = generic_delete_inode, 97 .drop_inode = generic_delete_inode,
98 .delete_inode = ncp_delete_inode, 98 .delete_inode = ncp_delete_inode,
99 .put_super = ncp_put_super, 99 .put_super = ncp_put_super,
100 .statfs = ncp_statfs, 100 .statfs = ncp_statfs,
101 .remount_fs = ncp_remount, 101 .remount_fs = ncp_remount,
102 }; 102 };
103 103
104 extern struct dentry_operations ncp_root_dentry_operations; 104 extern struct dentry_operations ncp_root_dentry_operations;
105 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) 105 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
106 extern const struct address_space_operations ncp_symlink_aops; 106 extern const struct address_space_operations ncp_symlink_aops;
107 extern int ncp_symlink(struct inode*, struct dentry*, const char*); 107 extern int ncp_symlink(struct inode*, struct dentry*, const char*);
108 #endif 108 #endif
109 109
110 /* 110 /*
111 * Fill in the ncpfs-specific information in the inode. 111 * Fill in the ncpfs-specific information in the inode.
112 */ 112 */
113 static void ncp_update_dirent(struct inode *inode, struct ncp_entry_info *nwinfo) 113 static void ncp_update_dirent(struct inode *inode, struct ncp_entry_info *nwinfo)
114 { 114 {
115 NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum; 115 NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
116 NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum; 116 NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
117 NCP_FINFO(inode)->volNumber = nwinfo->volume; 117 NCP_FINFO(inode)->volNumber = nwinfo->volume;
118 } 118 }
119 119
120 void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo) 120 void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo)
121 { 121 {
122 ncp_update_dirent(inode, nwinfo); 122 ncp_update_dirent(inode, nwinfo);
123 NCP_FINFO(inode)->nwattr = nwinfo->i.attributes; 123 NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
124 NCP_FINFO(inode)->access = nwinfo->access; 124 NCP_FINFO(inode)->access = nwinfo->access;
125 memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle, 125 memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
126 sizeof(nwinfo->file_handle)); 126 sizeof(nwinfo->file_handle));
127 DPRINTK("ncp_update_inode: updated %s, volnum=%d, dirent=%u\n", 127 DPRINTK("ncp_update_inode: updated %s, volnum=%d, dirent=%u\n",
128 nwinfo->i.entryName, NCP_FINFO(inode)->volNumber, 128 nwinfo->i.entryName, NCP_FINFO(inode)->volNumber,
129 NCP_FINFO(inode)->dirEntNum); 129 NCP_FINFO(inode)->dirEntNum);
130 } 130 }
131 131
132 static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi) 132 static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi)
133 { 133 {
134 /* NFS namespace mode overrides others if it's set. */ 134 /* NFS namespace mode overrides others if it's set. */
135 DPRINTK(KERN_DEBUG "ncp_update_dates_and_mode: (%s) nfs.mode=0%o\n", 135 DPRINTK(KERN_DEBUG "ncp_update_dates_and_mode: (%s) nfs.mode=0%o\n",
136 nwi->entryName, nwi->nfs.mode); 136 nwi->entryName, nwi->nfs.mode);
137 if (nwi->nfs.mode) { 137 if (nwi->nfs.mode) {
138 /* XXX Security? */ 138 /* XXX Security? */
139 inode->i_mode = nwi->nfs.mode; 139 inode->i_mode = nwi->nfs.mode;
140 } 140 }
141 141
142 inode->i_blocks = (inode->i_size + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT; 142 inode->i_blocks = (inode->i_size + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
143 143
144 inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate); 144 inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate);
145 inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate); 145 inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate);
146 inode->i_atime.tv_sec = ncp_date_dos2unix(0, nwi->lastAccessDate); 146 inode->i_atime.tv_sec = ncp_date_dos2unix(0, nwi->lastAccessDate);
147 inode->i_atime.tv_nsec = 0; 147 inode->i_atime.tv_nsec = 0;
148 inode->i_mtime.tv_nsec = 0; 148 inode->i_mtime.tv_nsec = 0;
149 inode->i_ctime.tv_nsec = 0; 149 inode->i_ctime.tv_nsec = 0;
150 } 150 }
151 151
152 static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo) 152 static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo)
153 { 153 {
154 struct nw_info_struct *nwi = &nwinfo->i; 154 struct nw_info_struct *nwi = &nwinfo->i;
155 struct ncp_server *server = NCP_SERVER(inode); 155 struct ncp_server *server = NCP_SERVER(inode);
156 156
157 if (nwi->attributes & aDIR) { 157 if (nwi->attributes & aDIR) {
158 inode->i_mode = server->m.dir_mode; 158 inode->i_mode = server->m.dir_mode;
159 /* for directories dataStreamSize seems to be some 159 /* for directories dataStreamSize seems to be some
160 Object ID ??? */ 160 Object ID ??? */
161 inode->i_size = NCP_BLOCK_SIZE; 161 inode->i_size = NCP_BLOCK_SIZE;
162 } else { 162 } else {
163 inode->i_mode = server->m.file_mode; 163 inode->i_mode = server->m.file_mode;
164 inode->i_size = le32_to_cpu(nwi->dataStreamSize); 164 inode->i_size = le32_to_cpu(nwi->dataStreamSize);
165 #ifdef CONFIG_NCPFS_EXTRAS 165 #ifdef CONFIG_NCPFS_EXTRAS
166 if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) 166 if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS))
167 && (nwi->attributes & aSHARED)) { 167 && (nwi->attributes & aSHARED)) {
168 switch (nwi->attributes & (aHIDDEN|aSYSTEM)) { 168 switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
169 case aHIDDEN: 169 case aHIDDEN:
170 if (server->m.flags & NCP_MOUNT_SYMLINKS) { 170 if (server->m.flags & NCP_MOUNT_SYMLINKS) {
171 if (/* (inode->i_size >= NCP_MIN_SYMLINK_SIZE) 171 if (/* (inode->i_size >= NCP_MIN_SYMLINK_SIZE)
172 && */ (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) { 172 && */ (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) {
173 inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK; 173 inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
174 NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK; 174 NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK;
175 break; 175 break;
176 } 176 }
177 } 177 }
178 /* FALLTHROUGH */ 178 /* FALLTHROUGH */
179 case 0: 179 case 0:
180 if (server->m.flags & NCP_MOUNT_EXTRAS) 180 if (server->m.flags & NCP_MOUNT_EXTRAS)
181 inode->i_mode |= S_IRUGO; 181 inode->i_mode |= S_IRUGO;
182 break; 182 break;
183 case aSYSTEM: 183 case aSYSTEM:
184 if (server->m.flags & NCP_MOUNT_EXTRAS) 184 if (server->m.flags & NCP_MOUNT_EXTRAS)
185 inode->i_mode |= (inode->i_mode >> 2) & S_IXUGO; 185 inode->i_mode |= (inode->i_mode >> 2) & S_IXUGO;
186 break; 186 break;
187 /* case aSYSTEM|aHIDDEN: */ 187 /* case aSYSTEM|aHIDDEN: */
188 default: 188 default:
189 /* reserved combination */ 189 /* reserved combination */
190 break; 190 break;
191 } 191 }
192 } 192 }
193 #endif 193 #endif
194 } 194 }
195 if (nwi->attributes & aRONLY) inode->i_mode &= ~S_IWUGO; 195 if (nwi->attributes & aRONLY) inode->i_mode &= ~S_IWUGO;
196 } 196 }
197 197
198 void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo) 198 void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo)
199 { 199 {
200 NCP_FINFO(inode)->flags = 0; 200 NCP_FINFO(inode)->flags = 0;
201 if (!atomic_read(&NCP_FINFO(inode)->opened)) { 201 if (!atomic_read(&NCP_FINFO(inode)->opened)) {
202 NCP_FINFO(inode)->nwattr = nwinfo->i.attributes; 202 NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
203 ncp_update_attrs(inode, nwinfo); 203 ncp_update_attrs(inode, nwinfo);
204 } 204 }
205 205
206 ncp_update_dates(inode, &nwinfo->i); 206 ncp_update_dates(inode, &nwinfo->i);
207 ncp_update_dirent(inode, nwinfo); 207 ncp_update_dirent(inode, nwinfo);
208 } 208 }
209 209
210 /* 210 /*
211 * Fill in the inode based on the ncp_entry_info structure. 211 * Fill in the inode based on the ncp_entry_info structure.
212 */ 212 */
213 static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo) 213 static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
214 { 214 {
215 struct ncp_server *server = NCP_SERVER(inode); 215 struct ncp_server *server = NCP_SERVER(inode);
216 216
217 NCP_FINFO(inode)->flags = 0; 217 NCP_FINFO(inode)->flags = 0;
218 218
219 ncp_update_attrs(inode, nwinfo); 219 ncp_update_attrs(inode, nwinfo);
220 220
221 DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode); 221 DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
222 222
223 inode->i_nlink = 1; 223 inode->i_nlink = 1;
224 inode->i_uid = server->m.uid; 224 inode->i_uid = server->m.uid;
225 inode->i_gid = server->m.gid; 225 inode->i_gid = server->m.gid;
226 226
227 ncp_update_dates(inode, &nwinfo->i); 227 ncp_update_dates(inode, &nwinfo->i);
228 ncp_update_inode(inode, nwinfo); 228 ncp_update_inode(inode, nwinfo);
229 } 229 }
230 230
231 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) 231 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
232 static struct inode_operations ncp_symlink_inode_operations = { 232 static struct inode_operations ncp_symlink_inode_operations = {
233 .readlink = generic_readlink, 233 .readlink = generic_readlink,
234 .follow_link = page_follow_link_light, 234 .follow_link = page_follow_link_light,
235 .put_link = page_put_link, 235 .put_link = page_put_link,
236 .setattr = ncp_notify_change, 236 .setattr = ncp_notify_change,
237 }; 237 };
238 #endif 238 #endif
239 239
240 /* 240 /*
241 * Get a new inode. 241 * Get a new inode.
242 */ 242 */
243 struct inode * 243 struct inode *
244 ncp_iget(struct super_block *sb, struct ncp_entry_info *info) 244 ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
245 { 245 {
246 struct inode *inode; 246 struct inode *inode;
247 247
248 if (info == NULL) { 248 if (info == NULL) {
249 printk(KERN_ERR "ncp_iget: info is NULL\n"); 249 printk(KERN_ERR "ncp_iget: info is NULL\n");
250 return NULL; 250 return NULL;
251 } 251 }
252 252
253 inode = new_inode(sb); 253 inode = new_inode(sb);
254 if (inode) { 254 if (inode) {
255 atomic_set(&NCP_FINFO(inode)->opened, info->opened); 255 atomic_set(&NCP_FINFO(inode)->opened, info->opened);
256 256
257 inode->i_ino = info->ino; 257 inode->i_ino = info->ino;
258 ncp_set_attr(inode, info); 258 ncp_set_attr(inode, info);
259 if (S_ISREG(inode->i_mode)) { 259 if (S_ISREG(inode->i_mode)) {
260 inode->i_op = &ncp_file_inode_operations; 260 inode->i_op = &ncp_file_inode_operations;
261 inode->i_fop = &ncp_file_operations; 261 inode->i_fop = &ncp_file_operations;
262 } else if (S_ISDIR(inode->i_mode)) { 262 } else if (S_ISDIR(inode->i_mode)) {
263 inode->i_op = &ncp_dir_inode_operations; 263 inode->i_op = &ncp_dir_inode_operations;
264 inode->i_fop = &ncp_dir_operations; 264 inode->i_fop = &ncp_dir_operations;
265 #ifdef CONFIG_NCPFS_NFS_NS 265 #ifdef CONFIG_NCPFS_NFS_NS
266 } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { 266 } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
267 init_special_inode(inode, inode->i_mode, 267 init_special_inode(inode, inode->i_mode,
268 new_decode_dev(info->i.nfs.rdev)); 268 new_decode_dev(info->i.nfs.rdev));
269 #endif 269 #endif
270 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) 270 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
271 } else if (S_ISLNK(inode->i_mode)) { 271 } else if (S_ISLNK(inode->i_mode)) {
272 inode->i_op = &ncp_symlink_inode_operations; 272 inode->i_op = &ncp_symlink_inode_operations;
273 inode->i_data.a_ops = &ncp_symlink_aops; 273 inode->i_data.a_ops = &ncp_symlink_aops;
274 #endif 274 #endif
275 } else { 275 } else {
276 make_bad_inode(inode); 276 make_bad_inode(inode);
277 } 277 }
278 insert_inode_hash(inode); 278 insert_inode_hash(inode);
279 } else 279 } else
280 printk(KERN_ERR "ncp_iget: iget failed!\n"); 280 printk(KERN_ERR "ncp_iget: iget failed!\n");
281 return inode; 281 return inode;
282 } 282 }
283 283
284 static void 284 static void
285 ncp_delete_inode(struct inode *inode) 285 ncp_delete_inode(struct inode *inode)
286 { 286 {
287 truncate_inode_pages(&inode->i_data, 0); 287 truncate_inode_pages(&inode->i_data, 0);
288 288
289 if (S_ISDIR(inode->i_mode)) { 289 if (S_ISDIR(inode->i_mode)) {
290 DDPRINTK("ncp_delete_inode: put directory %ld\n", inode->i_ino); 290 DDPRINTK("ncp_delete_inode: put directory %ld\n", inode->i_ino);
291 } 291 }
292 292
293 if (ncp_make_closed(inode) != 0) { 293 if (ncp_make_closed(inode) != 0) {
294 /* We can't do anything but complain. */ 294 /* We can't do anything but complain. */
295 printk(KERN_ERR "ncp_delete_inode: could not close\n"); 295 printk(KERN_ERR "ncp_delete_inode: could not close\n");
296 } 296 }
297 clear_inode(inode); 297 clear_inode(inode);
298 } 298 }
299 299
300 static void ncp_stop_tasks(struct ncp_server *server) { 300 static void ncp_stop_tasks(struct ncp_server *server) {
301 struct sock* sk = server->ncp_sock->sk; 301 struct sock* sk = server->ncp_sock->sk;
302 302
303 sk->sk_error_report = server->error_report; 303 sk->sk_error_report = server->error_report;
304 sk->sk_data_ready = server->data_ready; 304 sk->sk_data_ready = server->data_ready;
305 sk->sk_write_space = server->write_space; 305 sk->sk_write_space = server->write_space;
306 del_timer_sync(&server->timeout_tm); 306 del_timer_sync(&server->timeout_tm);
307 flush_scheduled_work(); 307 flush_scheduled_work();
308 } 308 }
309 309
310 static const struct ncp_option ncp_opts[] = { 310 static const struct ncp_option ncp_opts[] = {
311 { "uid", OPT_INT, 'u' }, 311 { "uid", OPT_INT, 'u' },
312 { "gid", OPT_INT, 'g' }, 312 { "gid", OPT_INT, 'g' },
313 { "owner", OPT_INT, 'o' }, 313 { "owner", OPT_INT, 'o' },
314 { "mode", OPT_INT, 'm' }, 314 { "mode", OPT_INT, 'm' },
315 { "dirmode", OPT_INT, 'd' }, 315 { "dirmode", OPT_INT, 'd' },
316 { "timeout", OPT_INT, 't' }, 316 { "timeout", OPT_INT, 't' },
317 { "retry", OPT_INT, 'r' }, 317 { "retry", OPT_INT, 'r' },
318 { "flags", OPT_INT, 'f' }, 318 { "flags", OPT_INT, 'f' },
319 { "wdogpid", OPT_INT, 'w' }, 319 { "wdogpid", OPT_INT, 'w' },
320 { "ncpfd", OPT_INT, 'n' }, 320 { "ncpfd", OPT_INT, 'n' },
321 { "infofd", OPT_INT, 'i' }, /* v5 */ 321 { "infofd", OPT_INT, 'i' }, /* v5 */
322 { "version", OPT_INT, 'v' }, 322 { "version", OPT_INT, 'v' },
323 { NULL, 0, 0 } }; 323 { NULL, 0, 0 } };
324 324
325 static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) { 325 static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) {
326 int optval; 326 int optval;
327 char *optarg; 327 char *optarg;
328 unsigned long optint; 328 unsigned long optint;
329 int version = 0; 329 int version = 0;
330 330
331 data->flags = 0; 331 data->flags = 0;
332 data->int_flags = 0; 332 data->int_flags = 0;
333 data->mounted_uid = 0; 333 data->mounted_uid = 0;
334 data->wdog_pid = -1; 334 data->wdog_pid = -1;
335 data->ncp_fd = ~0; 335 data->ncp_fd = ~0;
336 data->time_out = 10; 336 data->time_out = 10;
337 data->retry_count = 20; 337 data->retry_count = 20;
338 data->uid = 0; 338 data->uid = 0;
339 data->gid = 0; 339 data->gid = 0;
340 data->file_mode = 0600; 340 data->file_mode = 0600;
341 data->dir_mode = 0700; 341 data->dir_mode = 0700;
342 data->info_fd = -1; 342 data->info_fd = -1;
343 data->mounted_vol[0] = 0; 343 data->mounted_vol[0] = 0;
344 344
345 while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) { 345 while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
346 if (optval < 0) 346 if (optval < 0)
347 return optval; 347 return optval;
348 switch (optval) { 348 switch (optval) {
349 case 'u': 349 case 'u':
350 data->uid = optint; 350 data->uid = optint;
351 break; 351 break;
352 case 'g': 352 case 'g':
353 data->gid = optint; 353 data->gid = optint;
354 break; 354 break;
355 case 'o': 355 case 'o':
356 data->mounted_uid = optint; 356 data->mounted_uid = optint;
357 break; 357 break;
358 case 'm': 358 case 'm':
359 data->file_mode = optint; 359 data->file_mode = optint;
360 break; 360 break;
361 case 'd': 361 case 'd':
362 data->dir_mode = optint; 362 data->dir_mode = optint;
363 break; 363 break;
364 case 't': 364 case 't':
365 data->time_out = optint; 365 data->time_out = optint;
366 break; 366 break;
367 case 'r': 367 case 'r':
368 data->retry_count = optint; 368 data->retry_count = optint;
369 break; 369 break;
370 case 'f': 370 case 'f':
371 data->flags = optint; 371 data->flags = optint;
372 break; 372 break;
373 case 'w': 373 case 'w':
374 data->wdog_pid = optint; 374 data->wdog_pid = optint;
375 break; 375 break;
376 case 'n': 376 case 'n':
377 data->ncp_fd = optint; 377 data->ncp_fd = optint;
378 break; 378 break;
379 case 'i': 379 case 'i':
380 data->info_fd = optint; 380 data->info_fd = optint;
381 break; 381 break;
382 case 'v': 382 case 'v':
383 if (optint < NCP_MOUNT_VERSION_V4) { 383 if (optint < NCP_MOUNT_VERSION_V4) {
384 return -ECHRNG; 384 return -ECHRNG;
385 } 385 }
386 if (optint > NCP_MOUNT_VERSION_V5) { 386 if (optint > NCP_MOUNT_VERSION_V5) {
387 return -ECHRNG; 387 return -ECHRNG;
388 } 388 }
389 version = optint; 389 version = optint;
390 break; 390 break;
391 391
392 } 392 }
393 } 393 }
394 return 0; 394 return 0;
395 } 395 }
396 396
397 static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) 397 static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
398 { 398 {
399 struct ncp_mount_data_kernel data; 399 struct ncp_mount_data_kernel data;
400 struct ncp_server *server; 400 struct ncp_server *server;
401 struct file *ncp_filp; 401 struct file *ncp_filp;
402 struct inode *root_inode; 402 struct inode *root_inode;
403 struct inode *sock_inode; 403 struct inode *sock_inode;
404 struct socket *sock; 404 struct socket *sock;
405 int error; 405 int error;
406 int default_bufsize; 406 int default_bufsize;
407 #ifdef CONFIG_NCPFS_PACKET_SIGNING 407 #ifdef CONFIG_NCPFS_PACKET_SIGNING
408 int options; 408 int options;
409 #endif 409 #endif
410 struct ncp_entry_info finfo; 410 struct ncp_entry_info finfo;
411 411
412 server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL); 412 server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
413 if (!server) 413 if (!server)
414 return -ENOMEM; 414 return -ENOMEM;
415 sb->s_fs_info = server; 415 sb->s_fs_info = server;
416 416
417 error = -EFAULT; 417 error = -EFAULT;
418 if (raw_data == NULL) 418 if (raw_data == NULL)
419 goto out; 419 goto out;
420 switch (*(int*)raw_data) { 420 switch (*(int*)raw_data) {
421 case NCP_MOUNT_VERSION: 421 case NCP_MOUNT_VERSION:
422 { 422 {
423 struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data; 423 struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;
424 424
425 data.flags = md->flags; 425 data.flags = md->flags;
426 data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE; 426 data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
427 data.mounted_uid = md->mounted_uid; 427 data.mounted_uid = md->mounted_uid;
428 data.wdog_pid = md->wdog_pid; 428 data.wdog_pid = md->wdog_pid;
429 data.ncp_fd = md->ncp_fd; 429 data.ncp_fd = md->ncp_fd;
430 data.time_out = md->time_out; 430 data.time_out = md->time_out;
431 data.retry_count = md->retry_count; 431 data.retry_count = md->retry_count;
432 data.uid = md->uid; 432 data.uid = md->uid;
433 data.gid = md->gid; 433 data.gid = md->gid;
434 data.file_mode = md->file_mode; 434 data.file_mode = md->file_mode;
435 data.dir_mode = md->dir_mode; 435 data.dir_mode = md->dir_mode;
436 data.info_fd = -1; 436 data.info_fd = -1;
437 memcpy(data.mounted_vol, md->mounted_vol, 437 memcpy(data.mounted_vol, md->mounted_vol,
438 NCP_VOLNAME_LEN+1); 438 NCP_VOLNAME_LEN+1);
439 } 439 }
440 break; 440 break;
441 case NCP_MOUNT_VERSION_V4: 441 case NCP_MOUNT_VERSION_V4:
442 { 442 {
443 struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data; 443 struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;
444 444
445 data.flags = md->flags; 445 data.flags = md->flags;
446 data.int_flags = 0; 446 data.int_flags = 0;
447 data.mounted_uid = md->mounted_uid; 447 data.mounted_uid = md->mounted_uid;
448 data.wdog_pid = md->wdog_pid; 448 data.wdog_pid = md->wdog_pid;
449 data.ncp_fd = md->ncp_fd; 449 data.ncp_fd = md->ncp_fd;
450 data.time_out = md->time_out; 450 data.time_out = md->time_out;
451 data.retry_count = md->retry_count; 451 data.retry_count = md->retry_count;
452 data.uid = md->uid; 452 data.uid = md->uid;
453 data.gid = md->gid; 453 data.gid = md->gid;
454 data.file_mode = md->file_mode; 454 data.file_mode = md->file_mode;
455 data.dir_mode = md->dir_mode; 455 data.dir_mode = md->dir_mode;
456 data.info_fd = -1; 456 data.info_fd = -1;
457 data.mounted_vol[0] = 0; 457 data.mounted_vol[0] = 0;
458 } 458 }
459 break; 459 break;
460 default: 460 default:
461 error = -ECHRNG; 461 error = -ECHRNG;
462 if (memcmp(raw_data, "vers", 4) == 0) { 462 if (memcmp(raw_data, "vers", 4) == 0) {
463 error = ncp_parse_options(&data, raw_data); 463 error = ncp_parse_options(&data, raw_data);
464 } 464 }
465 if (error) 465 if (error)
466 goto out; 466 goto out;
467 break; 467 break;
468 } 468 }
469 error = -EBADF; 469 error = -EBADF;
470 ncp_filp = fget(data.ncp_fd); 470 ncp_filp = fget(data.ncp_fd);
471 if (!ncp_filp) 471 if (!ncp_filp)
472 goto out; 472 goto out;
473 error = -ENOTSOCK; 473 error = -ENOTSOCK;
474 sock_inode = ncp_filp->f_dentry->d_inode; 474 sock_inode = ncp_filp->f_path.dentry->d_inode;
475 if (!S_ISSOCK(sock_inode->i_mode)) 475 if (!S_ISSOCK(sock_inode->i_mode))
476 goto out_fput; 476 goto out_fput;
477 sock = SOCKET_I(sock_inode); 477 sock = SOCKET_I(sock_inode);
478 if (!sock) 478 if (!sock)
479 goto out_fput; 479 goto out_fput;
480 480
481 if (sock->type == SOCK_STREAM) 481 if (sock->type == SOCK_STREAM)
482 default_bufsize = 0xF000; 482 default_bufsize = 0xF000;
483 else 483 else
484 default_bufsize = 1024; 484 default_bufsize = 1024;
485 485
486 sb->s_flags |= MS_NODIRATIME; /* probably even noatime */ 486 sb->s_flags |= MS_NODIRATIME; /* probably even noatime */
487 sb->s_maxbytes = 0xFFFFFFFFU; 487 sb->s_maxbytes = 0xFFFFFFFFU;
488 sb->s_blocksize = 1024; /* Eh... Is this correct? */ 488 sb->s_blocksize = 1024; /* Eh... Is this correct? */
489 sb->s_blocksize_bits = 10; 489 sb->s_blocksize_bits = 10;
490 sb->s_magic = NCP_SUPER_MAGIC; 490 sb->s_magic = NCP_SUPER_MAGIC;
491 sb->s_op = &ncp_sops; 491 sb->s_op = &ncp_sops;
492 492
493 server = NCP_SBP(sb); 493 server = NCP_SBP(sb);
494 memset(server, 0, sizeof(*server)); 494 memset(server, 0, sizeof(*server));
495 495
496 server->ncp_filp = ncp_filp; 496 server->ncp_filp = ncp_filp;
497 server->ncp_sock = sock; 497 server->ncp_sock = sock;
498 498
499 if (data.info_fd != -1) { 499 if (data.info_fd != -1) {
500 struct socket *info_sock; 500 struct socket *info_sock;
501 501
502 error = -EBADF; 502 error = -EBADF;
503 server->info_filp = fget(data.info_fd); 503 server->info_filp = fget(data.info_fd);
504 if (!server->info_filp) 504 if (!server->info_filp)
505 goto out_fput; 505 goto out_fput;
506 error = -ENOTSOCK; 506 error = -ENOTSOCK;
507 sock_inode = server->info_filp->f_dentry->d_inode; 507 sock_inode = server->info_filp->f_path.dentry->d_inode;
508 if (!S_ISSOCK(sock_inode->i_mode)) 508 if (!S_ISSOCK(sock_inode->i_mode))
509 goto out_fput2; 509 goto out_fput2;
510 info_sock = SOCKET_I(sock_inode); 510 info_sock = SOCKET_I(sock_inode);
511 if (!info_sock) 511 if (!info_sock)
512 goto out_fput2; 512 goto out_fput2;
513 error = -EBADFD; 513 error = -EBADFD;
514 if (info_sock->type != SOCK_STREAM) 514 if (info_sock->type != SOCK_STREAM)
515 goto out_fput2; 515 goto out_fput2;
516 server->info_sock = info_sock; 516 server->info_sock = info_sock;
517 } 517 }
518 518
519 /* server->lock = 0; */ 519 /* server->lock = 0; */
520 mutex_init(&server->mutex); 520 mutex_init(&server->mutex);
521 server->packet = NULL; 521 server->packet = NULL;
522 /* server->buffer_size = 0; */ 522 /* server->buffer_size = 0; */
523 /* server->conn_status = 0; */ 523 /* server->conn_status = 0; */
524 /* server->root_dentry = NULL; */ 524 /* server->root_dentry = NULL; */
525 /* server->root_setuped = 0; */ 525 /* server->root_setuped = 0; */
526 #ifdef CONFIG_NCPFS_PACKET_SIGNING 526 #ifdef CONFIG_NCPFS_PACKET_SIGNING
527 /* server->sign_wanted = 0; */ 527 /* server->sign_wanted = 0; */
528 /* server->sign_active = 0; */ 528 /* server->sign_active = 0; */
529 #endif 529 #endif
530 server->auth.auth_type = NCP_AUTH_NONE; 530 server->auth.auth_type = NCP_AUTH_NONE;
531 /* server->auth.object_name_len = 0; */ 531 /* server->auth.object_name_len = 0; */
532 /* server->auth.object_name = NULL; */ 532 /* server->auth.object_name = NULL; */
533 /* server->auth.object_type = 0; */ 533 /* server->auth.object_type = 0; */
534 /* server->priv.len = 0; */ 534 /* server->priv.len = 0; */
535 /* server->priv.data = NULL; */ 535 /* server->priv.data = NULL; */
536 536
537 server->m = data; 537 server->m = data;
538 /* Althought anything producing this is buggy, it happens 538 /* Althought anything producing this is buggy, it happens
539 now because of PATH_MAX changes.. */ 539 now because of PATH_MAX changes.. */
540 if (server->m.time_out < 1) { 540 if (server->m.time_out < 1) {
541 server->m.time_out = 10; 541 server->m.time_out = 10;
542 printk(KERN_INFO "You need to recompile your ncpfs utils..\n"); 542 printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
543 } 543 }
544 server->m.time_out = server->m.time_out * HZ / 100; 544 server->m.time_out = server->m.time_out * HZ / 100;
545 server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG; 545 server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG;
546 server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR; 546 server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR;
547 547
548 #ifdef CONFIG_NCPFS_NLS 548 #ifdef CONFIG_NCPFS_NLS
549 /* load the default NLS charsets */ 549 /* load the default NLS charsets */
550 server->nls_vol = load_nls_default(); 550 server->nls_vol = load_nls_default();
551 server->nls_io = load_nls_default(); 551 server->nls_io = load_nls_default();
552 #endif /* CONFIG_NCPFS_NLS */ 552 #endif /* CONFIG_NCPFS_NLS */
553 553
554 server->dentry_ttl = 0; /* no caching */ 554 server->dentry_ttl = 0; /* no caching */
555 555
556 INIT_LIST_HEAD(&server->tx.requests); 556 INIT_LIST_HEAD(&server->tx.requests);
557 mutex_init(&server->rcv.creq_mutex); 557 mutex_init(&server->rcv.creq_mutex);
558 server->tx.creq = NULL; 558 server->tx.creq = NULL;
559 server->rcv.creq = NULL; 559 server->rcv.creq = NULL;
560 server->data_ready = sock->sk->sk_data_ready; 560 server->data_ready = sock->sk->sk_data_ready;
561 server->write_space = sock->sk->sk_write_space; 561 server->write_space = sock->sk->sk_write_space;
562 server->error_report = sock->sk->sk_error_report; 562 server->error_report = sock->sk->sk_error_report;
563 sock->sk->sk_user_data = server; 563 sock->sk->sk_user_data = server;
564 564
565 init_timer(&server->timeout_tm); 565 init_timer(&server->timeout_tm);
566 #undef NCP_PACKET_SIZE 566 #undef NCP_PACKET_SIZE
567 #define NCP_PACKET_SIZE 131072 567 #define NCP_PACKET_SIZE 131072
568 error = -ENOMEM; 568 error = -ENOMEM;
569 server->packet_size = NCP_PACKET_SIZE; 569 server->packet_size = NCP_PACKET_SIZE;
570 server->packet = vmalloc(NCP_PACKET_SIZE); 570 server->packet = vmalloc(NCP_PACKET_SIZE);
571 if (server->packet == NULL) 571 if (server->packet == NULL)
572 goto out_nls; 572 goto out_nls;
573 573
574 sock->sk->sk_data_ready = ncp_tcp_data_ready; 574 sock->sk->sk_data_ready = ncp_tcp_data_ready;
575 sock->sk->sk_error_report = ncp_tcp_error_report; 575 sock->sk->sk_error_report = ncp_tcp_error_report;
576 if (sock->type == SOCK_STREAM) { 576 if (sock->type == SOCK_STREAM) {
577 server->rcv.ptr = (unsigned char*)&server->rcv.buf; 577 server->rcv.ptr = (unsigned char*)&server->rcv.buf;
578 server->rcv.len = 10; 578 server->rcv.len = 10;
579 server->rcv.state = 0; 579 server->rcv.state = 0;
580 INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc); 580 INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc);
581 INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc); 581 INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc);
582 sock->sk->sk_write_space = ncp_tcp_write_space; 582 sock->sk->sk_write_space = ncp_tcp_write_space;
583 } else { 583 } else {
584 INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc); 584 INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc);
585 INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc); 585 INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc);
586 server->timeout_tm.data = (unsigned long)server; 586 server->timeout_tm.data = (unsigned long)server;
587 server->timeout_tm.function = ncpdgram_timeout_call; 587 server->timeout_tm.function = ncpdgram_timeout_call;
588 } 588 }
589 589
590 ncp_lock_server(server); 590 ncp_lock_server(server);
591 error = ncp_connect(server); 591 error = ncp_connect(server);
592 ncp_unlock_server(server); 592 ncp_unlock_server(server);
593 if (error < 0) 593 if (error < 0)
594 goto out_packet; 594 goto out_packet;
595 DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb)); 595 DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
596 596
597 error = -EMSGSIZE; /* -EREMOTESIDEINCOMPATIBLE */ 597 error = -EMSGSIZE; /* -EREMOTESIDEINCOMPATIBLE */
598 #ifdef CONFIG_NCPFS_PACKET_SIGNING 598 #ifdef CONFIG_NCPFS_PACKET_SIGNING
599 if (ncp_negotiate_size_and_options(server, default_bufsize, 599 if (ncp_negotiate_size_and_options(server, default_bufsize,
600 NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0) 600 NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
601 { 601 {
602 if (options != NCP_DEFAULT_OPTIONS) 602 if (options != NCP_DEFAULT_OPTIONS)
603 { 603 {
604 if (ncp_negotiate_size_and_options(server, 604 if (ncp_negotiate_size_and_options(server,
605 default_bufsize, 605 default_bufsize,
606 options & 2, 606 options & 2,
607 &(server->buffer_size), &options) != 0) 607 &(server->buffer_size), &options) != 0)
608 608
609 { 609 {
610 goto out_disconnect; 610 goto out_disconnect;
611 } 611 }
612 } 612 }
613 if (options & 2) 613 if (options & 2)
614 server->sign_wanted = 1; 614 server->sign_wanted = 1;
615 } 615 }
616 else 616 else
617 #endif /* CONFIG_NCPFS_PACKET_SIGNING */ 617 #endif /* CONFIG_NCPFS_PACKET_SIGNING */
618 if (ncp_negotiate_buffersize(server, default_bufsize, 618 if (ncp_negotiate_buffersize(server, default_bufsize,
619 &(server->buffer_size)) != 0) 619 &(server->buffer_size)) != 0)
620 goto out_disconnect; 620 goto out_disconnect;
621 DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size); 621 DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
622 622
623 memset(&finfo, 0, sizeof(finfo)); 623 memset(&finfo, 0, sizeof(finfo));
624 finfo.i.attributes = aDIR; 624 finfo.i.attributes = aDIR;
625 finfo.i.dataStreamSize = 0; /* ignored */ 625 finfo.i.dataStreamSize = 0; /* ignored */
626 finfo.i.dirEntNum = 0; 626 finfo.i.dirEntNum = 0;
627 finfo.i.DosDirNum = 0; 627 finfo.i.DosDirNum = 0;
628 #ifdef CONFIG_NCPFS_SMALLDOS 628 #ifdef CONFIG_NCPFS_SMALLDOS
629 finfo.i.NSCreator = NW_NS_DOS; 629 finfo.i.NSCreator = NW_NS_DOS;
630 #endif 630 #endif
631 finfo.volume = NCP_NUMBER_OF_VOLUMES; 631 finfo.volume = NCP_NUMBER_OF_VOLUMES;
632 /* set dates of mountpoint to Jan 1, 1986; 00:00 */ 632 /* set dates of mountpoint to Jan 1, 1986; 00:00 */
633 finfo.i.creationTime = finfo.i.modifyTime 633 finfo.i.creationTime = finfo.i.modifyTime
634 = cpu_to_le16(0x0000); 634 = cpu_to_le16(0x0000);
635 finfo.i.creationDate = finfo.i.modifyDate 635 finfo.i.creationDate = finfo.i.modifyDate
636 = finfo.i.lastAccessDate 636 = finfo.i.lastAccessDate
637 = cpu_to_le16(0x0C21); 637 = cpu_to_le16(0x0C21);
638 finfo.i.nameLen = 0; 638 finfo.i.nameLen = 0;
639 finfo.i.entryName[0] = '\0'; 639 finfo.i.entryName[0] = '\0';
640 640
641 finfo.opened = 0; 641 finfo.opened = 0;
642 finfo.ino = 2; /* tradition */ 642 finfo.ino = 2; /* tradition */
643 643
644 server->name_space[finfo.volume] = NW_NS_DOS; 644 server->name_space[finfo.volume] = NW_NS_DOS;
645 645
646 error = -ENOMEM; 646 error = -ENOMEM;
647 root_inode = ncp_iget(sb, &finfo); 647 root_inode = ncp_iget(sb, &finfo);
648 if (!root_inode) 648 if (!root_inode)
649 goto out_disconnect; 649 goto out_disconnect;
650 DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber); 650 DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
651 sb->s_root = d_alloc_root(root_inode); 651 sb->s_root = d_alloc_root(root_inode);
652 if (!sb->s_root) 652 if (!sb->s_root)
653 goto out_no_root; 653 goto out_no_root;
654 sb->s_root->d_op = &ncp_root_dentry_operations; 654 sb->s_root->d_op = &ncp_root_dentry_operations;
655 return 0; 655 return 0;
656 656
657 out_no_root: 657 out_no_root:
658 iput(root_inode); 658 iput(root_inode);
659 out_disconnect: 659 out_disconnect:
660 ncp_lock_server(server); 660 ncp_lock_server(server);
661 ncp_disconnect(server); 661 ncp_disconnect(server);
662 ncp_unlock_server(server); 662 ncp_unlock_server(server);
663 out_packet: 663 out_packet:
664 ncp_stop_tasks(server); 664 ncp_stop_tasks(server);
665 vfree(server->packet); 665 vfree(server->packet);
666 out_nls: 666 out_nls:
667 #ifdef CONFIG_NCPFS_NLS 667 #ifdef CONFIG_NCPFS_NLS
668 unload_nls(server->nls_io); 668 unload_nls(server->nls_io);
669 unload_nls(server->nls_vol); 669 unload_nls(server->nls_vol);
670 #endif 670 #endif
671 out_fput2: 671 out_fput2:
672 if (server->info_filp) 672 if (server->info_filp)
673 fput(server->info_filp); 673 fput(server->info_filp);
674 out_fput: 674 out_fput:
675 /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>: 675 /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
676 * 676 *
677 * The previously used put_filp(ncp_filp); was bogous, since 677 * The previously used put_filp(ncp_filp); was bogous, since
678 * it doesn't proper unlocking. 678 * it doesn't proper unlocking.
679 */ 679 */
680 fput(ncp_filp); 680 fput(ncp_filp);
681 out: 681 out:
682 sb->s_fs_info = NULL; 682 sb->s_fs_info = NULL;
683 kfree(server); 683 kfree(server);
684 return error; 684 return error;
685 } 685 }
686 686
687 static void ncp_put_super(struct super_block *sb) 687 static void ncp_put_super(struct super_block *sb)
688 { 688 {
689 struct ncp_server *server = NCP_SBP(sb); 689 struct ncp_server *server = NCP_SBP(sb);
690 690
691 ncp_lock_server(server); 691 ncp_lock_server(server);
692 ncp_disconnect(server); 692 ncp_disconnect(server);
693 ncp_unlock_server(server); 693 ncp_unlock_server(server);
694 694
695 ncp_stop_tasks(server); 695 ncp_stop_tasks(server);
696 696
697 #ifdef CONFIG_NCPFS_NLS 697 #ifdef CONFIG_NCPFS_NLS
698 /* unload the NLS charsets */ 698 /* unload the NLS charsets */
699 if (server->nls_vol) 699 if (server->nls_vol)
700 { 700 {
701 unload_nls(server->nls_vol); 701 unload_nls(server->nls_vol);
702 server->nls_vol = NULL; 702 server->nls_vol = NULL;
703 } 703 }
704 if (server->nls_io) 704 if (server->nls_io)
705 { 705 {
706 unload_nls(server->nls_io); 706 unload_nls(server->nls_io);
707 server->nls_io = NULL; 707 server->nls_io = NULL;
708 } 708 }
709 #endif /* CONFIG_NCPFS_NLS */ 709 #endif /* CONFIG_NCPFS_NLS */
710 710
711 if (server->info_filp) 711 if (server->info_filp)
712 fput(server->info_filp); 712 fput(server->info_filp);
713 fput(server->ncp_filp); 713 fput(server->ncp_filp);
714 kill_proc(server->m.wdog_pid, SIGTERM, 1); 714 kill_proc(server->m.wdog_pid, SIGTERM, 1);
715 715
716 kfree(server->priv.data); 716 kfree(server->priv.data);
717 kfree(server->auth.object_name); 717 kfree(server->auth.object_name);
718 vfree(server->packet); 718 vfree(server->packet);
719 sb->s_fs_info = NULL; 719 sb->s_fs_info = NULL;
720 kfree(server); 720 kfree(server);
721 } 721 }
722 722
723 static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf) 723 static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
724 { 724 {
725 struct dentry* d; 725 struct dentry* d;
726 struct inode* i; 726 struct inode* i;
727 struct ncp_inode_info* ni; 727 struct ncp_inode_info* ni;
728 struct ncp_server* s; 728 struct ncp_server* s;
729 struct ncp_volume_info vi; 729 struct ncp_volume_info vi;
730 struct super_block *sb = dentry->d_sb; 730 struct super_block *sb = dentry->d_sb;
731 int err; 731 int err;
732 __u8 dh; 732 __u8 dh;
733 733
734 d = sb->s_root; 734 d = sb->s_root;
735 if (!d) { 735 if (!d) {
736 goto dflt; 736 goto dflt;
737 } 737 }
738 i = d->d_inode; 738 i = d->d_inode;
739 if (!i) { 739 if (!i) {
740 goto dflt; 740 goto dflt;
741 } 741 }
742 ni = NCP_FINFO(i); 742 ni = NCP_FINFO(i);
743 if (!ni) { 743 if (!ni) {
744 goto dflt; 744 goto dflt;
745 } 745 }
746 s = NCP_SBP(sb); 746 s = NCP_SBP(sb);
747 if (!s) { 747 if (!s) {
748 goto dflt; 748 goto dflt;
749 } 749 }
750 if (!s->m.mounted_vol[0]) { 750 if (!s->m.mounted_vol[0]) {
751 goto dflt; 751 goto dflt;
752 } 752 }
753 753
754 err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh); 754 err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh);
755 if (err) { 755 if (err) {
756 goto dflt; 756 goto dflt;
757 } 757 }
758 err = ncp_get_directory_info(s, dh, &vi); 758 err = ncp_get_directory_info(s, dh, &vi);
759 ncp_dirhandle_free(s, dh); 759 ncp_dirhandle_free(s, dh);
760 if (err) { 760 if (err) {
761 goto dflt; 761 goto dflt;
762 } 762 }
763 buf->f_type = NCP_SUPER_MAGIC; 763 buf->f_type = NCP_SUPER_MAGIC;
764 buf->f_bsize = vi.sectors_per_block * 512; 764 buf->f_bsize = vi.sectors_per_block * 512;
765 buf->f_blocks = vi.total_blocks; 765 buf->f_blocks = vi.total_blocks;
766 buf->f_bfree = vi.free_blocks; 766 buf->f_bfree = vi.free_blocks;
767 buf->f_bavail = vi.free_blocks; 767 buf->f_bavail = vi.free_blocks;
768 buf->f_files = vi.total_dir_entries; 768 buf->f_files = vi.total_dir_entries;
769 buf->f_ffree = vi.available_dir_entries; 769 buf->f_ffree = vi.available_dir_entries;
770 buf->f_namelen = 12; 770 buf->f_namelen = 12;
771 return 0; 771 return 0;
772 772
773 /* We cannot say how much disk space is left on a mounted 773 /* We cannot say how much disk space is left on a mounted
774 NetWare Server, because free space is distributed over 774 NetWare Server, because free space is distributed over
775 volumes, and the current user might have disk quotas. So 775 volumes, and the current user might have disk quotas. So
776 free space is not that simple to determine. Our decision 776 free space is not that simple to determine. Our decision
777 here is to err conservatively. */ 777 here is to err conservatively. */
778 778
779 dflt:; 779 dflt:;
780 buf->f_type = NCP_SUPER_MAGIC; 780 buf->f_type = NCP_SUPER_MAGIC;
781 buf->f_bsize = NCP_BLOCK_SIZE; 781 buf->f_bsize = NCP_BLOCK_SIZE;
782 buf->f_blocks = 0; 782 buf->f_blocks = 0;
783 buf->f_bfree = 0; 783 buf->f_bfree = 0;
784 buf->f_bavail = 0; 784 buf->f_bavail = 0;
785 buf->f_namelen = 12; 785 buf->f_namelen = 12;
786 return 0; 786 return 0;
787 } 787 }
788 788
789 int ncp_notify_change(struct dentry *dentry, struct iattr *attr) 789 int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
790 { 790 {
791 struct inode *inode = dentry->d_inode; 791 struct inode *inode = dentry->d_inode;
792 int result = 0; 792 int result = 0;
793 __le32 info_mask; 793 __le32 info_mask;
794 struct nw_modify_dos_info info; 794 struct nw_modify_dos_info info;
795 struct ncp_server *server; 795 struct ncp_server *server;
796 796
797 result = -EIO; 797 result = -EIO;
798 798
799 lock_kernel(); 799 lock_kernel();
800 800
801 server = NCP_SERVER(inode); 801 server = NCP_SERVER(inode);
802 if ((!server) || !ncp_conn_valid(server)) 802 if ((!server) || !ncp_conn_valid(server))
803 goto out; 803 goto out;
804 804
805 /* ageing the dentry to force validation */ 805 /* ageing the dentry to force validation */
806 ncp_age_dentry(server, dentry); 806 ncp_age_dentry(server, dentry);
807 807
808 result = inode_change_ok(inode, attr); 808 result = inode_change_ok(inode, attr);
809 if (result < 0) 809 if (result < 0)
810 goto out; 810 goto out;
811 811
812 result = -EPERM; 812 result = -EPERM;
813 if (((attr->ia_valid & ATTR_UID) && 813 if (((attr->ia_valid & ATTR_UID) &&
814 (attr->ia_uid != server->m.uid))) 814 (attr->ia_uid != server->m.uid)))
815 goto out; 815 goto out;
816 816
817 if (((attr->ia_valid & ATTR_GID) && 817 if (((attr->ia_valid & ATTR_GID) &&
818 (attr->ia_gid != server->m.gid))) 818 (attr->ia_gid != server->m.gid)))
819 goto out; 819 goto out;
820 820
821 if (((attr->ia_valid & ATTR_MODE) && 821 if (((attr->ia_valid & ATTR_MODE) &&
822 (attr->ia_mode & 822 (attr->ia_mode &
823 ~(S_IFREG | S_IFDIR | S_IRWXUGO)))) 823 ~(S_IFREG | S_IFDIR | S_IRWXUGO))))
824 goto out; 824 goto out;
825 825
826 info_mask = 0; 826 info_mask = 0;
827 memset(&info, 0, sizeof(info)); 827 memset(&info, 0, sizeof(info));
828 828
829 #if 1 829 #if 1
830 if ((attr->ia_valid & ATTR_MODE) != 0) 830 if ((attr->ia_valid & ATTR_MODE) != 0)
831 { 831 {
832 umode_t newmode = attr->ia_mode; 832 umode_t newmode = attr->ia_mode;
833 833
834 info_mask |= DM_ATTRIBUTES; 834 info_mask |= DM_ATTRIBUTES;
835 835
836 if (S_ISDIR(inode->i_mode)) { 836 if (S_ISDIR(inode->i_mode)) {
837 newmode &= server->m.dir_mode; 837 newmode &= server->m.dir_mode;
838 } else { 838 } else {
839 #ifdef CONFIG_NCPFS_EXTRAS 839 #ifdef CONFIG_NCPFS_EXTRAS
840 if (server->m.flags & NCP_MOUNT_EXTRAS) { 840 if (server->m.flags & NCP_MOUNT_EXTRAS) {
841 /* any non-default execute bit set */ 841 /* any non-default execute bit set */
842 if (newmode & ~server->m.file_mode & S_IXUGO) 842 if (newmode & ~server->m.file_mode & S_IXUGO)
843 info.attributes |= aSHARED | aSYSTEM; 843 info.attributes |= aSHARED | aSYSTEM;
844 /* read for group/world and not in default file_mode */ 844 /* read for group/world and not in default file_mode */
845 else if (newmode & ~server->m.file_mode & S_IRUGO) 845 else if (newmode & ~server->m.file_mode & S_IRUGO)
846 info.attributes |= aSHARED; 846 info.attributes |= aSHARED;
847 } else 847 } else
848 #endif 848 #endif
849 newmode &= server->m.file_mode; 849 newmode &= server->m.file_mode;
850 } 850 }
851 if (newmode & S_IWUGO) 851 if (newmode & S_IWUGO)
852 info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); 852 info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
853 else 853 else
854 info.attributes |= (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT); 854 info.attributes |= (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
855 855
856 #ifdef CONFIG_NCPFS_NFS_NS 856 #ifdef CONFIG_NCPFS_NFS_NS
857 if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) { 857 if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) {
858 result = ncp_modify_nfs_info(server, 858 result = ncp_modify_nfs_info(server,
859 NCP_FINFO(inode)->volNumber, 859 NCP_FINFO(inode)->volNumber,
860 NCP_FINFO(inode)->dirEntNum, 860 NCP_FINFO(inode)->dirEntNum,
861 attr->ia_mode, 0); 861 attr->ia_mode, 0);
862 if (result != 0) 862 if (result != 0)
863 goto out; 863 goto out;
864 info.attributes &= ~(aSHARED | aSYSTEM); 864 info.attributes &= ~(aSHARED | aSYSTEM);
865 { 865 {
866 /* mark partial success */ 866 /* mark partial success */
867 struct iattr tmpattr; 867 struct iattr tmpattr;
868 868
869 tmpattr.ia_valid = ATTR_MODE; 869 tmpattr.ia_valid = ATTR_MODE;
870 tmpattr.ia_mode = attr->ia_mode; 870 tmpattr.ia_mode = attr->ia_mode;
871 871
872 result = inode_setattr(inode, &tmpattr); 872 result = inode_setattr(inode, &tmpattr);
873 if (result) 873 if (result)
874 goto out; 874 goto out;
875 } 875 }
876 } 876 }
877 #endif 877 #endif
878 } 878 }
879 #endif 879 #endif
880 880
881 /* Do SIZE before attributes, otherwise mtime together with size does not work... 881 /* Do SIZE before attributes, otherwise mtime together with size does not work...
882 */ 882 */
883 if ((attr->ia_valid & ATTR_SIZE) != 0) { 883 if ((attr->ia_valid & ATTR_SIZE) != 0) {
884 int written; 884 int written;
885 885
886 DPRINTK("ncpfs: trying to change size to %ld\n", 886 DPRINTK("ncpfs: trying to change size to %ld\n",
887 attr->ia_size); 887 attr->ia_size);
888 888
889 if ((result = ncp_make_open(inode, O_WRONLY)) < 0) { 889 if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
890 result = -EACCES; 890 result = -EACCES;
891 goto out; 891 goto out;
892 } 892 }
893 ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, 893 ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
894 attr->ia_size, 0, "", &written); 894 attr->ia_size, 0, "", &written);
895 895
896 /* According to ndir, the changes only take effect after 896 /* According to ndir, the changes only take effect after
897 closing the file */ 897 closing the file */
898 ncp_inode_close(inode); 898 ncp_inode_close(inode);
899 result = ncp_make_closed(inode); 899 result = ncp_make_closed(inode);
900 if (result) 900 if (result)
901 goto out; 901 goto out;
902 { 902 {
903 struct iattr tmpattr; 903 struct iattr tmpattr;
904 904
905 tmpattr.ia_valid = ATTR_SIZE; 905 tmpattr.ia_valid = ATTR_SIZE;
906 tmpattr.ia_size = attr->ia_size; 906 tmpattr.ia_size = attr->ia_size;
907 907
908 result = inode_setattr(inode, &tmpattr); 908 result = inode_setattr(inode, &tmpattr);
909 if (result) 909 if (result)
910 goto out; 910 goto out;
911 } 911 }
912 } 912 }
913 if ((attr->ia_valid & ATTR_CTIME) != 0) { 913 if ((attr->ia_valid & ATTR_CTIME) != 0) {
914 info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE); 914 info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
915 ncp_date_unix2dos(attr->ia_ctime.tv_sec, 915 ncp_date_unix2dos(attr->ia_ctime.tv_sec,
916 &info.creationTime, &info.creationDate); 916 &info.creationTime, &info.creationDate);
917 } 917 }
918 if ((attr->ia_valid & ATTR_MTIME) != 0) { 918 if ((attr->ia_valid & ATTR_MTIME) != 0) {
919 info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE); 919 info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
920 ncp_date_unix2dos(attr->ia_mtime.tv_sec, 920 ncp_date_unix2dos(attr->ia_mtime.tv_sec,
921 &info.modifyTime, &info.modifyDate); 921 &info.modifyTime, &info.modifyDate);
922 } 922 }
923 if ((attr->ia_valid & ATTR_ATIME) != 0) { 923 if ((attr->ia_valid & ATTR_ATIME) != 0) {
924 __le16 dummy; 924 __le16 dummy;
925 info_mask |= (DM_LAST_ACCESS_DATE); 925 info_mask |= (DM_LAST_ACCESS_DATE);
926 ncp_date_unix2dos(attr->ia_atime.tv_sec, 926 ncp_date_unix2dos(attr->ia_atime.tv_sec,
927 &dummy, &info.lastAccessDate); 927 &dummy, &info.lastAccessDate);
928 } 928 }
929 if (info_mask != 0) { 929 if (info_mask != 0) {
930 result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode), 930 result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
931 inode, info_mask, &info); 931 inode, info_mask, &info);
932 if (result != 0) { 932 if (result != 0) {
933 result = -EACCES; 933 result = -EACCES;
934 934
935 if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) { 935 if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
936 /* NetWare seems not to allow this. I 936 /* NetWare seems not to allow this. I
937 do not know why. So, just tell the 937 do not know why. So, just tell the
938 user everything went fine. This is 938 user everything went fine. This is
939 a terrible hack, but I do not know 939 a terrible hack, but I do not know
940 how to do this correctly. */ 940 how to do this correctly. */
941 result = 0; 941 result = 0;
942 } else 942 } else
943 goto out; 943 goto out;
944 } 944 }
945 #ifdef CONFIG_NCPFS_STRONG 945 #ifdef CONFIG_NCPFS_STRONG
946 if ((!result) && (info_mask & DM_ATTRIBUTES)) 946 if ((!result) && (info_mask & DM_ATTRIBUTES))
947 NCP_FINFO(inode)->nwattr = info.attributes; 947 NCP_FINFO(inode)->nwattr = info.attributes;
948 #endif 948 #endif
949 } 949 }
950 if (!result) 950 if (!result)
951 result = inode_setattr(inode, attr); 951 result = inode_setattr(inode, attr);
952 out: 952 out:
953 unlock_kernel(); 953 unlock_kernel();
954 return result; 954 return result;
955 } 955 }
956 956
957 static int ncp_get_sb(struct file_system_type *fs_type, 957 static int ncp_get_sb(struct file_system_type *fs_type,
958 int flags, const char *dev_name, void *data, struct vfsmount *mnt) 958 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
959 { 959 {
960 return get_sb_nodev(fs_type, flags, data, ncp_fill_super, mnt); 960 return get_sb_nodev(fs_type, flags, data, ncp_fill_super, mnt);
961 } 961 }
962 962
963 static struct file_system_type ncp_fs_type = { 963 static struct file_system_type ncp_fs_type = {
964 .owner = THIS_MODULE, 964 .owner = THIS_MODULE,
965 .name = "ncpfs", 965 .name = "ncpfs",
966 .get_sb = ncp_get_sb, 966 .get_sb = ncp_get_sb,
967 .kill_sb = kill_anon_super, 967 .kill_sb = kill_anon_super,
968 }; 968 };
969 969
970 static int __init init_ncp_fs(void) 970 static int __init init_ncp_fs(void)
971 { 971 {
972 int err; 972 int err;
973 DPRINTK("ncpfs: init_module called\n"); 973 DPRINTK("ncpfs: init_module called\n");
974 974
975 err = init_inodecache(); 975 err = init_inodecache();
976 if (err) 976 if (err)
977 goto out1; 977 goto out1;
978 err = register_filesystem(&ncp_fs_type); 978 err = register_filesystem(&ncp_fs_type);
979 if (err) 979 if (err)
980 goto out; 980 goto out;
981 return 0; 981 return 0;
982 out: 982 out:
983 destroy_inodecache(); 983 destroy_inodecache();
984 out1: 984 out1:
985 return err; 985 return err;
986 } 986 }
987 987
988 static void __exit exit_ncp_fs(void) 988 static void __exit exit_ncp_fs(void)
989 { 989 {
990 DPRINTK("ncpfs: cleanup_module called\n"); 990 DPRINTK("ncpfs: cleanup_module called\n");
991 unregister_filesystem(&ncp_fs_type); 991 unregister_filesystem(&ncp_fs_type);
992 destroy_inodecache(); 992 destroy_inodecache();
993 } 993 }
994 994
995 module_init(init_ncp_fs) 995 module_init(init_ncp_fs)
996 module_exit(exit_ncp_fs) 996 module_exit(exit_ncp_fs)
997 MODULE_LICENSE("GPL"); 997 MODULE_LICENSE("GPL");
998 998
1 /* 1 /*
2 * ioctl.c 2 * ioctl.c
3 * 3 *
4 * Copyright (C) 1995, 1996 by Volker Lendecke 4 * Copyright (C) 1995, 1996 by Volker Lendecke
5 * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache 5 * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
6 * Modified 1998, 1999 Wolfram Pienkoss for NLS 6 * Modified 1998, 1999 Wolfram Pienkoss for NLS
7 * 7 *
8 */ 8 */
9 9
10 #include <linux/capability.h> 10 #include <linux/capability.h>
11 #include <linux/compat.h> 11 #include <linux/compat.h>
12 #include <linux/errno.h> 12 #include <linux/errno.h>
13 #include <linux/fs.h> 13 #include <linux/fs.h>
14 #include <linux/ioctl.h> 14 #include <linux/ioctl.h>
15 #include <linux/time.h> 15 #include <linux/time.h>
16 #include <linux/mm.h> 16 #include <linux/mm.h>
17 #include <linux/highuid.h> 17 #include <linux/highuid.h>
18 #include <linux/smp_lock.h> 18 #include <linux/smp_lock.h>
19 #include <linux/vmalloc.h> 19 #include <linux/vmalloc.h>
20 20
21 #include <linux/ncp_fs.h> 21 #include <linux/ncp_fs.h>
22 22
23 #include <asm/uaccess.h> 23 #include <asm/uaccess.h>
24 24
25 #include "ncplib_kernel.h" 25 #include "ncplib_kernel.h"
26 26
27 /* maximum limit for ncp_objectname_ioctl */ 27 /* maximum limit for ncp_objectname_ioctl */
28 #define NCP_OBJECT_NAME_MAX_LEN 4096 28 #define NCP_OBJECT_NAME_MAX_LEN 4096
29 /* maximum limit for ncp_privatedata_ioctl */ 29 /* maximum limit for ncp_privatedata_ioctl */
30 #define NCP_PRIVATE_DATA_MAX_LEN 8192 30 #define NCP_PRIVATE_DATA_MAX_LEN 8192
31 /* maximum negotiable packet size */ 31 /* maximum negotiable packet size */
32 #define NCP_PACKET_SIZE_INTERNAL 65536 32 #define NCP_PACKET_SIZE_INTERNAL 65536
33 33
34 static int 34 static int
35 ncp_get_fs_info(struct ncp_server * server, struct file *file, 35 ncp_get_fs_info(struct ncp_server * server, struct file *file,
36 struct ncp_fs_info __user *arg) 36 struct ncp_fs_info __user *arg)
37 { 37 {
38 struct inode *inode = file->f_dentry->d_inode; 38 struct inode *inode = file->f_path.dentry->d_inode;
39 struct ncp_fs_info info; 39 struct ncp_fs_info info;
40 40
41 if ((file_permission(file, MAY_WRITE) != 0) 41 if ((file_permission(file, MAY_WRITE) != 0)
42 && (current->uid != server->m.mounted_uid)) { 42 && (current->uid != server->m.mounted_uid)) {
43 return -EACCES; 43 return -EACCES;
44 } 44 }
45 if (copy_from_user(&info, arg, sizeof(info))) 45 if (copy_from_user(&info, arg, sizeof(info)))
46 return -EFAULT; 46 return -EFAULT;
47 47
48 if (info.version != NCP_GET_FS_INFO_VERSION) { 48 if (info.version != NCP_GET_FS_INFO_VERSION) {
49 DPRINTK("info.version invalid: %d\n", info.version); 49 DPRINTK("info.version invalid: %d\n", info.version);
50 return -EINVAL; 50 return -EINVAL;
51 } 51 }
52 /* TODO: info.addr = server->m.serv_addr; */ 52 /* TODO: info.addr = server->m.serv_addr; */
53 SET_UID(info.mounted_uid, server->m.mounted_uid); 53 SET_UID(info.mounted_uid, server->m.mounted_uid);
54 info.connection = server->connection; 54 info.connection = server->connection;
55 info.buffer_size = server->buffer_size; 55 info.buffer_size = server->buffer_size;
56 info.volume_number = NCP_FINFO(inode)->volNumber; 56 info.volume_number = NCP_FINFO(inode)->volNumber;
57 info.directory_id = NCP_FINFO(inode)->DosDirNum; 57 info.directory_id = NCP_FINFO(inode)->DosDirNum;
58 58
59 if (copy_to_user(arg, &info, sizeof(info))) 59 if (copy_to_user(arg, &info, sizeof(info)))
60 return -EFAULT; 60 return -EFAULT;
61 return 0; 61 return 0;
62 } 62 }
63 63
64 static int 64 static int
65 ncp_get_fs_info_v2(struct ncp_server * server, struct file *file, 65 ncp_get_fs_info_v2(struct ncp_server * server, struct file *file,
66 struct ncp_fs_info_v2 __user * arg) 66 struct ncp_fs_info_v2 __user * arg)
67 { 67 {
68 struct inode *inode = file->f_dentry->d_inode; 68 struct inode *inode = file->f_path.dentry->d_inode;
69 struct ncp_fs_info_v2 info2; 69 struct ncp_fs_info_v2 info2;
70 70
71 if ((file_permission(file, MAY_WRITE) != 0) 71 if ((file_permission(file, MAY_WRITE) != 0)
72 && (current->uid != server->m.mounted_uid)) { 72 && (current->uid != server->m.mounted_uid)) {
73 return -EACCES; 73 return -EACCES;
74 } 74 }
75 if (copy_from_user(&info2, arg, sizeof(info2))) 75 if (copy_from_user(&info2, arg, sizeof(info2)))
76 return -EFAULT; 76 return -EFAULT;
77 77
78 if (info2.version != NCP_GET_FS_INFO_VERSION_V2) { 78 if (info2.version != NCP_GET_FS_INFO_VERSION_V2) {
79 DPRINTK("info.version invalid: %d\n", info2.version); 79 DPRINTK("info.version invalid: %d\n", info2.version);
80 return -EINVAL; 80 return -EINVAL;
81 } 81 }
82 info2.mounted_uid = server->m.mounted_uid; 82 info2.mounted_uid = server->m.mounted_uid;
83 info2.connection = server->connection; 83 info2.connection = server->connection;
84 info2.buffer_size = server->buffer_size; 84 info2.buffer_size = server->buffer_size;
85 info2.volume_number = NCP_FINFO(inode)->volNumber; 85 info2.volume_number = NCP_FINFO(inode)->volNumber;
86 info2.directory_id = NCP_FINFO(inode)->DosDirNum; 86 info2.directory_id = NCP_FINFO(inode)->DosDirNum;
87 info2.dummy1 = info2.dummy2 = info2.dummy3 = 0; 87 info2.dummy1 = info2.dummy2 = info2.dummy3 = 0;
88 88
89 if (copy_to_user(arg, &info2, sizeof(info2))) 89 if (copy_to_user(arg, &info2, sizeof(info2)))
90 return -EFAULT; 90 return -EFAULT;
91 return 0; 91 return 0;
92 } 92 }
93 93
94 #ifdef CONFIG_COMPAT 94 #ifdef CONFIG_COMPAT
95 struct compat_ncp_objectname_ioctl 95 struct compat_ncp_objectname_ioctl
96 { 96 {
97 s32 auth_type; 97 s32 auth_type;
98 u32 object_name_len; 98 u32 object_name_len;
99 compat_caddr_t object_name; /* an userspace data, in most cases user name */ 99 compat_caddr_t object_name; /* an userspace data, in most cases user name */
100 }; 100 };
101 101
102 struct compat_ncp_fs_info_v2 { 102 struct compat_ncp_fs_info_v2 {
103 s32 version; 103 s32 version;
104 u32 mounted_uid; 104 u32 mounted_uid;
105 u32 connection; 105 u32 connection;
106 u32 buffer_size; 106 u32 buffer_size;
107 107
108 u32 volume_number; 108 u32 volume_number;
109 u32 directory_id; 109 u32 directory_id;
110 110
111 u32 dummy1; 111 u32 dummy1;
112 u32 dummy2; 112 u32 dummy2;
113 u32 dummy3; 113 u32 dummy3;
114 }; 114 };
115 115
116 struct compat_ncp_ioctl_request { 116 struct compat_ncp_ioctl_request {
117 u32 function; 117 u32 function;
118 u32 size; 118 u32 size;
119 compat_caddr_t data; 119 compat_caddr_t data;
120 }; 120 };
121 121
122 struct compat_ncp_privatedata_ioctl 122 struct compat_ncp_privatedata_ioctl
123 { 123 {
124 u32 len; 124 u32 len;
125 compat_caddr_t data; /* ~1000 for NDS */ 125 compat_caddr_t data; /* ~1000 for NDS */
126 }; 126 };
127 127
128 #define NCP_IOC_GET_FS_INFO_V2_32 _IOWR('n', 4, struct compat_ncp_fs_info_v2) 128 #define NCP_IOC_GET_FS_INFO_V2_32 _IOWR('n', 4, struct compat_ncp_fs_info_v2)
129 #define NCP_IOC_NCPREQUEST_32 _IOR('n', 1, struct compat_ncp_ioctl_request) 129 #define NCP_IOC_NCPREQUEST_32 _IOR('n', 1, struct compat_ncp_ioctl_request)
130 #define NCP_IOC_GETOBJECTNAME_32 _IOWR('n', 9, struct compat_ncp_objectname_ioctl) 130 #define NCP_IOC_GETOBJECTNAME_32 _IOWR('n', 9, struct compat_ncp_objectname_ioctl)
131 #define NCP_IOC_SETOBJECTNAME_32 _IOR('n', 9, struct compat_ncp_objectname_ioctl) 131 #define NCP_IOC_SETOBJECTNAME_32 _IOR('n', 9, struct compat_ncp_objectname_ioctl)
132 #define NCP_IOC_GETPRIVATEDATA_32 _IOWR('n', 10, struct compat_ncp_privatedata_ioctl) 132 #define NCP_IOC_GETPRIVATEDATA_32 _IOWR('n', 10, struct compat_ncp_privatedata_ioctl)
133 #define NCP_IOC_SETPRIVATEDATA_32 _IOR('n', 10, struct compat_ncp_privatedata_ioctl) 133 #define NCP_IOC_SETPRIVATEDATA_32 _IOR('n', 10, struct compat_ncp_privatedata_ioctl)
134 134
135 static int 135 static int
136 ncp_get_compat_fs_info_v2(struct ncp_server * server, struct file *file, 136 ncp_get_compat_fs_info_v2(struct ncp_server * server, struct file *file,
137 struct compat_ncp_fs_info_v2 __user * arg) 137 struct compat_ncp_fs_info_v2 __user * arg)
138 { 138 {
139 struct inode *inode = file->f_dentry->d_inode; 139 struct inode *inode = file->f_path.dentry->d_inode;
140 struct compat_ncp_fs_info_v2 info2; 140 struct compat_ncp_fs_info_v2 info2;
141 141
142 if ((file_permission(file, MAY_WRITE) != 0) 142 if ((file_permission(file, MAY_WRITE) != 0)
143 && (current->uid != server->m.mounted_uid)) { 143 && (current->uid != server->m.mounted_uid)) {
144 return -EACCES; 144 return -EACCES;
145 } 145 }
146 if (copy_from_user(&info2, arg, sizeof(info2))) 146 if (copy_from_user(&info2, arg, sizeof(info2)))
147 return -EFAULT; 147 return -EFAULT;
148 148
149 if (info2.version != NCP_GET_FS_INFO_VERSION_V2) { 149 if (info2.version != NCP_GET_FS_INFO_VERSION_V2) {
150 DPRINTK("info.version invalid: %d\n", info2.version); 150 DPRINTK("info.version invalid: %d\n", info2.version);
151 return -EINVAL; 151 return -EINVAL;
152 } 152 }
153 info2.mounted_uid = server->m.mounted_uid; 153 info2.mounted_uid = server->m.mounted_uid;
154 info2.connection = server->connection; 154 info2.connection = server->connection;
155 info2.buffer_size = server->buffer_size; 155 info2.buffer_size = server->buffer_size;
156 info2.volume_number = NCP_FINFO(inode)->volNumber; 156 info2.volume_number = NCP_FINFO(inode)->volNumber;
157 info2.directory_id = NCP_FINFO(inode)->DosDirNum; 157 info2.directory_id = NCP_FINFO(inode)->DosDirNum;
158 info2.dummy1 = info2.dummy2 = info2.dummy3 = 0; 158 info2.dummy1 = info2.dummy2 = info2.dummy3 = 0;
159 159
160 if (copy_to_user(arg, &info2, sizeof(info2))) 160 if (copy_to_user(arg, &info2, sizeof(info2)))
161 return -EFAULT; 161 return -EFAULT;
162 return 0; 162 return 0;
163 } 163 }
164 #endif 164 #endif
165 165
166 #define NCP_IOC_GETMOUNTUID16 _IOW('n', 2, u16) 166 #define NCP_IOC_GETMOUNTUID16 _IOW('n', 2, u16)
167 #define NCP_IOC_GETMOUNTUID32 _IOW('n', 2, u32) 167 #define NCP_IOC_GETMOUNTUID32 _IOW('n', 2, u32)
168 #define NCP_IOC_GETMOUNTUID64 _IOW('n', 2, u64) 168 #define NCP_IOC_GETMOUNTUID64 _IOW('n', 2, u64)
169 169
170 #ifdef CONFIG_NCPFS_NLS 170 #ifdef CONFIG_NCPFS_NLS
171 /* Here we are select the iocharset and the codepage for NLS. 171 /* Here we are select the iocharset and the codepage for NLS.
172 * Thanks Petr Vandrovec for idea and many hints. 172 * Thanks Petr Vandrovec for idea and many hints.
173 */ 173 */
174 static int 174 static int
175 ncp_set_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg) 175 ncp_set_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg)
176 { 176 {
177 struct ncp_nls_ioctl user; 177 struct ncp_nls_ioctl user;
178 struct nls_table *codepage; 178 struct nls_table *codepage;
179 struct nls_table *iocharset; 179 struct nls_table *iocharset;
180 struct nls_table *oldset_io; 180 struct nls_table *oldset_io;
181 struct nls_table *oldset_cp; 181 struct nls_table *oldset_cp;
182 182
183 if (!capable(CAP_SYS_ADMIN)) 183 if (!capable(CAP_SYS_ADMIN))
184 return -EACCES; 184 return -EACCES;
185 if (server->root_setuped) 185 if (server->root_setuped)
186 return -EBUSY; 186 return -EBUSY;
187 187
188 if (copy_from_user(&user, arg, sizeof(user))) 188 if (copy_from_user(&user, arg, sizeof(user)))
189 return -EFAULT; 189 return -EFAULT;
190 190
191 codepage = NULL; 191 codepage = NULL;
192 user.codepage[NCP_IOCSNAME_LEN] = 0; 192 user.codepage[NCP_IOCSNAME_LEN] = 0;
193 if (!user.codepage[0] || !strcmp(user.codepage, "default")) 193 if (!user.codepage[0] || !strcmp(user.codepage, "default"))
194 codepage = load_nls_default(); 194 codepage = load_nls_default();
195 else { 195 else {
196 codepage = load_nls(user.codepage); 196 codepage = load_nls(user.codepage);
197 if (!codepage) { 197 if (!codepage) {
198 return -EBADRQC; 198 return -EBADRQC;
199 } 199 }
200 } 200 }
201 201
202 iocharset = NULL; 202 iocharset = NULL;
203 user.iocharset[NCP_IOCSNAME_LEN] = 0; 203 user.iocharset[NCP_IOCSNAME_LEN] = 0;
204 if (!user.iocharset[0] || !strcmp(user.iocharset, "default")) { 204 if (!user.iocharset[0] || !strcmp(user.iocharset, "default")) {
205 iocharset = load_nls_default(); 205 iocharset = load_nls_default();
206 NCP_CLR_FLAG(server, NCP_FLAG_UTF8); 206 NCP_CLR_FLAG(server, NCP_FLAG_UTF8);
207 } else if (!strcmp(user.iocharset, "utf8")) { 207 } else if (!strcmp(user.iocharset, "utf8")) {
208 iocharset = load_nls_default(); 208 iocharset = load_nls_default();
209 NCP_SET_FLAG(server, NCP_FLAG_UTF8); 209 NCP_SET_FLAG(server, NCP_FLAG_UTF8);
210 } else { 210 } else {
211 iocharset = load_nls(user.iocharset); 211 iocharset = load_nls(user.iocharset);
212 if (!iocharset) { 212 if (!iocharset) {
213 unload_nls(codepage); 213 unload_nls(codepage);
214 return -EBADRQC; 214 return -EBADRQC;
215 } 215 }
216 NCP_CLR_FLAG(server, NCP_FLAG_UTF8); 216 NCP_CLR_FLAG(server, NCP_FLAG_UTF8);
217 } 217 }
218 218
219 oldset_cp = server->nls_vol; 219 oldset_cp = server->nls_vol;
220 server->nls_vol = codepage; 220 server->nls_vol = codepage;
221 oldset_io = server->nls_io; 221 oldset_io = server->nls_io;
222 server->nls_io = iocharset; 222 server->nls_io = iocharset;
223 223
224 if (oldset_cp) 224 if (oldset_cp)
225 unload_nls(oldset_cp); 225 unload_nls(oldset_cp);
226 if (oldset_io) 226 if (oldset_io)
227 unload_nls(oldset_io); 227 unload_nls(oldset_io);
228 228
229 return 0; 229 return 0;
230 } 230 }
231 231
232 static int 232 static int
233 ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg) 233 ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg)
234 { 234 {
235 struct ncp_nls_ioctl user; 235 struct ncp_nls_ioctl user;
236 int len; 236 int len;
237 237
238 memset(&user, 0, sizeof(user)); 238 memset(&user, 0, sizeof(user));
239 if (server->nls_vol && server->nls_vol->charset) { 239 if (server->nls_vol && server->nls_vol->charset) {
240 len = strlen(server->nls_vol->charset); 240 len = strlen(server->nls_vol->charset);
241 if (len > NCP_IOCSNAME_LEN) 241 if (len > NCP_IOCSNAME_LEN)
242 len = NCP_IOCSNAME_LEN; 242 len = NCP_IOCSNAME_LEN;
243 strncpy(user.codepage, server->nls_vol->charset, len); 243 strncpy(user.codepage, server->nls_vol->charset, len);
244 user.codepage[len] = 0; 244 user.codepage[len] = 0;
245 } 245 }
246 246
247 if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) 247 if (NCP_IS_FLAG(server, NCP_FLAG_UTF8))
248 strcpy(user.iocharset, "utf8"); 248 strcpy(user.iocharset, "utf8");
249 else if (server->nls_io && server->nls_io->charset) { 249 else if (server->nls_io && server->nls_io->charset) {
250 len = strlen(server->nls_io->charset); 250 len = strlen(server->nls_io->charset);
251 if (len > NCP_IOCSNAME_LEN) 251 if (len > NCP_IOCSNAME_LEN)
252 len = NCP_IOCSNAME_LEN; 252 len = NCP_IOCSNAME_LEN;
253 strncpy(user.iocharset, server->nls_io->charset, len); 253 strncpy(user.iocharset, server->nls_io->charset, len);
254 user.iocharset[len] = 0; 254 user.iocharset[len] = 0;
255 } 255 }
256 256
257 if (copy_to_user(arg, &user, sizeof(user))) 257 if (copy_to_user(arg, &user, sizeof(user)))
258 return -EFAULT; 258 return -EFAULT;
259 return 0; 259 return 0;
260 } 260 }
261 #endif /* CONFIG_NCPFS_NLS */ 261 #endif /* CONFIG_NCPFS_NLS */
262 262
263 int ncp_ioctl(struct inode *inode, struct file *filp, 263 int ncp_ioctl(struct inode *inode, struct file *filp,
264 unsigned int cmd, unsigned long arg) 264 unsigned int cmd, unsigned long arg)
265 { 265 {
266 struct ncp_server *server = NCP_SERVER(inode); 266 struct ncp_server *server = NCP_SERVER(inode);
267 int result; 267 int result;
268 struct ncp_ioctl_request request; 268 struct ncp_ioctl_request request;
269 char* bouncebuffer; 269 char* bouncebuffer;
270 void __user *argp = (void __user *)arg; 270 void __user *argp = (void __user *)arg;
271 271
272 switch (cmd) { 272 switch (cmd) {
273 #ifdef CONFIG_COMPAT 273 #ifdef CONFIG_COMPAT
274 case NCP_IOC_NCPREQUEST_32: 274 case NCP_IOC_NCPREQUEST_32:
275 #endif 275 #endif
276 case NCP_IOC_NCPREQUEST: 276 case NCP_IOC_NCPREQUEST:
277 if ((file_permission(filp, MAY_WRITE) != 0) 277 if ((file_permission(filp, MAY_WRITE) != 0)
278 && (current->uid != server->m.mounted_uid)) { 278 && (current->uid != server->m.mounted_uid)) {
279 return -EACCES; 279 return -EACCES;
280 } 280 }
281 #ifdef CONFIG_COMPAT 281 #ifdef CONFIG_COMPAT
282 if (cmd == NCP_IOC_NCPREQUEST_32) { 282 if (cmd == NCP_IOC_NCPREQUEST_32) {
283 struct compat_ncp_ioctl_request request32; 283 struct compat_ncp_ioctl_request request32;
284 if (copy_from_user(&request32, argp, sizeof(request32))) 284 if (copy_from_user(&request32, argp, sizeof(request32)))
285 return -EFAULT; 285 return -EFAULT;
286 request.function = request32.function; 286 request.function = request32.function;
287 request.size = request32.size; 287 request.size = request32.size;
288 request.data = compat_ptr(request32.data); 288 request.data = compat_ptr(request32.data);
289 } else 289 } else
290 #endif 290 #endif
291 if (copy_from_user(&request, argp, sizeof(request))) 291 if (copy_from_user(&request, argp, sizeof(request)))
292 return -EFAULT; 292 return -EFAULT;
293 293
294 if ((request.function > 255) 294 if ((request.function > 255)
295 || (request.size > 295 || (request.size >
296 NCP_PACKET_SIZE - sizeof(struct ncp_request_header))) { 296 NCP_PACKET_SIZE - sizeof(struct ncp_request_header))) {
297 return -EINVAL; 297 return -EINVAL;
298 } 298 }
299 bouncebuffer = vmalloc(NCP_PACKET_SIZE_INTERNAL); 299 bouncebuffer = vmalloc(NCP_PACKET_SIZE_INTERNAL);
300 if (!bouncebuffer) 300 if (!bouncebuffer)
301 return -ENOMEM; 301 return -ENOMEM;
302 if (copy_from_user(bouncebuffer, request.data, request.size)) { 302 if (copy_from_user(bouncebuffer, request.data, request.size)) {
303 vfree(bouncebuffer); 303 vfree(bouncebuffer);
304 return -EFAULT; 304 return -EFAULT;
305 } 305 }
306 ncp_lock_server(server); 306 ncp_lock_server(server);
307 307
308 /* FIXME: We hack around in the server's structures 308 /* FIXME: We hack around in the server's structures
309 here to be able to use ncp_request */ 309 here to be able to use ncp_request */
310 310
311 server->has_subfunction = 0; 311 server->has_subfunction = 0;
312 server->current_size = request.size; 312 server->current_size = request.size;
313 memcpy(server->packet, bouncebuffer, request.size); 313 memcpy(server->packet, bouncebuffer, request.size);
314 314
315 result = ncp_request2(server, request.function, 315 result = ncp_request2(server, request.function,
316 bouncebuffer, NCP_PACKET_SIZE_INTERNAL); 316 bouncebuffer, NCP_PACKET_SIZE_INTERNAL);
317 if (result < 0) 317 if (result < 0)
318 result = -EIO; 318 result = -EIO;
319 else 319 else
320 result = server->reply_size; 320 result = server->reply_size;
321 ncp_unlock_server(server); 321 ncp_unlock_server(server);
322 DPRINTK("ncp_ioctl: copy %d bytes\n", 322 DPRINTK("ncp_ioctl: copy %d bytes\n",
323 result); 323 result);
324 if (result >= 0) 324 if (result >= 0)
325 if (copy_to_user(request.data, bouncebuffer, result)) 325 if (copy_to_user(request.data, bouncebuffer, result))
326 result = -EFAULT; 326 result = -EFAULT;
327 vfree(bouncebuffer); 327 vfree(bouncebuffer);
328 return result; 328 return result;
329 329
330 case NCP_IOC_CONN_LOGGED_IN: 330 case NCP_IOC_CONN_LOGGED_IN:
331 331
332 if (!capable(CAP_SYS_ADMIN)) 332 if (!capable(CAP_SYS_ADMIN))
333 return -EACCES; 333 return -EACCES;
334 if (!(server->m.int_flags & NCP_IMOUNT_LOGGEDIN_POSSIBLE)) 334 if (!(server->m.int_flags & NCP_IMOUNT_LOGGEDIN_POSSIBLE))
335 return -EINVAL; 335 return -EINVAL;
336 if (server->root_setuped) 336 if (server->root_setuped)
337 return -EBUSY; 337 return -EBUSY;
338 server->root_setuped = 1; 338 server->root_setuped = 1;
339 return ncp_conn_logged_in(inode->i_sb); 339 return ncp_conn_logged_in(inode->i_sb);
340 340
341 case NCP_IOC_GET_FS_INFO: 341 case NCP_IOC_GET_FS_INFO:
342 return ncp_get_fs_info(server, filp, argp); 342 return ncp_get_fs_info(server, filp, argp);
343 343
344 case NCP_IOC_GET_FS_INFO_V2: 344 case NCP_IOC_GET_FS_INFO_V2:
345 return ncp_get_fs_info_v2(server, filp, argp); 345 return ncp_get_fs_info_v2(server, filp, argp);
346 346
347 #ifdef CONFIG_COMPAT 347 #ifdef CONFIG_COMPAT
348 case NCP_IOC_GET_FS_INFO_V2_32: 348 case NCP_IOC_GET_FS_INFO_V2_32:
349 return ncp_get_compat_fs_info_v2(server, filp, argp); 349 return ncp_get_compat_fs_info_v2(server, filp, argp);
350 #endif 350 #endif
351 /* we have too many combinations of CONFIG_COMPAT, 351 /* we have too many combinations of CONFIG_COMPAT,
352 * CONFIG_64BIT and CONFIG_UID16, so just handle 352 * CONFIG_64BIT and CONFIG_UID16, so just handle
353 * any of the possible ioctls */ 353 * any of the possible ioctls */
354 case NCP_IOC_GETMOUNTUID16: 354 case NCP_IOC_GETMOUNTUID16:
355 case NCP_IOC_GETMOUNTUID32: 355 case NCP_IOC_GETMOUNTUID32:
356 case NCP_IOC_GETMOUNTUID64: 356 case NCP_IOC_GETMOUNTUID64:
357 if ((file_permission(filp, MAY_READ) != 0) 357 if ((file_permission(filp, MAY_READ) != 0)
358 && (current->uid != server->m.mounted_uid)) { 358 && (current->uid != server->m.mounted_uid)) {
359 return -EACCES; 359 return -EACCES;
360 } 360 }
361 if (cmd == NCP_IOC_GETMOUNTUID16) { 361 if (cmd == NCP_IOC_GETMOUNTUID16) {
362 u16 uid; 362 u16 uid;
363 SET_UID(uid, server->m.mounted_uid); 363 SET_UID(uid, server->m.mounted_uid);
364 if (put_user(uid, (u16 __user *)argp)) 364 if (put_user(uid, (u16 __user *)argp))
365 return -EFAULT; 365 return -EFAULT;
366 } else if (cmd == NCP_IOC_GETMOUNTUID32) { 366 } else if (cmd == NCP_IOC_GETMOUNTUID32) {
367 if (put_user(server->m.mounted_uid, 367 if (put_user(server->m.mounted_uid,
368 (u32 __user *)argp)) 368 (u32 __user *)argp))
369 return -EFAULT; 369 return -EFAULT;
370 } else { 370 } else {
371 if (put_user(server->m.mounted_uid, 371 if (put_user(server->m.mounted_uid,
372 (u64 __user *)argp)) 372 (u64 __user *)argp))
373 return -EFAULT; 373 return -EFAULT;
374 } 374 }
375 return 0; 375 return 0;
376 376
377 case NCP_IOC_GETROOT: 377 case NCP_IOC_GETROOT:
378 { 378 {
379 struct ncp_setroot_ioctl sr; 379 struct ncp_setroot_ioctl sr;
380 380
381 if ((file_permission(filp, MAY_READ) != 0) 381 if ((file_permission(filp, MAY_READ) != 0)
382 && (current->uid != server->m.mounted_uid)) 382 && (current->uid != server->m.mounted_uid))
383 { 383 {
384 return -EACCES; 384 return -EACCES;
385 } 385 }
386 if (server->m.mounted_vol[0]) { 386 if (server->m.mounted_vol[0]) {
387 struct dentry* dentry = inode->i_sb->s_root; 387 struct dentry* dentry = inode->i_sb->s_root;
388 388
389 if (dentry) { 389 if (dentry) {
390 struct inode* inode = dentry->d_inode; 390 struct inode* inode = dentry->d_inode;
391 391
392 if (inode) { 392 if (inode) {
393 sr.volNumber = NCP_FINFO(inode)->volNumber; 393 sr.volNumber = NCP_FINFO(inode)->volNumber;
394 sr.dirEntNum = NCP_FINFO(inode)->dirEntNum; 394 sr.dirEntNum = NCP_FINFO(inode)->dirEntNum;
395 sr.namespace = server->name_space[sr.volNumber]; 395 sr.namespace = server->name_space[sr.volNumber];
396 } else 396 } else
397 DPRINTK("ncpfs: s_root->d_inode==NULL\n"); 397 DPRINTK("ncpfs: s_root->d_inode==NULL\n");
398 } else 398 } else
399 DPRINTK("ncpfs: s_root==NULL\n"); 399 DPRINTK("ncpfs: s_root==NULL\n");
400 } else { 400 } else {
401 sr.volNumber = -1; 401 sr.volNumber = -1;
402 sr.namespace = 0; 402 sr.namespace = 0;
403 sr.dirEntNum = 0; 403 sr.dirEntNum = 0;
404 } 404 }
405 if (copy_to_user(argp, &sr, sizeof(sr))) 405 if (copy_to_user(argp, &sr, sizeof(sr)))
406 return -EFAULT; 406 return -EFAULT;
407 return 0; 407 return 0;
408 } 408 }
409 case NCP_IOC_SETROOT: 409 case NCP_IOC_SETROOT:
410 { 410 {
411 struct ncp_setroot_ioctl sr; 411 struct ncp_setroot_ioctl sr;
412 __u32 vnum; 412 __u32 vnum;
413 __le32 de; 413 __le32 de;
414 __le32 dosde; 414 __le32 dosde;
415 struct dentry* dentry; 415 struct dentry* dentry;
416 416
417 if (!capable(CAP_SYS_ADMIN)) 417 if (!capable(CAP_SYS_ADMIN))
418 { 418 {
419 return -EACCES; 419 return -EACCES;
420 } 420 }
421 if (server->root_setuped) return -EBUSY; 421 if (server->root_setuped) return -EBUSY;
422 if (copy_from_user(&sr, argp, sizeof(sr))) 422 if (copy_from_user(&sr, argp, sizeof(sr)))
423 return -EFAULT; 423 return -EFAULT;
424 if (sr.volNumber < 0) { 424 if (sr.volNumber < 0) {
425 server->m.mounted_vol[0] = 0; 425 server->m.mounted_vol[0] = 0;
426 vnum = NCP_NUMBER_OF_VOLUMES; 426 vnum = NCP_NUMBER_OF_VOLUMES;
427 de = 0; 427 de = 0;
428 dosde = 0; 428 dosde = 0;
429 } else if (sr.volNumber >= NCP_NUMBER_OF_VOLUMES) { 429 } else if (sr.volNumber >= NCP_NUMBER_OF_VOLUMES) {
430 return -EINVAL; 430 return -EINVAL;
431 } else if (ncp_mount_subdir(server, sr.volNumber, 431 } else if (ncp_mount_subdir(server, sr.volNumber,
432 sr.namespace, sr.dirEntNum, 432 sr.namespace, sr.dirEntNum,
433 &vnum, &de, &dosde)) { 433 &vnum, &de, &dosde)) {
434 return -ENOENT; 434 return -ENOENT;
435 } 435 }
436 436
437 dentry = inode->i_sb->s_root; 437 dentry = inode->i_sb->s_root;
438 server->root_setuped = 1; 438 server->root_setuped = 1;
439 if (dentry) { 439 if (dentry) {
440 struct inode* inode = dentry->d_inode; 440 struct inode* inode = dentry->d_inode;
441 441
442 if (inode) { 442 if (inode) {
443 NCP_FINFO(inode)->volNumber = vnum; 443 NCP_FINFO(inode)->volNumber = vnum;
444 NCP_FINFO(inode)->dirEntNum = de; 444 NCP_FINFO(inode)->dirEntNum = de;
445 NCP_FINFO(inode)->DosDirNum = dosde; 445 NCP_FINFO(inode)->DosDirNum = dosde;
446 } else 446 } else
447 DPRINTK("ncpfs: s_root->d_inode==NULL\n"); 447 DPRINTK("ncpfs: s_root->d_inode==NULL\n");
448 } else 448 } else
449 DPRINTK("ncpfs: s_root==NULL\n"); 449 DPRINTK("ncpfs: s_root==NULL\n");
450 450
451 return 0; 451 return 0;
452 } 452 }
453 453
454 #ifdef CONFIG_NCPFS_PACKET_SIGNING 454 #ifdef CONFIG_NCPFS_PACKET_SIGNING
455 case NCP_IOC_SIGN_INIT: 455 case NCP_IOC_SIGN_INIT:
456 if ((file_permission(filp, MAY_WRITE) != 0) 456 if ((file_permission(filp, MAY_WRITE) != 0)
457 && (current->uid != server->m.mounted_uid)) 457 && (current->uid != server->m.mounted_uid))
458 { 458 {
459 return -EACCES; 459 return -EACCES;
460 } 460 }
461 if (argp) { 461 if (argp) {
462 if (server->sign_wanted) 462 if (server->sign_wanted)
463 { 463 {
464 struct ncp_sign_init sign; 464 struct ncp_sign_init sign;
465 465
466 if (copy_from_user(&sign, argp, sizeof(sign))) 466 if (copy_from_user(&sign, argp, sizeof(sign)))
467 return -EFAULT; 467 return -EFAULT;
468 memcpy(server->sign_root,sign.sign_root,8); 468 memcpy(server->sign_root,sign.sign_root,8);
469 memcpy(server->sign_last,sign.sign_last,16); 469 memcpy(server->sign_last,sign.sign_last,16);
470 server->sign_active = 1; 470 server->sign_active = 1;
471 } 471 }
472 /* ignore when signatures not wanted */ 472 /* ignore when signatures not wanted */
473 } else { 473 } else {
474 server->sign_active = 0; 474 server->sign_active = 0;
475 } 475 }
476 return 0; 476 return 0;
477 477
478 case NCP_IOC_SIGN_WANTED: 478 case NCP_IOC_SIGN_WANTED:
479 if ((file_permission(filp, MAY_READ) != 0) 479 if ((file_permission(filp, MAY_READ) != 0)
480 && (current->uid != server->m.mounted_uid)) 480 && (current->uid != server->m.mounted_uid))
481 { 481 {
482 return -EACCES; 482 return -EACCES;
483 } 483 }
484 484
485 if (put_user(server->sign_wanted, (int __user *)argp)) 485 if (put_user(server->sign_wanted, (int __user *)argp))
486 return -EFAULT; 486 return -EFAULT;
487 return 0; 487 return 0;
488 case NCP_IOC_SET_SIGN_WANTED: 488 case NCP_IOC_SET_SIGN_WANTED:
489 { 489 {
490 int newstate; 490 int newstate;
491 491
492 if ((file_permission(filp, MAY_WRITE) != 0) 492 if ((file_permission(filp, MAY_WRITE) != 0)
493 && (current->uid != server->m.mounted_uid)) 493 && (current->uid != server->m.mounted_uid))
494 { 494 {
495 return -EACCES; 495 return -EACCES;
496 } 496 }
497 /* get only low 8 bits... */ 497 /* get only low 8 bits... */
498 if (get_user(newstate, (unsigned char __user *)argp)) 498 if (get_user(newstate, (unsigned char __user *)argp))
499 return -EFAULT; 499 return -EFAULT;
500 if (server->sign_active) { 500 if (server->sign_active) {
501 /* cannot turn signatures OFF when active */ 501 /* cannot turn signatures OFF when active */
502 if (!newstate) return -EINVAL; 502 if (!newstate) return -EINVAL;
503 } else { 503 } else {
504 server->sign_wanted = newstate != 0; 504 server->sign_wanted = newstate != 0;
505 } 505 }
506 return 0; 506 return 0;
507 } 507 }
508 508
509 #endif /* CONFIG_NCPFS_PACKET_SIGNING */ 509 #endif /* CONFIG_NCPFS_PACKET_SIGNING */
510 510
511 #ifdef CONFIG_NCPFS_IOCTL_LOCKING 511 #ifdef CONFIG_NCPFS_IOCTL_LOCKING
512 case NCP_IOC_LOCKUNLOCK: 512 case NCP_IOC_LOCKUNLOCK:
513 if ((file_permission(filp, MAY_WRITE) != 0) 513 if ((file_permission(filp, MAY_WRITE) != 0)
514 && (current->uid != server->m.mounted_uid)) 514 && (current->uid != server->m.mounted_uid))
515 { 515 {
516 return -EACCES; 516 return -EACCES;
517 } 517 }
518 { 518 {
519 struct ncp_lock_ioctl rqdata; 519 struct ncp_lock_ioctl rqdata;
520 int result; 520 int result;
521 521
522 if (copy_from_user(&rqdata, argp, sizeof(rqdata))) 522 if (copy_from_user(&rqdata, argp, sizeof(rqdata)))
523 return -EFAULT; 523 return -EFAULT;
524 if (rqdata.origin != 0) 524 if (rqdata.origin != 0)
525 return -EINVAL; 525 return -EINVAL;
526 /* check for cmd */ 526 /* check for cmd */
527 switch (rqdata.cmd) { 527 switch (rqdata.cmd) {
528 case NCP_LOCK_EX: 528 case NCP_LOCK_EX:
529 case NCP_LOCK_SH: 529 case NCP_LOCK_SH:
530 if (rqdata.timeout == 0) 530 if (rqdata.timeout == 0)
531 rqdata.timeout = NCP_LOCK_DEFAULT_TIMEOUT; 531 rqdata.timeout = NCP_LOCK_DEFAULT_TIMEOUT;
532 else if (rqdata.timeout > NCP_LOCK_MAX_TIMEOUT) 532 else if (rqdata.timeout > NCP_LOCK_MAX_TIMEOUT)
533 rqdata.timeout = NCP_LOCK_MAX_TIMEOUT; 533 rqdata.timeout = NCP_LOCK_MAX_TIMEOUT;
534 break; 534 break;
535 case NCP_LOCK_LOG: 535 case NCP_LOCK_LOG:
536 rqdata.timeout = NCP_LOCK_DEFAULT_TIMEOUT; /* has no effect */ 536 rqdata.timeout = NCP_LOCK_DEFAULT_TIMEOUT; /* has no effect */
537 case NCP_LOCK_CLEAR: 537 case NCP_LOCK_CLEAR:
538 break; 538 break;
539 default: 539 default:
540 return -EINVAL; 540 return -EINVAL;
541 } 541 }
542 /* locking needs both read and write access */ 542 /* locking needs both read and write access */
543 if ((result = ncp_make_open(inode, O_RDWR)) != 0) 543 if ((result = ncp_make_open(inode, O_RDWR)) != 0)
544 { 544 {
545 return result; 545 return result;
546 } 546 }
547 result = -EIO; 547 result = -EIO;
548 if (!ncp_conn_valid(server)) 548 if (!ncp_conn_valid(server))
549 goto outrel; 549 goto outrel;
550 result = -EISDIR; 550 result = -EISDIR;
551 if (!S_ISREG(inode->i_mode)) 551 if (!S_ISREG(inode->i_mode))
552 goto outrel; 552 goto outrel;
553 if (rqdata.cmd == NCP_LOCK_CLEAR) 553 if (rqdata.cmd == NCP_LOCK_CLEAR)
554 { 554 {
555 result = ncp_ClearPhysicalRecord(NCP_SERVER(inode), 555 result = ncp_ClearPhysicalRecord(NCP_SERVER(inode),
556 NCP_FINFO(inode)->file_handle, 556 NCP_FINFO(inode)->file_handle,
557 rqdata.offset, 557 rqdata.offset,
558 rqdata.length); 558 rqdata.length);
559 if (result > 0) result = 0; /* no such lock */ 559 if (result > 0) result = 0; /* no such lock */
560 } 560 }
561 else 561 else
562 { 562 {
563 int lockcmd; 563 int lockcmd;
564 564
565 switch (rqdata.cmd) 565 switch (rqdata.cmd)
566 { 566 {
567 case NCP_LOCK_EX: lockcmd=1; break; 567 case NCP_LOCK_EX: lockcmd=1; break;
568 case NCP_LOCK_SH: lockcmd=3; break; 568 case NCP_LOCK_SH: lockcmd=3; break;
569 default: lockcmd=0; break; 569 default: lockcmd=0; break;
570 } 570 }
571 result = ncp_LogPhysicalRecord(NCP_SERVER(inode), 571 result = ncp_LogPhysicalRecord(NCP_SERVER(inode),
572 NCP_FINFO(inode)->file_handle, 572 NCP_FINFO(inode)->file_handle,
573 lockcmd, 573 lockcmd,
574 rqdata.offset, 574 rqdata.offset,
575 rqdata.length, 575 rqdata.length,
576 rqdata.timeout); 576 rqdata.timeout);
577 if (result > 0) result = -EAGAIN; 577 if (result > 0) result = -EAGAIN;
578 } 578 }
579 outrel: 579 outrel:
580 ncp_inode_close(inode); 580 ncp_inode_close(inode);
581 return result; 581 return result;
582 } 582 }
583 #endif /* CONFIG_NCPFS_IOCTL_LOCKING */ 583 #endif /* CONFIG_NCPFS_IOCTL_LOCKING */
584 584
585 #ifdef CONFIG_COMPAT 585 #ifdef CONFIG_COMPAT
586 case NCP_IOC_GETOBJECTNAME_32: 586 case NCP_IOC_GETOBJECTNAME_32:
587 if (current->uid != server->m.mounted_uid) { 587 if (current->uid != server->m.mounted_uid) {
588 return -EACCES; 588 return -EACCES;
589 } 589 }
590 { 590 {
591 struct compat_ncp_objectname_ioctl user; 591 struct compat_ncp_objectname_ioctl user;
592 size_t outl; 592 size_t outl;
593 593
594 if (copy_from_user(&user, argp, sizeof(user))) 594 if (copy_from_user(&user, argp, sizeof(user)))
595 return -EFAULT; 595 return -EFAULT;
596 user.auth_type = server->auth.auth_type; 596 user.auth_type = server->auth.auth_type;
597 outl = user.object_name_len; 597 outl = user.object_name_len;
598 user.object_name_len = server->auth.object_name_len; 598 user.object_name_len = server->auth.object_name_len;
599 if (outl > user.object_name_len) 599 if (outl > user.object_name_len)
600 outl = user.object_name_len; 600 outl = user.object_name_len;
601 if (outl) { 601 if (outl) {
602 if (copy_to_user(compat_ptr(user.object_name), 602 if (copy_to_user(compat_ptr(user.object_name),
603 server->auth.object_name, 603 server->auth.object_name,
604 outl)) return -EFAULT; 604 outl)) return -EFAULT;
605 } 605 }
606 if (copy_to_user(argp, &user, sizeof(user))) 606 if (copy_to_user(argp, &user, sizeof(user)))
607 return -EFAULT; 607 return -EFAULT;
608 return 0; 608 return 0;
609 } 609 }
610 #endif 610 #endif
611 case NCP_IOC_GETOBJECTNAME: 611 case NCP_IOC_GETOBJECTNAME:
612 if (current->uid != server->m.mounted_uid) { 612 if (current->uid != server->m.mounted_uid) {
613 return -EACCES; 613 return -EACCES;
614 } 614 }
615 { 615 {
616 struct ncp_objectname_ioctl user; 616 struct ncp_objectname_ioctl user;
617 size_t outl; 617 size_t outl;
618 618
619 if (copy_from_user(&user, argp, sizeof(user))) 619 if (copy_from_user(&user, argp, sizeof(user)))
620 return -EFAULT; 620 return -EFAULT;
621 user.auth_type = server->auth.auth_type; 621 user.auth_type = server->auth.auth_type;
622 outl = user.object_name_len; 622 outl = user.object_name_len;
623 user.object_name_len = server->auth.object_name_len; 623 user.object_name_len = server->auth.object_name_len;
624 if (outl > user.object_name_len) 624 if (outl > user.object_name_len)
625 outl = user.object_name_len; 625 outl = user.object_name_len;
626 if (outl) { 626 if (outl) {
627 if (copy_to_user(user.object_name, 627 if (copy_to_user(user.object_name,
628 server->auth.object_name, 628 server->auth.object_name,
629 outl)) return -EFAULT; 629 outl)) return -EFAULT;
630 } 630 }
631 if (copy_to_user(argp, &user, sizeof(user))) 631 if (copy_to_user(argp, &user, sizeof(user)))
632 return -EFAULT; 632 return -EFAULT;
633 return 0; 633 return 0;
634 } 634 }
635 #ifdef CONFIG_COMPAT 635 #ifdef CONFIG_COMPAT
636 case NCP_IOC_SETOBJECTNAME_32: 636 case NCP_IOC_SETOBJECTNAME_32:
637 #endif 637 #endif
638 case NCP_IOC_SETOBJECTNAME: 638 case NCP_IOC_SETOBJECTNAME:
639 if (current->uid != server->m.mounted_uid) { 639 if (current->uid != server->m.mounted_uid) {
640 return -EACCES; 640 return -EACCES;
641 } 641 }
642 { 642 {
643 struct ncp_objectname_ioctl user; 643 struct ncp_objectname_ioctl user;
644 void* newname; 644 void* newname;
645 void* oldname; 645 void* oldname;
646 size_t oldnamelen; 646 size_t oldnamelen;
647 void* oldprivate; 647 void* oldprivate;
648 size_t oldprivatelen; 648 size_t oldprivatelen;
649 649
650 #ifdef CONFIG_COMPAT 650 #ifdef CONFIG_COMPAT
651 if (cmd == NCP_IOC_SETOBJECTNAME_32) { 651 if (cmd == NCP_IOC_SETOBJECTNAME_32) {
652 struct compat_ncp_objectname_ioctl user32; 652 struct compat_ncp_objectname_ioctl user32;
653 if (copy_from_user(&user32, argp, sizeof(user32))) 653 if (copy_from_user(&user32, argp, sizeof(user32)))
654 return -EFAULT; 654 return -EFAULT;
655 user.auth_type = user32.auth_type; 655 user.auth_type = user32.auth_type;
656 user.object_name_len = user32.object_name_len; 656 user.object_name_len = user32.object_name_len;
657 user.object_name = compat_ptr(user32.object_name); 657 user.object_name = compat_ptr(user32.object_name);
658 } else 658 } else
659 #endif 659 #endif
660 if (copy_from_user(&user, argp, sizeof(user))) 660 if (copy_from_user(&user, argp, sizeof(user)))
661 return -EFAULT; 661 return -EFAULT;
662 662
663 if (user.object_name_len > NCP_OBJECT_NAME_MAX_LEN) 663 if (user.object_name_len > NCP_OBJECT_NAME_MAX_LEN)
664 return -ENOMEM; 664 return -ENOMEM;
665 if (user.object_name_len) { 665 if (user.object_name_len) {
666 newname = kmalloc(user.object_name_len, GFP_USER); 666 newname = kmalloc(user.object_name_len, GFP_USER);
667 if (!newname) 667 if (!newname)
668 return -ENOMEM; 668 return -ENOMEM;
669 if (copy_from_user(newname, user.object_name, user.object_name_len)) { 669 if (copy_from_user(newname, user.object_name, user.object_name_len)) {
670 kfree(newname); 670 kfree(newname);
671 return -EFAULT; 671 return -EFAULT;
672 } 672 }
673 } else { 673 } else {
674 newname = NULL; 674 newname = NULL;
675 } 675 }
676 /* enter critical section */ 676 /* enter critical section */
677 /* maybe that kfree can sleep so do that this way */ 677 /* maybe that kfree can sleep so do that this way */
678 /* it is at least more SMP friendly (in future...) */ 678 /* it is at least more SMP friendly (in future...) */
679 oldname = server->auth.object_name; 679 oldname = server->auth.object_name;
680 oldnamelen = server->auth.object_name_len; 680 oldnamelen = server->auth.object_name_len;
681 oldprivate = server->priv.data; 681 oldprivate = server->priv.data;
682 oldprivatelen = server->priv.len; 682 oldprivatelen = server->priv.len;
683 server->auth.auth_type = user.auth_type; 683 server->auth.auth_type = user.auth_type;
684 server->auth.object_name_len = user.object_name_len; 684 server->auth.object_name_len = user.object_name_len;
685 server->auth.object_name = newname; 685 server->auth.object_name = newname;
686 server->priv.len = 0; 686 server->priv.len = 0;
687 server->priv.data = NULL; 687 server->priv.data = NULL;
688 /* leave critical section */ 688 /* leave critical section */
689 kfree(oldprivate); 689 kfree(oldprivate);
690 kfree(oldname); 690 kfree(oldname);
691 return 0; 691 return 0;
692 } 692 }
693 #ifdef CONFIG_COMPAT 693 #ifdef CONFIG_COMPAT
694 case NCP_IOC_GETPRIVATEDATA_32: 694 case NCP_IOC_GETPRIVATEDATA_32:
695 #endif 695 #endif
696 case NCP_IOC_GETPRIVATEDATA: 696 case NCP_IOC_GETPRIVATEDATA:
697 if (current->uid != server->m.mounted_uid) { 697 if (current->uid != server->m.mounted_uid) {
698 return -EACCES; 698 return -EACCES;
699 } 699 }
700 { 700 {
701 struct ncp_privatedata_ioctl user; 701 struct ncp_privatedata_ioctl user;
702 size_t outl; 702 size_t outl;
703 703
704 #ifdef CONFIG_COMPAT 704 #ifdef CONFIG_COMPAT
705 if (cmd == NCP_IOC_GETPRIVATEDATA_32) { 705 if (cmd == NCP_IOC_GETPRIVATEDATA_32) {
706 struct compat_ncp_privatedata_ioctl user32; 706 struct compat_ncp_privatedata_ioctl user32;
707 if (copy_from_user(&user32, argp, sizeof(user32))) 707 if (copy_from_user(&user32, argp, sizeof(user32)))
708 return -EFAULT; 708 return -EFAULT;
709 user.len = user32.len; 709 user.len = user32.len;
710 user.data = compat_ptr(user32.data); 710 user.data = compat_ptr(user32.data);
711 } else 711 } else
712 #endif 712 #endif
713 if (copy_from_user(&user, argp, sizeof(user))) 713 if (copy_from_user(&user, argp, sizeof(user)))
714 return -EFAULT; 714 return -EFAULT;
715 715
716 outl = user.len; 716 outl = user.len;
717 user.len = server->priv.len; 717 user.len = server->priv.len;
718 if (outl > user.len) outl = user.len; 718 if (outl > user.len) outl = user.len;
719 if (outl) { 719 if (outl) {
720 if (copy_to_user(user.data, 720 if (copy_to_user(user.data,
721 server->priv.data, 721 server->priv.data,
722 outl)) return -EFAULT; 722 outl)) return -EFAULT;
723 } 723 }
724 #ifdef CONFIG_COMPAT 724 #ifdef CONFIG_COMPAT
725 if (cmd == NCP_IOC_GETPRIVATEDATA_32) { 725 if (cmd == NCP_IOC_GETPRIVATEDATA_32) {
726 struct compat_ncp_privatedata_ioctl user32; 726 struct compat_ncp_privatedata_ioctl user32;
727 user32.len = user.len; 727 user32.len = user.len;
728 user32.data = (unsigned long) user.data; 728 user32.data = (unsigned long) user.data;
729 if (copy_to_user(argp, &user32, sizeof(user32))) 729 if (copy_to_user(argp, &user32, sizeof(user32)))
730 return -EFAULT; 730 return -EFAULT;
731 } else 731 } else
732 #endif 732 #endif
733 if (copy_to_user(argp, &user, sizeof(user))) 733 if (copy_to_user(argp, &user, sizeof(user)))
734 return -EFAULT; 734 return -EFAULT;
735 735
736 return 0; 736 return 0;
737 } 737 }
738 #ifdef CONFIG_COMPAT 738 #ifdef CONFIG_COMPAT
739 case NCP_IOC_SETPRIVATEDATA_32: 739 case NCP_IOC_SETPRIVATEDATA_32:
740 #endif 740 #endif
741 case NCP_IOC_SETPRIVATEDATA: 741 case NCP_IOC_SETPRIVATEDATA:
742 if (current->uid != server->m.mounted_uid) { 742 if (current->uid != server->m.mounted_uid) {
743 return -EACCES; 743 return -EACCES;
744 } 744 }
745 { 745 {
746 struct ncp_privatedata_ioctl user; 746 struct ncp_privatedata_ioctl user;
747 void* new; 747 void* new;
748 void* old; 748 void* old;
749 size_t oldlen; 749 size_t oldlen;
750 750
751 #ifdef CONFIG_COMPAT 751 #ifdef CONFIG_COMPAT
752 if (cmd == NCP_IOC_SETPRIVATEDATA_32) { 752 if (cmd == NCP_IOC_SETPRIVATEDATA_32) {
753 struct compat_ncp_privatedata_ioctl user32; 753 struct compat_ncp_privatedata_ioctl user32;
754 if (copy_from_user(&user32, argp, sizeof(user32))) 754 if (copy_from_user(&user32, argp, sizeof(user32)))
755 return -EFAULT; 755 return -EFAULT;
756 user.len = user32.len; 756 user.len = user32.len;
757 user.data = compat_ptr(user32.data); 757 user.data = compat_ptr(user32.data);
758 } else 758 } else
759 #endif 759 #endif
760 if (copy_from_user(&user, argp, sizeof(user))) 760 if (copy_from_user(&user, argp, sizeof(user)))
761 return -EFAULT; 761 return -EFAULT;
762 762
763 if (user.len > NCP_PRIVATE_DATA_MAX_LEN) 763 if (user.len > NCP_PRIVATE_DATA_MAX_LEN)
764 return -ENOMEM; 764 return -ENOMEM;
765 if (user.len) { 765 if (user.len) {
766 new = kmalloc(user.len, GFP_USER); 766 new = kmalloc(user.len, GFP_USER);
767 if (!new) 767 if (!new)
768 return -ENOMEM; 768 return -ENOMEM;
769 if (copy_from_user(new, user.data, user.len)) { 769 if (copy_from_user(new, user.data, user.len)) {
770 kfree(new); 770 kfree(new);
771 return -EFAULT; 771 return -EFAULT;
772 } 772 }
773 } else { 773 } else {
774 new = NULL; 774 new = NULL;
775 } 775 }
776 /* enter critical section */ 776 /* enter critical section */
777 old = server->priv.data; 777 old = server->priv.data;
778 oldlen = server->priv.len; 778 oldlen = server->priv.len;
779 server->priv.len = user.len; 779 server->priv.len = user.len;
780 server->priv.data = new; 780 server->priv.data = new;
781 /* leave critical section */ 781 /* leave critical section */
782 kfree(old); 782 kfree(old);
783 return 0; 783 return 0;
784 } 784 }
785 785
786 #ifdef CONFIG_NCPFS_NLS 786 #ifdef CONFIG_NCPFS_NLS
787 case NCP_IOC_SETCHARSETS: 787 case NCP_IOC_SETCHARSETS:
788 return ncp_set_charsets(server, argp); 788 return ncp_set_charsets(server, argp);
789 789
790 case NCP_IOC_GETCHARSETS: 790 case NCP_IOC_GETCHARSETS:
791 return ncp_get_charsets(server, argp); 791 return ncp_get_charsets(server, argp);
792 792
793 #endif /* CONFIG_NCPFS_NLS */ 793 #endif /* CONFIG_NCPFS_NLS */
794 794
795 case NCP_IOC_SETDENTRYTTL: 795 case NCP_IOC_SETDENTRYTTL:
796 if ((file_permission(filp, MAY_WRITE) != 0) && 796 if ((file_permission(filp, MAY_WRITE) != 0) &&
797 (current->uid != server->m.mounted_uid)) 797 (current->uid != server->m.mounted_uid))
798 return -EACCES; 798 return -EACCES;
799 { 799 {
800 u_int32_t user; 800 u_int32_t user;
801 801
802 if (copy_from_user(&user, argp, sizeof(user))) 802 if (copy_from_user(&user, argp, sizeof(user)))
803 return -EFAULT; 803 return -EFAULT;
804 /* 20 secs at most... */ 804 /* 20 secs at most... */
805 if (user > 20000) 805 if (user > 20000)
806 return -EINVAL; 806 return -EINVAL;
807 user = (user * HZ) / 1000; 807 user = (user * HZ) / 1000;
808 server->dentry_ttl = user; 808 server->dentry_ttl = user;
809 return 0; 809 return 0;
810 } 810 }
811 811
812 case NCP_IOC_GETDENTRYTTL: 812 case NCP_IOC_GETDENTRYTTL:
813 { 813 {
814 u_int32_t user = (server->dentry_ttl * 1000) / HZ; 814 u_int32_t user = (server->dentry_ttl * 1000) / HZ;
815 if (copy_to_user(argp, &user, sizeof(user))) 815 if (copy_to_user(argp, &user, sizeof(user)))
816 return -EFAULT; 816 return -EFAULT;
817 return 0; 817 return 0;
818 } 818 }
819 819
820 } 820 }
821 return -EINVAL; 821 return -EINVAL;
822 } 822 }
823 823
824 #ifdef CONFIG_COMPAT 824 #ifdef CONFIG_COMPAT
825 long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 825 long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
826 { 826 {
827 struct inode *inode = file->f_dentry->d_inode; 827 struct inode *inode = file->f_path.dentry->d_inode;
828 int ret; 828 int ret;
829 829
830 lock_kernel(); 830 lock_kernel();
831 arg = (unsigned long) compat_ptr(arg); 831 arg = (unsigned long) compat_ptr(arg);
832 ret = ncp_ioctl(inode, file, cmd, arg); 832 ret = ncp_ioctl(inode, file, cmd, arg);
833 unlock_kernel(); 833 unlock_kernel();
834 return ret; 834 return ret;
835 } 835 }
836 #endif 836 #endif
837 837
1 /* 1 /*
2 * mmap.c 2 * mmap.c
3 * 3 *
4 * Copyright (C) 1995, 1996 by Volker Lendecke 4 * Copyright (C) 1995, 1996 by Volker Lendecke
5 * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache 5 * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
6 * 6 *
7 */ 7 */
8 8
9 #include <linux/stat.h> 9 #include <linux/stat.h>
10 #include <linux/time.h> 10 #include <linux/time.h>
11 #include <linux/kernel.h> 11 #include <linux/kernel.h>
12 #include <linux/mm.h> 12 #include <linux/mm.h>
13 #include <linux/shm.h> 13 #include <linux/shm.h>
14 #include <linux/errno.h> 14 #include <linux/errno.h>
15 #include <linux/mman.h> 15 #include <linux/mman.h>
16 #include <linux/string.h> 16 #include <linux/string.h>
17 #include <linux/slab.h> 17 #include <linux/slab.h>
18 #include <linux/fcntl.h> 18 #include <linux/fcntl.h>
19 #include <linux/ncp_fs.h> 19 #include <linux/ncp_fs.h>
20 20
21 #include "ncplib_kernel.h" 21 #include "ncplib_kernel.h"
22 #include <asm/uaccess.h> 22 #include <asm/uaccess.h>
23 #include <asm/system.h> 23 #include <asm/system.h>
24 24
25 /* 25 /*
26 * Fill in the supplied page for mmap 26 * Fill in the supplied page for mmap
27 */ 27 */
28 static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area, 28 static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area,
29 unsigned long address, int *type) 29 unsigned long address, int *type)
30 { 30 {
31 struct file *file = area->vm_file; 31 struct file *file = area->vm_file;
32 struct dentry *dentry = file->f_dentry; 32 struct dentry *dentry = file->f_path.dentry;
33 struct inode *inode = dentry->d_inode; 33 struct inode *inode = dentry->d_inode;
34 struct page* page; 34 struct page* page;
35 char *pg_addr; 35 char *pg_addr;
36 unsigned int already_read; 36 unsigned int already_read;
37 unsigned int count; 37 unsigned int count;
38 int bufsize; 38 int bufsize;
39 int pos; 39 int pos;
40 40
41 page = alloc_page(GFP_HIGHUSER); /* ncpfs has nothing against high pages 41 page = alloc_page(GFP_HIGHUSER); /* ncpfs has nothing against high pages
42 as long as recvmsg and memset works on it */ 42 as long as recvmsg and memset works on it */
43 if (!page) 43 if (!page)
44 return page; 44 return page;
45 pg_addr = kmap(page); 45 pg_addr = kmap(page);
46 address &= PAGE_MASK; 46 address &= PAGE_MASK;
47 pos = address - area->vm_start + (area->vm_pgoff << PAGE_SHIFT); 47 pos = address - area->vm_start + (area->vm_pgoff << PAGE_SHIFT);
48 48
49 count = PAGE_SIZE; 49 count = PAGE_SIZE;
50 if (address + PAGE_SIZE > area->vm_end) { 50 if (address + PAGE_SIZE > area->vm_end) {
51 count = area->vm_end - address; 51 count = area->vm_end - address;
52 } 52 }
53 /* what we can read in one go */ 53 /* what we can read in one go */
54 bufsize = NCP_SERVER(inode)->buffer_size; 54 bufsize = NCP_SERVER(inode)->buffer_size;
55 55
56 already_read = 0; 56 already_read = 0;
57 if (ncp_make_open(inode, O_RDONLY) >= 0) { 57 if (ncp_make_open(inode, O_RDONLY) >= 0) {
58 while (already_read < count) { 58 while (already_read < count) {
59 int read_this_time; 59 int read_this_time;
60 int to_read; 60 int to_read;
61 61
62 to_read = bufsize - (pos % bufsize); 62 to_read = bufsize - (pos % bufsize);
63 63
64 to_read = min_t(unsigned int, to_read, count - already_read); 64 to_read = min_t(unsigned int, to_read, count - already_read);
65 65
66 if (ncp_read_kernel(NCP_SERVER(inode), 66 if (ncp_read_kernel(NCP_SERVER(inode),
67 NCP_FINFO(inode)->file_handle, 67 NCP_FINFO(inode)->file_handle,
68 pos, to_read, 68 pos, to_read,
69 pg_addr + already_read, 69 pg_addr + already_read,
70 &read_this_time) != 0) { 70 &read_this_time) != 0) {
71 read_this_time = 0; 71 read_this_time = 0;
72 } 72 }
73 pos += read_this_time; 73 pos += read_this_time;
74 already_read += read_this_time; 74 already_read += read_this_time;
75 75
76 if (read_this_time < to_read) { 76 if (read_this_time < to_read) {
77 break; 77 break;
78 } 78 }
79 } 79 }
80 ncp_inode_close(inode); 80 ncp_inode_close(inode);
81 81
82 } 82 }
83 83
84 if (already_read < PAGE_SIZE) 84 if (already_read < PAGE_SIZE)
85 memset(pg_addr + already_read, 0, PAGE_SIZE - already_read); 85 memset(pg_addr + already_read, 0, PAGE_SIZE - already_read);
86 flush_dcache_page(page); 86 flush_dcache_page(page);
87 kunmap(page); 87 kunmap(page);
88 88
89 /* 89 /*
90 * If I understand ncp_read_kernel() properly, the above always 90 * If I understand ncp_read_kernel() properly, the above always
91 * fetches from the network, here the analogue of disk. 91 * fetches from the network, here the analogue of disk.
92 * -- wli 92 * -- wli
93 */ 93 */
94 if (type) 94 if (type)
95 *type = VM_FAULT_MAJOR; 95 *type = VM_FAULT_MAJOR;
96 count_vm_event(PGMAJFAULT); 96 count_vm_event(PGMAJFAULT);
97 return page; 97 return page;
98 } 98 }
99 99
100 static struct vm_operations_struct ncp_file_mmap = 100 static struct vm_operations_struct ncp_file_mmap =
101 { 101 {
102 .nopage = ncp_file_mmap_nopage, 102 .nopage = ncp_file_mmap_nopage,
103 }; 103 };
104 104
105 105
106 /* This is used for a general mmap of a ncp file */ 106 /* This is used for a general mmap of a ncp file */
107 int ncp_mmap(struct file *file, struct vm_area_struct *vma) 107 int ncp_mmap(struct file *file, struct vm_area_struct *vma)
108 { 108 {
109 struct inode *inode = file->f_dentry->d_inode; 109 struct inode *inode = file->f_path.dentry->d_inode;
110 110
111 DPRINTK("ncp_mmap: called\n"); 111 DPRINTK("ncp_mmap: called\n");
112 112
113 if (!ncp_conn_valid(NCP_SERVER(inode))) 113 if (!ncp_conn_valid(NCP_SERVER(inode)))
114 return -EIO; 114 return -EIO;
115 115
116 /* only PAGE_COW or read-only supported now */ 116 /* only PAGE_COW or read-only supported now */
117 if (vma->vm_flags & VM_SHARED) 117 if (vma->vm_flags & VM_SHARED)
118 return -EINVAL; 118 return -EINVAL;
119 /* we do not support files bigger than 4GB... We eventually 119 /* we do not support files bigger than 4GB... We eventually
120 supports just 4GB... */ 120 supports just 4GB... */
121 if (((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff 121 if (((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff
122 > (1U << (32 - PAGE_SHIFT))) 122 > (1U << (32 - PAGE_SHIFT)))
123 return -EFBIG; 123 return -EFBIG;
124 124
125 vma->vm_ops = &ncp_file_mmap; 125 vma->vm_ops = &ncp_file_mmap;
126 file_accessed(file); 126 file_accessed(file);
127 return 0; 127 return 0;
128 } 128 }
129 129