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
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>
20 #include <asm/uaccess.h>
21 #include <asm/byteorder.h>
22 #include <linux/smp_lock.h>
24 #include <linux/ncp_fs.h>
26 #include "ncplib_kernel.h"
28 static void ncp_read_volume_list(struct file *, void *, filldir_t,
29 struct ncp_cache_control *);
30 static void ncp_do_readdir(struct file *, void *, filldir_t,
31 struct ncp_cache_control *);
33 static int ncp_readdir(struct file *, void *, filldir_t);
35 static int ncp_create(struct inode *, struct dentry *, int, struct nameidata *);
36 static struct dentry *ncp_lookup(struct inode *, struct dentry *, struct nameidata *);
37 static int ncp_unlink(struct inode *, struct dentry *);
38 static int ncp_mkdir(struct inode *, struct dentry *, int);
39 static int ncp_rmdir(struct inode *, struct dentry *);
40 static int ncp_rename(struct inode *, struct dentry *,
41 struct inode *, struct dentry *);
42 static int ncp_mknod(struct inode * dir, struct dentry *dentry,
43 int mode, dev_t rdev);
44 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
45 extern int ncp_symlink(struct inode *, struct dentry *, const char *);
47 #define ncp_symlink NULL
50 const struct file_operations ncp_dir_operations =
52 .llseek = generic_file_llseek,
53 .read = generic_read_dir,
54 .readdir = ncp_readdir,
55 .unlocked_ioctl = ncp_ioctl,
57 .compat_ioctl = ncp_compat_ioctl,
61 const struct inode_operations ncp_dir_inode_operations =
66 .symlink = ncp_symlink,
71 .setattr = ncp_notify_change,
75 * Dentry operations routines
77 static int ncp_lookup_validate(struct dentry *, struct nameidata *);
78 static int ncp_hash_dentry(struct dentry *, struct qstr *);
79 static int ncp_compare_dentry (struct dentry *, struct qstr *, struct qstr *);
80 static int ncp_delete_dentry(struct dentry *);
82 static const struct dentry_operations ncp_dentry_operations =
84 .d_revalidate = ncp_lookup_validate,
85 .d_hash = ncp_hash_dentry,
86 .d_compare = ncp_compare_dentry,
87 .d_delete = ncp_delete_dentry,
90 const struct dentry_operations ncp_root_dentry_operations =
92 .d_hash = ncp_hash_dentry,
93 .d_compare = ncp_compare_dentry,
94 .d_delete = ncp_delete_dentry,
98 #define ncp_namespace(i) (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber])
100 static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator)
102 #ifdef CONFIG_NCPFS_SMALLDOS
103 int ns = ncp_namespace(i);
105 if ((ns == NW_NS_DOS)
106 #ifdef CONFIG_NCPFS_OS2_NS
107 || ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS))
108 #endif /* CONFIG_NCPFS_OS2_NS */
111 #endif /* CONFIG_NCPFS_SMALLDOS */
115 #define ncp_preserve_case(i) (ncp_namespace(i) != NW_NS_DOS)
117 static inline int ncp_case_sensitive(struct dentry *dentry)
119 #ifdef CONFIG_NCPFS_NFS_NS
120 return ncp_namespace(dentry->d_inode) == NW_NS_NFS;
123 #endif /* CONFIG_NCPFS_NFS_NS */
127 * Note: leave the hash unchanged if the directory
131 ncp_hash_dentry(struct dentry *dentry, struct qstr *this)
133 if (!ncp_case_sensitive(dentry)) {
138 t = NCP_IO_TABLE(dentry);
139 hash = init_name_hash();
140 for (i=0; i<this->len ; i++)
141 hash = partial_name_hash(ncp_tolower(t, this->name[i]),
143 this->hash = end_name_hash(hash);
149 ncp_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b)
151 if (a->len != b->len)
154 if (ncp_case_sensitive(dentry))
155 return strncmp(a->name, b->name, a->len);
157 return ncp_strnicmp(NCP_IO_TABLE(dentry), a->name, b->name, a->len);
161 * This is the callback from dput() when d_count is going to 0.
162 * We use this to unhash dentries with bad inodes.
163 * Closing files can be safely postponed until iput() - it's done there anyway.
166 ncp_delete_dentry(struct dentry * dentry)
168 struct inode *inode = dentry->d_inode;
171 if (is_bad_inode(inode))
175 /* N.B. Unhash negative dentries? */
181 ncp_single_volume(struct ncp_server *server)
183 return (server->m.mounted_vol[0] != '\0');
186 static inline int ncp_is_server_root(struct inode *inode)
188 return (!ncp_single_volume(NCP_SERVER(inode)) &&
189 inode == inode->i_sb->s_root->d_inode);
194 * This is the callback when the dcache has a lookup hit.
198 #ifdef CONFIG_NCPFS_STRONG
199 /* try to delete a readonly file (NW R bit set) */
202 ncp_force_unlink(struct inode *dir, struct dentry* dentry)
205 struct nw_modify_dos_info info;
209 memset(&info, 0, sizeof(info));
211 /* remove the Read-Only flag on the NW server */
212 inode = dentry->d_inode;
214 old_nwattr = NCP_FINFO(inode)->nwattr;
215 info.attributes = old_nwattr & ~(aRONLY|aDELETEINHIBIT|aRENAMEINHIBIT);
216 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
220 /* now try again the delete operation */
221 res = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry);
223 if (res) /* delete failed, set R bit again */
225 info.attributes = old_nwattr;
226 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
233 #endif /* CONFIG_NCPFS_STRONG */
235 #ifdef CONFIG_NCPFS_STRONG
237 ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_name,
238 struct inode *new_dir, struct dentry* new_dentry, char *_new_name)
240 struct nw_modify_dos_info info;
242 struct inode *old_inode = old_dentry->d_inode;
243 __le32 old_nwattr = NCP_FINFO(old_inode)->nwattr;
244 __le32 new_nwattr = 0; /* shut compiler warning */
245 int old_nwattr_changed = 0;
246 int new_nwattr_changed = 0;
248 memset(&info, 0, sizeof(info));
250 /* remove the Read-Only flag on the NW server */
252 info.attributes = old_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
253 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
255 old_nwattr_changed = 1;
256 if (new_dentry && new_dentry->d_inode) {
257 new_nwattr = NCP_FINFO(new_dentry->d_inode)->nwattr;
258 info.attributes = new_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
259 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
261 new_nwattr_changed = 1;
263 /* now try again the rename operation */
264 /* but only if something really happened */
265 if (new_nwattr_changed || old_nwattr_changed) {
266 res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
272 /* file was successfully renamed, so:
273 do not set attributes on old file - it no longer exists
274 copy attributes from old file to new */
275 new_nwattr_changed = old_nwattr_changed;
276 new_nwattr = old_nwattr;
277 old_nwattr_changed = 0;
280 if (old_nwattr_changed) {
281 info.attributes = old_nwattr;
282 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
285 if (new_nwattr_changed) {
286 info.attributes = new_nwattr;
287 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
292 #endif /* CONFIG_NCPFS_STRONG */
296 ncp_lookup_validate(struct dentry *dentry, struct nameidata *nd)
298 struct ncp_server *server;
299 struct dentry *parent;
301 struct ncp_entry_info finfo;
302 int res, val = 0, len;
303 __u8 __name[NCP_MAXPATHLEN + 1];
305 parent = dget_parent(dentry);
306 dir = parent->d_inode;
308 if (!dentry->d_inode)
311 server = NCP_SERVER(dir);
315 * The default validation is based on dentry age:
316 * We set the max age at mount time. (But each
317 * successful server lookup renews the timestamp.)
319 val = NCP_TEST_AGE(server, dentry);
323 DDPRINTK("ncp_lookup_validate: %s/%s not valid, age=%ld, server lookup\n",
324 dentry->d_parent->d_name.name, dentry->d_name.name,
325 NCP_GET_AGE(dentry));
327 len = sizeof(__name);
328 if (ncp_is_server_root(dir)) {
329 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
330 dentry->d_name.len, 1);
332 res = ncp_lookup_volume(server, __name, &(finfo.i));
334 ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
337 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
338 dentry->d_name.len, !ncp_preserve_case(dir));
340 res = ncp_obtain_info(server, dir, __name, &(finfo.i));
342 finfo.volume = finfo.i.volNumber;
343 DDPRINTK("ncp_lookup_validate: looked for %s/%s, res=%d\n",
344 dentry->d_parent->d_name.name, __name, res);
346 * If we didn't find it, or if it has a different dirEntNum to
347 * what we remember, it's not valid any more.
350 struct inode *inode = dentry->d_inode;
352 mutex_lock(&inode->i_mutex);
353 if (finfo.i.dirEntNum == NCP_FINFO(inode)->dirEntNum) {
354 ncp_new_dentry(dentry);
357 DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");
359 ncp_update_inode2(inode, &finfo);
360 mutex_unlock(&inode->i_mutex);
364 DDPRINTK("ncp_lookup_validate: result=%d\n", val);
369 static struct dentry *
370 ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
372 struct dentry *dent = dentry;
373 struct list_head *next;
375 if (d_validate(dent, parent)) {
376 if (dent->d_name.len <= NCP_MAXPATHLEN &&
377 (unsigned long)dent->d_fsdata == fpos) {
378 if (!dent->d_inode) {
387 /* If a pointer is invalid, we search the dentry. */
388 spin_lock(&dcache_lock);
389 next = parent->d_subdirs.next;
390 while (next != &parent->d_subdirs) {
391 dent = list_entry(next, struct dentry, d_u.d_child);
392 if ((unsigned long)dent->d_fsdata == fpos) {
397 spin_unlock(&dcache_lock);
402 spin_unlock(&dcache_lock);
409 static time_t ncp_obtain_mtime(struct dentry *dentry)
411 struct inode *inode = dentry->d_inode;
412 struct ncp_server *server = NCP_SERVER(inode);
413 struct nw_info_struct i;
415 if (!ncp_conn_valid(server) || ncp_is_server_root(inode))
418 if (ncp_obtain_info(server, inode, NULL, &i))
421 return ncp_date_dos2unix(i.modifyTime, i.modifyDate);
424 static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
426 struct dentry *dentry = filp->f_path.dentry;
427 struct inode *inode = dentry->d_inode;
428 struct page *page = NULL;
429 struct ncp_server *server = NCP_SERVER(inode);
430 union ncp_dir_cache *cache = NULL;
431 struct ncp_cache_control ctl;
432 int result, mtime_valid = 0;
438 DDPRINTK("ncp_readdir: reading %s/%s, pos=%d\n",
439 dentry->d_parent->d_name.name, dentry->d_name.name,
443 /* Do not generate '.' and '..' when server is dead. */
444 if (!ncp_conn_valid(server))
448 if (filp->f_pos == 0) {
449 if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR))
453 if (filp->f_pos == 1) {
454 if (filldir(dirent, "..", 2, 1, parent_ino(dentry), DT_DIR))
459 page = grab_cache_page(&inode->i_data, 0);
463 ctl.cache = cache = kmap(page);
464 ctl.head = cache->head;
466 if (!PageUptodate(page) || !ctl.head.eof)
469 if (filp->f_pos == 2) {
470 if (jiffies - ctl.head.time >= NCP_MAX_AGE(server))
473 mtime = ncp_obtain_mtime(dentry);
475 if ((!mtime) || (mtime != ctl.head.mtime))
479 if (filp->f_pos > ctl.head.end)
482 ctl.fpos = filp->f_pos + (NCP_DIRCACHE_START - 2);
483 ctl.ofs = ctl.fpos / NCP_DIRCACHE_SIZE;
484 ctl.idx = ctl.fpos % NCP_DIRCACHE_SIZE;
488 ctl.page = find_lock_page(&inode->i_data, ctl.ofs);
491 ctl.cache = kmap(ctl.page);
492 if (!PageUptodate(ctl.page))
495 while (ctl.idx < NCP_DIRCACHE_SIZE) {
499 dent = ncp_dget_fpos(ctl.cache->dentry[ctl.idx],
500 dentry, filp->f_pos);
503 res = filldir(dirent, dent->d_name.name,
504 dent->d_name.len, filp->f_pos,
505 dent->d_inode->i_ino, DT_UNKNOWN);
511 if (filp->f_pos > ctl.head.end)
516 SetPageUptodate(ctl.page);
517 unlock_page(ctl.page);
518 page_cache_release(ctl.page);
527 unlock_page(ctl.page);
528 page_cache_release(ctl.page);
533 ncp_invalidate_dircache_entries(dentry);
535 mtime = ncp_obtain_mtime(dentry);
538 ctl.head.mtime = mtime;
539 ctl.head.time = jiffies;
543 ctl.idx = NCP_DIRCACHE_START;
547 if (ncp_is_server_root(inode)) {
548 ncp_read_volume_list(filp, dirent, filldir, &ctl);
550 ncp_do_readdir(filp, dirent, filldir, &ctl);
552 ctl.head.end = ctl.fpos - 1;
553 ctl.head.eof = ctl.valid;
557 SetPageUptodate(ctl.page);
558 unlock_page(ctl.page);
559 page_cache_release(ctl.page);
562 cache->head = ctl.head;
564 SetPageUptodate(page);
566 page_cache_release(page);
573 ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
574 struct ncp_cache_control *ctrl, struct ncp_entry_info *entry,
577 struct dentry *newdent, *dentry = filp->f_path.dentry;
578 struct inode *dir = dentry->d_inode;
579 struct ncp_cache_control ctl = *ctrl;
584 __u8 __name[NCP_MAXPATHLEN + 1];
586 qname.len = sizeof(__name);
587 if (ncp_vol2io(NCP_SERVER(dir), __name, &qname.len,
588 entry->i.entryName, entry->i.nameLen,
589 !ncp_preserve_entry_case(dir, entry->i.NSCreator)))
590 return 1; /* I'm not sure */
593 qname.hash = full_name_hash(qname.name, qname.len);
595 if (dentry->d_op && dentry->d_op->d_hash)
596 if (dentry->d_op->d_hash(dentry, &qname) != 0)
599 newdent = d_lookup(dentry, &qname);
602 newdent = d_alloc(dentry, &qname);
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. */
612 shrink_dcache_parent(newdent);
615 * It is not as dangerous as it looks. NetWare's OS2 namespace is
616 * case preserving yet case insensitive. So we update dentry's name
617 * as received from server. We found dentry via d_lookup with our
618 * hash, so we know that hash does not change, and so replacing name
619 * should be reasonably safe.
621 if (qname.len == newdent->d_name.len &&
622 memcmp(newdent->d_name.name, qname.name, newdent->d_name.len)) {
623 struct inode *inode = newdent->d_inode;
626 * Inside ncpfs all uses of d_name are either for debugging,
627 * or on functions which acquire inode mutex (mknod, creat,
628 * lookup). So grab i_mutex here, to be sure. d_path
629 * uses dcache_lock when generating path, so we should too.
630 * And finally d_compare is protected by dentry's d_lock, so
634 mutex_lock(&inode->i_mutex);
635 spin_lock(&dcache_lock);
636 spin_lock(&newdent->d_lock);
637 memcpy((char *) newdent->d_name.name, qname.name,
638 newdent->d_name.len);
639 spin_unlock(&newdent->d_lock);
640 spin_unlock(&dcache_lock);
642 mutex_unlock(&inode->i_mutex);
646 if (!newdent->d_inode) {
650 entry->ino = iunique(dir->i_sb, 2);
651 inode = ncp_iget(dir->i_sb, entry);
653 newdent->d_op = &ncp_dentry_operations;
654 d_instantiate(newdent, inode);
659 struct inode *inode = newdent->d_inode;
661 mutex_lock(&inode->i_mutex);
662 ncp_update_inode2(inode, entry);
663 mutex_unlock(&inode->i_mutex);
666 if (newdent->d_inode) {
667 ino = newdent->d_inode->i_ino;
668 newdent->d_fsdata = (void *) ctl.fpos;
669 ncp_new_dentry(newdent);
672 if (ctl.idx >= NCP_DIRCACHE_SIZE) {
675 SetPageUptodate(ctl.page);
676 unlock_page(ctl.page);
677 page_cache_release(ctl.page);
680 ctl.idx -= NCP_DIRCACHE_SIZE;
682 ctl.page = grab_cache_page(&dir->i_data, ctl.ofs);
684 ctl.cache = kmap(ctl.page);
687 ctl.cache->dentry[ctl.idx] = newdent;
694 if (!ctl.filled && (ctl.fpos == filp->f_pos)) {
696 ino = find_inode_number(dentry, &qname);
698 ino = iunique(dir->i_sb, 2);
699 ctl.filled = filldir(dirent, qname.name, qname.len,
700 filp->f_pos, ino, DT_UNKNOWN);
707 return (ctl.valid || !ctl.filled);
711 ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir,
712 struct ncp_cache_control *ctl)
714 struct dentry *dentry = filp->f_path.dentry;
715 struct inode *inode = dentry->d_inode;
716 struct ncp_server *server = NCP_SERVER(inode);
717 struct ncp_volume_info info;
718 struct ncp_entry_info entry;
721 DPRINTK("ncp_read_volume_list: pos=%ld\n",
722 (unsigned long) filp->f_pos);
724 for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) {
727 if (ncp_get_volume_info_with_number(server, i, &info) != 0)
729 if (!strlen(info.volume_name))
732 DPRINTK("ncp_read_volume_list: found vol: %s\n",
735 if (ncp_lookup_volume(server, info.volume_name,
737 DPRINTK("ncpfs: could not lookup vol %s\n",
741 inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL);
742 entry.volume = entry.i.volNumber;
743 if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, inval_dentry))
749 ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
750 struct ncp_cache_control *ctl)
752 struct dentry *dentry = filp->f_path.dentry;
753 struct inode *dir = dentry->d_inode;
754 struct ncp_server *server = NCP_SERVER(dir);
755 struct nw_search_sequence seq;
756 struct ncp_entry_info entry;
762 DPRINTK("ncp_do_readdir: %s/%s, fpos=%ld\n",
763 dentry->d_parent->d_name.name, dentry->d_name.name,
764 (unsigned long) filp->f_pos);
765 PPRINTK("ncp_do_readdir: init %s, volnum=%d, dirent=%u\n",
766 dentry->d_name.name, NCP_FINFO(dir)->volNumber,
767 NCP_FINFO(dir)->dirEntNum);
769 err = ncp_initialize_search(server, dir, &seq);
771 DPRINTK("ncp_do_readdir: init failed, err=%d\n", err);
774 /* We MUST NOT use server->buffer_size handshaked with server if we are
775 using UDP, as for UDP server uses max. buffer size determined by
776 MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes).
777 So we use 128KB, just to be sure, as there is no way how to know
778 this value in advance. */
780 buf = vmalloc(bufsize);
788 err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls);
791 if (!cnt) /* prevent endless loop */
796 if (rpls < offsetof(struct nw_info_struct, entryName))
797 break; /* short packet */
798 ncp_extract_file_info(rpl, &entry.i);
799 onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen;
801 break; /* short packet */
802 (void)ncp_obtain_nfs_info(server, &entry.i);
805 entry.volume = entry.i.volNumber;
806 if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, 0))
814 int ncp_conn_logged_in(struct super_block *sb)
816 struct ncp_server* server = NCP_SBP(sb);
819 if (ncp_single_volume(server)) {
825 __u8 __name[NCP_MAXPATHLEN + 1];
827 len = sizeof(__name);
828 result = ncp_io2vol(server, __name, &len, server->m.mounted_vol,
829 strlen(server->m.mounted_vol), 1);
833 if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) {
834 PPRINTK("ncp_conn_logged_in: %s not found\n",
835 server->m.mounted_vol);
840 struct inode* ino = dent->d_inode;
842 ncp_update_known_namespace(server, volNumber, NULL);
843 NCP_FINFO(ino)->volNumber = volNumber;
844 NCP_FINFO(ino)->dirEntNum = dirEntNum;
845 NCP_FINFO(ino)->DosDirNum = DosDirNum;
848 DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n");
851 DPRINTK("ncpfs: sb->s_root == NULL!\n");
860 static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
862 struct ncp_server *server = NCP_SERVER(dir);
863 struct inode *inode = NULL;
864 struct ncp_entry_info finfo;
866 __u8 __name[NCP_MAXPATHLEN + 1];
869 if (!ncp_conn_valid(server))
872 PPRINTK("ncp_lookup: server lookup for %s/%s\n",
873 dentry->d_parent->d_name.name, dentry->d_name.name);
875 len = sizeof(__name);
876 if (ncp_is_server_root(dir)) {
877 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
878 dentry->d_name.len, 1);
880 res = ncp_lookup_volume(server, __name, &(finfo.i));
882 ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
884 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
885 dentry->d_name.len, !ncp_preserve_case(dir));
887 res = ncp_obtain_info(server, dir, __name, &(finfo.i));
889 PPRINTK("ncp_lookup: looked for %s/%s, res=%d\n",
890 dentry->d_parent->d_name.name, __name, res);
892 * If we didn't find an entry, make a negative dentry.
898 * Create an inode for the entry.
901 finfo.ino = iunique(dir->i_sb, 2);
902 finfo.volume = finfo.i.volNumber;
904 inode = ncp_iget(dir->i_sb, &finfo);
907 ncp_new_dentry(dentry);
909 dentry->d_op = &ncp_dentry_operations;
910 d_add(dentry, inode);
915 PPRINTK("ncp_lookup: result=%d\n", error);
916 return ERR_PTR(error);
920 * This code is common to create, mkdir, and mknod.
922 static int ncp_instantiate(struct inode *dir, struct dentry *dentry,
923 struct ncp_entry_info *finfo)
928 finfo->ino = iunique(dir->i_sb, 2);
929 inode = ncp_iget(dir->i_sb, finfo);
932 d_instantiate(dentry,inode);
938 PPRINTK("ncp_instantiate: %s/%s failed, closing file\n",
939 dentry->d_parent->d_name.name, dentry->d_name.name);
940 ncp_close_file(NCP_SERVER(dir), finfo->file_handle);
944 int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
945 dev_t rdev, __le32 attributes)
947 struct ncp_server *server = NCP_SERVER(dir);
948 struct ncp_entry_info finfo;
949 int error, result, len;
951 __u8 __name[NCP_MAXPATHLEN + 1];
953 PPRINTK("ncp_create_new: creating %s/%s, mode=%x\n",
954 dentry->d_parent->d_name.name, dentry->d_name.name, mode);
956 ncp_age_dentry(server, dentry);
957 len = sizeof(__name);
958 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
959 dentry->d_name.len, !ncp_preserve_case(dir));
966 (server->m.flags & NCP_MOUNT_EXTRAS) &&
968 attributes |= aSYSTEM | aSHARED;
970 result = ncp_open_create_file_or_subdir(server, dir, __name,
971 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
972 attributes, AR_READ | AR_WRITE, &finfo);
975 result = ncp_open_create_file_or_subdir(server, dir, __name,
976 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
977 attributes, AR_WRITE, &finfo);
980 error = -ENAMETOOLONG;
983 DPRINTK("ncp_create: %s/%s failed\n",
984 dentry->d_parent->d_name.name, dentry->d_name.name);
989 finfo.access = opmode;
990 if (ncp_is_nfs_extras(server, finfo.volume)) {
991 finfo.i.nfs.mode = mode;
992 finfo.i.nfs.rdev = new_encode_dev(rdev);
993 if (ncp_modify_nfs_info(server, finfo.volume,
995 mode, new_encode_dev(rdev)) != 0)
999 error = ncp_instantiate(dir, dentry, &finfo);
1004 static int ncp_create(struct inode *dir, struct dentry *dentry, int mode,
1005 struct nameidata *nd)
1007 return ncp_create_new(dir, dentry, mode, 0, 0);
1010 static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode)
1012 struct ncp_entry_info finfo;
1013 struct ncp_server *server = NCP_SERVER(dir);
1015 __u8 __name[NCP_MAXPATHLEN + 1];
1017 DPRINTK("ncp_mkdir: making %s/%s\n",
1018 dentry->d_parent->d_name.name, dentry->d_name.name);
1020 ncp_age_dentry(server, dentry);
1021 len = sizeof(__name);
1022 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
1023 dentry->d_name.len, !ncp_preserve_case(dir));
1027 error = ncp_open_create_file_or_subdir(server, dir, __name,
1028 OC_MODE_CREATE, aDIR,
1029 cpu_to_le16(0xffff),
1032 if (ncp_is_nfs_extras(server, finfo.volume)) {
1034 finfo.i.nfs.mode = mode;
1035 if (ncp_modify_nfs_info(server,
1041 error = ncp_instantiate(dir, dentry, &finfo);
1042 } else if (error > 0) {
1049 static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
1051 struct ncp_server *server = NCP_SERVER(dir);
1052 int error, result, len;
1053 __u8 __name[NCP_MAXPATHLEN + 1];
1055 DPRINTK("ncp_rmdir: removing %s/%s\n",
1056 dentry->d_parent->d_name.name, dentry->d_name.name);
1059 if (!d_unhashed(dentry))
1062 len = sizeof(__name);
1063 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
1064 dentry->d_name.len, !ncp_preserve_case(dir));
1068 result = ncp_del_file_or_subdir(server, dir, __name);
1073 case 0x85: /* unauthorized to delete file */
1074 case 0x8A: /* unauthorized to delete file */
1078 case 0x90: /* read only */
1081 case 0x9F: /* in use by another client */
1084 case 0xA0: /* directory not empty */
1087 case 0xFF: /* someone deleted file */
1091 error = result < 0 ? result : -EACCES;
1098 static int ncp_unlink(struct inode *dir, struct dentry *dentry)
1100 struct inode *inode = dentry->d_inode;
1101 struct ncp_server *server;
1104 server = NCP_SERVER(dir);
1105 DPRINTK("ncp_unlink: unlinking %s/%s\n",
1106 dentry->d_parent->d_name.name, dentry->d_name.name);
1109 * Check whether to close the file ...
1112 PPRINTK("ncp_unlink: closing file\n");
1113 ncp_make_closed(inode);
1116 error = ncp_del_file_or_subdir2(server, dentry);
1117 #ifdef CONFIG_NCPFS_STRONG
1118 /* 9C is Invalid path.. It should be 8F, 90 - read only, but
1120 if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */
1121 error = ncp_force_unlink(dir, dentry);
1126 DPRINTK("ncp: removed %s/%s\n",
1127 dentry->d_parent->d_name.name, dentry->d_name.name);
1133 case 0x8D: /* some files in use */
1134 case 0x8E: /* all files in use */
1137 case 0x8F: /* some read only */
1138 case 0x90: /* all read only */
1139 case 0x9C: /* !!! returned when in-use or read-only by NW4 */
1146 error = error < 0 ? error : -EACCES;
1152 static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
1153 struct inode *new_dir, struct dentry *new_dentry)
1155 struct ncp_server *server = NCP_SERVER(old_dir);
1157 int old_len, new_len;
1158 __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1];
1160 DPRINTK("ncp_rename: %s/%s to %s/%s\n",
1161 old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
1162 new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
1164 ncp_age_dentry(server, old_dentry);
1165 ncp_age_dentry(server, new_dentry);
1167 old_len = sizeof(__old_name);
1168 error = ncp_io2vol(server, __old_name, &old_len,
1169 old_dentry->d_name.name, old_dentry->d_name.len,
1170 !ncp_preserve_case(old_dir));
1174 new_len = sizeof(__new_name);
1175 error = ncp_io2vol(server, __new_name, &new_len,
1176 new_dentry->d_name.name, new_dentry->d_name.len,
1177 !ncp_preserve_case(new_dir));
1181 error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name,
1182 new_dir, __new_name);
1183 #ifdef CONFIG_NCPFS_STRONG
1184 if ((error == 0x90 || error == 0x8B || error == -EACCES) &&
1185 server->m.flags & NCP_MOUNT_STRONG) { /* RO */
1186 error = ncp_force_rename(old_dir, old_dentry, __old_name,
1187 new_dir, new_dentry, __new_name);
1192 DPRINTK("ncp renamed %s -> %s.\n",
1193 old_dentry->d_name.name,new_dentry->d_name.name);
1196 error = -ENAMETOOLONG;
1202 error = error < 0 ? error : -EACCES;
1209 static int ncp_mknod(struct inode * dir, struct dentry *dentry,
1210 int mode, dev_t rdev)
1212 if (!new_valid_dev(rdev))
1214 if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) {
1215 DPRINTK(KERN_DEBUG "ncp_mknod: mode = 0%o\n", mode);
1216 return ncp_create_new(dir, dentry, mode, rdev, 0);
1218 return -EPERM; /* Strange, but true */
1221 /* The following routines are taken directly from msdos-fs */
1223 /* Linear day numbers of the respective 1sts in non-leap years. */
1225 static int day_n[] =
1226 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
1227 /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
1230 extern struct timezone sys_tz;
1232 static int utc2local(int time)
1234 return time - sys_tz.tz_minuteswest * 60;
1237 static int local2utc(int time)
1239 return time + sys_tz.tz_minuteswest * 60;
1242 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
1244 ncp_date_dos2unix(__le16 t, __le16 d)
1246 unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d);
1247 int month, year, secs;
1249 /* first subtract and mask after that... Otherwise, if
1250 date == 0, bad things happen */
1251 month = ((date >> 5) - 1) & 15;
1253 secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
1254 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) +
1255 year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653);
1256 /* days since 1.1.70 plus 80's leap day */
1257 return local2utc(secs);
1261 /* Convert linear UNIX date to a MS-DOS time/date pair. */
1263 ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
1265 int day, year, nl_day, month;
1267 unix_date = utc2local(unix_date);
1268 *time = cpu_to_le16(
1269 (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
1270 (((unix_date / 3600) % 24) << 11));
1271 day = unix_date / 86400 - 3652;
1273 if ((year + 3) / 4 + 365 * year > day)
1275 day -= (year + 3) / 4 + 365 * year;
1276 if (day == 59 && !(year & 3)) {
1280 nl_day = (year & 3) || day <= 59 ? day : day - 1;
1281 for (month = 1; month < 12; month++)
1282 if (day_n[month] > nl_day)
1285 *date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));