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 *, struct qstr *);
77 static int ncp_compare_dentry(const struct 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)) {
136 struct super_block *sb = dentry->d_sb;
141 t = NCP_IO_TABLE(sb);
142 hash = init_name_hash();
143 for (i=0; i<this->len ; i++)
144 hash = partial_name_hash(ncp_tolower(t, this->name[i]),
146 this->hash = end_name_hash(hash);
152 * Accessing the parent inode can be racy under RCU pathwalking.
153 * Use ACCESS_ONCE() to make sure we use _one_ particular inode,
154 * the callers will handle races.
157 ncp_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
158 unsigned int len, const char *str, const struct qstr *name)
160 struct inode *pinode;
162 if (len != name->len)
165 pinode = d_inode_rcu(parent);
169 if (ncp_case_sensitive(pinode))
170 return strncmp(str, name->name, len);
172 return ncp_strnicmp(NCP_IO_TABLE(pinode->i_sb), str, name->name, len);
176 * This is the callback from dput() when d_count is going to 0.
177 * We use this to unhash dentries with bad inodes.
178 * Closing files can be safely postponed until iput() - it's done there anyway.
181 ncp_delete_dentry(const struct dentry * dentry)
183 struct inode *inode = d_inode(dentry);
186 if (is_bad_inode(inode))
190 /* N.B. Unhash negative dentries? */
196 ncp_single_volume(struct ncp_server *server)
198 return (server->m.mounted_vol[0] != '\0');
201 static inline int ncp_is_server_root(struct inode *inode)
203 return !ncp_single_volume(NCP_SERVER(inode)) &&
204 is_root_inode(inode);
209 * This is the callback when the dcache has a lookup hit.
213 #ifdef CONFIG_NCPFS_STRONG
214 /* try to delete a readonly file (NW R bit set) */
217 ncp_force_unlink(struct inode *dir, struct dentry* dentry)
220 struct nw_modify_dos_info info;
224 memset(&info, 0, sizeof(info));
226 /* remove the Read-Only flag on the NW server */
227 inode = d_inode(dentry);
229 old_nwattr = NCP_FINFO(inode)->nwattr;
230 info.attributes = old_nwattr & ~(aRONLY|aDELETEINHIBIT|aRENAMEINHIBIT);
231 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
235 /* now try again the delete operation */
236 res = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry);
238 if (res) /* delete failed, set R bit again */
240 info.attributes = old_nwattr;
241 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
248 #endif /* CONFIG_NCPFS_STRONG */
250 #ifdef CONFIG_NCPFS_STRONG
252 ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_name,
253 struct inode *new_dir, struct dentry* new_dentry, char *_new_name)
255 struct nw_modify_dos_info info;
257 struct inode *old_inode = d_inode(old_dentry);
258 __le32 old_nwattr = NCP_FINFO(old_inode)->nwattr;
259 __le32 new_nwattr = 0; /* shut compiler warning */
260 int old_nwattr_changed = 0;
261 int new_nwattr_changed = 0;
263 memset(&info, 0, sizeof(info));
265 /* remove the Read-Only flag on the NW server */
267 info.attributes = old_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
268 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
270 old_nwattr_changed = 1;
271 if (new_dentry && d_really_is_positive(new_dentry)) {
272 new_nwattr = NCP_FINFO(d_inode(new_dentry))->nwattr;
273 info.attributes = new_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
274 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
276 new_nwattr_changed = 1;
278 /* now try again the rename operation */
279 /* but only if something really happened */
280 if (new_nwattr_changed || old_nwattr_changed) {
281 res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
287 /* file was successfully renamed, so:
288 do not set attributes on old file - it no longer exists
289 copy attributes from old file to new */
290 new_nwattr_changed = old_nwattr_changed;
291 new_nwattr = old_nwattr;
292 old_nwattr_changed = 0;
295 if (old_nwattr_changed) {
296 info.attributes = old_nwattr;
297 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
300 if (new_nwattr_changed) {
301 info.attributes = new_nwattr;
302 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
307 #endif /* CONFIG_NCPFS_STRONG */
311 ncp_lookup_validate(struct dentry *dentry, unsigned int flags)
313 struct ncp_server *server;
314 struct dentry *parent;
316 struct ncp_entry_info finfo;
317 int res, val = 0, len;
318 __u8 __name[NCP_MAXPATHLEN + 1];
320 if (dentry == dentry->d_sb->s_root)
323 if (flags & LOOKUP_RCU)
326 parent = dget_parent(dentry);
327 dir = d_inode(parent);
329 if (d_really_is_negative(dentry))
332 server = NCP_SERVER(dir);
336 * The default validation is based on dentry age:
337 * We set the max age at mount time. (But each
338 * successful server lookup renews the timestamp.)
340 val = NCP_TEST_AGE(server, dentry);
344 ncp_dbg(2, "%pd2 not valid, age=%ld, server lookup\n",
345 dentry, NCP_GET_AGE(dentry));
347 len = sizeof(__name);
348 if (ncp_is_server_root(dir)) {
349 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
350 dentry->d_name.len, 1);
352 res = ncp_lookup_volume(server, __name, &(finfo.i));
354 ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
357 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
358 dentry->d_name.len, !ncp_preserve_case(dir));
360 res = ncp_obtain_info(server, dir, __name, &(finfo.i));
362 finfo.volume = finfo.i.volNumber;
363 ncp_dbg(2, "looked for %pd/%s, res=%d\n",
364 dentry->d_parent, __name, res);
366 * If we didn't find it, or if it has a different dirEntNum to
367 * what we remember, it's not valid any more.
370 struct inode *inode = d_inode(dentry);
373 if (finfo.i.dirEntNum == NCP_FINFO(inode)->dirEntNum) {
374 ncp_new_dentry(dentry);
377 ncp_dbg(2, "found, but dirEntNum changed\n");
379 ncp_update_inode2(inode, &finfo);
384 ncp_dbg(2, "result=%d\n", val);
389 static time_t ncp_obtain_mtime(struct dentry *dentry)
391 struct inode *inode = d_inode(dentry);
392 struct ncp_server *server = NCP_SERVER(inode);
393 struct nw_info_struct i;
395 if (!ncp_conn_valid(server) || ncp_is_server_root(inode))
398 if (ncp_obtain_info(server, inode, NULL, &i))
401 return ncp_date_dos2unix(i.modifyTime, i.modifyDate);
405 ncp_invalidate_dircache_entries(struct dentry *parent)
407 struct ncp_server *server = NCP_SERVER(d_inode(parent));
408 struct dentry *dentry;
410 spin_lock(&parent->d_lock);
411 list_for_each_entry(dentry, &parent->d_subdirs, d_child) {
412 dentry->d_fsdata = NULL;
413 ncp_age_dentry(server, dentry);
415 spin_unlock(&parent->d_lock);
418 static int ncp_readdir(struct file *file, struct dir_context *ctx)
420 struct dentry *dentry = file->f_path.dentry;
421 struct inode *inode = d_inode(dentry);
422 struct page *page = NULL;
423 struct ncp_server *server = NCP_SERVER(inode);
424 union ncp_dir_cache *cache = NULL;
425 struct ncp_cache_control ctl;
426 int result, mtime_valid = 0;
432 ncp_dbg(2, "reading %pD2, pos=%d\n", file, (int)ctx->pos);
435 /* Do not generate '.' and '..' when server is dead. */
436 if (!ncp_conn_valid(server))
440 if (!dir_emit_dots(file, ctx))
443 page = grab_cache_page(&inode->i_data, 0);
447 ctl.cache = cache = kmap(page);
448 ctl.head = cache->head;
450 if (!PageUptodate(page) || !ctl.head.eof)
454 if (jiffies - ctl.head.time >= NCP_MAX_AGE(server))
457 mtime = ncp_obtain_mtime(dentry);
459 if ((!mtime) || (mtime != ctl.head.mtime))
463 if (ctx->pos > ctl.head.end)
466 ctl.fpos = ctx->pos + (NCP_DIRCACHE_START - 2);
467 ctl.ofs = ctl.fpos / NCP_DIRCACHE_SIZE;
468 ctl.idx = ctl.fpos % NCP_DIRCACHE_SIZE;
472 ctl.page = find_lock_page(&inode->i_data, ctl.ofs);
475 ctl.cache = kmap(ctl.page);
476 if (!PageUptodate(ctl.page))
479 while (ctl.idx < NCP_DIRCACHE_SIZE) {
483 spin_lock(&dentry->d_lock);
484 if (!(NCP_FINFO(inode)->flags & NCPI_DIR_CACHE)) {
485 spin_unlock(&dentry->d_lock);
488 dent = ctl.cache->dentry[ctl.idx];
489 if (unlikely(!lockref_get_not_dead(&dent->d_lockref))) {
490 spin_unlock(&dentry->d_lock);
493 spin_unlock(&dentry->d_lock);
494 if (d_really_is_negative(dent)) {
498 over = !dir_emit(ctx, dent->d_name.name,
500 d_inode(dent)->i_ino, DT_UNKNOWN);
506 if (ctx->pos > ctl.head.end)
511 SetPageUptodate(ctl.page);
512 unlock_page(ctl.page);
522 unlock_page(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 spin_lock(&dentry->d_lock);
543 NCP_FINFO(inode)->flags |= NCPI_DIR_CACHE;
544 spin_unlock(&dentry->d_lock);
545 if (ncp_is_server_root(inode)) {
546 ncp_read_volume_list(file, ctx, &ctl);
548 ncp_do_readdir(file, ctx, &ctl);
550 ctl.head.end = ctl.fpos - 1;
551 ctl.head.eof = ctl.valid;
555 SetPageUptodate(ctl.page);
556 unlock_page(ctl.page);
560 cache->head = ctl.head;
562 SetPageUptodate(page);
570 static void ncp_d_prune(struct dentry *dentry)
572 if (!dentry->d_fsdata) /* not referenced from page cache */
574 NCP_FINFO(d_inode(dentry->d_parent))->flags &= ~NCPI_DIR_CACHE;
578 ncp_fill_cache(struct file *file, struct dir_context *ctx,
579 struct ncp_cache_control *ctrl, struct ncp_entry_info *entry,
582 struct dentry *newdent, *dentry = file->f_path.dentry;
583 struct inode *dir = d_inode(dentry);
584 struct ncp_cache_control ctl = *ctrl;
589 __u8 __name[NCP_MAXPATHLEN + 1];
591 qname.len = sizeof(__name);
592 if (ncp_vol2io(NCP_SERVER(dir), __name, &qname.len,
593 entry->i.entryName, entry->i.nameLen,
594 !ncp_preserve_entry_case(dir, entry->i.NSCreator)))
595 return 1; /* I'm not sure */
599 newdent = d_hash_and_lookup(dentry, &qname);
603 newdent = d_alloc(dentry, &qname);
609 /* If case sensitivity changed for this volume, all entries below this one
610 should be thrown away. This entry itself is not affected, as its case
611 sensitivity is controlled by its own parent. */
613 shrink_dcache_parent(newdent);
616 * NetWare's OS2 namespace is case preserving yet case
617 * insensitive. So we update dentry's name as received from
618 * server. Parent dir's i_mutex is locked because we're in
621 dentry_update_name_case(newdent, &qname);
624 if (d_really_is_negative(newdent)) {
628 entry->ino = iunique(dir->i_sb, 2);
629 inode = ncp_iget(dir->i_sb, entry);
631 d_instantiate(newdent, inode);
635 spin_lock(&dentry->d_lock);
636 NCP_FINFO(dir)->flags &= ~NCPI_DIR_CACHE;
637 spin_unlock(&dentry->d_lock);
640 struct inode *inode = d_inode(newdent);
642 inode_lock_nested(inode, I_MUTEX_CHILD);
643 ncp_update_inode2(inode, entry);
647 if (ctl.idx >= NCP_DIRCACHE_SIZE) {
650 SetPageUptodate(ctl.page);
651 unlock_page(ctl.page);
655 ctl.idx -= NCP_DIRCACHE_SIZE;
657 ctl.page = grab_cache_page(&dir->i_data, ctl.ofs);
659 ctl.cache = kmap(ctl.page);
662 if (d_really_is_positive(newdent)) {
663 newdent->d_fsdata = newdent;
664 ctl.cache->dentry[ctl.idx] = newdent;
665 ino = d_inode(newdent)->i_ino;
666 ncp_new_dentry(newdent);
674 if (!ctl.filled && (ctl.fpos == ctx->pos)) {
676 ino = iunique(dir->i_sb, 2);
677 ctl.filled = !dir_emit(ctx, qname.name, qname.len,
685 return (ctl.valid || !ctl.filled);
689 ncp_read_volume_list(struct file *file, struct dir_context *ctx,
690 struct ncp_cache_control *ctl)
692 struct inode *inode = file_inode(file);
693 struct ncp_server *server = NCP_SERVER(inode);
694 struct ncp_volume_info info;
695 struct ncp_entry_info entry;
698 ncp_dbg(1, "pos=%ld\n", (unsigned long)ctx->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 ncp_dbg(1, "found vol: %s\n", info.volume_name);
710 if (ncp_lookup_volume(server, info.volume_name,
712 ncp_dbg(1, "could not lookup vol %s\n",
716 inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL);
717 entry.volume = entry.i.volNumber;
718 if (!ncp_fill_cache(file, ctx, ctl, &entry, inval_dentry))
724 ncp_do_readdir(struct file *file, struct dir_context *ctx,
725 struct ncp_cache_control *ctl)
727 struct inode *dir = file_inode(file);
728 struct ncp_server *server = NCP_SERVER(dir);
729 struct nw_search_sequence seq;
730 struct ncp_entry_info entry;
736 ncp_dbg(1, "%pD2, fpos=%ld\n", file, (unsigned long)ctx->pos);
737 ncp_vdbg("init %pD, volnum=%d, dirent=%u\n",
738 file, NCP_FINFO(dir)->volNumber, NCP_FINFO(dir)->dirEntNum);
740 err = ncp_initialize_search(server, dir, &seq);
742 ncp_dbg(1, "init failed, err=%d\n", err);
745 /* We MUST NOT use server->buffer_size handshaked with server if we are
746 using UDP, as for UDP server uses max. buffer size determined by
747 MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes).
748 So we use 128KB, just to be sure, as there is no way how to know
749 this value in advance. */
751 buf = vmalloc(bufsize);
759 err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls);
762 if (!cnt) /* prevent endless loop */
767 if (rpls < offsetof(struct nw_info_struct, entryName))
768 break; /* short packet */
769 ncp_extract_file_info(rpl, &entry.i);
770 onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen;
772 break; /* short packet */
773 (void)ncp_obtain_nfs_info(server, &entry.i);
776 entry.volume = entry.i.volNumber;
777 if (!ncp_fill_cache(file, ctx, ctl, &entry, 0))
785 int ncp_conn_logged_in(struct super_block *sb)
787 struct ncp_server* server = NCP_SBP(sb);
790 if (ncp_single_volume(server)) {
796 __u8 __name[NCP_MAXPATHLEN + 1];
798 len = sizeof(__name);
799 result = ncp_io2vol(server, __name, &len, server->m.mounted_vol,
800 strlen(server->m.mounted_vol), 1);
804 if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) {
805 ncp_vdbg("%s not found\n", server->m.mounted_vol);
810 struct inode* ino = d_inode(dent);
812 ncp_update_known_namespace(server, volNumber, NULL);
813 NCP_FINFO(ino)->volNumber = volNumber;
814 NCP_FINFO(ino)->dirEntNum = dirEntNum;
815 NCP_FINFO(ino)->DosDirNum = DosDirNum;
818 ncp_dbg(1, "d_inode(sb->s_root) == NULL!\n");
821 ncp_dbg(1, "sb->s_root == NULL!\n");
830 static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
832 struct ncp_server *server = NCP_SERVER(dir);
833 struct inode *inode = NULL;
834 struct ncp_entry_info finfo;
836 __u8 __name[NCP_MAXPATHLEN + 1];
839 if (!ncp_conn_valid(server))
842 ncp_vdbg("server lookup for %pd2\n", dentry);
844 len = sizeof(__name);
845 if (ncp_is_server_root(dir)) {
846 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
847 dentry->d_name.len, 1);
849 res = ncp_lookup_volume(server, __name, &(finfo.i));
851 ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
853 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
854 dentry->d_name.len, !ncp_preserve_case(dir));
856 res = ncp_obtain_info(server, dir, __name, &(finfo.i));
858 ncp_vdbg("looked for %pd2, res=%d\n", dentry, res);
860 * If we didn't find an entry, make a negative dentry.
866 * Create an inode for the entry.
869 finfo.ino = iunique(dir->i_sb, 2);
870 finfo.volume = finfo.i.volNumber;
872 inode = ncp_iget(dir->i_sb, &finfo);
875 ncp_new_dentry(dentry);
877 d_add(dentry, inode);
882 ncp_vdbg("result=%d\n", error);
883 return ERR_PTR(error);
887 * This code is common to create, mkdir, and mknod.
889 static int ncp_instantiate(struct inode *dir, struct dentry *dentry,
890 struct ncp_entry_info *finfo)
895 finfo->ino = iunique(dir->i_sb, 2);
896 inode = ncp_iget(dir->i_sb, finfo);
899 d_instantiate(dentry,inode);
905 ncp_vdbg("%pd2 failed, closing file\n", dentry);
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 ncp_vdbg("creating %pd2, mode=%hx\n", dentry, mode);
921 ncp_age_dentry(server, dentry);
922 len = sizeof(__name);
923 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
924 dentry->d_name.len, !ncp_preserve_case(dir));
931 (server->m.flags & NCP_MOUNT_EXTRAS) &&
933 attributes |= aSYSTEM | aSHARED;
935 result = ncp_open_create_file_or_subdir(server, dir, __name,
936 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
937 attributes, AR_READ | AR_WRITE, &finfo);
940 result = ncp_open_create_file_or_subdir(server, dir, __name,
941 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
942 attributes, AR_WRITE, &finfo);
945 error = -ENAMETOOLONG;
948 ncp_dbg(1, "%pd2 failed\n", dentry);
953 finfo.access = opmode;
954 if (ncp_is_nfs_extras(server, finfo.volume)) {
955 finfo.i.nfs.mode = mode;
956 finfo.i.nfs.rdev = new_encode_dev(rdev);
957 if (ncp_modify_nfs_info(server, finfo.volume,
959 mode, new_encode_dev(rdev)) != 0)
963 error = ncp_instantiate(dir, dentry, &finfo);
968 static int ncp_create(struct inode *dir, struct dentry *dentry, umode_t mode,
971 return ncp_create_new(dir, dentry, mode, 0, 0);
974 static int ncp_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
976 struct ncp_entry_info finfo;
977 struct ncp_server *server = NCP_SERVER(dir);
979 __u8 __name[NCP_MAXPATHLEN + 1];
981 ncp_dbg(1, "making %pd2\n", dentry);
983 ncp_age_dentry(server, dentry);
984 len = sizeof(__name);
985 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
986 dentry->d_name.len, !ncp_preserve_case(dir));
990 error = ncp_open_create_file_or_subdir(server, dir, __name,
991 OC_MODE_CREATE, aDIR,
995 if (ncp_is_nfs_extras(server, finfo.volume)) {
997 finfo.i.nfs.mode = mode;
998 if (ncp_modify_nfs_info(server,
1004 error = ncp_instantiate(dir, dentry, &finfo);
1005 } else if (error > 0) {
1012 static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
1014 struct ncp_server *server = NCP_SERVER(dir);
1015 int error, result, len;
1016 __u8 __name[NCP_MAXPATHLEN + 1];
1018 ncp_dbg(1, "removing %pd2\n", dentry);
1020 len = sizeof(__name);
1021 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
1022 dentry->d_name.len, !ncp_preserve_case(dir));
1026 result = ncp_del_file_or_subdir(server, dir, __name);
1031 case 0x85: /* unauthorized to delete file */
1032 case 0x8A: /* unauthorized to delete file */
1036 case 0x90: /* read only */
1039 case 0x9F: /* in use by another client */
1042 case 0xA0: /* directory not empty */
1045 case 0xFF: /* someone deleted file */
1049 error = result < 0 ? result : -EACCES;
1056 static int ncp_unlink(struct inode *dir, struct dentry *dentry)
1058 struct inode *inode = d_inode(dentry);
1059 struct ncp_server *server;
1062 server = NCP_SERVER(dir);
1063 ncp_dbg(1, "unlinking %pd2\n", dentry);
1066 * Check whether to close the file ...
1069 ncp_vdbg("closing file\n");
1070 ncp_make_closed(inode);
1073 error = ncp_del_file_or_subdir2(server, dentry);
1074 #ifdef CONFIG_NCPFS_STRONG
1075 /* 9C is Invalid path.. It should be 8F, 90 - read only, but
1077 if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */
1078 error = ncp_force_unlink(dir, dentry);
1083 ncp_dbg(1, "removed %pd2\n", dentry);
1089 case 0x8D: /* some files in use */
1090 case 0x8E: /* all files in use */
1093 case 0x8F: /* some read only */
1094 case 0x90: /* all read only */
1095 case 0x9C: /* !!! returned when in-use or read-only by NW4 */
1102 error = error < 0 ? error : -EACCES;
1108 static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
1109 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];
1116 ncp_dbg(1, "%pd2 to %pd2\n", old_dentry, new_dentry);
1118 ncp_age_dentry(server, old_dentry);
1119 ncp_age_dentry(server, new_dentry);
1121 old_len = sizeof(__old_name);
1122 error = ncp_io2vol(server, __old_name, &old_len,
1123 old_dentry->d_name.name, old_dentry->d_name.len,
1124 !ncp_preserve_case(old_dir));
1128 new_len = sizeof(__new_name);
1129 error = ncp_io2vol(server, __new_name, &new_len,
1130 new_dentry->d_name.name, new_dentry->d_name.len,
1131 !ncp_preserve_case(new_dir));
1135 error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name,
1136 new_dir, __new_name);
1137 #ifdef CONFIG_NCPFS_STRONG
1138 if ((error == 0x90 || error == 0x8B || error == -EACCES) &&
1139 server->m.flags & NCP_MOUNT_STRONG) { /* RO */
1140 error = ncp_force_rename(old_dir, old_dentry, __old_name,
1141 new_dir, new_dentry, __new_name);
1146 ncp_dbg(1, "renamed %pd -> %pd\n",
1147 old_dentry, new_dentry);
1148 ncp_d_prune(old_dentry);
1149 ncp_d_prune(new_dentry);
1152 error = -ENAMETOOLONG;
1158 error = error < 0 ? error : -EACCES;
1165 static int ncp_mknod(struct inode * dir, struct dentry *dentry,
1166 umode_t mode, dev_t rdev)
1168 if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) {
1169 ncp_dbg(1, "mode = 0%ho\n", mode);
1170 return ncp_create_new(dir, dentry, mode, rdev, 0);
1172 return -EPERM; /* Strange, but true */
1175 /* The following routines are taken directly from msdos-fs */
1177 /* Linear day numbers of the respective 1sts in non-leap years. */
1179 static int day_n[] =
1180 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
1181 /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
1183 static int utc2local(int time)
1185 return time - sys_tz.tz_minuteswest * 60;
1188 static int local2utc(int time)
1190 return time + sys_tz.tz_minuteswest * 60;
1193 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
1195 ncp_date_dos2unix(__le16 t, __le16 d)
1197 unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d);
1198 int month, year, secs;
1200 /* first subtract and mask after that... Otherwise, if
1201 date == 0, bad things happen */
1202 month = ((date >> 5) - 1) & 15;
1204 secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
1205 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) +
1206 year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653);
1207 /* days since 1.1.70 plus 80's leap day */
1208 return local2utc(secs);
1212 /* Convert linear UNIX date to a MS-DOS time/date pair. */
1214 ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
1216 int day, year, nl_day, month;
1218 unix_date = utc2local(unix_date);
1219 *time = cpu_to_le16(
1220 (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
1221 (((unix_date / 3600) % 24) << 11));
1222 day = unix_date / 86400 - 3652;
1224 if ((year + 3) / 4 + 365 * year > day)
1226 day -= (year + 3) / 4 + 365 * year;
1227 if (day == 59 && !(year & 3)) {
1231 nl_day = (year & 3) || day <= 59 ? day : day - 1;
1232 for (month = 1; month < 12; month++)
1233 if (day_n[month] > nl_day)
1236 *date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));