fs: dcache scale d_unhashed
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / fs / ncpfs / dir.c
CommitLineData
1da177e4
LT
1/*
2 * dir.c
3 *
4 * Copyright (C) 1995, 1996 by Volker Lendecke
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
7 * Modified 1998, 1999 Wolfram Pienkoss for NLS
8 * Modified 1999 Wolfram Pienkoss for directory caching
9 * Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
10 *
11 */
12
1da177e4
LT
13
14#include <linux/time.h>
15#include <linux/errno.h>
16#include <linux/stat.h>
17#include <linux/kernel.h>
1da177e4
LT
18#include <linux/vmalloc.h>
19#include <linux/mm.h>
20#include <asm/uaccess.h>
21#include <asm/byteorder.h>
1da177e4
LT
22
23#include <linux/ncp_fs.h>
24
25#include "ncplib_kernel.h"
26
27static void ncp_read_volume_list(struct file *, void *, filldir_t,
28 struct ncp_cache_control *);
29static void ncp_do_readdir(struct file *, void *, filldir_t,
30 struct ncp_cache_control *);
31
32static int ncp_readdir(struct file *, void *, filldir_t);
33
34static int ncp_create(struct inode *, struct dentry *, int, struct nameidata *);
35static struct dentry *ncp_lookup(struct inode *, struct dentry *, struct nameidata *);
36static int ncp_unlink(struct inode *, struct dentry *);
37static int ncp_mkdir(struct inode *, struct dentry *, int);
38static int ncp_rmdir(struct inode *, struct dentry *);
39static int ncp_rename(struct inode *, struct dentry *,
40 struct inode *, struct dentry *);
41static int ncp_mknod(struct inode * dir, struct dentry *dentry,
42 int mode, dev_t rdev);
43#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
44extern int ncp_symlink(struct inode *, struct dentry *, const char *);
45#else
46#define ncp_symlink NULL
47#endif
48
4b6f5d20 49const struct file_operations ncp_dir_operations =
1da177e4 50{
ca572727 51 .llseek = generic_file_llseek,
1da177e4
LT
52 .read = generic_read_dir,
53 .readdir = ncp_readdir,
93d84b6d 54 .unlocked_ioctl = ncp_ioctl,
54f67f63
PV
55#ifdef CONFIG_COMPAT
56 .compat_ioctl = ncp_compat_ioctl,
57#endif
1da177e4
LT
58};
59
92e1d5be 60const struct inode_operations ncp_dir_inode_operations =
1da177e4
LT
61{
62 .create = ncp_create,
63 .lookup = ncp_lookup,
64 .unlink = ncp_unlink,
65 .symlink = ncp_symlink,
66 .mkdir = ncp_mkdir,
67 .rmdir = ncp_rmdir,
68 .mknod = ncp_mknod,
69 .rename = ncp_rename,
70 .setattr = ncp_notify_change,
71};
72
73/*
74 * Dentry operations routines
75 */
76static int ncp_lookup_validate(struct dentry *, struct nameidata *);
b1e6a015
NP
77static int ncp_hash_dentry(const struct dentry *, const struct inode *,
78 struct qstr *);
621e155a
NP
79static int ncp_compare_dentry(const struct dentry *, const struct inode *,
80 const struct dentry *, const struct inode *,
81 unsigned int, const char *, const struct qstr *);
fe15ce44 82static int ncp_delete_dentry(const struct dentry *);
1da177e4 83
e16404ed 84static const struct dentry_operations ncp_dentry_operations =
1da177e4
LT
85{
86 .d_revalidate = ncp_lookup_validate,
87 .d_hash = ncp_hash_dentry,
88 .d_compare = ncp_compare_dentry,
89 .d_delete = ncp_delete_dentry,
90};
91
e16404ed 92const struct dentry_operations ncp_root_dentry_operations =
1da177e4
LT
93{
94 .d_hash = ncp_hash_dentry,
95 .d_compare = ncp_compare_dentry,
96 .d_delete = ncp_delete_dentry,
97};
98
99
2e54eb96
PV
100#define ncp_namespace(i) (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber])
101
102static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator)
103{
104#ifdef CONFIG_NCPFS_SMALLDOS
105 int ns = ncp_namespace(i);
106
107 if ((ns == NW_NS_DOS)
108#ifdef CONFIG_NCPFS_OS2_NS
109 || ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS))
110#endif /* CONFIG_NCPFS_OS2_NS */
111 )
112 return 0;
113#endif /* CONFIG_NCPFS_SMALLDOS */
114 return 1;
115}
116
117#define ncp_preserve_case(i) (ncp_namespace(i) != NW_NS_DOS)
118
621e155a 119static inline int ncp_case_sensitive(const struct inode *i)
2e54eb96
PV
120{
121#ifdef CONFIG_NCPFS_NFS_NS
621e155a 122 return ncp_namespace(i) == NW_NS_NFS;
2e54eb96
PV
123#else
124 return 0;
125#endif /* CONFIG_NCPFS_NFS_NS */
126}
127
1da177e4
LT
128/*
129 * Note: leave the hash unchanged if the directory
130 * is case-sensitive.
131 */
132static int
b1e6a015
NP
133ncp_hash_dentry(const struct dentry *dentry, const struct inode *inode,
134 struct qstr *this)
1da177e4 135{
b1e6a015 136 if (!ncp_case_sensitive(inode)) {
621e155a 137 struct super_block *sb = dentry->d_sb;
2e54eb96
PV
138 struct nls_table *t;
139 unsigned long hash;
140 int i;
1da177e4 141
621e155a 142 t = NCP_IO_TABLE(sb);
1da177e4
LT
143 hash = init_name_hash();
144 for (i=0; i<this->len ; i++)
145 hash = partial_name_hash(ncp_tolower(t, this->name[i]),
146 hash);
147 this->hash = end_name_hash(hash);
148 }
149 return 0;
150}
151
152static int
621e155a
NP
153ncp_compare_dentry(const struct dentry *parent, const struct inode *pinode,
154 const struct dentry *dentry, const struct inode *inode,
155 unsigned int len, const char *str, const struct qstr *name)
1da177e4 156{
621e155a 157 if (len != name->len)
1da177e4
LT
158 return 1;
159
621e155a
NP
160 if (ncp_case_sensitive(pinode))
161 return strncmp(str, name->name, len);
1da177e4 162
621e155a 163 return ncp_strnicmp(NCP_IO_TABLE(pinode->i_sb), str, name->name, len);
1da177e4
LT
164}
165
166/*
167 * This is the callback from dput() when d_count is going to 0.
168 * We use this to unhash dentries with bad inodes.
169 * Closing files can be safely postponed until iput() - it's done there anyway.
170 */
171static int
fe15ce44 172ncp_delete_dentry(const struct dentry * dentry)
1da177e4
LT
173{
174 struct inode *inode = dentry->d_inode;
175
176 if (inode) {
177 if (is_bad_inode(inode))
178 return 1;
179 } else
180 {
181 /* N.B. Unhash negative dentries? */
182 }
183 return 0;
184}
185
186static inline int
187ncp_single_volume(struct ncp_server *server)
188{
189 return (server->m.mounted_vol[0] != '\0');
190}
191
192static inline int ncp_is_server_root(struct inode *inode)
193{
194 return (!ncp_single_volume(NCP_SERVER(inode)) &&
195 inode == inode->i_sb->s_root->d_inode);
196}
197
198
199/*
200 * This is the callback when the dcache has a lookup hit.
201 */
202
203
204#ifdef CONFIG_NCPFS_STRONG
205/* try to delete a readonly file (NW R bit set) */
206
207static int
208ncp_force_unlink(struct inode *dir, struct dentry* dentry)
209{
210 int res=0x9c,res2;
211 struct nw_modify_dos_info info;
212 __le32 old_nwattr;
213 struct inode *inode;
214
215 memset(&info, 0, sizeof(info));
216
217 /* remove the Read-Only flag on the NW server */
218 inode = dentry->d_inode;
219
220 old_nwattr = NCP_FINFO(inode)->nwattr;
221 info.attributes = old_nwattr & ~(aRONLY|aDELETEINHIBIT|aRENAMEINHIBIT);
222 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
223 if (res2)
224 goto leave_me;
225
226 /* now try again the delete operation */
227 res = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry);
228
229 if (res) /* delete failed, set R bit again */
230 {
231 info.attributes = old_nwattr;
232 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
233 if (res2)
234 goto leave_me;
235 }
236leave_me:
237 return(res);
238}
239#endif /* CONFIG_NCPFS_STRONG */
240
241#ifdef CONFIG_NCPFS_STRONG
242static int
243ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_name,
244 struct inode *new_dir, struct dentry* new_dentry, char *_new_name)
245{
246 struct nw_modify_dos_info info;
247 int res=0x90,res2;
248 struct inode *old_inode = old_dentry->d_inode;
249 __le32 old_nwattr = NCP_FINFO(old_inode)->nwattr;
250 __le32 new_nwattr = 0; /* shut compiler warning */
251 int old_nwattr_changed = 0;
252 int new_nwattr_changed = 0;
253
254 memset(&info, 0, sizeof(info));
255
256 /* remove the Read-Only flag on the NW server */
257
258 info.attributes = old_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
259 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
260 if (!res2)
261 old_nwattr_changed = 1;
262 if (new_dentry && new_dentry->d_inode) {
263 new_nwattr = NCP_FINFO(new_dentry->d_inode)->nwattr;
264 info.attributes = new_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
265 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
266 if (!res2)
267 new_nwattr_changed = 1;
268 }
269 /* now try again the rename operation */
270 /* but only if something really happened */
271 if (new_nwattr_changed || old_nwattr_changed) {
272 res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
273 old_dir, _old_name,
274 new_dir, _new_name);
275 }
276 if (res)
277 goto leave_me;
278 /* file was successfully renamed, so:
279 do not set attributes on old file - it no longer exists
280 copy attributes from old file to new */
281 new_nwattr_changed = old_nwattr_changed;
282 new_nwattr = old_nwattr;
283 old_nwattr_changed = 0;
284
285leave_me:;
286 if (old_nwattr_changed) {
287 info.attributes = old_nwattr;
288 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
289 /* ignore errors */
290 }
291 if (new_nwattr_changed) {
292 info.attributes = new_nwattr;
293 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
294 /* ignore errors */
295 }
296 return(res);
297}
298#endif /* CONFIG_NCPFS_STRONG */
299
300
301static int
2e54eb96 302ncp_lookup_validate(struct dentry *dentry, struct nameidata *nd)
1da177e4
LT
303{
304 struct ncp_server *server;
305 struct dentry *parent;
306 struct inode *dir;
307 struct ncp_entry_info finfo;
308 int res, val = 0, len;
309 __u8 __name[NCP_MAXPATHLEN + 1];
310
311 parent = dget_parent(dentry);
312 dir = parent->d_inode;
313
314 if (!dentry->d_inode)
315 goto finished;
316
317 server = NCP_SERVER(dir);
318
1da177e4
LT
319 /*
320 * Inspired by smbfs:
321 * The default validation is based on dentry age:
322 * We set the max age at mount time. (But each
323 * successful server lookup renews the timestamp.)
324 */
325 val = NCP_TEST_AGE(server, dentry);
326 if (val)
327 goto finished;
328
329 DDPRINTK("ncp_lookup_validate: %s/%s not valid, age=%ld, server lookup\n",
330 dentry->d_parent->d_name.name, dentry->d_name.name,
331 NCP_GET_AGE(dentry));
332
333 len = sizeof(__name);
334 if (ncp_is_server_root(dir)) {
335 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
336 dentry->d_name.len, 1);
2e54eb96 337 if (!res) {
1da177e4 338 res = ncp_lookup_volume(server, __name, &(finfo.i));
2e54eb96
PV
339 if (!res)
340 ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
341 }
1da177e4
LT
342 } else {
343 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
344 dentry->d_name.len, !ncp_preserve_case(dir));
345 if (!res)
346 res = ncp_obtain_info(server, dir, __name, &(finfo.i));
347 }
348 finfo.volume = finfo.i.volNumber;
349 DDPRINTK("ncp_lookup_validate: looked for %s/%s, res=%d\n",
350 dentry->d_parent->d_name.name, __name, res);
351 /*
352 * If we didn't find it, or if it has a different dirEntNum to
353 * what we remember, it's not valid any more.
354 */
355 if (!res) {
2e54eb96
PV
356 struct inode *inode = dentry->d_inode;
357
358 mutex_lock(&inode->i_mutex);
359 if (finfo.i.dirEntNum == NCP_FINFO(inode)->dirEntNum) {
1da177e4
LT
360 ncp_new_dentry(dentry);
361 val=1;
362 } else
363 DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");
364
2e54eb96
PV
365 ncp_update_inode2(inode, &finfo);
366 mutex_unlock(&inode->i_mutex);
1da177e4
LT
367 }
368
369finished:
370 DDPRINTK("ncp_lookup_validate: result=%d\n", val);
371 dput(parent);
372 return val;
373}
374
1da177e4
LT
375static struct dentry *
376ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
377{
378 struct dentry *dent = dentry;
379 struct list_head *next;
380
381 if (d_validate(dent, parent)) {
382 if (dent->d_name.len <= NCP_MAXPATHLEN &&
383 (unsigned long)dent->d_fsdata == fpos) {
384 if (!dent->d_inode) {
385 dput(dent);
386 dent = NULL;
387 }
388 return dent;
389 }
390 dput(dent);
391 }
392
393 /* If a pointer is invalid, we search the dentry. */
394 spin_lock(&dcache_lock);
395 next = parent->d_subdirs.next;
396 while (next != &parent->d_subdirs) {
5160ee6f 397 dent = list_entry(next, struct dentry, d_u.d_child);
1da177e4
LT
398 if ((unsigned long)dent->d_fsdata == fpos) {
399 if (dent->d_inode)
400 dget_locked(dent);
401 else
402 dent = NULL;
403 spin_unlock(&dcache_lock);
404 goto out;
405 }
406 next = next->next;
407 }
408 spin_unlock(&dcache_lock);
409 return NULL;
410
411out:
412 return dent;
413}
414
415static time_t ncp_obtain_mtime(struct dentry *dentry)
416{
417 struct inode *inode = dentry->d_inode;
418 struct ncp_server *server = NCP_SERVER(inode);
419 struct nw_info_struct i;
420
421 if (!ncp_conn_valid(server) || ncp_is_server_root(inode))
422 return 0;
423
424 if (ncp_obtain_info(server, inode, NULL, &i))
425 return 0;
426
427 return ncp_date_dos2unix(i.modifyTime, i.modifyDate);
428}
429
430static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
431{
92e5baef 432 struct dentry *dentry = filp->f_path.dentry;
1da177e4
LT
433 struct inode *inode = dentry->d_inode;
434 struct page *page = NULL;
435 struct ncp_server *server = NCP_SERVER(inode);
436 union ncp_dir_cache *cache = NULL;
437 struct ncp_cache_control ctl;
438 int result, mtime_valid = 0;
439 time_t mtime = 0;
440
1da177e4
LT
441 ctl.page = NULL;
442 ctl.cache = NULL;
443
444 DDPRINTK("ncp_readdir: reading %s/%s, pos=%d\n",
445 dentry->d_parent->d_name.name, dentry->d_name.name,
446 (int) filp->f_pos);
447
448 result = -EIO;
2e54eb96 449 /* Do not generate '.' and '..' when server is dead. */
1da177e4
LT
450 if (!ncp_conn_valid(server))
451 goto out;
452
453 result = 0;
454 if (filp->f_pos == 0) {
455 if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR))
456 goto out;
457 filp->f_pos = 1;
458 }
459 if (filp->f_pos == 1) {
460 if (filldir(dirent, "..", 2, 1, parent_ino(dentry), DT_DIR))
461 goto out;
462 filp->f_pos = 2;
463 }
464
465 page = grab_cache_page(&inode->i_data, 0);
466 if (!page)
467 goto read_really;
468
469 ctl.cache = cache = kmap(page);
470 ctl.head = cache->head;
471
472 if (!PageUptodate(page) || !ctl.head.eof)
473 goto init_cache;
474
475 if (filp->f_pos == 2) {
476 if (jiffies - ctl.head.time >= NCP_MAX_AGE(server))
477 goto init_cache;
478
479 mtime = ncp_obtain_mtime(dentry);
480 mtime_valid = 1;
481 if ((!mtime) || (mtime != ctl.head.mtime))
482 goto init_cache;
483 }
484
485 if (filp->f_pos > ctl.head.end)
486 goto finished;
487
488 ctl.fpos = filp->f_pos + (NCP_DIRCACHE_START - 2);
489 ctl.ofs = ctl.fpos / NCP_DIRCACHE_SIZE;
490 ctl.idx = ctl.fpos % NCP_DIRCACHE_SIZE;
491
492 for (;;) {
493 if (ctl.ofs != 0) {
494 ctl.page = find_lock_page(&inode->i_data, ctl.ofs);
495 if (!ctl.page)
496 goto invalid_cache;
497 ctl.cache = kmap(ctl.page);
498 if (!PageUptodate(ctl.page))
499 goto invalid_cache;
500 }
501 while (ctl.idx < NCP_DIRCACHE_SIZE) {
502 struct dentry *dent;
503 int res;
504
505 dent = ncp_dget_fpos(ctl.cache->dentry[ctl.idx],
506 dentry, filp->f_pos);
507 if (!dent)
508 goto invalid_cache;
509 res = filldir(dirent, dent->d_name.name,
510 dent->d_name.len, filp->f_pos,
511 dent->d_inode->i_ino, DT_UNKNOWN);
512 dput(dent);
513 if (res)
514 goto finished;
515 filp->f_pos += 1;
516 ctl.idx += 1;
517 if (filp->f_pos > ctl.head.end)
518 goto finished;
519 }
520 if (ctl.page) {
521 kunmap(ctl.page);
522 SetPageUptodate(ctl.page);
523 unlock_page(ctl.page);
524 page_cache_release(ctl.page);
525 ctl.page = NULL;
526 }
527 ctl.idx = 0;
528 ctl.ofs += 1;
529 }
530invalid_cache:
531 if (ctl.page) {
532 kunmap(ctl.page);
533 unlock_page(ctl.page);
534 page_cache_release(ctl.page);
535 ctl.page = NULL;
536 }
537 ctl.cache = cache;
538init_cache:
539 ncp_invalidate_dircache_entries(dentry);
540 if (!mtime_valid) {
541 mtime = ncp_obtain_mtime(dentry);
542 mtime_valid = 1;
543 }
544 ctl.head.mtime = mtime;
545 ctl.head.time = jiffies;
546 ctl.head.eof = 0;
547 ctl.fpos = 2;
548 ctl.ofs = 0;
549 ctl.idx = NCP_DIRCACHE_START;
550 ctl.filled = 0;
551 ctl.valid = 1;
552read_really:
553 if (ncp_is_server_root(inode)) {
554 ncp_read_volume_list(filp, dirent, filldir, &ctl);
555 } else {
556 ncp_do_readdir(filp, dirent, filldir, &ctl);
557 }
558 ctl.head.end = ctl.fpos - 1;
559 ctl.head.eof = ctl.valid;
560finished:
2e54eb96
PV
561 if (ctl.page) {
562 kunmap(ctl.page);
563 SetPageUptodate(ctl.page);
564 unlock_page(ctl.page);
565 page_cache_release(ctl.page);
566 }
1da177e4
LT
567 if (page) {
568 cache->head = ctl.head;
569 kunmap(page);
570 SetPageUptodate(page);
571 unlock_page(page);
572 page_cache_release(page);
573 }
1da177e4 574out:
1da177e4
LT
575 return result;
576}
577
578static int
579ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
2e54eb96
PV
580 struct ncp_cache_control *ctrl, struct ncp_entry_info *entry,
581 int inval_childs)
1da177e4 582{
92e5baef 583 struct dentry *newdent, *dentry = filp->f_path.dentry;
2e54eb96 584 struct inode *dir = dentry->d_inode;
1da177e4
LT
585 struct ncp_cache_control ctl = *ctrl;
586 struct qstr qname;
587 int valid = 0;
588 int hashed = 0;
589 ino_t ino = 0;
590 __u8 __name[NCP_MAXPATHLEN + 1];
591
592 qname.len = sizeof(__name);
2e54eb96 593 if (ncp_vol2io(NCP_SERVER(dir), __name, &qname.len,
1da177e4 594 entry->i.entryName, entry->i.nameLen,
2e54eb96 595 !ncp_preserve_entry_case(dir, entry->i.NSCreator)))
1da177e4
LT
596 return 1; /* I'm not sure */
597
598 qname.name = __name;
599 qname.hash = full_name_hash(qname.name, qname.len);
600
601 if (dentry->d_op && dentry->d_op->d_hash)
b1e6a015 602 if (dentry->d_op->d_hash(dentry, dentry->d_inode, &qname) != 0)
1da177e4
LT
603 goto end_advance;
604
605 newdent = d_lookup(dentry, &qname);
606
607 if (!newdent) {
608 newdent = d_alloc(dentry, &qname);
609 if (!newdent)
610 goto end_advance;
611 } else {
612 hashed = 1;
2e54eb96
PV
613
614 /* If case sensitivity changed for this volume, all entries below this one
615 should be thrown away. This entry itself is not affected, as its case
616 sensitivity is controlled by its own parent. */
617 if (inval_childs)
618 shrink_dcache_parent(newdent);
619
620 /*
fb2d5b86
NP
621 * NetWare's OS2 namespace is case preserving yet case
622 * insensitive. So we update dentry's name as received from
623 * server. Parent dir's i_mutex is locked because we're in
624 * readdir.
2e54eb96 625 */
fb2d5b86 626 dentry_update_name_case(newdent, &qname);
1da177e4
LT
627 }
628
629 if (!newdent->d_inode) {
2e54eb96
PV
630 struct inode *inode;
631
1da177e4 632 entry->opened = 0;
2e54eb96
PV
633 entry->ino = iunique(dir->i_sb, 2);
634 inode = ncp_iget(dir->i_sb, entry);
635 if (inode) {
1da177e4 636 newdent->d_op = &ncp_dentry_operations;
2e54eb96 637 d_instantiate(newdent, inode);
1da177e4
LT
638 if (!hashed)
639 d_rehash(newdent);
640 }
2e54eb96
PV
641 } else {
642 struct inode *inode = newdent->d_inode;
643
fb2d5b86 644 mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
2e54eb96
PV
645 ncp_update_inode2(inode, entry);
646 mutex_unlock(&inode->i_mutex);
647 }
1da177e4
LT
648
649 if (newdent->d_inode) {
650 ino = newdent->d_inode->i_ino;
651 newdent->d_fsdata = (void *) ctl.fpos;
652 ncp_new_dentry(newdent);
653 }
654
655 if (ctl.idx >= NCP_DIRCACHE_SIZE) {
656 if (ctl.page) {
657 kunmap(ctl.page);
658 SetPageUptodate(ctl.page);
659 unlock_page(ctl.page);
660 page_cache_release(ctl.page);
661 }
662 ctl.cache = NULL;
663 ctl.idx -= NCP_DIRCACHE_SIZE;
664 ctl.ofs += 1;
2e54eb96 665 ctl.page = grab_cache_page(&dir->i_data, ctl.ofs);
1da177e4
LT
666 if (ctl.page)
667 ctl.cache = kmap(ctl.page);
668 }
669 if (ctl.cache) {
670 ctl.cache->dentry[ctl.idx] = newdent;
671 valid = 1;
672 }
673 dput(newdent);
674end_advance:
675 if (!valid)
676 ctl.valid = 0;
677 if (!ctl.filled && (ctl.fpos == filp->f_pos)) {
678 if (!ino)
679 ino = find_inode_number(dentry, &qname);
680 if (!ino)
2e54eb96 681 ino = iunique(dir->i_sb, 2);
1da177e4
LT
682 ctl.filled = filldir(dirent, qname.name, qname.len,
683 filp->f_pos, ino, DT_UNKNOWN);
684 if (!ctl.filled)
685 filp->f_pos += 1;
686 }
687 ctl.fpos += 1;
688 ctl.idx += 1;
689 *ctrl = ctl;
690 return (ctl.valid || !ctl.filled);
691}
692
693static void
694ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir,
695 struct ncp_cache_control *ctl)
696{
92e5baef 697 struct dentry *dentry = filp->f_path.dentry;
1da177e4
LT
698 struct inode *inode = dentry->d_inode;
699 struct ncp_server *server = NCP_SERVER(inode);
700 struct ncp_volume_info info;
701 struct ncp_entry_info entry;
702 int i;
703
704 DPRINTK("ncp_read_volume_list: pos=%ld\n",
705 (unsigned long) filp->f_pos);
706
707 for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) {
2e54eb96 708 int inval_dentry;
1da177e4
LT
709
710 if (ncp_get_volume_info_with_number(server, i, &info) != 0)
711 return;
712 if (!strlen(info.volume_name))
713 continue;
714
715 DPRINTK("ncp_read_volume_list: found vol: %s\n",
716 info.volume_name);
717
718 if (ncp_lookup_volume(server, info.volume_name,
719 &entry.i)) {
720 DPRINTK("ncpfs: could not lookup vol %s\n",
721 info.volume_name);
722 continue;
723 }
2e54eb96 724 inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL);
1da177e4 725 entry.volume = entry.i.volNumber;
2e54eb96 726 if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, inval_dentry))
1da177e4
LT
727 return;
728 }
729}
730
731static void
732ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
733 struct ncp_cache_control *ctl)
734{
92e5baef 735 struct dentry *dentry = filp->f_path.dentry;
1da177e4
LT
736 struct inode *dir = dentry->d_inode;
737 struct ncp_server *server = NCP_SERVER(dir);
738 struct nw_search_sequence seq;
739 struct ncp_entry_info entry;
740 int err;
741 void* buf;
742 int more;
743 size_t bufsize;
744
745 DPRINTK("ncp_do_readdir: %s/%s, fpos=%ld\n",
746 dentry->d_parent->d_name.name, dentry->d_name.name,
747 (unsigned long) filp->f_pos);
748 PPRINTK("ncp_do_readdir: init %s, volnum=%d, dirent=%u\n",
749 dentry->d_name.name, NCP_FINFO(dir)->volNumber,
750 NCP_FINFO(dir)->dirEntNum);
751
752 err = ncp_initialize_search(server, dir, &seq);
753 if (err) {
754 DPRINTK("ncp_do_readdir: init failed, err=%d\n", err);
755 return;
756 }
1da177e4
LT
757 /* We MUST NOT use server->buffer_size handshaked with server if we are
758 using UDP, as for UDP server uses max. buffer size determined by
759 MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes).
760 So we use 128KB, just to be sure, as there is no way how to know
761 this value in advance. */
762 bufsize = 131072;
763 buf = vmalloc(bufsize);
764 if (!buf)
765 return;
766 do {
767 int cnt;
768 char* rpl;
769 size_t rpls;
770
771 err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls);
772 if (err) /* Error */
773 break;
774 if (!cnt) /* prevent endless loop */
775 break;
776 while (cnt--) {
777 size_t onerpl;
778
779 if (rpls < offsetof(struct nw_info_struct, entryName))
780 break; /* short packet */
781 ncp_extract_file_info(rpl, &entry.i);
782 onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen;
783 if (rpls < onerpl)
784 break; /* short packet */
785 (void)ncp_obtain_nfs_info(server, &entry.i);
786 rpl += onerpl;
787 rpls -= onerpl;
788 entry.volume = entry.i.volNumber;
2e54eb96 789 if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, 0))
1da177e4
LT
790 break;
791 }
792 } while (more);
793 vfree(buf);
1da177e4
LT
794 return;
795}
796
797int ncp_conn_logged_in(struct super_block *sb)
798{
799 struct ncp_server* server = NCP_SBP(sb);
800 int result;
801
802 if (ncp_single_volume(server)) {
803 int len;
804 struct dentry* dent;
805 __u32 volNumber;
806 __le32 dirEntNum;
807 __le32 DosDirNum;
808 __u8 __name[NCP_MAXPATHLEN + 1];
809
810 len = sizeof(__name);
811 result = ncp_io2vol(server, __name, &len, server->m.mounted_vol,
812 strlen(server->m.mounted_vol), 1);
813 if (result)
814 goto out;
815 result = -ENOENT;
816 if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) {
817 PPRINTK("ncp_conn_logged_in: %s not found\n",
818 server->m.mounted_vol);
819 goto out;
820 }
821 dent = sb->s_root;
822 if (dent) {
823 struct inode* ino = dent->d_inode;
824 if (ino) {
2e54eb96 825 ncp_update_known_namespace(server, volNumber, NULL);
1da177e4
LT
826 NCP_FINFO(ino)->volNumber = volNumber;
827 NCP_FINFO(ino)->dirEntNum = dirEntNum;
828 NCP_FINFO(ino)->DosDirNum = DosDirNum;
2e54eb96 829 result = 0;
1da177e4
LT
830 } else {
831 DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n");
832 }
833 } else {
834 DPRINTK("ncpfs: sb->s_root == NULL!\n");
835 }
2e54eb96
PV
836 } else
837 result = 0;
1da177e4
LT
838
839out:
840 return result;
841}
842
843static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
844{
845 struct ncp_server *server = NCP_SERVER(dir);
846 struct inode *inode = NULL;
847 struct ncp_entry_info finfo;
848 int error, res, len;
849 __u8 __name[NCP_MAXPATHLEN + 1];
850
1da177e4
LT
851 error = -EIO;
852 if (!ncp_conn_valid(server))
853 goto finished;
854
855 PPRINTK("ncp_lookup: server lookup for %s/%s\n",
856 dentry->d_parent->d_name.name, dentry->d_name.name);
857
858 len = sizeof(__name);
859 if (ncp_is_server_root(dir)) {
860 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
861 dentry->d_name.len, 1);
862 if (!res)
863 res = ncp_lookup_volume(server, __name, &(finfo.i));
2e54eb96
PV
864 if (!res)
865 ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
1da177e4
LT
866 } else {
867 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
868 dentry->d_name.len, !ncp_preserve_case(dir));
869 if (!res)
870 res = ncp_obtain_info(server, dir, __name, &(finfo.i));
871 }
872 PPRINTK("ncp_lookup: looked for %s/%s, res=%d\n",
873 dentry->d_parent->d_name.name, __name, res);
874 /*
875 * If we didn't find an entry, make a negative dentry.
876 */
877 if (res)
878 goto add_entry;
879
880 /*
881 * Create an inode for the entry.
882 */
883 finfo.opened = 0;
884 finfo.ino = iunique(dir->i_sb, 2);
885 finfo.volume = finfo.i.volNumber;
886 error = -EACCES;
887 inode = ncp_iget(dir->i_sb, &finfo);
888
889 if (inode) {
890 ncp_new_dentry(dentry);
891add_entry:
892 dentry->d_op = &ncp_dentry_operations;
893 d_add(dentry, inode);
894 error = 0;
895 }
896
897finished:
898 PPRINTK("ncp_lookup: result=%d\n", error);
1da177e4
LT
899 return ERR_PTR(error);
900}
901
902/*
903 * This code is common to create, mkdir, and mknod.
904 */
905static int ncp_instantiate(struct inode *dir, struct dentry *dentry,
906 struct ncp_entry_info *finfo)
907{
908 struct inode *inode;
909 int error = -EINVAL;
910
911 finfo->ino = iunique(dir->i_sb, 2);
912 inode = ncp_iget(dir->i_sb, finfo);
913 if (!inode)
914 goto out_close;
915 d_instantiate(dentry,inode);
916 error = 0;
917out:
918 return error;
919
920out_close:
921 PPRINTK("ncp_instantiate: %s/%s failed, closing file\n",
922 dentry->d_parent->d_name.name, dentry->d_name.name);
923 ncp_close_file(NCP_SERVER(dir), finfo->file_handle);
924 goto out;
925}
926
927int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
928 dev_t rdev, __le32 attributes)
929{
930 struct ncp_server *server = NCP_SERVER(dir);
931 struct ncp_entry_info finfo;
932 int error, result, len;
933 int opmode;
934 __u8 __name[NCP_MAXPATHLEN + 1];
935
936 PPRINTK("ncp_create_new: creating %s/%s, mode=%x\n",
937 dentry->d_parent->d_name.name, dentry->d_name.name, mode);
938
1da177e4
LT
939 ncp_age_dentry(server, dentry);
940 len = sizeof(__name);
941 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
942 dentry->d_name.len, !ncp_preserve_case(dir));
943 if (error)
944 goto out;
945
946 error = -EACCES;
947
948 if (S_ISREG(mode) &&
949 (server->m.flags & NCP_MOUNT_EXTRAS) &&
950 (mode & S_IXUGO))
951 attributes |= aSYSTEM | aSHARED;
952
953 result = ncp_open_create_file_or_subdir(server, dir, __name,
954 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
955 attributes, AR_READ | AR_WRITE, &finfo);
956 opmode = O_RDWR;
957 if (result) {
958 result = ncp_open_create_file_or_subdir(server, dir, __name,
959 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
960 attributes, AR_WRITE, &finfo);
961 if (result) {
962 if (result == 0x87)
963 error = -ENAMETOOLONG;
2e54eb96
PV
964 else if (result < 0)
965 error = result;
1da177e4
LT
966 DPRINTK("ncp_create: %s/%s failed\n",
967 dentry->d_parent->d_name.name, dentry->d_name.name);
968 goto out;
969 }
970 opmode = O_WRONLY;
971 }
972 finfo.access = opmode;
973 if (ncp_is_nfs_extras(server, finfo.volume)) {
974 finfo.i.nfs.mode = mode;
975 finfo.i.nfs.rdev = new_encode_dev(rdev);
976 if (ncp_modify_nfs_info(server, finfo.volume,
977 finfo.i.dirEntNum,
978 mode, new_encode_dev(rdev)) != 0)
979 goto out;
980 }
981
982 error = ncp_instantiate(dir, dentry, &finfo);
983out:
1da177e4
LT
984 return error;
985}
986
987static int ncp_create(struct inode *dir, struct dentry *dentry, int mode,
988 struct nameidata *nd)
989{
990 return ncp_create_new(dir, dentry, mode, 0, 0);
991}
992
993static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode)
994{
995 struct ncp_entry_info finfo;
996 struct ncp_server *server = NCP_SERVER(dir);
997 int error, len;
998 __u8 __name[NCP_MAXPATHLEN + 1];
999
1000 DPRINTK("ncp_mkdir: making %s/%s\n",
1001 dentry->d_parent->d_name.name, dentry->d_name.name);
1002
1da177e4
LT
1003 ncp_age_dentry(server, dentry);
1004 len = sizeof(__name);
1005 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
1006 dentry->d_name.len, !ncp_preserve_case(dir));
1007 if (error)
1008 goto out;
1009
2e54eb96 1010 error = ncp_open_create_file_or_subdir(server, dir, __name,
1da177e4
LT
1011 OC_MODE_CREATE, aDIR,
1012 cpu_to_le16(0xffff),
2e54eb96
PV
1013 &finfo);
1014 if (error == 0) {
1da177e4
LT
1015 if (ncp_is_nfs_extras(server, finfo.volume)) {
1016 mode |= S_IFDIR;
1017 finfo.i.nfs.mode = mode;
1018 if (ncp_modify_nfs_info(server,
1019 finfo.volume,
1020 finfo.i.dirEntNum,
1021 mode, 0) != 0)
1022 goto out;
1023 }
1024 error = ncp_instantiate(dir, dentry, &finfo);
2e54eb96
PV
1025 } else if (error > 0) {
1026 error = -EACCES;
1da177e4
LT
1027 }
1028out:
1da177e4
LT
1029 return error;
1030}
1031
1032static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
1033{
1034 struct ncp_server *server = NCP_SERVER(dir);
1035 int error, result, len;
1036 __u8 __name[NCP_MAXPATHLEN + 1];
1037
1038 DPRINTK("ncp_rmdir: removing %s/%s\n",
1039 dentry->d_parent->d_name.name, dentry->d_name.name);
1040
1da177e4
LT
1041 error = -EBUSY;
1042 if (!d_unhashed(dentry))
1043 goto out;
1044
1045 len = sizeof(__name);
1046 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
1047 dentry->d_name.len, !ncp_preserve_case(dir));
1048 if (error)
1049 goto out;
1050
1051 result = ncp_del_file_or_subdir(server, dir, __name);
1052 switch (result) {
1053 case 0x00:
1054 error = 0;
1055 break;
1056 case 0x85: /* unauthorized to delete file */
1057 case 0x8A: /* unauthorized to delete file */
1058 error = -EACCES;
1059 break;
1060 case 0x8F:
1061 case 0x90: /* read only */
1062 error = -EPERM;
1063 break;
1064 case 0x9F: /* in use by another client */
1065 error = -EBUSY;
1066 break;
1067 case 0xA0: /* directory not empty */
1068 error = -ENOTEMPTY;
1069 break;
1070 case 0xFF: /* someone deleted file */
1071 error = -ENOENT;
1072 break;
1073 default:
2e54eb96 1074 error = result < 0 ? result : -EACCES;
1da177e4
LT
1075 break;
1076 }
1077out:
1da177e4
LT
1078 return error;
1079}
1080
1081static int ncp_unlink(struct inode *dir, struct dentry *dentry)
1082{
1083 struct inode *inode = dentry->d_inode;
1084 struct ncp_server *server;
1085 int error;
1086
1da177e4
LT
1087 server = NCP_SERVER(dir);
1088 DPRINTK("ncp_unlink: unlinking %s/%s\n",
1089 dentry->d_parent->d_name.name, dentry->d_name.name);
1090
1da177e4
LT
1091 /*
1092 * Check whether to close the file ...
1093 */
1094 if (inode) {
1095 PPRINTK("ncp_unlink: closing file\n");
1096 ncp_make_closed(inode);
1097 }
1098
1099 error = ncp_del_file_or_subdir2(server, dentry);
1100#ifdef CONFIG_NCPFS_STRONG
1101 /* 9C is Invalid path.. It should be 8F, 90 - read only, but
1102 it is not :-( */
1103 if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */
1104 error = ncp_force_unlink(dir, dentry);
1105 }
1106#endif
1107 switch (error) {
1108 case 0x00:
1109 DPRINTK("ncp: removed %s/%s\n",
1110 dentry->d_parent->d_name.name, dentry->d_name.name);
1111 break;
1112 case 0x85:
1113 case 0x8A:
1114 error = -EACCES;
1115 break;
1116 case 0x8D: /* some files in use */
1117 case 0x8E: /* all files in use */
1118 error = -EBUSY;
1119 break;
1120 case 0x8F: /* some read only */
1121 case 0x90: /* all read only */
1122 case 0x9C: /* !!! returned when in-use or read-only by NW4 */
1123 error = -EPERM;
1124 break;
1125 case 0xFF:
1126 error = -ENOENT;
1127 break;
1128 default:
2e54eb96 1129 error = error < 0 ? error : -EACCES;
1da177e4
LT
1130 break;
1131 }
1da177e4
LT
1132 return error;
1133}
1134
1135static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
1136 struct inode *new_dir, struct dentry *new_dentry)
1137{
1138 struct ncp_server *server = NCP_SERVER(old_dir);
1139 int error;
1140 int old_len, new_len;
1141 __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1];
1142
1143 DPRINTK("ncp_rename: %s/%s to %s/%s\n",
1144 old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
1145 new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
1146
1da177e4
LT
1147 ncp_age_dentry(server, old_dentry);
1148 ncp_age_dentry(server, new_dentry);
1149
1150 old_len = sizeof(__old_name);
1151 error = ncp_io2vol(server, __old_name, &old_len,
1152 old_dentry->d_name.name, old_dentry->d_name.len,
1153 !ncp_preserve_case(old_dir));
1154 if (error)
1155 goto out;
1156
1157 new_len = sizeof(__new_name);
1158 error = ncp_io2vol(server, __new_name, &new_len,
1159 new_dentry->d_name.name, new_dentry->d_name.len,
1160 !ncp_preserve_case(new_dir));
1161 if (error)
1162 goto out;
1163
1164 error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name,
1165 new_dir, __new_name);
1166#ifdef CONFIG_NCPFS_STRONG
1167 if ((error == 0x90 || error == 0x8B || error == -EACCES) &&
1168 server->m.flags & NCP_MOUNT_STRONG) { /* RO */
1169 error = ncp_force_rename(old_dir, old_dentry, __old_name,
1170 new_dir, new_dentry, __new_name);
1171 }
1172#endif
1173 switch (error) {
1174 case 0x00:
1175 DPRINTK("ncp renamed %s -> %s.\n",
1176 old_dentry->d_name.name,new_dentry->d_name.name);
1177 break;
1178 case 0x9E:
1179 error = -ENAMETOOLONG;
1180 break;
1181 case 0xFF:
1182 error = -ENOENT;
1183 break;
1184 default:
2e54eb96 1185 error = error < 0 ? error : -EACCES;
1da177e4
LT
1186 break;
1187 }
1188out:
1da177e4
LT
1189 return error;
1190}
1191
1192static int ncp_mknod(struct inode * dir, struct dentry *dentry,
1193 int mode, dev_t rdev)
1194{
1195 if (!new_valid_dev(rdev))
1196 return -EINVAL;
1197 if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) {
1198 DPRINTK(KERN_DEBUG "ncp_mknod: mode = 0%o\n", mode);
1199 return ncp_create_new(dir, dentry, mode, rdev, 0);
1200 }
1201 return -EPERM; /* Strange, but true */
1202}
1203
1204/* The following routines are taken directly from msdos-fs */
1205
1206/* Linear day numbers of the respective 1sts in non-leap years. */
1207
1208static int day_n[] =
1209{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
1210/* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
1211
1212
1213extern struct timezone sys_tz;
1214
1215static int utc2local(int time)
1216{
1217 return time - sys_tz.tz_minuteswest * 60;
1218}
1219
1220static int local2utc(int time)
1221{
1222 return time + sys_tz.tz_minuteswest * 60;
1223}
1224
1225/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
1226int
1227ncp_date_dos2unix(__le16 t, __le16 d)
1228{
1229 unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d);
1230 int month, year, secs;
1231
1232 /* first subtract and mask after that... Otherwise, if
1233 date == 0, bad things happen */
1234 month = ((date >> 5) - 1) & 15;
1235 year = date >> 9;
1236 secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
1237 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) +
1238 year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653);
1239 /* days since 1.1.70 plus 80's leap day */
1240 return local2utc(secs);
1241}
1242
1243
1244/* Convert linear UNIX date to a MS-DOS time/date pair. */
1245void
1246ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
1247{
1248 int day, year, nl_day, month;
1249
1250 unix_date = utc2local(unix_date);
1251 *time = cpu_to_le16(
1252 (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
1253 (((unix_date / 3600) % 24) << 11));
1254 day = unix_date / 86400 - 3652;
1255 year = day / 365;
1256 if ((year + 3) / 4 + 365 * year > day)
1257 year--;
1258 day -= (year + 3) / 4 + 365 * year;
1259 if (day == 59 && !(year & 3)) {
1260 nl_day = day;
1261 month = 2;
1262 } else {
1263 nl_day = (year & 3) || day <= 59 ? day : day - 1;
c5df5913 1264 for (month = 1; month < 12; month++)
1da177e4
LT
1265 if (day_n[month] > nl_day)
1266 break;
1267 }
1268 *date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));
1269}