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