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];
830 if (!ncp_conn_valid(server))
833 ncp_vdbg("server lookup for %pd2\n", dentry);
835 len = sizeof(__name);
836 if (ncp_is_server_root(dir)) {
837 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
838 dentry->d_name.len, 1);
840 res = ncp_lookup_volume(server, __name, &(finfo.i));
842 ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
844 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
845 dentry->d_name.len, !ncp_preserve_case(dir));
847 res = ncp_obtain_info(server, dir, __name, &(finfo.i));
849 ncp_vdbg("looked for %pd2, res=%d\n", dentry, res);
851 * If we didn't find an entry, make a negative dentry.
857 * Create an inode for the entry.
860 finfo.ino = iunique(dir->i_sb, 2);
861 finfo.volume = finfo.i.volNumber;
863 inode = ncp_iget(dir->i_sb, &finfo);
866 ncp_new_dentry(dentry);
868 d_add(dentry, inode);
873 ncp_vdbg("result=%d\n", error);
874 return ERR_PTR(error);
878 * This code is common to create, mkdir, and mknod.
880 static int ncp_instantiate(struct inode *dir, struct dentry *dentry,
881 struct ncp_entry_info *finfo)
886 finfo->ino = iunique(dir->i_sb, 2);
887 inode = ncp_iget(dir->i_sb, finfo);
890 d_instantiate(dentry,inode);
896 ncp_vdbg("%pd2 failed, closing file\n", dentry);
897 ncp_close_file(NCP_SERVER(dir), finfo->file_handle);
901 int ncp_create_new(struct inode *dir, struct dentry *dentry, umode_t mode,
902 dev_t rdev, __le32 attributes)
904 struct ncp_server *server = NCP_SERVER(dir);
905 struct ncp_entry_info finfo;
906 int error, result, len;
908 __u8 __name[NCP_MAXPATHLEN + 1];
910 ncp_vdbg("creating %pd2, mode=%hx\n", dentry, mode);
912 ncp_age_dentry(server, dentry);
913 len = sizeof(__name);
914 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
915 dentry->d_name.len, !ncp_preserve_case(dir));
922 (server->m.flags & NCP_MOUNT_EXTRAS) &&
924 attributes |= aSYSTEM | aSHARED;
926 result = ncp_open_create_file_or_subdir(server, dir, __name,
927 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
928 attributes, AR_READ | AR_WRITE, &finfo);
931 result = ncp_open_create_file_or_subdir(server, dir, __name,
932 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
933 attributes, AR_WRITE, &finfo);
936 error = -ENAMETOOLONG;
939 ncp_dbg(1, "%pd2 failed\n", dentry);
944 finfo.access = opmode;
945 if (ncp_is_nfs_extras(server, finfo.volume)) {
946 finfo.i.nfs.mode = mode;
947 finfo.i.nfs.rdev = new_encode_dev(rdev);
948 if (ncp_modify_nfs_info(server, finfo.volume,
950 mode, new_encode_dev(rdev)) != 0)
954 error = ncp_instantiate(dir, dentry, &finfo);
959 static int ncp_create(struct inode *dir, struct dentry *dentry, umode_t mode,
962 return ncp_create_new(dir, dentry, mode, 0, 0);
965 static int ncp_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
967 struct ncp_entry_info finfo;
968 struct ncp_server *server = NCP_SERVER(dir);
970 __u8 __name[NCP_MAXPATHLEN + 1];
972 ncp_dbg(1, "making %pd2\n", dentry);
974 ncp_age_dentry(server, dentry);
975 len = sizeof(__name);
976 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
977 dentry->d_name.len, !ncp_preserve_case(dir));
981 error = ncp_open_create_file_or_subdir(server, dir, __name,
982 OC_MODE_CREATE, aDIR,
986 if (ncp_is_nfs_extras(server, finfo.volume)) {
988 finfo.i.nfs.mode = mode;
989 if (ncp_modify_nfs_info(server,
995 error = ncp_instantiate(dir, dentry, &finfo);
996 } else if (error > 0) {
1003 static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
1005 struct ncp_server *server = NCP_SERVER(dir);
1006 int error, result, len;
1007 __u8 __name[NCP_MAXPATHLEN + 1];
1009 ncp_dbg(1, "removing %pd2\n", dentry);
1011 len = sizeof(__name);
1012 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
1013 dentry->d_name.len, !ncp_preserve_case(dir));
1017 result = ncp_del_file_or_subdir(server, dir, __name);
1022 case 0x85: /* unauthorized to delete file */
1023 case 0x8A: /* unauthorized to delete file */
1027 case 0x90: /* read only */
1030 case 0x9F: /* in use by another client */
1033 case 0xA0: /* directory not empty */
1036 case 0xFF: /* someone deleted file */
1040 error = result < 0 ? result : -EACCES;
1047 static int ncp_unlink(struct inode *dir, struct dentry *dentry)
1049 struct inode *inode = d_inode(dentry);
1050 struct ncp_server *server;
1053 server = NCP_SERVER(dir);
1054 ncp_dbg(1, "unlinking %pd2\n", dentry);
1057 * Check whether to close the file ...
1060 ncp_vdbg("closing file\n");
1061 ncp_make_closed(inode);
1064 error = ncp_del_file_or_subdir2(server, dentry);
1065 #ifdef CONFIG_NCPFS_STRONG
1066 /* 9C is Invalid path.. It should be 8F, 90 - read only, but
1068 if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */
1069 error = ncp_force_unlink(dir, dentry);
1074 ncp_dbg(1, "removed %pd2\n", dentry);
1080 case 0x8D: /* some files in use */
1081 case 0x8E: /* all files in use */
1084 case 0x8F: /* some read only */
1085 case 0x90: /* all read only */
1086 case 0x9C: /* !!! returned when in-use or read-only by NW4 */
1093 error = error < 0 ? error : -EACCES;
1099 static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
1100 struct inode *new_dir, struct dentry *new_dentry,
1103 struct ncp_server *server = NCP_SERVER(old_dir);
1105 int old_len, new_len;
1106 __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1];
1111 ncp_dbg(1, "%pd2 to %pd2\n", old_dentry, new_dentry);
1113 ncp_age_dentry(server, old_dentry);
1114 ncp_age_dentry(server, new_dentry);
1116 old_len = sizeof(__old_name);
1117 error = ncp_io2vol(server, __old_name, &old_len,
1118 old_dentry->d_name.name, old_dentry->d_name.len,
1119 !ncp_preserve_case(old_dir));
1123 new_len = sizeof(__new_name);
1124 error = ncp_io2vol(server, __new_name, &new_len,
1125 new_dentry->d_name.name, new_dentry->d_name.len,
1126 !ncp_preserve_case(new_dir));
1130 error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name,
1131 new_dir, __new_name);
1132 #ifdef CONFIG_NCPFS_STRONG
1133 if ((error == 0x90 || error == 0x8B || error == -EACCES) &&
1134 server->m.flags & NCP_MOUNT_STRONG) { /* RO */
1135 error = ncp_force_rename(old_dir, old_dentry, __old_name,
1136 new_dir, new_dentry, __new_name);
1141 ncp_dbg(1, "renamed %pd -> %pd\n",
1142 old_dentry, new_dentry);
1143 ncp_d_prune(old_dentry);
1144 ncp_d_prune(new_dentry);
1147 error = -ENAMETOOLONG;
1153 error = error < 0 ? error : -EACCES;
1160 static int ncp_mknod(struct inode * dir, struct dentry *dentry,
1161 umode_t mode, dev_t rdev)
1163 if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) {
1164 ncp_dbg(1, "mode = 0%ho\n", mode);
1165 return ncp_create_new(dir, dentry, mode, rdev, 0);
1167 return -EPERM; /* Strange, but true */
1170 /* The following routines are taken directly from msdos-fs */
1172 /* Linear day numbers of the respective 1sts in non-leap years. */
1174 static int day_n[] =
1175 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
1176 /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
1178 static int utc2local(int time)
1180 return time - sys_tz.tz_minuteswest * 60;
1183 static int local2utc(int time)
1185 return time + sys_tz.tz_minuteswest * 60;
1188 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
1190 ncp_date_dos2unix(__le16 t, __le16 d)
1192 unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d);
1193 int month, year, secs;
1195 /* first subtract and mask after that... Otherwise, if
1196 date == 0, bad things happen */
1197 month = ((date >> 5) - 1) & 15;
1199 secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
1200 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) +
1201 year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653);
1202 /* days since 1.1.70 plus 80's leap day */
1203 return local2utc(secs);
1207 /* Convert linear UNIX date to a MS-DOS time/date pair. */
1209 ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
1211 int day, year, nl_day, month;
1213 unix_date = utc2local(unix_date);
1214 *time = cpu_to_le16(
1215 (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
1216 (((unix_date / 3600) % 24) << 11));
1217 day = unix_date / 86400 - 3652;
1219 if ((year + 3) / 4 + 365 * year > day)
1221 day -= (year + 3) / 4 + 365 * year;
1222 if (day == 59 && !(year & 3)) {
1226 nl_day = (year & 3) || day <= 59 ? day : day - 1;
1227 for (month = 1; month < 12; month++)
1228 if (day_n[month] > nl_day)
1231 *date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));