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(const struct dentry *, const struct inode *,
79 static int ncp_compare_dentry(const struct dentry *, const struct inode *,
80 const struct dentry *, const struct inode *,
81 unsigned int, const char *, const struct qstr *);
82 static int ncp_delete_dentry(const struct dentry *);
84 static const struct dentry_operations ncp_dentry_operations =
86 .d_revalidate = ncp_lookup_validate,
87 .d_hash = ncp_hash_dentry,
88 .d_compare = ncp_compare_dentry,
89 .d_delete = ncp_delete_dentry,
92 const struct dentry_operations ncp_root_dentry_operations =
94 .d_hash = ncp_hash_dentry,
95 .d_compare = ncp_compare_dentry,
96 .d_delete = ncp_delete_dentry,
100 #define ncp_namespace(i) (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber])
102 static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator)
104 #ifdef CONFIG_NCPFS_SMALLDOS
105 int ns = ncp_namespace(i);
107 if ((ns == NW_NS_DOS)
108 #ifdef CONFIG_NCPFS_OS2_NS
109 || ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS))
110 #endif /* CONFIG_NCPFS_OS2_NS */
113 #endif /* CONFIG_NCPFS_SMALLDOS */
117 #define ncp_preserve_case(i) (ncp_namespace(i) != NW_NS_DOS)
119 static inline int ncp_case_sensitive(const struct inode *i)
121 #ifdef CONFIG_NCPFS_NFS_NS
122 return ncp_namespace(i) == NW_NS_NFS;
125 #endif /* CONFIG_NCPFS_NFS_NS */
129 * Note: leave the hash unchanged if the directory
133 ncp_hash_dentry(const struct dentry *dentry, const struct inode *inode,
136 if (!ncp_case_sensitive(inode)) {
137 struct super_block *sb = dentry->d_sb;
142 t = NCP_IO_TABLE(sb);
143 hash = init_name_hash();
144 for (i=0; i<this->len ; i++)
145 hash = partial_name_hash(ncp_tolower(t, this->name[i]),
147 this->hash = end_name_hash(hash);
153 ncp_compare_dentry(const struct dentry *parent, const struct inode *pinode,
154 const struct dentry *dentry, const struct inode *inode,
155 unsigned int len, const char *str, const struct qstr *name)
157 if (len != name->len)
160 if (ncp_case_sensitive(pinode))
161 return strncmp(str, name->name, len);
163 return ncp_strnicmp(NCP_IO_TABLE(pinode->i_sb), str, name->name, len);
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.
172 ncp_delete_dentry(const struct dentry * dentry)
174 struct inode *inode = dentry->d_inode;
177 if (is_bad_inode(inode))
181 /* N.B. Unhash negative dentries? */
187 ncp_single_volume(struct ncp_server *server)
189 return (server->m.mounted_vol[0] != '\0');
192 static inline int ncp_is_server_root(struct inode *inode)
194 return (!ncp_single_volume(NCP_SERVER(inode)) &&
195 inode == inode->i_sb->s_root->d_inode);
200 * This is the callback when the dcache has a lookup hit.
204 #ifdef CONFIG_NCPFS_STRONG
205 /* try to delete a readonly file (NW R bit set) */
208 ncp_force_unlink(struct inode *dir, struct dentry* dentry)
211 struct nw_modify_dos_info info;
215 memset(&info, 0, sizeof(info));
217 /* remove the Read-Only flag on the NW server */
218 inode = dentry->d_inode;
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);
226 /* now try again the delete operation */
227 res = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry);
229 if (res) /* delete failed, set R bit again */
231 info.attributes = old_nwattr;
232 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
239 #endif /* CONFIG_NCPFS_STRONG */
241 #ifdef CONFIG_NCPFS_STRONG
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)
246 struct nw_modify_dos_info info;
248 struct inode *old_inode = old_dentry->d_inode;
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;
254 memset(&info, 0, sizeof(info));
256 /* remove the Read-Only flag on the NW server */
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);
261 old_nwattr_changed = 1;
262 if (new_dentry && new_dentry->d_inode) {
263 new_nwattr = NCP_FINFO(new_dentry->d_inode)->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);
267 new_nwattr_changed = 1;
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),
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;
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);
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);
298 #endif /* CONFIG_NCPFS_STRONG */
302 ncp_lookup_validate(struct dentry *dentry, struct nameidata *nd)
304 struct ncp_server *server;
305 struct dentry *parent;
307 struct ncp_entry_info finfo;
308 int res, val = 0, len;
309 __u8 __name[NCP_MAXPATHLEN + 1];
311 parent = dget_parent(dentry);
312 dir = parent->d_inode;
314 if (!dentry->d_inode)
317 server = NCP_SERVER(dir);
321 * The default validation is based on dentry age:
322 * We set the max age at mount time. (But each
323 * successful server lookup renews the timestamp.)
325 val = NCP_TEST_AGE(server, dentry);
329 DDPRINTK("ncp_lookup_validate: %s/%s not valid, age=%ld, server lookup\n",
330 dentry->d_parent->d_name.name, dentry->d_name.name,
331 NCP_GET_AGE(dentry));
333 len = sizeof(__name);
334 if (ncp_is_server_root(dir)) {
335 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
336 dentry->d_name.len, 1);
338 res = ncp_lookup_volume(server, __name, &(finfo.i));
340 ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
343 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
344 dentry->d_name.len, !ncp_preserve_case(dir));
346 res = ncp_obtain_info(server, dir, __name, &(finfo.i));
348 finfo.volume = finfo.i.volNumber;
349 DDPRINTK("ncp_lookup_validate: looked for %s/%s, res=%d\n",
350 dentry->d_parent->d_name.name, __name, res);
352 * If we didn't find it, or if it has a different dirEntNum to
353 * what we remember, it's not valid any more.
356 struct inode *inode = dentry->d_inode;
358 mutex_lock(&inode->i_mutex);
359 if (finfo.i.dirEntNum == NCP_FINFO(inode)->dirEntNum) {
360 ncp_new_dentry(dentry);
363 DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");
365 ncp_update_inode2(inode, &finfo);
366 mutex_unlock(&inode->i_mutex);
370 DDPRINTK("ncp_lookup_validate: result=%d\n", val);
375 static struct dentry *
376 ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
378 struct dentry *dent = dentry;
379 struct list_head *next;
381 if (d_validate(dent, parent)) {
382 if (dent->d_name.len <= NCP_MAXPATHLEN &&
383 (unsigned long)dent->d_fsdata == fpos) {
384 if (!dent->d_inode) {
393 /* If a pointer is invalid, we search the dentry. */
394 spin_lock(&dcache_lock);
395 spin_lock(&parent->d_lock);
396 next = parent->d_subdirs.next;
397 while (next != &parent->d_subdirs) {
398 dent = list_entry(next, struct dentry, d_u.d_child);
399 if ((unsigned long)dent->d_fsdata == fpos) {
404 spin_unlock(&parent->d_lock);
405 spin_unlock(&dcache_lock);
410 spin_unlock(&parent->d_lock);
411 spin_unlock(&dcache_lock);
418 static time_t ncp_obtain_mtime(struct dentry *dentry)
420 struct inode *inode = dentry->d_inode;
421 struct ncp_server *server = NCP_SERVER(inode);
422 struct nw_info_struct i;
424 if (!ncp_conn_valid(server) || ncp_is_server_root(inode))
427 if (ncp_obtain_info(server, inode, NULL, &i))
430 return ncp_date_dos2unix(i.modifyTime, i.modifyDate);
433 static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
435 struct dentry *dentry = filp->f_path.dentry;
436 struct inode *inode = dentry->d_inode;
437 struct page *page = NULL;
438 struct ncp_server *server = NCP_SERVER(inode);
439 union ncp_dir_cache *cache = NULL;
440 struct ncp_cache_control ctl;
441 int result, mtime_valid = 0;
447 DDPRINTK("ncp_readdir: reading %s/%s, pos=%d\n",
448 dentry->d_parent->d_name.name, dentry->d_name.name,
452 /* Do not generate '.' and '..' when server is dead. */
453 if (!ncp_conn_valid(server))
457 if (filp->f_pos == 0) {
458 if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR))
462 if (filp->f_pos == 1) {
463 if (filldir(dirent, "..", 2, 1, parent_ino(dentry), DT_DIR))
468 page = grab_cache_page(&inode->i_data, 0);
472 ctl.cache = cache = kmap(page);
473 ctl.head = cache->head;
475 if (!PageUptodate(page) || !ctl.head.eof)
478 if (filp->f_pos == 2) {
479 if (jiffies - ctl.head.time >= NCP_MAX_AGE(server))
482 mtime = ncp_obtain_mtime(dentry);
484 if ((!mtime) || (mtime != ctl.head.mtime))
488 if (filp->f_pos > ctl.head.end)
491 ctl.fpos = filp->f_pos + (NCP_DIRCACHE_START - 2);
492 ctl.ofs = ctl.fpos / NCP_DIRCACHE_SIZE;
493 ctl.idx = ctl.fpos % NCP_DIRCACHE_SIZE;
497 ctl.page = find_lock_page(&inode->i_data, ctl.ofs);
500 ctl.cache = kmap(ctl.page);
501 if (!PageUptodate(ctl.page))
504 while (ctl.idx < NCP_DIRCACHE_SIZE) {
508 dent = ncp_dget_fpos(ctl.cache->dentry[ctl.idx],
509 dentry, filp->f_pos);
512 res = filldir(dirent, dent->d_name.name,
513 dent->d_name.len, filp->f_pos,
514 dent->d_inode->i_ino, DT_UNKNOWN);
520 if (filp->f_pos > ctl.head.end)
525 SetPageUptodate(ctl.page);
526 unlock_page(ctl.page);
527 page_cache_release(ctl.page);
536 unlock_page(ctl.page);
537 page_cache_release(ctl.page);
542 ncp_invalidate_dircache_entries(dentry);
544 mtime = ncp_obtain_mtime(dentry);
547 ctl.head.mtime = mtime;
548 ctl.head.time = jiffies;
552 ctl.idx = NCP_DIRCACHE_START;
556 if (ncp_is_server_root(inode)) {
557 ncp_read_volume_list(filp, dirent, filldir, &ctl);
559 ncp_do_readdir(filp, dirent, filldir, &ctl);
561 ctl.head.end = ctl.fpos - 1;
562 ctl.head.eof = ctl.valid;
566 SetPageUptodate(ctl.page);
567 unlock_page(ctl.page);
568 page_cache_release(ctl.page);
571 cache->head = ctl.head;
573 SetPageUptodate(page);
575 page_cache_release(page);
582 ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
583 struct ncp_cache_control *ctrl, struct ncp_entry_info *entry,
586 struct dentry *newdent, *dentry = filp->f_path.dentry;
587 struct inode *dir = dentry->d_inode;
588 struct ncp_cache_control ctl = *ctrl;
593 __u8 __name[NCP_MAXPATHLEN + 1];
595 qname.len = sizeof(__name);
596 if (ncp_vol2io(NCP_SERVER(dir), __name, &qname.len,
597 entry->i.entryName, entry->i.nameLen,
598 !ncp_preserve_entry_case(dir, entry->i.NSCreator)))
599 return 1; /* I'm not sure */
602 qname.hash = full_name_hash(qname.name, qname.len);
604 if (dentry->d_op && dentry->d_op->d_hash)
605 if (dentry->d_op->d_hash(dentry, dentry->d_inode, &qname) != 0)
608 newdent = d_lookup(dentry, &qname);
611 newdent = d_alloc(dentry, &qname);
617 /* If case sensitivity changed for this volume, all entries below this one
618 should be thrown away. This entry itself is not affected, as its case
619 sensitivity is controlled by its own parent. */
621 shrink_dcache_parent(newdent);
624 * NetWare's OS2 namespace is case preserving yet case
625 * insensitive. So we update dentry's name as received from
626 * server. Parent dir's i_mutex is locked because we're in
629 dentry_update_name_case(newdent, &qname);
632 if (!newdent->d_inode) {
636 entry->ino = iunique(dir->i_sb, 2);
637 inode = ncp_iget(dir->i_sb, entry);
639 newdent->d_op = &ncp_dentry_operations;
640 d_instantiate(newdent, inode);
645 struct inode *inode = newdent->d_inode;
647 mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
648 ncp_update_inode2(inode, entry);
649 mutex_unlock(&inode->i_mutex);
652 if (newdent->d_inode) {
653 ino = newdent->d_inode->i_ino;
654 newdent->d_fsdata = (void *) ctl.fpos;
655 ncp_new_dentry(newdent);
658 if (ctl.idx >= NCP_DIRCACHE_SIZE) {
661 SetPageUptodate(ctl.page);
662 unlock_page(ctl.page);
663 page_cache_release(ctl.page);
666 ctl.idx -= NCP_DIRCACHE_SIZE;
668 ctl.page = grab_cache_page(&dir->i_data, ctl.ofs);
670 ctl.cache = kmap(ctl.page);
673 ctl.cache->dentry[ctl.idx] = newdent;
680 if (!ctl.filled && (ctl.fpos == filp->f_pos)) {
682 ino = find_inode_number(dentry, &qname);
684 ino = iunique(dir->i_sb, 2);
685 ctl.filled = filldir(dirent, qname.name, qname.len,
686 filp->f_pos, ino, DT_UNKNOWN);
693 return (ctl.valid || !ctl.filled);
697 ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir,
698 struct ncp_cache_control *ctl)
700 struct dentry *dentry = filp->f_path.dentry;
701 struct inode *inode = dentry->d_inode;
702 struct ncp_server *server = NCP_SERVER(inode);
703 struct ncp_volume_info info;
704 struct ncp_entry_info entry;
707 DPRINTK("ncp_read_volume_list: pos=%ld\n",
708 (unsigned long) filp->f_pos);
710 for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) {
713 if (ncp_get_volume_info_with_number(server, i, &info) != 0)
715 if (!strlen(info.volume_name))
718 DPRINTK("ncp_read_volume_list: found vol: %s\n",
721 if (ncp_lookup_volume(server, info.volume_name,
723 DPRINTK("ncpfs: could not lookup vol %s\n",
727 inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL);
728 entry.volume = entry.i.volNumber;
729 if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, inval_dentry))
735 ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
736 struct ncp_cache_control *ctl)
738 struct dentry *dentry = filp->f_path.dentry;
739 struct inode *dir = dentry->d_inode;
740 struct ncp_server *server = NCP_SERVER(dir);
741 struct nw_search_sequence seq;
742 struct ncp_entry_info entry;
748 DPRINTK("ncp_do_readdir: %s/%s, fpos=%ld\n",
749 dentry->d_parent->d_name.name, dentry->d_name.name,
750 (unsigned long) filp->f_pos);
751 PPRINTK("ncp_do_readdir: init %s, volnum=%d, dirent=%u\n",
752 dentry->d_name.name, NCP_FINFO(dir)->volNumber,
753 NCP_FINFO(dir)->dirEntNum);
755 err = ncp_initialize_search(server, dir, &seq);
757 DPRINTK("ncp_do_readdir: init failed, err=%d\n", err);
760 /* We MUST NOT use server->buffer_size handshaked with server if we are
761 using UDP, as for UDP server uses max. buffer size determined by
762 MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes).
763 So we use 128KB, just to be sure, as there is no way how to know
764 this value in advance. */
766 buf = vmalloc(bufsize);
774 err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls);
777 if (!cnt) /* prevent endless loop */
782 if (rpls < offsetof(struct nw_info_struct, entryName))
783 break; /* short packet */
784 ncp_extract_file_info(rpl, &entry.i);
785 onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen;
787 break; /* short packet */
788 (void)ncp_obtain_nfs_info(server, &entry.i);
791 entry.volume = entry.i.volNumber;
792 if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, 0))
800 int ncp_conn_logged_in(struct super_block *sb)
802 struct ncp_server* server = NCP_SBP(sb);
805 if (ncp_single_volume(server)) {
811 __u8 __name[NCP_MAXPATHLEN + 1];
813 len = sizeof(__name);
814 result = ncp_io2vol(server, __name, &len, server->m.mounted_vol,
815 strlen(server->m.mounted_vol), 1);
819 if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) {
820 PPRINTK("ncp_conn_logged_in: %s not found\n",
821 server->m.mounted_vol);
826 struct inode* ino = dent->d_inode;
828 ncp_update_known_namespace(server, volNumber, NULL);
829 NCP_FINFO(ino)->volNumber = volNumber;
830 NCP_FINFO(ino)->dirEntNum = dirEntNum;
831 NCP_FINFO(ino)->DosDirNum = DosDirNum;
834 DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n");
837 DPRINTK("ncpfs: sb->s_root == NULL!\n");
846 static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
848 struct ncp_server *server = NCP_SERVER(dir);
849 struct inode *inode = NULL;
850 struct ncp_entry_info finfo;
852 __u8 __name[NCP_MAXPATHLEN + 1];
855 if (!ncp_conn_valid(server))
858 PPRINTK("ncp_lookup: server lookup for %s/%s\n",
859 dentry->d_parent->d_name.name, dentry->d_name.name);
861 len = sizeof(__name);
862 if (ncp_is_server_root(dir)) {
863 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
864 dentry->d_name.len, 1);
866 res = ncp_lookup_volume(server, __name, &(finfo.i));
868 ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
870 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
871 dentry->d_name.len, !ncp_preserve_case(dir));
873 res = ncp_obtain_info(server, dir, __name, &(finfo.i));
875 PPRINTK("ncp_lookup: looked for %s/%s, res=%d\n",
876 dentry->d_parent->d_name.name, __name, res);
878 * If we didn't find an entry, make a negative dentry.
884 * Create an inode for the entry.
887 finfo.ino = iunique(dir->i_sb, 2);
888 finfo.volume = finfo.i.volNumber;
890 inode = ncp_iget(dir->i_sb, &finfo);
893 ncp_new_dentry(dentry);
895 dentry->d_op = &ncp_dentry_operations;
896 d_add(dentry, inode);
901 PPRINTK("ncp_lookup: result=%d\n", error);
902 return ERR_PTR(error);
906 * This code is common to create, mkdir, and mknod.
908 static int ncp_instantiate(struct inode *dir, struct dentry *dentry,
909 struct ncp_entry_info *finfo)
914 finfo->ino = iunique(dir->i_sb, 2);
915 inode = ncp_iget(dir->i_sb, finfo);
918 d_instantiate(dentry,inode);
924 PPRINTK("ncp_instantiate: %s/%s failed, closing file\n",
925 dentry->d_parent->d_name.name, dentry->d_name.name);
926 ncp_close_file(NCP_SERVER(dir), finfo->file_handle);
930 int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
931 dev_t rdev, __le32 attributes)
933 struct ncp_server *server = NCP_SERVER(dir);
934 struct ncp_entry_info finfo;
935 int error, result, len;
937 __u8 __name[NCP_MAXPATHLEN + 1];
939 PPRINTK("ncp_create_new: creating %s/%s, mode=%x\n",
940 dentry->d_parent->d_name.name, dentry->d_name.name, mode);
942 ncp_age_dentry(server, dentry);
943 len = sizeof(__name);
944 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
945 dentry->d_name.len, !ncp_preserve_case(dir));
952 (server->m.flags & NCP_MOUNT_EXTRAS) &&
954 attributes |= aSYSTEM | aSHARED;
956 result = ncp_open_create_file_or_subdir(server, dir, __name,
957 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
958 attributes, AR_READ | AR_WRITE, &finfo);
961 result = ncp_open_create_file_or_subdir(server, dir, __name,
962 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
963 attributes, AR_WRITE, &finfo);
966 error = -ENAMETOOLONG;
969 DPRINTK("ncp_create: %s/%s failed\n",
970 dentry->d_parent->d_name.name, dentry->d_name.name);
975 finfo.access = opmode;
976 if (ncp_is_nfs_extras(server, finfo.volume)) {
977 finfo.i.nfs.mode = mode;
978 finfo.i.nfs.rdev = new_encode_dev(rdev);
979 if (ncp_modify_nfs_info(server, finfo.volume,
981 mode, new_encode_dev(rdev)) != 0)
985 error = ncp_instantiate(dir, dentry, &finfo);
990 static int ncp_create(struct inode *dir, struct dentry *dentry, int mode,
991 struct nameidata *nd)
993 return ncp_create_new(dir, dentry, mode, 0, 0);
996 static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode)
998 struct ncp_entry_info finfo;
999 struct ncp_server *server = NCP_SERVER(dir);
1001 __u8 __name[NCP_MAXPATHLEN + 1];
1003 DPRINTK("ncp_mkdir: making %s/%s\n",
1004 dentry->d_parent->d_name.name, dentry->d_name.name);
1006 ncp_age_dentry(server, dentry);
1007 len = sizeof(__name);
1008 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
1009 dentry->d_name.len, !ncp_preserve_case(dir));
1013 error = ncp_open_create_file_or_subdir(server, dir, __name,
1014 OC_MODE_CREATE, aDIR,
1015 cpu_to_le16(0xffff),
1018 if (ncp_is_nfs_extras(server, finfo.volume)) {
1020 finfo.i.nfs.mode = mode;
1021 if (ncp_modify_nfs_info(server,
1027 error = ncp_instantiate(dir, dentry, &finfo);
1028 } else if (error > 0) {
1035 static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
1037 struct ncp_server *server = NCP_SERVER(dir);
1038 int error, result, len;
1039 __u8 __name[NCP_MAXPATHLEN + 1];
1041 DPRINTK("ncp_rmdir: removing %s/%s\n",
1042 dentry->d_parent->d_name.name, dentry->d_name.name);
1045 if (!d_unhashed(dentry))
1048 len = sizeof(__name);
1049 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
1050 dentry->d_name.len, !ncp_preserve_case(dir));
1054 result = ncp_del_file_or_subdir(server, dir, __name);
1059 case 0x85: /* unauthorized to delete file */
1060 case 0x8A: /* unauthorized to delete file */
1064 case 0x90: /* read only */
1067 case 0x9F: /* in use by another client */
1070 case 0xA0: /* directory not empty */
1073 case 0xFF: /* someone deleted file */
1077 error = result < 0 ? result : -EACCES;
1084 static int ncp_unlink(struct inode *dir, struct dentry *dentry)
1086 struct inode *inode = dentry->d_inode;
1087 struct ncp_server *server;
1090 server = NCP_SERVER(dir);
1091 DPRINTK("ncp_unlink: unlinking %s/%s\n",
1092 dentry->d_parent->d_name.name, dentry->d_name.name);
1095 * Check whether to close the file ...
1098 PPRINTK("ncp_unlink: closing file\n");
1099 ncp_make_closed(inode);
1102 error = ncp_del_file_or_subdir2(server, dentry);
1103 #ifdef CONFIG_NCPFS_STRONG
1104 /* 9C is Invalid path.. It should be 8F, 90 - read only, but
1106 if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */
1107 error = ncp_force_unlink(dir, dentry);
1112 DPRINTK("ncp: removed %s/%s\n",
1113 dentry->d_parent->d_name.name, dentry->d_name.name);
1119 case 0x8D: /* some files in use */
1120 case 0x8E: /* all files in use */
1123 case 0x8F: /* some read only */
1124 case 0x90: /* all read only */
1125 case 0x9C: /* !!! returned when in-use or read-only by NW4 */
1132 error = error < 0 ? error : -EACCES;
1138 static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
1139 struct inode *new_dir, struct dentry *new_dentry)
1141 struct ncp_server *server = NCP_SERVER(old_dir);
1143 int old_len, new_len;
1144 __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1];
1146 DPRINTK("ncp_rename: %s/%s to %s/%s\n",
1147 old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
1148 new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
1150 ncp_age_dentry(server, old_dentry);
1151 ncp_age_dentry(server, new_dentry);
1153 old_len = sizeof(__old_name);
1154 error = ncp_io2vol(server, __old_name, &old_len,
1155 old_dentry->d_name.name, old_dentry->d_name.len,
1156 !ncp_preserve_case(old_dir));
1160 new_len = sizeof(__new_name);
1161 error = ncp_io2vol(server, __new_name, &new_len,
1162 new_dentry->d_name.name, new_dentry->d_name.len,
1163 !ncp_preserve_case(new_dir));
1167 error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name,
1168 new_dir, __new_name);
1169 #ifdef CONFIG_NCPFS_STRONG
1170 if ((error == 0x90 || error == 0x8B || error == -EACCES) &&
1171 server->m.flags & NCP_MOUNT_STRONG) { /* RO */
1172 error = ncp_force_rename(old_dir, old_dentry, __old_name,
1173 new_dir, new_dentry, __new_name);
1178 DPRINTK("ncp renamed %s -> %s.\n",
1179 old_dentry->d_name.name,new_dentry->d_name.name);
1182 error = -ENAMETOOLONG;
1188 error = error < 0 ? error : -EACCES;
1195 static int ncp_mknod(struct inode * dir, struct dentry *dentry,
1196 int mode, dev_t rdev)
1198 if (!new_valid_dev(rdev))
1200 if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) {
1201 DPRINTK(KERN_DEBUG "ncp_mknod: mode = 0%o\n", mode);
1202 return ncp_create_new(dir, dentry, mode, rdev, 0);
1204 return -EPERM; /* Strange, but true */
1207 /* The following routines are taken directly from msdos-fs */
1209 /* Linear day numbers of the respective 1sts in non-leap years. */
1211 static int day_n[] =
1212 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
1213 /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
1216 extern struct timezone sys_tz;
1218 static int utc2local(int time)
1220 return time - sys_tz.tz_minuteswest * 60;
1223 static int local2utc(int time)
1225 return time + sys_tz.tz_minuteswest * 60;
1228 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
1230 ncp_date_dos2unix(__le16 t, __le16 d)
1232 unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d);
1233 int month, year, secs;
1235 /* first subtract and mask after that... Otherwise, if
1236 date == 0, bad things happen */
1237 month = ((date >> 5) - 1) & 15;
1239 secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
1240 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) +
1241 year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653);
1242 /* days since 1.1.70 plus 80's leap day */
1243 return local2utc(secs);
1247 /* Convert linear UNIX date to a MS-DOS time/date pair. */
1249 ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
1251 int day, year, nl_day, month;
1253 unix_date = utc2local(unix_date);
1254 *time = cpu_to_le16(
1255 (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
1256 (((unix_date / 3600) % 24) << 11));
1257 day = unix_date / 86400 - 3652;
1259 if ((year + 3) / 4 + 365 * year > day)
1261 day -= (year + 3) / 4 + 365 * year;
1262 if (day == 59 && !(year & 3)) {
1266 nl_day = (year & 3) || day <= 59 ? day : day - 1;
1267 for (month = 1; month < 12; month++)
1268 if (day_n[month] > nl_day)
1271 *date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));