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 *, unsigned int);
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 *, struct qstr *);
77 static int ncp_compare_dentry(const struct dentry *,
78 unsigned int, const char *, const struct qstr *);
79 static int ncp_delete_dentry(const struct dentry *);
80 static void ncp_d_prune(struct dentry *dentry);
82 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,
88 .d_prune = ncp_d_prune,
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
123 * Accessing the parent inode can be racy under RCU pathwalking.
124 * Use ACCESS_ONCE() to make sure we use _one_ particular inode,
125 * the callers will handle races.
128 ncp_hash_dentry(const struct dentry *dentry, struct qstr *this)
130 struct inode *inode = d_inode_rcu(dentry);
135 if (!ncp_case_sensitive(inode)) {
140 t = NCP_IO_TABLE(dentry->d_sb);
141 hash = init_name_hash(dentry);
142 for (i=0; i<this->len ; i++)
143 hash = partial_name_hash(ncp_tolower(t, this->name[i]),
145 this->hash = end_name_hash(hash);
151 * Accessing the parent inode can be racy under RCU pathwalking.
152 * Use ACCESS_ONCE() to make sure we use _one_ particular inode,
153 * the callers will handle races.
156 ncp_compare_dentry(const struct dentry *dentry,
157 unsigned int len, const char *str, const struct qstr *name)
159 struct inode *pinode;
161 if (len != name->len)
164 pinode = d_inode_rcu(dentry->d_parent);
168 if (ncp_case_sensitive(pinode))
169 return strncmp(str, name->name, len);
171 return ncp_strnicmp(NCP_IO_TABLE(pinode->i_sb), str, name->name, len);
175 * This is the callback from dput() when d_count is going to 0.
176 * We use this to unhash dentries with bad inodes.
177 * Closing files can be safely postponed until iput() - it's done there anyway.
180 ncp_delete_dentry(const struct dentry * dentry)
182 struct inode *inode = d_inode(dentry);
185 if (is_bad_inode(inode))
189 /* N.B. Unhash negative dentries? */
195 ncp_single_volume(struct ncp_server *server)
197 return (server->m.mounted_vol[0] != '\0');
200 static inline int ncp_is_server_root(struct inode *inode)
202 return !ncp_single_volume(NCP_SERVER(inode)) &&
203 is_root_inode(inode);
208 * This is the callback when the dcache has a lookup hit.
212 #ifdef CONFIG_NCPFS_STRONG
213 /* try to delete a readonly file (NW R bit set) */
216 ncp_force_unlink(struct inode *dir, struct dentry* dentry)
219 struct nw_modify_dos_info info;
223 memset(&info, 0, sizeof(info));
225 /* remove the Read-Only flag on the NW server */
226 inode = d_inode(dentry);
228 old_nwattr = NCP_FINFO(inode)->nwattr;
229 info.attributes = old_nwattr & ~(aRONLY|aDELETEINHIBIT|aRENAMEINHIBIT);
230 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
234 /* now try again the delete operation */
235 res = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry);
237 if (res) /* delete failed, set R bit again */
239 info.attributes = old_nwattr;
240 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
247 #endif /* CONFIG_NCPFS_STRONG */
249 #ifdef CONFIG_NCPFS_STRONG
251 ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_name,
252 struct inode *new_dir, struct dentry* new_dentry, char *_new_name)
254 struct nw_modify_dos_info info;
256 struct inode *old_inode = d_inode(old_dentry);
257 __le32 old_nwattr = NCP_FINFO(old_inode)->nwattr;
258 __le32 new_nwattr = 0; /* shut compiler warning */
259 int old_nwattr_changed = 0;
260 int new_nwattr_changed = 0;
262 memset(&info, 0, sizeof(info));
264 /* remove the Read-Only flag on the NW server */
266 info.attributes = old_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
267 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
269 old_nwattr_changed = 1;
270 if (new_dentry && d_really_is_positive(new_dentry)) {
271 new_nwattr = NCP_FINFO(d_inode(new_dentry))->nwattr;
272 info.attributes = new_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
273 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
275 new_nwattr_changed = 1;
277 /* now try again the rename operation */
278 /* but only if something really happened */
279 if (new_nwattr_changed || old_nwattr_changed) {
280 res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
286 /* file was successfully renamed, so:
287 do not set attributes on old file - it no longer exists
288 copy attributes from old file to new */
289 new_nwattr_changed = old_nwattr_changed;
290 new_nwattr = old_nwattr;
291 old_nwattr_changed = 0;
294 if (old_nwattr_changed) {
295 info.attributes = old_nwattr;
296 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
299 if (new_nwattr_changed) {
300 info.attributes = new_nwattr;
301 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
306 #endif /* CONFIG_NCPFS_STRONG */
310 ncp_lookup_validate(struct dentry *dentry, unsigned int flags)
312 struct ncp_server *server;
313 struct dentry *parent;
315 struct ncp_entry_info finfo;
316 int res, val = 0, len;
317 __u8 __name[NCP_MAXPATHLEN + 1];
319 if (dentry == dentry->d_sb->s_root)
322 if (flags & LOOKUP_RCU)
325 parent = dget_parent(dentry);
326 dir = d_inode(parent);
328 if (d_really_is_negative(dentry))
331 server = NCP_SERVER(dir);
335 * The default validation is based on dentry age:
336 * We set the max age at mount time. (But each
337 * successful server lookup renews the timestamp.)
339 val = NCP_TEST_AGE(server, dentry);
343 ncp_dbg(2, "%pd2 not valid, age=%ld, server lookup\n",
344 dentry, NCP_GET_AGE(dentry));
346 len = sizeof(__name);
347 if (ncp_is_server_root(dir)) {
348 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
349 dentry->d_name.len, 1);
351 res = ncp_lookup_volume(server, __name, &(finfo.i));
353 ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
356 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
357 dentry->d_name.len, !ncp_preserve_case(dir));
359 res = ncp_obtain_info(server, dir, __name, &(finfo.i));
361 finfo.volume = finfo.i.volNumber;
362 ncp_dbg(2, "looked for %pd/%s, res=%d\n",
363 dentry->d_parent, __name, res);
365 * If we didn't find it, or if it has a different dirEntNum to
366 * what we remember, it's not valid any more.
369 struct inode *inode = d_inode(dentry);
372 if (finfo.i.dirEntNum == NCP_FINFO(inode)->dirEntNum) {
373 ncp_new_dentry(dentry);
376 ncp_dbg(2, "found, but dirEntNum changed\n");
378 ncp_update_inode2(inode, &finfo);
383 ncp_dbg(2, "result=%d\n", val);
388 static time_t ncp_obtain_mtime(struct dentry *dentry)
390 struct inode *inode = d_inode(dentry);
391 struct ncp_server *server = NCP_SERVER(inode);
392 struct nw_info_struct i;
394 if (!ncp_conn_valid(server) || ncp_is_server_root(inode))
397 if (ncp_obtain_info(server, inode, NULL, &i))
400 return ncp_date_dos2unix(i.modifyTime, i.modifyDate);
404 ncp_invalidate_dircache_entries(struct dentry *parent)
406 struct ncp_server *server = NCP_SERVER(d_inode(parent));
407 struct dentry *dentry;
409 spin_lock(&parent->d_lock);
410 list_for_each_entry(dentry, &parent->d_subdirs, d_child) {
411 dentry->d_fsdata = NULL;
412 ncp_age_dentry(server, dentry);
414 spin_unlock(&parent->d_lock);
417 static int ncp_readdir(struct file *file, struct dir_context *ctx)
419 struct dentry *dentry = file->f_path.dentry;
420 struct inode *inode = d_inode(dentry);
421 struct page *page = NULL;
422 struct ncp_server *server = NCP_SERVER(inode);
423 union ncp_dir_cache *cache = NULL;
424 struct ncp_cache_control ctl;
425 int result, mtime_valid = 0;
431 ncp_dbg(2, "reading %pD2, pos=%d\n", file, (int)ctx->pos);
434 /* Do not generate '.' and '..' when server is dead. */
435 if (!ncp_conn_valid(server))
439 if (!dir_emit_dots(file, ctx))
442 page = grab_cache_page(&inode->i_data, 0);
446 ctl.cache = cache = kmap(page);
447 ctl.head = cache->head;
449 if (!PageUptodate(page) || !ctl.head.eof)
453 if (jiffies - ctl.head.time >= NCP_MAX_AGE(server))
456 mtime = ncp_obtain_mtime(dentry);
458 if ((!mtime) || (mtime != ctl.head.mtime))
462 if (ctx->pos > ctl.head.end)
465 ctl.fpos = ctx->pos + (NCP_DIRCACHE_START - 2);
466 ctl.ofs = ctl.fpos / NCP_DIRCACHE_SIZE;
467 ctl.idx = ctl.fpos % NCP_DIRCACHE_SIZE;
471 ctl.page = find_lock_page(&inode->i_data, ctl.ofs);
474 ctl.cache = kmap(ctl.page);
475 if (!PageUptodate(ctl.page))
478 while (ctl.idx < NCP_DIRCACHE_SIZE) {
482 spin_lock(&dentry->d_lock);
483 if (!(NCP_FINFO(inode)->flags & NCPI_DIR_CACHE)) {
484 spin_unlock(&dentry->d_lock);
487 dent = ctl.cache->dentry[ctl.idx];
488 if (unlikely(!lockref_get_not_dead(&dent->d_lockref))) {
489 spin_unlock(&dentry->d_lock);
492 spin_unlock(&dentry->d_lock);
493 if (d_really_is_negative(dent)) {
497 over = !dir_emit(ctx, dent->d_name.name,
499 d_inode(dent)->i_ino, DT_UNKNOWN);
505 if (ctx->pos > ctl.head.end)
510 SetPageUptodate(ctl.page);
511 unlock_page(ctl.page);
521 unlock_page(ctl.page);
527 ncp_invalidate_dircache_entries(dentry);
529 mtime = ncp_obtain_mtime(dentry);
532 ctl.head.mtime = mtime;
533 ctl.head.time = jiffies;
537 ctl.idx = NCP_DIRCACHE_START;
541 spin_lock(&dentry->d_lock);
542 NCP_FINFO(inode)->flags |= NCPI_DIR_CACHE;
543 spin_unlock(&dentry->d_lock);
544 if (ncp_is_server_root(inode)) {
545 ncp_read_volume_list(file, ctx, &ctl);
547 ncp_do_readdir(file, ctx, &ctl);
549 ctl.head.end = ctl.fpos - 1;
550 ctl.head.eof = ctl.valid;
554 SetPageUptodate(ctl.page);
555 unlock_page(ctl.page);
559 cache->head = ctl.head;
561 SetPageUptodate(page);
569 static void ncp_d_prune(struct dentry *dentry)
571 if (!dentry->d_fsdata) /* not referenced from page cache */
573 NCP_FINFO(d_inode(dentry->d_parent))->flags &= ~NCPI_DIR_CACHE;
577 ncp_fill_cache(struct file *file, struct dir_context *ctx,
578 struct ncp_cache_control *ctrl, struct ncp_entry_info *entry,
581 struct dentry *newdent, *dentry = file->f_path.dentry;
582 struct inode *dir = d_inode(dentry);
583 struct ncp_cache_control ctl = *ctrl;
588 __u8 __name[NCP_MAXPATHLEN + 1];
590 qname.len = sizeof(__name);
591 if (ncp_vol2io(NCP_SERVER(dir), __name, &qname.len,
592 entry->i.entryName, entry->i.nameLen,
593 !ncp_preserve_entry_case(dir, entry->i.NSCreator)))
594 return 1; /* I'm not sure */
598 newdent = d_hash_and_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 * NetWare's OS2 namespace is case preserving yet case
616 * insensitive. So we update dentry's name as received from
617 * server. Parent dir's i_mutex is locked because we're in
620 dentry_update_name_case(newdent, &qname);
623 if (d_really_is_negative(newdent)) {
627 entry->ino = iunique(dir->i_sb, 2);
628 inode = ncp_iget(dir->i_sb, entry);
630 d_instantiate(newdent, inode);
634 spin_lock(&dentry->d_lock);
635 NCP_FINFO(dir)->flags &= ~NCPI_DIR_CACHE;
636 spin_unlock(&dentry->d_lock);
639 struct inode *inode = d_inode(newdent);
641 inode_lock_nested(inode, I_MUTEX_CHILD);
642 ncp_update_inode2(inode, entry);
646 if (ctl.idx >= NCP_DIRCACHE_SIZE) {
649 SetPageUptodate(ctl.page);
650 unlock_page(ctl.page);
654 ctl.idx -= NCP_DIRCACHE_SIZE;
656 ctl.page = grab_cache_page(&dir->i_data, ctl.ofs);
658 ctl.cache = kmap(ctl.page);
661 if (d_really_is_positive(newdent)) {
662 newdent->d_fsdata = newdent;
663 ctl.cache->dentry[ctl.idx] = newdent;
664 ino = d_inode(newdent)->i_ino;
665 ncp_new_dentry(newdent);
673 if (!ctl.filled && (ctl.fpos == ctx->pos)) {
675 ino = iunique(dir->i_sb, 2);
676 ctl.filled = !dir_emit(ctx, qname.name, qname.len,
684 return (ctl.valid || !ctl.filled);
688 ncp_read_volume_list(struct file *file, struct dir_context *ctx,
689 struct ncp_cache_control *ctl)
691 struct inode *inode = file_inode(file);
692 struct ncp_server *server = NCP_SERVER(inode);
693 struct ncp_volume_info info;
694 struct ncp_entry_info entry;
697 ncp_dbg(1, "pos=%ld\n", (unsigned long)ctx->pos);
699 for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) {
702 if (ncp_get_volume_info_with_number(server, i, &info) != 0)
704 if (!strlen(info.volume_name))
707 ncp_dbg(1, "found vol: %s\n", info.volume_name);
709 if (ncp_lookup_volume(server, info.volume_name,
711 ncp_dbg(1, "could not lookup vol %s\n",
715 inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL);
716 entry.volume = entry.i.volNumber;
717 if (!ncp_fill_cache(file, ctx, ctl, &entry, inval_dentry))
723 ncp_do_readdir(struct file *file, struct dir_context *ctx,
724 struct ncp_cache_control *ctl)
726 struct inode *dir = file_inode(file);
727 struct ncp_server *server = NCP_SERVER(dir);
728 struct nw_search_sequence seq;
729 struct ncp_entry_info entry;
735 ncp_dbg(1, "%pD2, fpos=%ld\n", file, (unsigned long)ctx->pos);
736 ncp_vdbg("init %pD, volnum=%d, dirent=%u\n",
737 file, NCP_FINFO(dir)->volNumber, NCP_FINFO(dir)->dirEntNum);
739 err = ncp_initialize_search(server, dir, &seq);
741 ncp_dbg(1, "init failed, err=%d\n", err);
744 /* We MUST NOT use server->buffer_size handshaked with server if we are
745 using UDP, as for UDP server uses max. buffer size determined by
746 MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes).
747 So we use 128KB, just to be sure, as there is no way how to know
748 this value in advance. */
750 buf = vmalloc(bufsize);
758 err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls);
761 if (!cnt) /* prevent endless loop */
766 if (rpls < offsetof(struct nw_info_struct, entryName))
767 break; /* short packet */
768 ncp_extract_file_info(rpl, &entry.i);
769 onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen;
771 break; /* short packet */
772 (void)ncp_obtain_nfs_info(server, &entry.i);
775 entry.volume = entry.i.volNumber;
776 if (!ncp_fill_cache(file, ctx, ctl, &entry, 0))
784 int ncp_conn_logged_in(struct super_block *sb)
786 struct ncp_server* server = NCP_SBP(sb);
789 if (ncp_single_volume(server)) {
795 __u8 __name[NCP_MAXPATHLEN + 1];
797 len = sizeof(__name);
798 result = ncp_io2vol(server, __name, &len, server->m.mounted_vol,
799 strlen(server->m.mounted_vol), 1);
803 if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) {
804 ncp_vdbg("%s not found\n", server->m.mounted_vol);
809 struct inode* ino = d_inode(dent);
811 ncp_update_known_namespace(server, volNumber, NULL);
812 NCP_FINFO(ino)->volNumber = volNumber;
813 NCP_FINFO(ino)->dirEntNum = dirEntNum;
814 NCP_FINFO(ino)->DosDirNum = DosDirNum;
817 ncp_dbg(1, "d_inode(sb->s_root) == NULL!\n");
820 ncp_dbg(1, "sb->s_root == NULL!\n");
829 static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
831 struct ncp_server *server = NCP_SERVER(dir);
832 struct inode *inode = NULL;
833 struct ncp_entry_info finfo;
835 __u8 __name[NCP_MAXPATHLEN + 1];
838 if (!ncp_conn_valid(server))
841 ncp_vdbg("server lookup for %pd2\n", dentry);
843 len = sizeof(__name);
844 if (ncp_is_server_root(dir)) {
845 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
846 dentry->d_name.len, 1);
848 res = ncp_lookup_volume(server, __name, &(finfo.i));
850 ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
852 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
853 dentry->d_name.len, !ncp_preserve_case(dir));
855 res = ncp_obtain_info(server, dir, __name, &(finfo.i));
857 ncp_vdbg("looked for %pd2, res=%d\n", dentry, 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 ncp_vdbg("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 ncp_vdbg("%pd2 failed, closing file\n", dentry);
905 ncp_close_file(NCP_SERVER(dir), finfo->file_handle);
909 int ncp_create_new(struct inode *dir, struct dentry *dentry, umode_t mode,
910 dev_t rdev, __le32 attributes)
912 struct ncp_server *server = NCP_SERVER(dir);
913 struct ncp_entry_info finfo;
914 int error, result, len;
916 __u8 __name[NCP_MAXPATHLEN + 1];
918 ncp_vdbg("creating %pd2, mode=%hx\n", dentry, mode);
920 ncp_age_dentry(server, dentry);
921 len = sizeof(__name);
922 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
923 dentry->d_name.len, !ncp_preserve_case(dir));
930 (server->m.flags & NCP_MOUNT_EXTRAS) &&
932 attributes |= aSYSTEM | aSHARED;
934 result = ncp_open_create_file_or_subdir(server, dir, __name,
935 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
936 attributes, AR_READ | AR_WRITE, &finfo);
939 result = ncp_open_create_file_or_subdir(server, dir, __name,
940 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
941 attributes, AR_WRITE, &finfo);
944 error = -ENAMETOOLONG;
947 ncp_dbg(1, "%pd2 failed\n", dentry);
952 finfo.access = opmode;
953 if (ncp_is_nfs_extras(server, finfo.volume)) {
954 finfo.i.nfs.mode = mode;
955 finfo.i.nfs.rdev = new_encode_dev(rdev);
956 if (ncp_modify_nfs_info(server, finfo.volume,
958 mode, new_encode_dev(rdev)) != 0)
962 error = ncp_instantiate(dir, dentry, &finfo);
967 static int ncp_create(struct inode *dir, struct dentry *dentry, umode_t mode,
970 return ncp_create_new(dir, dentry, mode, 0, 0);
973 static int ncp_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
975 struct ncp_entry_info finfo;
976 struct ncp_server *server = NCP_SERVER(dir);
978 __u8 __name[NCP_MAXPATHLEN + 1];
980 ncp_dbg(1, "making %pd2\n", dentry);
982 ncp_age_dentry(server, dentry);
983 len = sizeof(__name);
984 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
985 dentry->d_name.len, !ncp_preserve_case(dir));
989 error = ncp_open_create_file_or_subdir(server, dir, __name,
990 OC_MODE_CREATE, aDIR,
994 if (ncp_is_nfs_extras(server, finfo.volume)) {
996 finfo.i.nfs.mode = mode;
997 if (ncp_modify_nfs_info(server,
1003 error = ncp_instantiate(dir, dentry, &finfo);
1004 } else if (error > 0) {
1011 static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
1013 struct ncp_server *server = NCP_SERVER(dir);
1014 int error, result, len;
1015 __u8 __name[NCP_MAXPATHLEN + 1];
1017 ncp_dbg(1, "removing %pd2\n", dentry);
1019 len = sizeof(__name);
1020 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
1021 dentry->d_name.len, !ncp_preserve_case(dir));
1025 result = ncp_del_file_or_subdir(server, dir, __name);
1030 case 0x85: /* unauthorized to delete file */
1031 case 0x8A: /* unauthorized to delete file */
1035 case 0x90: /* read only */
1038 case 0x9F: /* in use by another client */
1041 case 0xA0: /* directory not empty */
1044 case 0xFF: /* someone deleted file */
1048 error = result < 0 ? result : -EACCES;
1055 static int ncp_unlink(struct inode *dir, struct dentry *dentry)
1057 struct inode *inode = d_inode(dentry);
1058 struct ncp_server *server;
1061 server = NCP_SERVER(dir);
1062 ncp_dbg(1, "unlinking %pd2\n", dentry);
1065 * Check whether to close the file ...
1068 ncp_vdbg("closing file\n");
1069 ncp_make_closed(inode);
1072 error = ncp_del_file_or_subdir2(server, dentry);
1073 #ifdef CONFIG_NCPFS_STRONG
1074 /* 9C is Invalid path.. It should be 8F, 90 - read only, but
1076 if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */
1077 error = ncp_force_unlink(dir, dentry);
1082 ncp_dbg(1, "removed %pd2\n", dentry);
1088 case 0x8D: /* some files in use */
1089 case 0x8E: /* all files in use */
1092 case 0x8F: /* some read only */
1093 case 0x90: /* all read only */
1094 case 0x9C: /* !!! returned when in-use or read-only by NW4 */
1101 error = error < 0 ? error : -EACCES;
1107 static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
1108 struct inode *new_dir, struct dentry *new_dentry,
1111 struct ncp_server *server = NCP_SERVER(old_dir);
1113 int old_len, new_len;
1114 __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1];
1119 ncp_dbg(1, "%pd2 to %pd2\n", old_dentry, new_dentry);
1121 ncp_age_dentry(server, old_dentry);
1122 ncp_age_dentry(server, new_dentry);
1124 old_len = sizeof(__old_name);
1125 error = ncp_io2vol(server, __old_name, &old_len,
1126 old_dentry->d_name.name, old_dentry->d_name.len,
1127 !ncp_preserve_case(old_dir));
1131 new_len = sizeof(__new_name);
1132 error = ncp_io2vol(server, __new_name, &new_len,
1133 new_dentry->d_name.name, new_dentry->d_name.len,
1134 !ncp_preserve_case(new_dir));
1138 error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name,
1139 new_dir, __new_name);
1140 #ifdef CONFIG_NCPFS_STRONG
1141 if ((error == 0x90 || error == 0x8B || error == -EACCES) &&
1142 server->m.flags & NCP_MOUNT_STRONG) { /* RO */
1143 error = ncp_force_rename(old_dir, old_dentry, __old_name,
1144 new_dir, new_dentry, __new_name);
1149 ncp_dbg(1, "renamed %pd -> %pd\n",
1150 old_dentry, new_dentry);
1151 ncp_d_prune(old_dentry);
1152 ncp_d_prune(new_dentry);
1155 error = -ENAMETOOLONG;
1161 error = error < 0 ? error : -EACCES;
1168 static int ncp_mknod(struct inode * dir, struct dentry *dentry,
1169 umode_t mode, dev_t rdev)
1171 if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) {
1172 ncp_dbg(1, "mode = 0%ho\n", mode);
1173 return ncp_create_new(dir, dentry, mode, rdev, 0);
1175 return -EPERM; /* Strange, but true */
1178 /* The following routines are taken directly from msdos-fs */
1180 /* Linear day numbers of the respective 1sts in non-leap years. */
1182 static int day_n[] =
1183 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
1184 /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
1186 static int utc2local(int time)
1188 return time - sys_tz.tz_minuteswest * 60;
1191 static int local2utc(int time)
1193 return time + sys_tz.tz_minuteswest * 60;
1196 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
1198 ncp_date_dos2unix(__le16 t, __le16 d)
1200 unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d);
1201 int month, year, secs;
1203 /* first subtract and mask after that... Otherwise, if
1204 date == 0, bad things happen */
1205 month = ((date >> 5) - 1) & 15;
1207 secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
1208 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) +
1209 year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653);
1210 /* days since 1.1.70 plus 80's leap day */
1211 return local2utc(secs);
1215 /* Convert linear UNIX date to a MS-DOS time/date pair. */
1217 ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
1219 int day, year, nl_day, month;
1221 unix_date = utc2local(unix_date);
1222 *time = cpu_to_le16(
1223 (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
1224 (((unix_date / 3600) % 24) << 11));
1225 day = unix_date / 86400 - 3652;
1227 if ((year + 3) / 4 + 365 * year > day)
1229 day -= (year + 3) / 4 + 365 * year;
1230 if (day == 59 && !(year & 3)) {
1234 nl_day = (year & 3) || day <= 59 ? day : day - 1;
1235 for (month = 1; month < 12; month++)
1236 if (day_n[month] > nl_day)
1239 *date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));