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>
23 #include <linux/ncp_fs.h>
25 #include "ncplib_kernel.h"
27 static void ncp_read_volume_list(struct file *, void *, filldir_t,
28 struct ncp_cache_control *);
29 static void ncp_do_readdir(struct file *, void *, filldir_t,
30 struct ncp_cache_control *);
32 static int ncp_readdir(struct file *, void *, filldir_t);
34 static int ncp_create(struct inode *, struct dentry *, int, struct nameidata *);
35 static struct dentry *ncp_lookup(struct inode *, struct dentry *, struct nameidata *);
36 static int ncp_unlink(struct inode *, struct dentry *);
37 static int ncp_mkdir(struct inode *, struct dentry *, int);
38 static int ncp_rmdir(struct inode *, struct dentry *);
39 static int ncp_rename(struct inode *, struct dentry *,
40 struct inode *, struct dentry *);
41 static int ncp_mknod(struct inode * dir, struct dentry *dentry,
42 int mode, dev_t rdev);
43 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
44 extern int ncp_symlink(struct inode *, struct dentry *, const char *);
46 #define ncp_symlink NULL
49 const struct file_operations ncp_dir_operations =
51 .llseek = generic_file_llseek,
52 .read = generic_read_dir,
53 .readdir = ncp_readdir,
54 .unlocked_ioctl = ncp_ioctl,
56 .compat_ioctl = ncp_compat_ioctl,
60 const struct inode_operations ncp_dir_inode_operations =
65 .symlink = ncp_symlink,
70 .setattr = ncp_notify_change,
74 * Dentry operations routines
76 static int ncp_lookup_validate(struct dentry *, struct nameidata *);
77 static int ncp_hash_dentry(struct dentry *, struct qstr *);
78 static int ncp_compare_dentry (struct dentry *, struct qstr *, struct qstr *);
79 static int ncp_delete_dentry(const struct dentry *);
81 static const struct dentry_operations ncp_dentry_operations =
83 .d_revalidate = ncp_lookup_validate,
84 .d_hash = ncp_hash_dentry,
85 .d_compare = ncp_compare_dentry,
86 .d_delete = ncp_delete_dentry,
89 const struct dentry_operations ncp_root_dentry_operations =
91 .d_hash = ncp_hash_dentry,
92 .d_compare = ncp_compare_dentry,
93 .d_delete = ncp_delete_dentry,
97 #define ncp_namespace(i) (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber])
99 static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator)
101 #ifdef CONFIG_NCPFS_SMALLDOS
102 int ns = ncp_namespace(i);
104 if ((ns == NW_NS_DOS)
105 #ifdef CONFIG_NCPFS_OS2_NS
106 || ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS))
107 #endif /* CONFIG_NCPFS_OS2_NS */
110 #endif /* CONFIG_NCPFS_SMALLDOS */
114 #define ncp_preserve_case(i) (ncp_namespace(i) != NW_NS_DOS)
116 static inline int ncp_case_sensitive(struct dentry *dentry)
118 #ifdef CONFIG_NCPFS_NFS_NS
119 return ncp_namespace(dentry->d_inode) == NW_NS_NFS;
122 #endif /* CONFIG_NCPFS_NFS_NS */
126 * Note: leave the hash unchanged if the directory
130 ncp_hash_dentry(struct dentry *dentry, struct qstr *this)
132 if (!ncp_case_sensitive(dentry)) {
137 t = NCP_IO_TABLE(dentry);
138 hash = init_name_hash();
139 for (i=0; i<this->len ; i++)
140 hash = partial_name_hash(ncp_tolower(t, this->name[i]),
142 this->hash = end_name_hash(hash);
148 ncp_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b)
150 if (a->len != b->len)
153 if (ncp_case_sensitive(dentry))
154 return strncmp(a->name, b->name, a->len);
156 return ncp_strnicmp(NCP_IO_TABLE(dentry), a->name, b->name, a->len);
160 * This is the callback from dput() when d_count is going to 0.
161 * We use this to unhash dentries with bad inodes.
162 * Closing files can be safely postponed until iput() - it's done there anyway.
165 ncp_delete_dentry(const struct dentry * dentry)
167 struct inode *inode = dentry->d_inode;
170 if (is_bad_inode(inode))
174 /* N.B. Unhash negative dentries? */
180 ncp_single_volume(struct ncp_server *server)
182 return (server->m.mounted_vol[0] != '\0');
185 static inline int ncp_is_server_root(struct inode *inode)
187 return (!ncp_single_volume(NCP_SERVER(inode)) &&
188 inode == inode->i_sb->s_root->d_inode);
193 * This is the callback when the dcache has a lookup hit.
197 #ifdef CONFIG_NCPFS_STRONG
198 /* try to delete a readonly file (NW R bit set) */
201 ncp_force_unlink(struct inode *dir, struct dentry* dentry)
204 struct nw_modify_dos_info info;
208 memset(&info, 0, sizeof(info));
210 /* remove the Read-Only flag on the NW server */
211 inode = dentry->d_inode;
213 old_nwattr = NCP_FINFO(inode)->nwattr;
214 info.attributes = old_nwattr & ~(aRONLY|aDELETEINHIBIT|aRENAMEINHIBIT);
215 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
219 /* now try again the delete operation */
220 res = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry);
222 if (res) /* delete failed, set R bit again */
224 info.attributes = old_nwattr;
225 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
232 #endif /* CONFIG_NCPFS_STRONG */
234 #ifdef CONFIG_NCPFS_STRONG
236 ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_name,
237 struct inode *new_dir, struct dentry* new_dentry, char *_new_name)
239 struct nw_modify_dos_info info;
241 struct inode *old_inode = old_dentry->d_inode;
242 __le32 old_nwattr = NCP_FINFO(old_inode)->nwattr;
243 __le32 new_nwattr = 0; /* shut compiler warning */
244 int old_nwattr_changed = 0;
245 int new_nwattr_changed = 0;
247 memset(&info, 0, sizeof(info));
249 /* remove the Read-Only flag on the NW server */
251 info.attributes = old_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
252 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
254 old_nwattr_changed = 1;
255 if (new_dentry && new_dentry->d_inode) {
256 new_nwattr = NCP_FINFO(new_dentry->d_inode)->nwattr;
257 info.attributes = new_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
258 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
260 new_nwattr_changed = 1;
262 /* now try again the rename operation */
263 /* but only if something really happened */
264 if (new_nwattr_changed || old_nwattr_changed) {
265 res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
271 /* file was successfully renamed, so:
272 do not set attributes on old file - it no longer exists
273 copy attributes from old file to new */
274 new_nwattr_changed = old_nwattr_changed;
275 new_nwattr = old_nwattr;
276 old_nwattr_changed = 0;
279 if (old_nwattr_changed) {
280 info.attributes = old_nwattr;
281 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
284 if (new_nwattr_changed) {
285 info.attributes = new_nwattr;
286 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
291 #endif /* CONFIG_NCPFS_STRONG */
295 ncp_lookup_validate(struct dentry *dentry, struct nameidata *nd)
297 struct ncp_server *server;
298 struct dentry *parent;
300 struct ncp_entry_info finfo;
301 int res, val = 0, len;
302 __u8 __name[NCP_MAXPATHLEN + 1];
304 parent = dget_parent(dentry);
305 dir = parent->d_inode;
307 if (!dentry->d_inode)
310 server = NCP_SERVER(dir);
314 * The default validation is based on dentry age:
315 * We set the max age at mount time. (But each
316 * successful server lookup renews the timestamp.)
318 val = NCP_TEST_AGE(server, dentry);
322 DDPRINTK("ncp_lookup_validate: %s/%s not valid, age=%ld, server lookup\n",
323 dentry->d_parent->d_name.name, dentry->d_name.name,
324 NCP_GET_AGE(dentry));
326 len = sizeof(__name);
327 if (ncp_is_server_root(dir)) {
328 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
329 dentry->d_name.len, 1);
331 res = ncp_lookup_volume(server, __name, &(finfo.i));
333 ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
336 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
337 dentry->d_name.len, !ncp_preserve_case(dir));
339 res = ncp_obtain_info(server, dir, __name, &(finfo.i));
341 finfo.volume = finfo.i.volNumber;
342 DDPRINTK("ncp_lookup_validate: looked for %s/%s, res=%d\n",
343 dentry->d_parent->d_name.name, __name, res);
345 * If we didn't find it, or if it has a different dirEntNum to
346 * what we remember, it's not valid any more.
349 struct inode *inode = dentry->d_inode;
351 mutex_lock(&inode->i_mutex);
352 if (finfo.i.dirEntNum == NCP_FINFO(inode)->dirEntNum) {
353 ncp_new_dentry(dentry);
356 DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");
358 ncp_update_inode2(inode, &finfo);
359 mutex_unlock(&inode->i_mutex);
363 DDPRINTK("ncp_lookup_validate: result=%d\n", val);
368 static struct dentry *
369 ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
371 struct dentry *dent = dentry;
372 struct list_head *next;
374 if (d_validate(dent, parent)) {
375 if (dent->d_name.len <= NCP_MAXPATHLEN &&
376 (unsigned long)dent->d_fsdata == fpos) {
377 if (!dent->d_inode) {
386 /* If a pointer is invalid, we search the dentry. */
387 spin_lock(&dcache_lock);
388 next = parent->d_subdirs.next;
389 while (next != &parent->d_subdirs) {
390 dent = list_entry(next, struct dentry, d_u.d_child);
391 if ((unsigned long)dent->d_fsdata == fpos) {
396 spin_unlock(&dcache_lock);
401 spin_unlock(&dcache_lock);
408 static time_t ncp_obtain_mtime(struct dentry *dentry)
410 struct inode *inode = dentry->d_inode;
411 struct ncp_server *server = NCP_SERVER(inode);
412 struct nw_info_struct i;
414 if (!ncp_conn_valid(server) || ncp_is_server_root(inode))
417 if (ncp_obtain_info(server, inode, NULL, &i))
420 return ncp_date_dos2unix(i.modifyTime, i.modifyDate);
423 static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
425 struct dentry *dentry = filp->f_path.dentry;
426 struct inode *inode = dentry->d_inode;
427 struct page *page = NULL;
428 struct ncp_server *server = NCP_SERVER(inode);
429 union ncp_dir_cache *cache = NULL;
430 struct ncp_cache_control ctl;
431 int result, mtime_valid = 0;
437 DDPRINTK("ncp_readdir: reading %s/%s, pos=%d\n",
438 dentry->d_parent->d_name.name, dentry->d_name.name,
442 /* Do not generate '.' and '..' when server is dead. */
443 if (!ncp_conn_valid(server))
447 if (filp->f_pos == 0) {
448 if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR))
452 if (filp->f_pos == 1) {
453 if (filldir(dirent, "..", 2, 1, parent_ino(dentry), DT_DIR))
458 page = grab_cache_page(&inode->i_data, 0);
462 ctl.cache = cache = kmap(page);
463 ctl.head = cache->head;
465 if (!PageUptodate(page) || !ctl.head.eof)
468 if (filp->f_pos == 2) {
469 if (jiffies - ctl.head.time >= NCP_MAX_AGE(server))
472 mtime = ncp_obtain_mtime(dentry);
474 if ((!mtime) || (mtime != ctl.head.mtime))
478 if (filp->f_pos > ctl.head.end)
481 ctl.fpos = filp->f_pos + (NCP_DIRCACHE_START - 2);
482 ctl.ofs = ctl.fpos / NCP_DIRCACHE_SIZE;
483 ctl.idx = ctl.fpos % NCP_DIRCACHE_SIZE;
487 ctl.page = find_lock_page(&inode->i_data, ctl.ofs);
490 ctl.cache = kmap(ctl.page);
491 if (!PageUptodate(ctl.page))
494 while (ctl.idx < NCP_DIRCACHE_SIZE) {
498 dent = ncp_dget_fpos(ctl.cache->dentry[ctl.idx],
499 dentry, filp->f_pos);
502 res = filldir(dirent, dent->d_name.name,
503 dent->d_name.len, filp->f_pos,
504 dent->d_inode->i_ino, DT_UNKNOWN);
510 if (filp->f_pos > ctl.head.end)
515 SetPageUptodate(ctl.page);
516 unlock_page(ctl.page);
517 page_cache_release(ctl.page);
526 unlock_page(ctl.page);
527 page_cache_release(ctl.page);
532 ncp_invalidate_dircache_entries(dentry);
534 mtime = ncp_obtain_mtime(dentry);
537 ctl.head.mtime = mtime;
538 ctl.head.time = jiffies;
542 ctl.idx = NCP_DIRCACHE_START;
546 if (ncp_is_server_root(inode)) {
547 ncp_read_volume_list(filp, dirent, filldir, &ctl);
549 ncp_do_readdir(filp, dirent, filldir, &ctl);
551 ctl.head.end = ctl.fpos - 1;
552 ctl.head.eof = ctl.valid;
556 SetPageUptodate(ctl.page);
557 unlock_page(ctl.page);
558 page_cache_release(ctl.page);
561 cache->head = ctl.head;
563 SetPageUptodate(page);
565 page_cache_release(page);
572 ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
573 struct ncp_cache_control *ctrl, struct ncp_entry_info *entry,
576 struct dentry *newdent, *dentry = filp->f_path.dentry;
577 struct inode *dir = dentry->d_inode;
578 struct ncp_cache_control ctl = *ctrl;
583 __u8 __name[NCP_MAXPATHLEN + 1];
585 qname.len = sizeof(__name);
586 if (ncp_vol2io(NCP_SERVER(dir), __name, &qname.len,
587 entry->i.entryName, entry->i.nameLen,
588 !ncp_preserve_entry_case(dir, entry->i.NSCreator)))
589 return 1; /* I'm not sure */
592 qname.hash = full_name_hash(qname.name, qname.len);
594 if (dentry->d_op && dentry->d_op->d_hash)
595 if (dentry->d_op->d_hash(dentry, &qname) != 0)
598 newdent = d_lookup(dentry, &qname);
601 newdent = d_alloc(dentry, &qname);
607 /* If case sensitivity changed for this volume, all entries below this one
608 should be thrown away. This entry itself is not affected, as its case
609 sensitivity is controlled by its own parent. */
611 shrink_dcache_parent(newdent);
614 * NetWare's OS2 namespace is case preserving yet case
615 * insensitive. So we update dentry's name as received from
616 * server. Parent dir's i_mutex is locked because we're in
619 dentry_update_name_case(newdent, &qname);
622 if (!newdent->d_inode) {
626 entry->ino = iunique(dir->i_sb, 2);
627 inode = ncp_iget(dir->i_sb, entry);
629 newdent->d_op = &ncp_dentry_operations;
630 d_instantiate(newdent, inode);
635 struct inode *inode = newdent->d_inode;
637 mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
638 ncp_update_inode2(inode, entry);
639 mutex_unlock(&inode->i_mutex);
642 if (newdent->d_inode) {
643 ino = newdent->d_inode->i_ino;
644 newdent->d_fsdata = (void *) ctl.fpos;
645 ncp_new_dentry(newdent);
648 if (ctl.idx >= NCP_DIRCACHE_SIZE) {
651 SetPageUptodate(ctl.page);
652 unlock_page(ctl.page);
653 page_cache_release(ctl.page);
656 ctl.idx -= NCP_DIRCACHE_SIZE;
658 ctl.page = grab_cache_page(&dir->i_data, ctl.ofs);
660 ctl.cache = kmap(ctl.page);
663 ctl.cache->dentry[ctl.idx] = newdent;
670 if (!ctl.filled && (ctl.fpos == filp->f_pos)) {
672 ino = find_inode_number(dentry, &qname);
674 ino = iunique(dir->i_sb, 2);
675 ctl.filled = filldir(dirent, qname.name, qname.len,
676 filp->f_pos, ino, DT_UNKNOWN);
683 return (ctl.valid || !ctl.filled);
687 ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir,
688 struct ncp_cache_control *ctl)
690 struct dentry *dentry = filp->f_path.dentry;
691 struct inode *inode = dentry->d_inode;
692 struct ncp_server *server = NCP_SERVER(inode);
693 struct ncp_volume_info info;
694 struct ncp_entry_info entry;
697 DPRINTK("ncp_read_volume_list: pos=%ld\n",
698 (unsigned long) filp->f_pos);
700 for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) {
703 if (ncp_get_volume_info_with_number(server, i, &info) != 0)
705 if (!strlen(info.volume_name))
708 DPRINTK("ncp_read_volume_list: found vol: %s\n",
711 if (ncp_lookup_volume(server, info.volume_name,
713 DPRINTK("ncpfs: could not lookup vol %s\n",
717 inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL);
718 entry.volume = entry.i.volNumber;
719 if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, inval_dentry))
725 ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
726 struct ncp_cache_control *ctl)
728 struct dentry *dentry = filp->f_path.dentry;
729 struct inode *dir = dentry->d_inode;
730 struct ncp_server *server = NCP_SERVER(dir);
731 struct nw_search_sequence seq;
732 struct ncp_entry_info entry;
738 DPRINTK("ncp_do_readdir: %s/%s, fpos=%ld\n",
739 dentry->d_parent->d_name.name, dentry->d_name.name,
740 (unsigned long) filp->f_pos);
741 PPRINTK("ncp_do_readdir: init %s, volnum=%d, dirent=%u\n",
742 dentry->d_name.name, NCP_FINFO(dir)->volNumber,
743 NCP_FINFO(dir)->dirEntNum);
745 err = ncp_initialize_search(server, dir, &seq);
747 DPRINTK("ncp_do_readdir: init failed, err=%d\n", err);
750 /* We MUST NOT use server->buffer_size handshaked with server if we are
751 using UDP, as for UDP server uses max. buffer size determined by
752 MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes).
753 So we use 128KB, just to be sure, as there is no way how to know
754 this value in advance. */
756 buf = vmalloc(bufsize);
764 err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls);
767 if (!cnt) /* prevent endless loop */
772 if (rpls < offsetof(struct nw_info_struct, entryName))
773 break; /* short packet */
774 ncp_extract_file_info(rpl, &entry.i);
775 onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen;
777 break; /* short packet */
778 (void)ncp_obtain_nfs_info(server, &entry.i);
781 entry.volume = entry.i.volNumber;
782 if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, 0))
790 int ncp_conn_logged_in(struct super_block *sb)
792 struct ncp_server* server = NCP_SBP(sb);
795 if (ncp_single_volume(server)) {
801 __u8 __name[NCP_MAXPATHLEN + 1];
803 len = sizeof(__name);
804 result = ncp_io2vol(server, __name, &len, server->m.mounted_vol,
805 strlen(server->m.mounted_vol), 1);
809 if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) {
810 PPRINTK("ncp_conn_logged_in: %s not found\n",
811 server->m.mounted_vol);
816 struct inode* ino = dent->d_inode;
818 ncp_update_known_namespace(server, volNumber, NULL);
819 NCP_FINFO(ino)->volNumber = volNumber;
820 NCP_FINFO(ino)->dirEntNum = dirEntNum;
821 NCP_FINFO(ino)->DosDirNum = DosDirNum;
824 DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n");
827 DPRINTK("ncpfs: sb->s_root == NULL!\n");
836 static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
838 struct ncp_server *server = NCP_SERVER(dir);
839 struct inode *inode = NULL;
840 struct ncp_entry_info finfo;
842 __u8 __name[NCP_MAXPATHLEN + 1];
845 if (!ncp_conn_valid(server))
848 PPRINTK("ncp_lookup: server lookup for %s/%s\n",
849 dentry->d_parent->d_name.name, dentry->d_name.name);
851 len = sizeof(__name);
852 if (ncp_is_server_root(dir)) {
853 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
854 dentry->d_name.len, 1);
856 res = ncp_lookup_volume(server, __name, &(finfo.i));
858 ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
860 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
861 dentry->d_name.len, !ncp_preserve_case(dir));
863 res = ncp_obtain_info(server, dir, __name, &(finfo.i));
865 PPRINTK("ncp_lookup: looked for %s/%s, res=%d\n",
866 dentry->d_parent->d_name.name, __name, res);
868 * If we didn't find an entry, make a negative dentry.
874 * Create an inode for the entry.
877 finfo.ino = iunique(dir->i_sb, 2);
878 finfo.volume = finfo.i.volNumber;
880 inode = ncp_iget(dir->i_sb, &finfo);
883 ncp_new_dentry(dentry);
885 dentry->d_op = &ncp_dentry_operations;
886 d_add(dentry, inode);
891 PPRINTK("ncp_lookup: result=%d\n", error);
892 return ERR_PTR(error);
896 * This code is common to create, mkdir, and mknod.
898 static int ncp_instantiate(struct inode *dir, struct dentry *dentry,
899 struct ncp_entry_info *finfo)
904 finfo->ino = iunique(dir->i_sb, 2);
905 inode = ncp_iget(dir->i_sb, finfo);
908 d_instantiate(dentry,inode);
914 PPRINTK("ncp_instantiate: %s/%s failed, closing file\n",
915 dentry->d_parent->d_name.name, dentry->d_name.name);
916 ncp_close_file(NCP_SERVER(dir), finfo->file_handle);
920 int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
921 dev_t rdev, __le32 attributes)
923 struct ncp_server *server = NCP_SERVER(dir);
924 struct ncp_entry_info finfo;
925 int error, result, len;
927 __u8 __name[NCP_MAXPATHLEN + 1];
929 PPRINTK("ncp_create_new: creating %s/%s, mode=%x\n",
930 dentry->d_parent->d_name.name, dentry->d_name.name, mode);
932 ncp_age_dentry(server, dentry);
933 len = sizeof(__name);
934 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
935 dentry->d_name.len, !ncp_preserve_case(dir));
942 (server->m.flags & NCP_MOUNT_EXTRAS) &&
944 attributes |= aSYSTEM | aSHARED;
946 result = ncp_open_create_file_or_subdir(server, dir, __name,
947 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
948 attributes, AR_READ | AR_WRITE, &finfo);
951 result = ncp_open_create_file_or_subdir(server, dir, __name,
952 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
953 attributes, AR_WRITE, &finfo);
956 error = -ENAMETOOLONG;
959 DPRINTK("ncp_create: %s/%s failed\n",
960 dentry->d_parent->d_name.name, dentry->d_name.name);
965 finfo.access = opmode;
966 if (ncp_is_nfs_extras(server, finfo.volume)) {
967 finfo.i.nfs.mode = mode;
968 finfo.i.nfs.rdev = new_encode_dev(rdev);
969 if (ncp_modify_nfs_info(server, finfo.volume,
971 mode, new_encode_dev(rdev)) != 0)
975 error = ncp_instantiate(dir, dentry, &finfo);
980 static int ncp_create(struct inode *dir, struct dentry *dentry, int mode,
981 struct nameidata *nd)
983 return ncp_create_new(dir, dentry, mode, 0, 0);
986 static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode)
988 struct ncp_entry_info finfo;
989 struct ncp_server *server = NCP_SERVER(dir);
991 __u8 __name[NCP_MAXPATHLEN + 1];
993 DPRINTK("ncp_mkdir: making %s/%s\n",
994 dentry->d_parent->d_name.name, dentry->d_name.name);
996 ncp_age_dentry(server, dentry);
997 len = sizeof(__name);
998 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
999 dentry->d_name.len, !ncp_preserve_case(dir));
1003 error = ncp_open_create_file_or_subdir(server, dir, __name,
1004 OC_MODE_CREATE, aDIR,
1005 cpu_to_le16(0xffff),
1008 if (ncp_is_nfs_extras(server, finfo.volume)) {
1010 finfo.i.nfs.mode = mode;
1011 if (ncp_modify_nfs_info(server,
1017 error = ncp_instantiate(dir, dentry, &finfo);
1018 } else if (error > 0) {
1025 static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
1027 struct ncp_server *server = NCP_SERVER(dir);
1028 int error, result, len;
1029 __u8 __name[NCP_MAXPATHLEN + 1];
1031 DPRINTK("ncp_rmdir: removing %s/%s\n",
1032 dentry->d_parent->d_name.name, dentry->d_name.name);
1035 if (!d_unhashed(dentry))
1038 len = sizeof(__name);
1039 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
1040 dentry->d_name.len, !ncp_preserve_case(dir));
1044 result = ncp_del_file_or_subdir(server, dir, __name);
1049 case 0x85: /* unauthorized to delete file */
1050 case 0x8A: /* unauthorized to delete file */
1054 case 0x90: /* read only */
1057 case 0x9F: /* in use by another client */
1060 case 0xA0: /* directory not empty */
1063 case 0xFF: /* someone deleted file */
1067 error = result < 0 ? result : -EACCES;
1074 static int ncp_unlink(struct inode *dir, struct dentry *dentry)
1076 struct inode *inode = dentry->d_inode;
1077 struct ncp_server *server;
1080 server = NCP_SERVER(dir);
1081 DPRINTK("ncp_unlink: unlinking %s/%s\n",
1082 dentry->d_parent->d_name.name, dentry->d_name.name);
1085 * Check whether to close the file ...
1088 PPRINTK("ncp_unlink: closing file\n");
1089 ncp_make_closed(inode);
1092 error = ncp_del_file_or_subdir2(server, dentry);
1093 #ifdef CONFIG_NCPFS_STRONG
1094 /* 9C is Invalid path.. It should be 8F, 90 - read only, but
1096 if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */
1097 error = ncp_force_unlink(dir, dentry);
1102 DPRINTK("ncp: removed %s/%s\n",
1103 dentry->d_parent->d_name.name, dentry->d_name.name);
1109 case 0x8D: /* some files in use */
1110 case 0x8E: /* all files in use */
1113 case 0x8F: /* some read only */
1114 case 0x90: /* all read only */
1115 case 0x9C: /* !!! returned when in-use or read-only by NW4 */
1122 error = error < 0 ? error : -EACCES;
1128 static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
1129 struct inode *new_dir, struct dentry *new_dentry)
1131 struct ncp_server *server = NCP_SERVER(old_dir);
1133 int old_len, new_len;
1134 __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1];
1136 DPRINTK("ncp_rename: %s/%s to %s/%s\n",
1137 old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
1138 new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
1140 ncp_age_dentry(server, old_dentry);
1141 ncp_age_dentry(server, new_dentry);
1143 old_len = sizeof(__old_name);
1144 error = ncp_io2vol(server, __old_name, &old_len,
1145 old_dentry->d_name.name, old_dentry->d_name.len,
1146 !ncp_preserve_case(old_dir));
1150 new_len = sizeof(__new_name);
1151 error = ncp_io2vol(server, __new_name, &new_len,
1152 new_dentry->d_name.name, new_dentry->d_name.len,
1153 !ncp_preserve_case(new_dir));
1157 error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name,
1158 new_dir, __new_name);
1159 #ifdef CONFIG_NCPFS_STRONG
1160 if ((error == 0x90 || error == 0x8B || error == -EACCES) &&
1161 server->m.flags & NCP_MOUNT_STRONG) { /* RO */
1162 error = ncp_force_rename(old_dir, old_dentry, __old_name,
1163 new_dir, new_dentry, __new_name);
1168 DPRINTK("ncp renamed %s -> %s.\n",
1169 old_dentry->d_name.name,new_dentry->d_name.name);
1172 error = -ENAMETOOLONG;
1178 error = error < 0 ? error : -EACCES;
1185 static int ncp_mknod(struct inode * dir, struct dentry *dentry,
1186 int mode, dev_t rdev)
1188 if (!new_valid_dev(rdev))
1190 if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) {
1191 DPRINTK(KERN_DEBUG "ncp_mknod: mode = 0%o\n", mode);
1192 return ncp_create_new(dir, dentry, mode, rdev, 0);
1194 return -EPERM; /* Strange, but true */
1197 /* The following routines are taken directly from msdos-fs */
1199 /* Linear day numbers of the respective 1sts in non-leap years. */
1201 static int day_n[] =
1202 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
1203 /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
1206 extern struct timezone sys_tz;
1208 static int utc2local(int time)
1210 return time - sys_tz.tz_minuteswest * 60;
1213 static int local2utc(int time)
1215 return time + sys_tz.tz_minuteswest * 60;
1218 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
1220 ncp_date_dos2unix(__le16 t, __le16 d)
1222 unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d);
1223 int month, year, secs;
1225 /* first subtract and mask after that... Otherwise, if
1226 date == 0, bad things happen */
1227 month = ((date >> 5) - 1) & 15;
1229 secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
1230 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) +
1231 year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653);
1232 /* days since 1.1.70 plus 80's leap day */
1233 return local2utc(secs);
1237 /* Convert linear UNIX date to a MS-DOS time/date pair. */
1239 ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
1241 int day, year, nl_day, month;
1243 unix_date = utc2local(unix_date);
1244 *time = cpu_to_le16(
1245 (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
1246 (((unix_date / 3600) % 24) << 11));
1247 day = unix_date / 86400 - 3652;
1249 if ((year + 3) / 4 + 365 * year > day)
1251 day -= (year + 3) / 4 + 365 * year;
1252 if (day == 59 && !(year & 3)) {
1256 nl_day = (year & 3) || day <= 59 ? day : day - 1;
1257 for (month = 1; month < 12; month++)
1258 if (day_n[month] > nl_day)
1261 *date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));