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