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