1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright (C) 1995, 1996 by Volker Lendecke
6 * Modified for big endian by J.F. Chadima and David S. Miller
7 * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
8 * Modified 1998, 1999 Wolfram Pienkoss for NLS
9 * Modified 1999 Wolfram Pienkoss for directory caching
10 * Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
15 #include <linux/time.h>
16 #include <linux/errno.h>
17 #include <linux/stat.h>
18 #include <linux/kernel.h>
19 #include <linux/vmalloc.h>
21 #include <linux/namei.h>
22 #include <linux/uaccess.h>
23 #include <asm/byteorder.h>
27 static void ncp_read_volume_list(struct file *, struct dir_context *,
28 struct ncp_cache_control *);
29 static void ncp_do_readdir(struct file *, struct dir_context *,
30 struct ncp_cache_control *);
32 static int ncp_readdir(struct file *, struct dir_context *);
34 static int ncp_create(struct inode *, struct dentry *, umode_t, bool);
35 static struct dentry *ncp_lookup(struct inode *, struct dentry *, unsigned int);
36 static int ncp_unlink(struct inode *, struct dentry *);
37 static int ncp_mkdir(struct inode *, struct dentry *, umode_t);
38 static int ncp_rmdir(struct inode *, struct dentry *);
39 static int ncp_rename(struct inode *, struct dentry *,
40 struct inode *, struct dentry *, unsigned int);
41 static int ncp_mknod(struct inode * dir, struct dentry *dentry,
42 umode_t 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 .iterate = 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 *, unsigned int);
77 static int ncp_hash_dentry(const struct dentry *, struct qstr *);
78 static int ncp_compare_dentry(const struct dentry *,
79 unsigned int, const char *, const struct qstr *);
80 static int ncp_delete_dentry(const struct dentry *);
81 static void ncp_d_prune(struct dentry *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,
89 .d_prune = ncp_d_prune,
92 #define ncp_namespace(i) (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber])
94 static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator)
96 #ifdef CONFIG_NCPFS_SMALLDOS
97 int ns = ncp_namespace(i);
100 #ifdef CONFIG_NCPFS_OS2_NS
101 || ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS))
102 #endif /* CONFIG_NCPFS_OS2_NS */
105 #endif /* CONFIG_NCPFS_SMALLDOS */
109 #define ncp_preserve_case(i) (ncp_namespace(i) != NW_NS_DOS)
111 static inline int ncp_case_sensitive(const struct inode *i)
113 #ifdef CONFIG_NCPFS_NFS_NS
114 return ncp_namespace(i) == NW_NS_NFS;
117 #endif /* CONFIG_NCPFS_NFS_NS */
121 * Note: leave the hash unchanged if the directory
125 ncp_hash_dentry(const struct dentry *dentry, struct qstr *this)
127 struct inode *inode = d_inode_rcu(dentry);
132 if (!ncp_case_sensitive(inode)) {
137 t = NCP_IO_TABLE(dentry->d_sb);
138 hash = init_name_hash(dentry);
139 for (i=0; i<this->len ; i++)
140 hash = partial_name_hash(ncp_tolower(t, this->name[i]),
142 this->hash = end_name_hash(hash);
148 ncp_compare_dentry(const struct dentry *dentry,
149 unsigned int len, const char *str, const struct qstr *name)
151 struct inode *pinode;
153 if (len != name->len)
156 pinode = d_inode_rcu(dentry->d_parent);
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 = d_inode(dentry);
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 is_root_inode(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 = d_inode(dentry);
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 = d_inode(old_dentry);
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 && d_really_is_positive(new_dentry)) {
263 new_nwattr = NCP_FINFO(d_inode(new_dentry))->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, unsigned int flags)
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 if (dentry == dentry->d_sb->s_root)
314 if (flags & LOOKUP_RCU)
317 parent = dget_parent(dentry);
318 dir = d_inode(parent);
320 if (d_really_is_negative(dentry))
323 server = NCP_SERVER(dir);
327 * The default validation is based on dentry age:
328 * We set the max age at mount time. (But each
329 * successful server lookup renews the timestamp.)
331 val = NCP_TEST_AGE(server, dentry);
335 ncp_dbg(2, "%pd2 not valid, age=%ld, server lookup\n",
336 dentry, NCP_GET_AGE(dentry));
338 len = sizeof(__name);
339 if (ncp_is_server_root(dir)) {
340 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
341 dentry->d_name.len, 1);
343 res = ncp_lookup_volume(server, __name, &(finfo.i));
345 ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
348 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
349 dentry->d_name.len, !ncp_preserve_case(dir));
351 res = ncp_obtain_info(server, dir, __name, &(finfo.i));
353 finfo.volume = finfo.i.volNumber;
354 ncp_dbg(2, "looked for %pd/%s, res=%d\n",
355 dentry->d_parent, __name, res);
357 * If we didn't find it, or if it has a different dirEntNum to
358 * what we remember, it's not valid any more.
361 struct inode *inode = d_inode(dentry);
364 if (finfo.i.dirEntNum == NCP_FINFO(inode)->dirEntNum) {
365 ncp_new_dentry(dentry);
368 ncp_dbg(2, "found, but dirEntNum changed\n");
370 ncp_update_inode2(inode, &finfo);
375 ncp_dbg(2, "result=%d\n", val);
380 static time_t ncp_obtain_mtime(struct dentry *dentry)
382 struct inode *inode = d_inode(dentry);
383 struct ncp_server *server = NCP_SERVER(inode);
384 struct nw_info_struct i;
386 if (!ncp_conn_valid(server) || ncp_is_server_root(inode))
389 if (ncp_obtain_info(server, inode, NULL, &i))
392 return ncp_date_dos2unix(i.modifyTime, i.modifyDate);
396 ncp_invalidate_dircache_entries(struct dentry *parent)
398 struct ncp_server *server = NCP_SERVER(d_inode(parent));
399 struct dentry *dentry;
401 spin_lock(&parent->d_lock);
402 list_for_each_entry(dentry, &parent->d_subdirs, d_child) {
403 dentry->d_fsdata = NULL;
404 ncp_age_dentry(server, dentry);
406 spin_unlock(&parent->d_lock);
409 static int ncp_readdir(struct file *file, struct dir_context *ctx)
411 struct dentry *dentry = file->f_path.dentry;
412 struct inode *inode = d_inode(dentry);
413 struct page *page = NULL;
414 struct ncp_server *server = NCP_SERVER(inode);
415 union ncp_dir_cache *cache = NULL;
416 struct ncp_cache_control ctl;
417 int result, mtime_valid = 0;
423 ncp_dbg(2, "reading %pD2, pos=%d\n", file, (int)ctx->pos);
426 /* Do not generate '.' and '..' when server is dead. */
427 if (!ncp_conn_valid(server))
431 if (!dir_emit_dots(file, ctx))
434 page = grab_cache_page(&inode->i_data, 0);
438 ctl.cache = cache = kmap(page);
439 ctl.head = cache->head;
441 if (!PageUptodate(page) || !ctl.head.eof)
445 if (jiffies - ctl.head.time >= NCP_MAX_AGE(server))
448 mtime = ncp_obtain_mtime(dentry);
450 if ((!mtime) || (mtime != ctl.head.mtime))
454 if (ctx->pos > ctl.head.end)
457 ctl.fpos = ctx->pos + (NCP_DIRCACHE_START - 2);
458 ctl.ofs = ctl.fpos / NCP_DIRCACHE_SIZE;
459 ctl.idx = ctl.fpos % NCP_DIRCACHE_SIZE;
463 ctl.page = find_lock_page(&inode->i_data, ctl.ofs);
466 ctl.cache = kmap(ctl.page);
467 if (!PageUptodate(ctl.page))
470 while (ctl.idx < NCP_DIRCACHE_SIZE) {
474 spin_lock(&dentry->d_lock);
475 if (!(NCP_FINFO(inode)->flags & NCPI_DIR_CACHE)) {
476 spin_unlock(&dentry->d_lock);
479 dent = ctl.cache->dentry[ctl.idx];
480 if (unlikely(!lockref_get_not_dead(&dent->d_lockref))) {
481 spin_unlock(&dentry->d_lock);
484 spin_unlock(&dentry->d_lock);
485 if (d_really_is_negative(dent)) {
489 over = !dir_emit(ctx, dent->d_name.name,
491 d_inode(dent)->i_ino, DT_UNKNOWN);
497 if (ctx->pos > ctl.head.end)
502 SetPageUptodate(ctl.page);
503 unlock_page(ctl.page);
513 unlock_page(ctl.page);
519 ncp_invalidate_dircache_entries(dentry);
521 mtime = ncp_obtain_mtime(dentry);
524 ctl.head.mtime = mtime;
525 ctl.head.time = jiffies;
529 ctl.idx = NCP_DIRCACHE_START;
533 spin_lock(&dentry->d_lock);
534 NCP_FINFO(inode)->flags |= NCPI_DIR_CACHE;
535 spin_unlock(&dentry->d_lock);
536 if (ncp_is_server_root(inode)) {
537 ncp_read_volume_list(file, ctx, &ctl);
539 ncp_do_readdir(file, ctx, &ctl);
541 ctl.head.end = ctl.fpos - 1;
542 ctl.head.eof = ctl.valid;
546 SetPageUptodate(ctl.page);
547 unlock_page(ctl.page);
551 cache->head = ctl.head;
553 SetPageUptodate(page);
561 static void ncp_d_prune(struct dentry *dentry)
563 if (!dentry->d_fsdata) /* not referenced from page cache */
565 NCP_FINFO(d_inode(dentry->d_parent))->flags &= ~NCPI_DIR_CACHE;
569 ncp_fill_cache(struct file *file, struct dir_context *ctx,
570 struct ncp_cache_control *ctrl, struct ncp_entry_info *entry,
573 struct dentry *newdent, *dentry = file->f_path.dentry;
574 struct inode *dir = d_inode(dentry);
575 struct ncp_cache_control ctl = *ctrl;
580 __u8 __name[NCP_MAXPATHLEN + 1];
582 qname.len = sizeof(__name);
583 if (ncp_vol2io(NCP_SERVER(dir), __name, &qname.len,
584 entry->i.entryName, entry->i.nameLen,
585 !ncp_preserve_entry_case(dir, entry->i.NSCreator)))
586 return 1; /* I'm not sure */
590 newdent = d_hash_and_lookup(dentry, &qname);
594 newdent = d_alloc(dentry, &qname);
600 /* If case sensitivity changed for this volume, all entries below this one
601 should be thrown away. This entry itself is not affected, as its case
602 sensitivity is controlled by its own parent. */
604 shrink_dcache_parent(newdent);
607 * NetWare's OS2 namespace is case preserving yet case
608 * insensitive. So we update dentry's name as received from
609 * server. Parent dir's i_mutex is locked because we're in
612 dentry_update_name_case(newdent, &qname);
615 if (d_really_is_negative(newdent)) {
619 entry->ino = iunique(dir->i_sb, 2);
620 inode = ncp_iget(dir->i_sb, entry);
622 d_instantiate(newdent, inode);
626 spin_lock(&dentry->d_lock);
627 NCP_FINFO(dir)->flags &= ~NCPI_DIR_CACHE;
628 spin_unlock(&dentry->d_lock);
631 struct inode *inode = d_inode(newdent);
633 inode_lock_nested(inode, I_MUTEX_CHILD);
634 ncp_update_inode2(inode, entry);
638 if (ctl.idx >= NCP_DIRCACHE_SIZE) {
641 SetPageUptodate(ctl.page);
642 unlock_page(ctl.page);
646 ctl.idx -= NCP_DIRCACHE_SIZE;
648 ctl.page = grab_cache_page(&dir->i_data, ctl.ofs);
650 ctl.cache = kmap(ctl.page);
653 if (d_really_is_positive(newdent)) {
654 newdent->d_fsdata = newdent;
655 ctl.cache->dentry[ctl.idx] = newdent;
656 ino = d_inode(newdent)->i_ino;
657 ncp_new_dentry(newdent);
665 if (!ctl.filled && (ctl.fpos == ctx->pos)) {
667 ino = iunique(dir->i_sb, 2);
668 ctl.filled = !dir_emit(ctx, qname.name, qname.len,
676 return (ctl.valid || !ctl.filled);
680 ncp_read_volume_list(struct file *file, struct dir_context *ctx,
681 struct ncp_cache_control *ctl)
683 struct inode *inode = file_inode(file);
684 struct ncp_server *server = NCP_SERVER(inode);
685 struct ncp_volume_info info;
686 struct ncp_entry_info entry;
689 ncp_dbg(1, "pos=%ld\n", (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 ncp_dbg(1, "found vol: %s\n", info.volume_name);
701 if (ncp_lookup_volume(server, info.volume_name,
703 ncp_dbg(1, "could not lookup vol %s\n",
707 inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL);
708 entry.volume = entry.i.volNumber;
709 if (!ncp_fill_cache(file, ctx, ctl, &entry, inval_dentry))
715 ncp_do_readdir(struct file *file, struct dir_context *ctx,
716 struct ncp_cache_control *ctl)
718 struct inode *dir = file_inode(file);
719 struct ncp_server *server = NCP_SERVER(dir);
720 struct nw_search_sequence seq;
721 struct ncp_entry_info entry;
727 ncp_dbg(1, "%pD2, fpos=%ld\n", file, (unsigned long)ctx->pos);
728 ncp_vdbg("init %pD, volnum=%d, dirent=%u\n",
729 file, NCP_FINFO(dir)->volNumber, NCP_FINFO(dir)->dirEntNum);
731 err = ncp_initialize_search(server, dir, &seq);
733 ncp_dbg(1, "init failed, err=%d\n", err);
736 /* We MUST NOT use server->buffer_size handshaked with server if we are
737 using UDP, as for UDP server uses max. buffer size determined by
738 MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes).
739 So we use 128KB, just to be sure, as there is no way how to know
740 this value in advance. */
742 buf = vmalloc(bufsize);
750 err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls);
753 if (!cnt) /* prevent endless loop */
758 if (rpls < offsetof(struct nw_info_struct, entryName))
759 break; /* short packet */
760 ncp_extract_file_info(rpl, &entry.i);
761 onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen;
763 break; /* short packet */
764 (void)ncp_obtain_nfs_info(server, &entry.i);
767 entry.volume = entry.i.volNumber;
768 if (!ncp_fill_cache(file, ctx, ctl, &entry, 0))
776 int ncp_conn_logged_in(struct super_block *sb)
778 struct ncp_server* server = NCP_SBP(sb);
781 if (ncp_single_volume(server)) {
787 __u8 __name[NCP_MAXPATHLEN + 1];
789 len = sizeof(__name);
790 result = ncp_io2vol(server, __name, &len, server->m.mounted_vol,
791 strlen(server->m.mounted_vol), 1);
795 if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) {
796 ncp_vdbg("%s not found\n", server->m.mounted_vol);
801 struct inode* ino = d_inode(dent);
803 ncp_update_known_namespace(server, volNumber, NULL);
804 NCP_FINFO(ino)->volNumber = volNumber;
805 NCP_FINFO(ino)->dirEntNum = dirEntNum;
806 NCP_FINFO(ino)->DosDirNum = DosDirNum;
809 ncp_dbg(1, "d_inode(sb->s_root) == NULL!\n");
812 ncp_dbg(1, "sb->s_root == NULL!\n");
821 static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
823 struct ncp_server *server = NCP_SERVER(dir);
824 struct inode *inode = NULL;
825 struct ncp_entry_info finfo;
827 __u8 __name[NCP_MAXPATHLEN + 1];
829 if (!ncp_conn_valid(server))
830 return ERR_PTR(-EIO);
832 ncp_vdbg("server lookup for %pd2\n", dentry);
834 len = sizeof(__name);
835 if (ncp_is_server_root(dir)) {
836 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
837 dentry->d_name.len, 1);
839 res = ncp_lookup_volume(server, __name, &(finfo.i));
841 ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
843 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
844 dentry->d_name.len, !ncp_preserve_case(dir));
846 res = ncp_obtain_info(server, dir, __name, &(finfo.i));
848 ncp_vdbg("looked for %pd2, res=%d\n", dentry, res);
851 * Entry found; create an inode for it.
854 finfo.ino = iunique(dir->i_sb, 2);
855 finfo.volume = finfo.i.volNumber;
856 inode = ncp_iget(dir->i_sb, &finfo);
857 if (unlikely(!inode))
858 inode = ERR_PTR(-EACCES);
860 ncp_new_dentry(dentry);
862 return d_splice_alias(inode, dentry);
866 * This code is common to create, mkdir, and mknod.
868 static int ncp_instantiate(struct inode *dir, struct dentry *dentry,
869 struct ncp_entry_info *finfo)
874 finfo->ino = iunique(dir->i_sb, 2);
875 inode = ncp_iget(dir->i_sb, finfo);
878 d_instantiate(dentry,inode);
884 ncp_vdbg("%pd2 failed, closing file\n", dentry);
885 ncp_close_file(NCP_SERVER(dir), finfo->file_handle);
889 int ncp_create_new(struct inode *dir, struct dentry *dentry, umode_t mode,
890 dev_t rdev, __le32 attributes)
892 struct ncp_server *server = NCP_SERVER(dir);
893 struct ncp_entry_info finfo;
894 int error, result, len;
896 __u8 __name[NCP_MAXPATHLEN + 1];
898 ncp_vdbg("creating %pd2, mode=%hx\n", dentry, mode);
900 ncp_age_dentry(server, dentry);
901 len = sizeof(__name);
902 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
903 dentry->d_name.len, !ncp_preserve_case(dir));
910 (server->m.flags & NCP_MOUNT_EXTRAS) &&
912 attributes |= aSYSTEM | aSHARED;
914 result = ncp_open_create_file_or_subdir(server, dir, __name,
915 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
916 attributes, AR_READ | AR_WRITE, &finfo);
919 result = ncp_open_create_file_or_subdir(server, dir, __name,
920 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
921 attributes, AR_WRITE, &finfo);
924 error = -ENAMETOOLONG;
927 ncp_dbg(1, "%pd2 failed\n", dentry);
932 finfo.access = opmode;
933 if (ncp_is_nfs_extras(server, finfo.volume)) {
934 finfo.i.nfs.mode = mode;
935 finfo.i.nfs.rdev = new_encode_dev(rdev);
936 if (ncp_modify_nfs_info(server, finfo.volume,
938 mode, new_encode_dev(rdev)) != 0)
942 error = ncp_instantiate(dir, dentry, &finfo);
947 static int ncp_create(struct inode *dir, struct dentry *dentry, umode_t mode,
950 return ncp_create_new(dir, dentry, mode, 0, 0);
953 static int ncp_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
955 struct ncp_entry_info finfo;
956 struct ncp_server *server = NCP_SERVER(dir);
958 __u8 __name[NCP_MAXPATHLEN + 1];
960 ncp_dbg(1, "making %pd2\n", dentry);
962 ncp_age_dentry(server, dentry);
963 len = sizeof(__name);
964 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
965 dentry->d_name.len, !ncp_preserve_case(dir));
969 error = ncp_open_create_file_or_subdir(server, dir, __name,
970 OC_MODE_CREATE, aDIR,
974 if (ncp_is_nfs_extras(server, finfo.volume)) {
976 finfo.i.nfs.mode = mode;
977 if (ncp_modify_nfs_info(server,
983 error = ncp_instantiate(dir, dentry, &finfo);
984 } else if (error > 0) {
991 static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
993 struct ncp_server *server = NCP_SERVER(dir);
994 int error, result, len;
995 __u8 __name[NCP_MAXPATHLEN + 1];
997 ncp_dbg(1, "removing %pd2\n", dentry);
999 len = sizeof(__name);
1000 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
1001 dentry->d_name.len, !ncp_preserve_case(dir));
1005 result = ncp_del_file_or_subdir(server, dir, __name);
1010 case 0x85: /* unauthorized to delete file */
1011 case 0x8A: /* unauthorized to delete file */
1015 case 0x90: /* read only */
1018 case 0x9F: /* in use by another client */
1021 case 0xA0: /* directory not empty */
1024 case 0xFF: /* someone deleted file */
1028 error = result < 0 ? result : -EACCES;
1035 static int ncp_unlink(struct inode *dir, struct dentry *dentry)
1037 struct inode *inode = d_inode(dentry);
1038 struct ncp_server *server;
1041 server = NCP_SERVER(dir);
1042 ncp_dbg(1, "unlinking %pd2\n", dentry);
1045 * Check whether to close the file ...
1048 ncp_vdbg("closing file\n");
1049 ncp_make_closed(inode);
1052 error = ncp_del_file_or_subdir2(server, dentry);
1053 #ifdef CONFIG_NCPFS_STRONG
1054 /* 9C is Invalid path.. It should be 8F, 90 - read only, but
1056 if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */
1057 error = ncp_force_unlink(dir, dentry);
1062 ncp_dbg(1, "removed %pd2\n", dentry);
1068 case 0x8D: /* some files in use */
1069 case 0x8E: /* all files in use */
1072 case 0x8F: /* some read only */
1073 case 0x90: /* all read only */
1074 case 0x9C: /* !!! returned when in-use or read-only by NW4 */
1081 error = error < 0 ? error : -EACCES;
1087 static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
1088 struct inode *new_dir, struct dentry *new_dentry,
1091 struct ncp_server *server = NCP_SERVER(old_dir);
1093 int old_len, new_len;
1094 __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1];
1099 ncp_dbg(1, "%pd2 to %pd2\n", old_dentry, new_dentry);
1101 ncp_age_dentry(server, old_dentry);
1102 ncp_age_dentry(server, new_dentry);
1104 old_len = sizeof(__old_name);
1105 error = ncp_io2vol(server, __old_name, &old_len,
1106 old_dentry->d_name.name, old_dentry->d_name.len,
1107 !ncp_preserve_case(old_dir));
1111 new_len = sizeof(__new_name);
1112 error = ncp_io2vol(server, __new_name, &new_len,
1113 new_dentry->d_name.name, new_dentry->d_name.len,
1114 !ncp_preserve_case(new_dir));
1118 error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name,
1119 new_dir, __new_name);
1120 #ifdef CONFIG_NCPFS_STRONG
1121 if ((error == 0x90 || error == 0x8B || error == -EACCES) &&
1122 server->m.flags & NCP_MOUNT_STRONG) { /* RO */
1123 error = ncp_force_rename(old_dir, old_dentry, __old_name,
1124 new_dir, new_dentry, __new_name);
1129 ncp_dbg(1, "renamed %pd -> %pd\n",
1130 old_dentry, new_dentry);
1131 ncp_d_prune(old_dentry);
1132 ncp_d_prune(new_dentry);
1135 error = -ENAMETOOLONG;
1141 error = error < 0 ? error : -EACCES;
1148 static int ncp_mknod(struct inode * dir, struct dentry *dentry,
1149 umode_t mode, dev_t rdev)
1151 if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) {
1152 ncp_dbg(1, "mode = 0%ho\n", mode);
1153 return ncp_create_new(dir, dentry, mode, rdev, 0);
1155 return -EPERM; /* Strange, but true */
1158 /* The following routines are taken directly from msdos-fs */
1160 /* Linear day numbers of the respective 1sts in non-leap years. */
1162 static int day_n[] =
1163 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
1164 /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
1166 static int utc2local(int time)
1168 return time - sys_tz.tz_minuteswest * 60;
1171 static int local2utc(int time)
1173 return time + sys_tz.tz_minuteswest * 60;
1176 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
1178 ncp_date_dos2unix(__le16 t, __le16 d)
1180 unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d);
1181 int month, year, secs;
1183 /* first subtract and mask after that... Otherwise, if
1184 date == 0, bad things happen */
1185 month = ((date >> 5) - 1) & 15;
1187 secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
1188 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) +
1189 year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653);
1190 /* days since 1.1.70 plus 80's leap day */
1191 return local2utc(secs);
1195 /* Convert linear UNIX date to a MS-DOS time/date pair. */
1197 ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
1199 int day, year, nl_day, month;
1201 unix_date = utc2local(unix_date);
1202 *time = cpu_to_le16(
1203 (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
1204 (((unix_date / 3600) % 24) << 11));
1205 day = unix_date / 86400 - 3652;
1207 if ((year + 3) / 4 + 365 * year > day)
1209 day -= (year + 3) / 4 + 365 * year;
1210 if (day == 59 && !(year & 3)) {
1214 nl_day = (year & 3) || day <= 59 ? day : day - 1;
1215 for (month = 1; month < 12; month++)
1216 if (day_n[month] > nl_day)
1219 *date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));