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 <linux/namei.h>
21 #include <asm/uaccess.h>
22 #include <asm/byteorder.h>
26 static void ncp_read_volume_list(struct file *, struct dir_context *,
27 struct ncp_cache_control *);
28 static void ncp_do_readdir(struct file *, struct dir_context *,
29 struct ncp_cache_control *);
31 static int ncp_readdir(struct file *, struct dir_context *);
33 static int ncp_create(struct inode *, struct dentry *, umode_t, bool);
34 static struct dentry *ncp_lookup(struct inode *, struct dentry *, unsigned int);
35 static int ncp_unlink(struct inode *, struct dentry *);
36 static int ncp_mkdir(struct inode *, struct dentry *, umode_t);
37 static int ncp_rmdir(struct inode *, struct dentry *);
38 static int ncp_rename(struct inode *, struct dentry *,
39 struct inode *, struct dentry *);
40 static int ncp_mknod(struct inode * dir, struct dentry *dentry,
41 umode_t mode, dev_t rdev);
42 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
43 extern int ncp_symlink(struct inode *, struct dentry *, const char *);
45 #define ncp_symlink NULL
48 const struct file_operations ncp_dir_operations =
50 .llseek = generic_file_llseek,
51 .read = generic_read_dir,
52 .iterate = ncp_readdir,
53 .unlocked_ioctl = ncp_ioctl,
55 .compat_ioctl = ncp_compat_ioctl,
59 const struct inode_operations ncp_dir_inode_operations =
64 .symlink = ncp_symlink,
69 .setattr = ncp_notify_change,
73 * Dentry operations routines
75 static int ncp_lookup_validate(struct dentry *, unsigned int);
76 static int ncp_hash_dentry(const struct dentry *, const struct inode *,
78 static int ncp_compare_dentry(const struct dentry *, const struct inode *,
79 const struct dentry *, const struct inode *,
80 unsigned int, const char *, const struct qstr *);
81 static int ncp_delete_dentry(const struct dentry *);
83 const struct dentry_operations ncp_dentry_operations =
85 .d_revalidate = ncp_lookup_validate,
86 .d_hash = ncp_hash_dentry,
87 .d_compare = ncp_compare_dentry,
88 .d_delete = ncp_delete_dentry,
91 #define ncp_namespace(i) (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber])
93 static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator)
95 #ifdef CONFIG_NCPFS_SMALLDOS
96 int ns = ncp_namespace(i);
99 #ifdef CONFIG_NCPFS_OS2_NS
100 || ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS))
101 #endif /* CONFIG_NCPFS_OS2_NS */
104 #endif /* CONFIG_NCPFS_SMALLDOS */
108 #define ncp_preserve_case(i) (ncp_namespace(i) != NW_NS_DOS)
110 static inline int ncp_case_sensitive(const struct inode *i)
112 #ifdef CONFIG_NCPFS_NFS_NS
113 return ncp_namespace(i) == NW_NS_NFS;
116 #endif /* CONFIG_NCPFS_NFS_NS */
120 * Note: leave the hash unchanged if the directory
124 ncp_hash_dentry(const struct dentry *dentry, const struct inode *inode,
127 if (!ncp_case_sensitive(inode)) {
128 struct super_block *sb = dentry->d_sb;
133 t = NCP_IO_TABLE(sb);
134 hash = init_name_hash();
135 for (i=0; i<this->len ; i++)
136 hash = partial_name_hash(ncp_tolower(t, this->name[i]),
138 this->hash = end_name_hash(hash);
144 ncp_compare_dentry(const struct dentry *parent, const struct inode *pinode,
145 const struct dentry *dentry, const struct inode *inode,
146 unsigned int len, const char *str, const struct qstr *name)
148 if (len != name->len)
151 if (ncp_case_sensitive(pinode))
152 return strncmp(str, name->name, len);
154 return ncp_strnicmp(NCP_IO_TABLE(pinode->i_sb), str, name->name, len);
158 * This is the callback from dput() when d_count is going to 0.
159 * We use this to unhash dentries with bad inodes.
160 * Closing files can be safely postponed until iput() - it's done there anyway.
163 ncp_delete_dentry(const struct dentry * dentry)
165 struct inode *inode = dentry->d_inode;
168 if (is_bad_inode(inode))
172 /* N.B. Unhash negative dentries? */
178 ncp_single_volume(struct ncp_server *server)
180 return (server->m.mounted_vol[0] != '\0');
183 static inline int ncp_is_server_root(struct inode *inode)
185 return (!ncp_single_volume(NCP_SERVER(inode)) &&
186 inode == inode->i_sb->s_root->d_inode);
191 * This is the callback when the dcache has a lookup hit.
195 #ifdef CONFIG_NCPFS_STRONG
196 /* try to delete a readonly file (NW R bit set) */
199 ncp_force_unlink(struct inode *dir, struct dentry* dentry)
202 struct nw_modify_dos_info info;
206 memset(&info, 0, sizeof(info));
208 /* remove the Read-Only flag on the NW server */
209 inode = dentry->d_inode;
211 old_nwattr = NCP_FINFO(inode)->nwattr;
212 info.attributes = old_nwattr & ~(aRONLY|aDELETEINHIBIT|aRENAMEINHIBIT);
213 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
217 /* now try again the delete operation */
218 res = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry);
220 if (res) /* delete failed, set R bit again */
222 info.attributes = old_nwattr;
223 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
230 #endif /* CONFIG_NCPFS_STRONG */
232 #ifdef CONFIG_NCPFS_STRONG
234 ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_name,
235 struct inode *new_dir, struct dentry* new_dentry, char *_new_name)
237 struct nw_modify_dos_info info;
239 struct inode *old_inode = old_dentry->d_inode;
240 __le32 old_nwattr = NCP_FINFO(old_inode)->nwattr;
241 __le32 new_nwattr = 0; /* shut compiler warning */
242 int old_nwattr_changed = 0;
243 int new_nwattr_changed = 0;
245 memset(&info, 0, sizeof(info));
247 /* remove the Read-Only flag on the NW server */
249 info.attributes = old_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
250 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
252 old_nwattr_changed = 1;
253 if (new_dentry && new_dentry->d_inode) {
254 new_nwattr = NCP_FINFO(new_dentry->d_inode)->nwattr;
255 info.attributes = new_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
256 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
258 new_nwattr_changed = 1;
260 /* now try again the rename operation */
261 /* but only if something really happened */
262 if (new_nwattr_changed || old_nwattr_changed) {
263 res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
269 /* file was successfully renamed, so:
270 do not set attributes on old file - it no longer exists
271 copy attributes from old file to new */
272 new_nwattr_changed = old_nwattr_changed;
273 new_nwattr = old_nwattr;
274 old_nwattr_changed = 0;
277 if (old_nwattr_changed) {
278 info.attributes = old_nwattr;
279 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
282 if (new_nwattr_changed) {
283 info.attributes = new_nwattr;
284 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
289 #endif /* CONFIG_NCPFS_STRONG */
293 ncp_lookup_validate(struct dentry *dentry, unsigned int flags)
295 struct ncp_server *server;
296 struct dentry *parent;
298 struct ncp_entry_info finfo;
299 int res, val = 0, len;
300 __u8 __name[NCP_MAXPATHLEN + 1];
302 if (dentry == dentry->d_sb->s_root)
305 if (flags & LOOKUP_RCU)
308 parent = dget_parent(dentry);
309 dir = parent->d_inode;
311 if (!dentry->d_inode)
314 server = NCP_SERVER(dir);
318 * The default validation is based on dentry age:
319 * We set the max age at mount time. (But each
320 * successful server lookup renews the timestamp.)
322 val = NCP_TEST_AGE(server, dentry);
326 DDPRINTK("ncp_lookup_validate: %s/%s not valid, age=%ld, server lookup\n",
327 dentry->d_parent->d_name.name, dentry->d_name.name,
328 NCP_GET_AGE(dentry));
330 len = sizeof(__name);
331 if (ncp_is_server_root(dir)) {
332 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
333 dentry->d_name.len, 1);
335 res = ncp_lookup_volume(server, __name, &(finfo.i));
337 ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
340 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
341 dentry->d_name.len, !ncp_preserve_case(dir));
343 res = ncp_obtain_info(server, dir, __name, &(finfo.i));
345 finfo.volume = finfo.i.volNumber;
346 DDPRINTK("ncp_lookup_validate: looked for %s/%s, res=%d\n",
347 dentry->d_parent->d_name.name, __name, res);
349 * If we didn't find it, or if it has a different dirEntNum to
350 * what we remember, it's not valid any more.
353 struct inode *inode = dentry->d_inode;
355 mutex_lock(&inode->i_mutex);
356 if (finfo.i.dirEntNum == NCP_FINFO(inode)->dirEntNum) {
357 ncp_new_dentry(dentry);
360 DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");
362 ncp_update_inode2(inode, &finfo);
363 mutex_unlock(&inode->i_mutex);
367 DDPRINTK("ncp_lookup_validate: result=%d\n", val);
372 static struct dentry *
373 ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
375 struct dentry *dent = dentry;
376 struct list_head *next;
378 if (d_validate(dent, parent)) {
379 if (dent->d_name.len <= NCP_MAXPATHLEN &&
380 (unsigned long)dent->d_fsdata == fpos) {
381 if (!dent->d_inode) {
390 /* If a pointer is invalid, we search the dentry. */
391 spin_lock(&parent->d_lock);
392 next = parent->d_subdirs.next;
393 while (next != &parent->d_subdirs) {
394 dent = list_entry(next, struct dentry, d_u.d_child);
395 if ((unsigned long)dent->d_fsdata == fpos) {
400 spin_unlock(&parent->d_lock);
405 spin_unlock(&parent->d_lock);
412 static time_t ncp_obtain_mtime(struct dentry *dentry)
414 struct inode *inode = dentry->d_inode;
415 struct ncp_server *server = NCP_SERVER(inode);
416 struct nw_info_struct i;
418 if (!ncp_conn_valid(server) || ncp_is_server_root(inode))
421 if (ncp_obtain_info(server, inode, NULL, &i))
424 return ncp_date_dos2unix(i.modifyTime, i.modifyDate);
427 static int ncp_readdir(struct file *file, struct dir_context *ctx)
429 struct dentry *dentry = file->f_path.dentry;
430 struct inode *inode = dentry->d_inode;
431 struct page *page = NULL;
432 struct ncp_server *server = NCP_SERVER(inode);
433 union ncp_dir_cache *cache = NULL;
434 struct ncp_cache_control ctl;
435 int result, mtime_valid = 0;
441 DDPRINTK("ncp_readdir: reading %s/%s, pos=%d\n",
442 dentry->d_parent->d_name.name, dentry->d_name.name,
446 /* Do not generate '.' and '..' when server is dead. */
447 if (!ncp_conn_valid(server))
451 if (!dir_emit_dots(file, ctx))
454 page = grab_cache_page(&inode->i_data, 0);
458 ctl.cache = cache = kmap(page);
459 ctl.head = cache->head;
461 if (!PageUptodate(page) || !ctl.head.eof)
465 if (jiffies - ctl.head.time >= NCP_MAX_AGE(server))
468 mtime = ncp_obtain_mtime(dentry);
470 if ((!mtime) || (mtime != ctl.head.mtime))
474 if (ctx->pos > ctl.head.end)
477 ctl.fpos = ctx->pos + (NCP_DIRCACHE_START - 2);
478 ctl.ofs = ctl.fpos / NCP_DIRCACHE_SIZE;
479 ctl.idx = ctl.fpos % NCP_DIRCACHE_SIZE;
483 ctl.page = find_lock_page(&inode->i_data, ctl.ofs);
486 ctl.cache = kmap(ctl.page);
487 if (!PageUptodate(ctl.page))
490 while (ctl.idx < NCP_DIRCACHE_SIZE) {
494 dent = ncp_dget_fpos(ctl.cache->dentry[ctl.idx],
498 over = !dir_emit(ctx, dent->d_name.name,
500 dent->d_inode->i_ino, DT_UNKNOWN);
506 if (ctx->pos > ctl.head.end)
511 SetPageUptodate(ctl.page);
512 unlock_page(ctl.page);
513 page_cache_release(ctl.page);
522 unlock_page(ctl.page);
523 page_cache_release(ctl.page);
528 ncp_invalidate_dircache_entries(dentry);
530 mtime = ncp_obtain_mtime(dentry);
533 ctl.head.mtime = mtime;
534 ctl.head.time = jiffies;
538 ctl.idx = NCP_DIRCACHE_START;
542 if (ncp_is_server_root(inode)) {
543 ncp_read_volume_list(file, ctx, &ctl);
545 ncp_do_readdir(file, ctx, &ctl);
547 ctl.head.end = ctl.fpos - 1;
548 ctl.head.eof = ctl.valid;
552 SetPageUptodate(ctl.page);
553 unlock_page(ctl.page);
554 page_cache_release(ctl.page);
557 cache->head = ctl.head;
559 SetPageUptodate(page);
561 page_cache_release(page);
568 ncp_fill_cache(struct file *file, struct dir_context *ctx,
569 struct ncp_cache_control *ctrl, struct ncp_entry_info *entry,
572 struct dentry *newdent, *dentry = file->f_path.dentry;
573 struct inode *dir = dentry->d_inode;
574 struct ncp_cache_control ctl = *ctrl;
579 __u8 __name[NCP_MAXPATHLEN + 1];
581 qname.len = sizeof(__name);
582 if (ncp_vol2io(NCP_SERVER(dir), __name, &qname.len,
583 entry->i.entryName, entry->i.nameLen,
584 !ncp_preserve_entry_case(dir, entry->i.NSCreator)))
585 return 1; /* I'm not sure */
589 newdent = d_hash_and_lookup(dentry, &qname);
590 if (unlikely(IS_ERR(newdent)))
593 newdent = d_alloc(dentry, &qname);
599 /* If case sensitivity changed for this volume, all entries below this one
600 should be thrown away. This entry itself is not affected, as its case
601 sensitivity is controlled by its own parent. */
603 shrink_dcache_parent(newdent);
606 * NetWare's OS2 namespace is case preserving yet case
607 * insensitive. So we update dentry's name as received from
608 * server. Parent dir's i_mutex is locked because we're in
611 dentry_update_name_case(newdent, &qname);
614 if (!newdent->d_inode) {
618 entry->ino = iunique(dir->i_sb, 2);
619 inode = ncp_iget(dir->i_sb, entry);
621 d_instantiate(newdent, inode);
626 struct inode *inode = newdent->d_inode;
628 mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
629 ncp_update_inode2(inode, entry);
630 mutex_unlock(&inode->i_mutex);
633 if (newdent->d_inode) {
634 ino = newdent->d_inode->i_ino;
635 newdent->d_fsdata = (void *) ctl.fpos;
636 ncp_new_dentry(newdent);
639 if (ctl.idx >= NCP_DIRCACHE_SIZE) {
642 SetPageUptodate(ctl.page);
643 unlock_page(ctl.page);
644 page_cache_release(ctl.page);
647 ctl.idx -= NCP_DIRCACHE_SIZE;
649 ctl.page = grab_cache_page(&dir->i_data, ctl.ofs);
651 ctl.cache = kmap(ctl.page);
654 ctl.cache->dentry[ctl.idx] = newdent;
661 if (!ctl.filled && (ctl.fpos == ctx->pos)) {
663 ino = find_inode_number(dentry, &qname);
665 ino = iunique(dir->i_sb, 2);
666 ctl.filled = !dir_emit(ctx, qname.name, qname.len,
674 return (ctl.valid || !ctl.filled);
678 ncp_read_volume_list(struct file *file, struct dir_context *ctx,
679 struct ncp_cache_control *ctl)
681 struct dentry *dentry = file->f_path.dentry;
682 struct inode *inode = dentry->d_inode;
683 struct ncp_server *server = NCP_SERVER(inode);
684 struct ncp_volume_info info;
685 struct ncp_entry_info entry;
688 DPRINTK("ncp_read_volume_list: pos=%ld\n",
689 (unsigned long) ctx->pos);
691 for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) {
694 if (ncp_get_volume_info_with_number(server, i, &info) != 0)
696 if (!strlen(info.volume_name))
699 DPRINTK("ncp_read_volume_list: found vol: %s\n",
702 if (ncp_lookup_volume(server, info.volume_name,
704 DPRINTK("ncpfs: could not lookup vol %s\n",
708 inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL);
709 entry.volume = entry.i.volNumber;
710 if (!ncp_fill_cache(file, ctx, ctl, &entry, inval_dentry))
716 ncp_do_readdir(struct file *file, struct dir_context *ctx,
717 struct ncp_cache_control *ctl)
719 struct dentry *dentry = file->f_path.dentry;
720 struct inode *dir = dentry->d_inode;
721 struct ncp_server *server = NCP_SERVER(dir);
722 struct nw_search_sequence seq;
723 struct ncp_entry_info entry;
729 DPRINTK("ncp_do_readdir: %s/%s, fpos=%ld\n",
730 dentry->d_parent->d_name.name, dentry->d_name.name,
731 (unsigned long) ctx->pos);
732 PPRINTK("ncp_do_readdir: init %s, volnum=%d, dirent=%u\n",
733 dentry->d_name.name, NCP_FINFO(dir)->volNumber,
734 NCP_FINFO(dir)->dirEntNum);
736 err = ncp_initialize_search(server, dir, &seq);
738 DPRINTK("ncp_do_readdir: init failed, err=%d\n", err);
741 /* We MUST NOT use server->buffer_size handshaked with server if we are
742 using UDP, as for UDP server uses max. buffer size determined by
743 MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes).
744 So we use 128KB, just to be sure, as there is no way how to know
745 this value in advance. */
747 buf = vmalloc(bufsize);
755 err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls);
758 if (!cnt) /* prevent endless loop */
763 if (rpls < offsetof(struct nw_info_struct, entryName))
764 break; /* short packet */
765 ncp_extract_file_info(rpl, &entry.i);
766 onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen;
768 break; /* short packet */
769 (void)ncp_obtain_nfs_info(server, &entry.i);
772 entry.volume = entry.i.volNumber;
773 if (!ncp_fill_cache(file, ctx, ctl, &entry, 0))
781 int ncp_conn_logged_in(struct super_block *sb)
783 struct ncp_server* server = NCP_SBP(sb);
786 if (ncp_single_volume(server)) {
792 __u8 __name[NCP_MAXPATHLEN + 1];
794 len = sizeof(__name);
795 result = ncp_io2vol(server, __name, &len, server->m.mounted_vol,
796 strlen(server->m.mounted_vol), 1);
800 if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) {
801 PPRINTK("ncp_conn_logged_in: %s not found\n",
802 server->m.mounted_vol);
807 struct inode* ino = dent->d_inode;
809 ncp_update_known_namespace(server, volNumber, NULL);
810 NCP_FINFO(ino)->volNumber = volNumber;
811 NCP_FINFO(ino)->dirEntNum = dirEntNum;
812 NCP_FINFO(ino)->DosDirNum = DosDirNum;
815 DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n");
818 DPRINTK("ncpfs: sb->s_root == NULL!\n");
827 static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
829 struct ncp_server *server = NCP_SERVER(dir);
830 struct inode *inode = NULL;
831 struct ncp_entry_info finfo;
833 __u8 __name[NCP_MAXPATHLEN + 1];
836 if (!ncp_conn_valid(server))
839 PPRINTK("ncp_lookup: server lookup for %s/%s\n",
840 dentry->d_parent->d_name.name, dentry->d_name.name);
842 len = sizeof(__name);
843 if (ncp_is_server_root(dir)) {
844 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
845 dentry->d_name.len, 1);
847 res = ncp_lookup_volume(server, __name, &(finfo.i));
849 ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
851 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
852 dentry->d_name.len, !ncp_preserve_case(dir));
854 res = ncp_obtain_info(server, dir, __name, &(finfo.i));
856 PPRINTK("ncp_lookup: looked for %s/%s, res=%d\n",
857 dentry->d_parent->d_name.name, __name, res);
859 * If we didn't find an entry, make a negative dentry.
865 * Create an inode for the entry.
868 finfo.ino = iunique(dir->i_sb, 2);
869 finfo.volume = finfo.i.volNumber;
871 inode = ncp_iget(dir->i_sb, &finfo);
874 ncp_new_dentry(dentry);
876 d_add(dentry, inode);
881 PPRINTK("ncp_lookup: result=%d\n", error);
882 return ERR_PTR(error);
886 * This code is common to create, mkdir, and mknod.
888 static int ncp_instantiate(struct inode *dir, struct dentry *dentry,
889 struct ncp_entry_info *finfo)
894 finfo->ino = iunique(dir->i_sb, 2);
895 inode = ncp_iget(dir->i_sb, finfo);
898 d_instantiate(dentry,inode);
904 PPRINTK("ncp_instantiate: %s/%s failed, closing file\n",
905 dentry->d_parent->d_name.name, dentry->d_name.name);
906 ncp_close_file(NCP_SERVER(dir), finfo->file_handle);
910 int ncp_create_new(struct inode *dir, struct dentry *dentry, umode_t mode,
911 dev_t rdev, __le32 attributes)
913 struct ncp_server *server = NCP_SERVER(dir);
914 struct ncp_entry_info finfo;
915 int error, result, len;
917 __u8 __name[NCP_MAXPATHLEN + 1];
919 PPRINTK("ncp_create_new: creating %s/%s, mode=%hx\n",
920 dentry->d_parent->d_name.name, dentry->d_name.name, mode);
922 ncp_age_dentry(server, dentry);
923 len = sizeof(__name);
924 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
925 dentry->d_name.len, !ncp_preserve_case(dir));
932 (server->m.flags & NCP_MOUNT_EXTRAS) &&
934 attributes |= aSYSTEM | aSHARED;
936 result = ncp_open_create_file_or_subdir(server, dir, __name,
937 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
938 attributes, AR_READ | AR_WRITE, &finfo);
941 result = ncp_open_create_file_or_subdir(server, dir, __name,
942 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
943 attributes, AR_WRITE, &finfo);
946 error = -ENAMETOOLONG;
949 DPRINTK("ncp_create: %s/%s failed\n",
950 dentry->d_parent->d_name.name, dentry->d_name.name);
955 finfo.access = opmode;
956 if (ncp_is_nfs_extras(server, finfo.volume)) {
957 finfo.i.nfs.mode = mode;
958 finfo.i.nfs.rdev = new_encode_dev(rdev);
959 if (ncp_modify_nfs_info(server, finfo.volume,
961 mode, new_encode_dev(rdev)) != 0)
965 error = ncp_instantiate(dir, dentry, &finfo);
970 static int ncp_create(struct inode *dir, struct dentry *dentry, umode_t mode,
973 return ncp_create_new(dir, dentry, mode, 0, 0);
976 static int ncp_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
978 struct ncp_entry_info finfo;
979 struct ncp_server *server = NCP_SERVER(dir);
981 __u8 __name[NCP_MAXPATHLEN + 1];
983 DPRINTK("ncp_mkdir: making %s/%s\n",
984 dentry->d_parent->d_name.name, dentry->d_name.name);
986 ncp_age_dentry(server, dentry);
987 len = sizeof(__name);
988 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
989 dentry->d_name.len, !ncp_preserve_case(dir));
993 error = ncp_open_create_file_or_subdir(server, dir, __name,
994 OC_MODE_CREATE, aDIR,
998 if (ncp_is_nfs_extras(server, finfo.volume)) {
1000 finfo.i.nfs.mode = mode;
1001 if (ncp_modify_nfs_info(server,
1007 error = ncp_instantiate(dir, dentry, &finfo);
1008 } else if (error > 0) {
1015 static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
1017 struct ncp_server *server = NCP_SERVER(dir);
1018 int error, result, len;
1019 __u8 __name[NCP_MAXPATHLEN + 1];
1021 DPRINTK("ncp_rmdir: removing %s/%s\n",
1022 dentry->d_parent->d_name.name, dentry->d_name.name);
1024 len = sizeof(__name);
1025 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
1026 dentry->d_name.len, !ncp_preserve_case(dir));
1030 result = ncp_del_file_or_subdir(server, dir, __name);
1035 case 0x85: /* unauthorized to delete file */
1036 case 0x8A: /* unauthorized to delete file */
1040 case 0x90: /* read only */
1043 case 0x9F: /* in use by another client */
1046 case 0xA0: /* directory not empty */
1049 case 0xFF: /* someone deleted file */
1053 error = result < 0 ? result : -EACCES;
1060 static int ncp_unlink(struct inode *dir, struct dentry *dentry)
1062 struct inode *inode = dentry->d_inode;
1063 struct ncp_server *server;
1066 server = NCP_SERVER(dir);
1067 DPRINTK("ncp_unlink: unlinking %s/%s\n",
1068 dentry->d_parent->d_name.name, dentry->d_name.name);
1071 * Check whether to close the file ...
1074 PPRINTK("ncp_unlink: closing file\n");
1075 ncp_make_closed(inode);
1078 error = ncp_del_file_or_subdir2(server, dentry);
1079 #ifdef CONFIG_NCPFS_STRONG
1080 /* 9C is Invalid path.. It should be 8F, 90 - read only, but
1082 if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */
1083 error = ncp_force_unlink(dir, dentry);
1088 DPRINTK("ncp: removed %s/%s\n",
1089 dentry->d_parent->d_name.name, dentry->d_name.name);
1095 case 0x8D: /* some files in use */
1096 case 0x8E: /* all files in use */
1099 case 0x8F: /* some read only */
1100 case 0x90: /* all read only */
1101 case 0x9C: /* !!! returned when in-use or read-only by NW4 */
1108 error = error < 0 ? error : -EACCES;
1114 static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
1115 struct inode *new_dir, struct dentry *new_dentry)
1117 struct ncp_server *server = NCP_SERVER(old_dir);
1119 int old_len, new_len;
1120 __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1];
1122 DPRINTK("ncp_rename: %s/%s to %s/%s\n",
1123 old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
1124 new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
1126 if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) {
1128 * fail with EBUSY if there are still references to this
1131 dentry_unhash(new_dentry);
1133 if (!d_unhashed(new_dentry))
1137 ncp_age_dentry(server, old_dentry);
1138 ncp_age_dentry(server, new_dentry);
1140 old_len = sizeof(__old_name);
1141 error = ncp_io2vol(server, __old_name, &old_len,
1142 old_dentry->d_name.name, old_dentry->d_name.len,
1143 !ncp_preserve_case(old_dir));
1147 new_len = sizeof(__new_name);
1148 error = ncp_io2vol(server, __new_name, &new_len,
1149 new_dentry->d_name.name, new_dentry->d_name.len,
1150 !ncp_preserve_case(new_dir));
1154 error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name,
1155 new_dir, __new_name);
1156 #ifdef CONFIG_NCPFS_STRONG
1157 if ((error == 0x90 || error == 0x8B || error == -EACCES) &&
1158 server->m.flags & NCP_MOUNT_STRONG) { /* RO */
1159 error = ncp_force_rename(old_dir, old_dentry, __old_name,
1160 new_dir, new_dentry, __new_name);
1165 DPRINTK("ncp renamed %s -> %s.\n",
1166 old_dentry->d_name.name,new_dentry->d_name.name);
1169 error = -ENAMETOOLONG;
1175 error = error < 0 ? error : -EACCES;
1182 static int ncp_mknod(struct inode * dir, struct dentry *dentry,
1183 umode_t mode, dev_t rdev)
1185 if (!new_valid_dev(rdev))
1187 if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) {
1188 DPRINTK(KERN_DEBUG "ncp_mknod: mode = 0%ho\n", mode);
1189 return ncp_create_new(dir, dentry, mode, rdev, 0);
1191 return -EPERM; /* Strange, but true */
1194 /* The following routines are taken directly from msdos-fs */
1196 /* Linear day numbers of the respective 1sts in non-leap years. */
1198 static int day_n[] =
1199 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
1200 /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
1203 extern struct timezone sys_tz;
1205 static int utc2local(int time)
1207 return time - sys_tz.tz_minuteswest * 60;
1210 static int local2utc(int time)
1212 return time + sys_tz.tz_minuteswest * 60;
1215 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
1217 ncp_date_dos2unix(__le16 t, __le16 d)
1219 unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d);
1220 int month, year, secs;
1222 /* first subtract and mask after that... Otherwise, if
1223 date == 0, bad things happen */
1224 month = ((date >> 5) - 1) & 15;
1226 secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
1227 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) +
1228 year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653);
1229 /* days since 1.1.70 plus 80's leap day */
1230 return local2utc(secs);
1234 /* Convert linear UNIX date to a MS-DOS time/date pair. */
1236 ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
1238 int day, year, nl_day, month;
1240 unix_date = utc2local(unix_date);
1241 *time = cpu_to_le16(
1242 (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
1243 (((unix_date / 3600) % 24) << 11));
1244 day = unix_date / 86400 - 3652;
1246 if ((year + 3) / 4 + 365 * year > day)
1248 day -= (year + 3) / 4 + 365 * year;
1249 if (day == 59 && !(year & 3)) {
1253 nl_day = (year & 3) || day <= 59 ? day : day - 1;
1254 for (month = 1; month < 12; month++)
1255 if (day_n[month] > nl_day)
1258 *date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));