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 *);
81 const struct dentry_operations ncp_dentry_operations =
83 .d_revalidate = ncp_lookup_validate,
84 .d_hash = ncp_hash_dentry,
85 .d_compare = ncp_compare_dentry,
86 .d_delete = ncp_delete_dentry,
89 #define ncp_namespace(i) (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber])
91 static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator)
93 #ifdef CONFIG_NCPFS_SMALLDOS
94 int ns = ncp_namespace(i);
97 #ifdef CONFIG_NCPFS_OS2_NS
98 || ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS))
99 #endif /* CONFIG_NCPFS_OS2_NS */
102 #endif /* CONFIG_NCPFS_SMALLDOS */
106 #define ncp_preserve_case(i) (ncp_namespace(i) != NW_NS_DOS)
108 static inline int ncp_case_sensitive(const struct inode *i)
110 #ifdef CONFIG_NCPFS_NFS_NS
111 return ncp_namespace(i) == NW_NS_NFS;
114 #endif /* CONFIG_NCPFS_NFS_NS */
118 * Note: leave the hash unchanged if the directory
121 * Accessing the parent inode can be racy under RCU pathwalking.
122 * Use ACCESS_ONCE() to make sure we use _one_ particular inode,
123 * the callers will handle races.
126 ncp_hash_dentry(const struct dentry *dentry, struct qstr *this)
128 struct inode *inode = ACCESS_ONCE(dentry->d_inode);
133 if (!ncp_case_sensitive(inode)) {
134 struct super_block *sb = dentry->d_sb;
139 t = NCP_IO_TABLE(sb);
140 hash = init_name_hash();
141 for (i=0; i<this->len ; i++)
142 hash = partial_name_hash(ncp_tolower(t, this->name[i]),
144 this->hash = end_name_hash(hash);
150 * Accessing the parent inode can be racy under RCU pathwalking.
151 * Use ACCESS_ONCE() to make sure we use _one_ particular inode,
152 * the callers will handle races.
155 ncp_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
156 unsigned int len, const char *str, const struct qstr *name)
158 struct inode *pinode;
160 if (len != name->len)
163 pinode = ACCESS_ONCE(parent->d_inode);
167 if (ncp_case_sensitive(pinode))
168 return strncmp(str, name->name, len);
170 return ncp_strnicmp(NCP_IO_TABLE(pinode->i_sb), str, name->name, len);
174 * This is the callback from dput() when d_count is going to 0.
175 * We use this to unhash dentries with bad inodes.
176 * Closing files can be safely postponed until iput() - it's done there anyway.
179 ncp_delete_dentry(const struct dentry * dentry)
181 struct inode *inode = dentry->d_inode;
184 if (is_bad_inode(inode))
188 /* N.B. Unhash negative dentries? */
194 ncp_single_volume(struct ncp_server *server)
196 return (server->m.mounted_vol[0] != '\0');
199 static inline int ncp_is_server_root(struct inode *inode)
201 return (!ncp_single_volume(NCP_SERVER(inode)) &&
202 inode == inode->i_sb->s_root->d_inode);
207 * This is the callback when the dcache has a lookup hit.
211 #ifdef CONFIG_NCPFS_STRONG
212 /* try to delete a readonly file (NW R bit set) */
215 ncp_force_unlink(struct inode *dir, struct dentry* dentry)
218 struct nw_modify_dos_info info;
222 memset(&info, 0, sizeof(info));
224 /* remove the Read-Only flag on the NW server */
225 inode = dentry->d_inode;
227 old_nwattr = NCP_FINFO(inode)->nwattr;
228 info.attributes = old_nwattr & ~(aRONLY|aDELETEINHIBIT|aRENAMEINHIBIT);
229 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
233 /* now try again the delete operation */
234 res = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry);
236 if (res) /* delete failed, set R bit again */
238 info.attributes = old_nwattr;
239 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
246 #endif /* CONFIG_NCPFS_STRONG */
248 #ifdef CONFIG_NCPFS_STRONG
250 ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_name,
251 struct inode *new_dir, struct dentry* new_dentry, char *_new_name)
253 struct nw_modify_dos_info info;
255 struct inode *old_inode = old_dentry->d_inode;
256 __le32 old_nwattr = NCP_FINFO(old_inode)->nwattr;
257 __le32 new_nwattr = 0; /* shut compiler warning */
258 int old_nwattr_changed = 0;
259 int new_nwattr_changed = 0;
261 memset(&info, 0, sizeof(info));
263 /* remove the Read-Only flag on the NW server */
265 info.attributes = old_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
266 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
268 old_nwattr_changed = 1;
269 if (new_dentry && new_dentry->d_inode) {
270 new_nwattr = NCP_FINFO(new_dentry->d_inode)->nwattr;
271 info.attributes = new_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
272 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
274 new_nwattr_changed = 1;
276 /* now try again the rename operation */
277 /* but only if something really happened */
278 if (new_nwattr_changed || old_nwattr_changed) {
279 res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
285 /* file was successfully renamed, so:
286 do not set attributes on old file - it no longer exists
287 copy attributes from old file to new */
288 new_nwattr_changed = old_nwattr_changed;
289 new_nwattr = old_nwattr;
290 old_nwattr_changed = 0;
293 if (old_nwattr_changed) {
294 info.attributes = old_nwattr;
295 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
298 if (new_nwattr_changed) {
299 info.attributes = new_nwattr;
300 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
305 #endif /* CONFIG_NCPFS_STRONG */
309 ncp_lookup_validate(struct dentry *dentry, unsigned int flags)
311 struct ncp_server *server;
312 struct dentry *parent;
314 struct ncp_entry_info finfo;
315 int res, val = 0, len;
316 __u8 __name[NCP_MAXPATHLEN + 1];
318 if (dentry == dentry->d_sb->s_root)
321 if (flags & LOOKUP_RCU)
324 parent = dget_parent(dentry);
325 dir = parent->d_inode;
327 if (!dentry->d_inode)
330 server = NCP_SERVER(dir);
334 * The default validation is based on dentry age:
335 * We set the max age at mount time. (But each
336 * successful server lookup renews the timestamp.)
338 val = NCP_TEST_AGE(server, dentry);
342 DDPRINTK("ncp_lookup_validate: %pd2 not valid, age=%ld, server lookup\n",
343 dentry, NCP_GET_AGE(dentry));
345 len = sizeof(__name);
346 if (ncp_is_server_root(dir)) {
347 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
348 dentry->d_name.len, 1);
350 res = ncp_lookup_volume(server, __name, &(finfo.i));
352 ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
355 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
356 dentry->d_name.len, !ncp_preserve_case(dir));
358 res = ncp_obtain_info(server, dir, __name, &(finfo.i));
360 finfo.volume = finfo.i.volNumber;
361 DDPRINTK("ncp_lookup_validate: looked for %pd/%s, res=%d\n",
362 dentry->d_parent, __name, res);
364 * If we didn't find it, or if it has a different dirEntNum to
365 * what we remember, it's not valid any more.
368 struct inode *inode = dentry->d_inode;
370 mutex_lock(&inode->i_mutex);
371 if (finfo.i.dirEntNum == NCP_FINFO(inode)->dirEntNum) {
372 ncp_new_dentry(dentry);
375 DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");
377 ncp_update_inode2(inode, &finfo);
378 mutex_unlock(&inode->i_mutex);
382 DDPRINTK("ncp_lookup_validate: result=%d\n", val);
387 static struct dentry *
388 ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
390 struct dentry *dent = dentry;
391 struct list_head *next;
393 if (d_validate(dent, parent)) {
394 if (dent->d_name.len <= NCP_MAXPATHLEN &&
395 (unsigned long)dent->d_fsdata == fpos) {
396 if (!dent->d_inode) {
405 /* If a pointer is invalid, we search the dentry. */
406 spin_lock(&parent->d_lock);
407 next = parent->d_subdirs.next;
408 while (next != &parent->d_subdirs) {
409 dent = list_entry(next, struct dentry, d_u.d_child);
410 if ((unsigned long)dent->d_fsdata == fpos) {
415 spin_unlock(&parent->d_lock);
420 spin_unlock(&parent->d_lock);
427 static time_t ncp_obtain_mtime(struct dentry *dentry)
429 struct inode *inode = dentry->d_inode;
430 struct ncp_server *server = NCP_SERVER(inode);
431 struct nw_info_struct i;
433 if (!ncp_conn_valid(server) || ncp_is_server_root(inode))
436 if (ncp_obtain_info(server, inode, NULL, &i))
439 return ncp_date_dos2unix(i.modifyTime, i.modifyDate);
442 static int ncp_readdir(struct file *file, struct dir_context *ctx)
444 struct dentry *dentry = file->f_path.dentry;
445 struct inode *inode = dentry->d_inode;
446 struct page *page = NULL;
447 struct ncp_server *server = NCP_SERVER(inode);
448 union ncp_dir_cache *cache = NULL;
449 struct ncp_cache_control ctl;
450 int result, mtime_valid = 0;
456 DDPRINTK("ncp_readdir: reading %pD2, pos=%d\n", file,
460 /* Do not generate '.' and '..' when server is dead. */
461 if (!ncp_conn_valid(server))
465 if (!dir_emit_dots(file, ctx))
468 page = grab_cache_page(&inode->i_data, 0);
472 ctl.cache = cache = kmap(page);
473 ctl.head = cache->head;
475 if (!PageUptodate(page) || !ctl.head.eof)
479 if (jiffies - ctl.head.time >= NCP_MAX_AGE(server))
482 mtime = ncp_obtain_mtime(dentry);
484 if ((!mtime) || (mtime != ctl.head.mtime))
488 if (ctx->pos > ctl.head.end)
491 ctl.fpos = ctx->pos + (NCP_DIRCACHE_START - 2);
492 ctl.ofs = ctl.fpos / NCP_DIRCACHE_SIZE;
493 ctl.idx = ctl.fpos % NCP_DIRCACHE_SIZE;
497 ctl.page = find_lock_page(&inode->i_data, ctl.ofs);
500 ctl.cache = kmap(ctl.page);
501 if (!PageUptodate(ctl.page))
504 while (ctl.idx < NCP_DIRCACHE_SIZE) {
508 dent = ncp_dget_fpos(ctl.cache->dentry[ctl.idx],
512 over = !dir_emit(ctx, dent->d_name.name,
514 dent->d_inode->i_ino, DT_UNKNOWN);
520 if (ctx->pos > ctl.head.end)
525 SetPageUptodate(ctl.page);
526 unlock_page(ctl.page);
527 page_cache_release(ctl.page);
536 unlock_page(ctl.page);
537 page_cache_release(ctl.page);
542 ncp_invalidate_dircache_entries(dentry);
544 mtime = ncp_obtain_mtime(dentry);
547 ctl.head.mtime = mtime;
548 ctl.head.time = jiffies;
552 ctl.idx = NCP_DIRCACHE_START;
556 if (ncp_is_server_root(inode)) {
557 ncp_read_volume_list(file, ctx, &ctl);
559 ncp_do_readdir(file, ctx, &ctl);
561 ctl.head.end = ctl.fpos - 1;
562 ctl.head.eof = ctl.valid;
566 SetPageUptodate(ctl.page);
567 unlock_page(ctl.page);
568 page_cache_release(ctl.page);
571 cache->head = ctl.head;
573 SetPageUptodate(page);
575 page_cache_release(page);
582 ncp_fill_cache(struct file *file, struct dir_context *ctx,
583 struct ncp_cache_control *ctrl, struct ncp_entry_info *entry,
586 struct dentry *newdent, *dentry = file->f_path.dentry;
587 struct inode *dir = dentry->d_inode;
588 struct ncp_cache_control ctl = *ctrl;
593 __u8 __name[NCP_MAXPATHLEN + 1];
595 qname.len = sizeof(__name);
596 if (ncp_vol2io(NCP_SERVER(dir), __name, &qname.len,
597 entry->i.entryName, entry->i.nameLen,
598 !ncp_preserve_entry_case(dir, entry->i.NSCreator)))
599 return 1; /* I'm not sure */
603 newdent = d_hash_and_lookup(dentry, &qname);
604 if (unlikely(IS_ERR(newdent)))
607 newdent = d_alloc(dentry, &qname);
613 /* If case sensitivity changed for this volume, all entries below this one
614 should be thrown away. This entry itself is not affected, as its case
615 sensitivity is controlled by its own parent. */
617 shrink_dcache_parent(newdent);
620 * NetWare's OS2 namespace is case preserving yet case
621 * insensitive. So we update dentry's name as received from
622 * server. Parent dir's i_mutex is locked because we're in
625 dentry_update_name_case(newdent, &qname);
628 if (!newdent->d_inode) {
632 entry->ino = iunique(dir->i_sb, 2);
633 inode = ncp_iget(dir->i_sb, entry);
635 d_instantiate(newdent, inode);
640 struct inode *inode = newdent->d_inode;
642 mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
643 ncp_update_inode2(inode, entry);
644 mutex_unlock(&inode->i_mutex);
647 if (newdent->d_inode) {
648 ino = newdent->d_inode->i_ino;
649 newdent->d_fsdata = (void *) ctl.fpos;
650 ncp_new_dentry(newdent);
653 if (ctl.idx >= NCP_DIRCACHE_SIZE) {
656 SetPageUptodate(ctl.page);
657 unlock_page(ctl.page);
658 page_cache_release(ctl.page);
661 ctl.idx -= NCP_DIRCACHE_SIZE;
663 ctl.page = grab_cache_page(&dir->i_data, ctl.ofs);
665 ctl.cache = kmap(ctl.page);
668 ctl.cache->dentry[ctl.idx] = newdent;
675 if (!ctl.filled && (ctl.fpos == ctx->pos)) {
677 ino = iunique(dir->i_sb, 2);
678 ctl.filled = !dir_emit(ctx, qname.name, qname.len,
686 return (ctl.valid || !ctl.filled);
690 ncp_read_volume_list(struct file *file, struct dir_context *ctx,
691 struct ncp_cache_control *ctl)
693 struct dentry *dentry = file->f_path.dentry;
694 struct inode *inode = dentry->d_inode;
695 struct ncp_server *server = NCP_SERVER(inode);
696 struct ncp_volume_info info;
697 struct ncp_entry_info entry;
700 DPRINTK("ncp_read_volume_list: pos=%ld\n",
701 (unsigned long) ctx->pos);
703 for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) {
706 if (ncp_get_volume_info_with_number(server, i, &info) != 0)
708 if (!strlen(info.volume_name))
711 DPRINTK("ncp_read_volume_list: found vol: %s\n",
714 if (ncp_lookup_volume(server, info.volume_name,
716 DPRINTK("ncpfs: could not lookup vol %s\n",
720 inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL);
721 entry.volume = entry.i.volNumber;
722 if (!ncp_fill_cache(file, ctx, ctl, &entry, inval_dentry))
728 ncp_do_readdir(struct file *file, struct dir_context *ctx,
729 struct ncp_cache_control *ctl)
731 struct dentry *dentry = file->f_path.dentry;
732 struct inode *dir = dentry->d_inode;
733 struct ncp_server *server = NCP_SERVER(dir);
734 struct nw_search_sequence seq;
735 struct ncp_entry_info entry;
741 DPRINTK("ncp_do_readdir: %pD2, fpos=%ld\n", file,
742 (unsigned long) ctx->pos);
743 PPRINTK("ncp_do_readdir: init %pD, volnum=%d, dirent=%u\n",
744 file, NCP_FINFO(dir)->volNumber, NCP_FINFO(dir)->dirEntNum);
746 err = ncp_initialize_search(server, dir, &seq);
748 DPRINTK("ncp_do_readdir: init failed, err=%d\n", err);
751 /* We MUST NOT use server->buffer_size handshaked with server if we are
752 using UDP, as for UDP server uses max. buffer size determined by
753 MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes).
754 So we use 128KB, just to be sure, as there is no way how to know
755 this value in advance. */
757 buf = vmalloc(bufsize);
765 err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls);
768 if (!cnt) /* prevent endless loop */
773 if (rpls < offsetof(struct nw_info_struct, entryName))
774 break; /* short packet */
775 ncp_extract_file_info(rpl, &entry.i);
776 onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen;
778 break; /* short packet */
779 (void)ncp_obtain_nfs_info(server, &entry.i);
782 entry.volume = entry.i.volNumber;
783 if (!ncp_fill_cache(file, ctx, ctl, &entry, 0))
791 int ncp_conn_logged_in(struct super_block *sb)
793 struct ncp_server* server = NCP_SBP(sb);
796 if (ncp_single_volume(server)) {
802 __u8 __name[NCP_MAXPATHLEN + 1];
804 len = sizeof(__name);
805 result = ncp_io2vol(server, __name, &len, server->m.mounted_vol,
806 strlen(server->m.mounted_vol), 1);
810 if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) {
811 PPRINTK("ncp_conn_logged_in: %s not found\n",
812 server->m.mounted_vol);
817 struct inode* ino = dent->d_inode;
819 ncp_update_known_namespace(server, volNumber, NULL);
820 NCP_FINFO(ino)->volNumber = volNumber;
821 NCP_FINFO(ino)->dirEntNum = dirEntNum;
822 NCP_FINFO(ino)->DosDirNum = DosDirNum;
825 DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n");
828 DPRINTK("ncpfs: sb->s_root == NULL!\n");
837 static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
839 struct ncp_server *server = NCP_SERVER(dir);
840 struct inode *inode = NULL;
841 struct ncp_entry_info finfo;
843 __u8 __name[NCP_MAXPATHLEN + 1];
846 if (!ncp_conn_valid(server))
849 PPRINTK("ncp_lookup: server lookup for %pd2\n", dentry);
851 len = sizeof(__name);
852 if (ncp_is_server_root(dir)) {
853 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
854 dentry->d_name.len, 1);
856 res = ncp_lookup_volume(server, __name, &(finfo.i));
858 ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
860 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
861 dentry->d_name.len, !ncp_preserve_case(dir));
863 res = ncp_obtain_info(server, dir, __name, &(finfo.i));
865 PPRINTK("ncp_lookup: looked for %pd2, res=%d\n", dentry, res);
867 * If we didn't find an entry, make a negative dentry.
873 * Create an inode for the entry.
876 finfo.ino = iunique(dir->i_sb, 2);
877 finfo.volume = finfo.i.volNumber;
879 inode = ncp_iget(dir->i_sb, &finfo);
882 ncp_new_dentry(dentry);
884 d_add(dentry, inode);
889 PPRINTK("ncp_lookup: result=%d\n", error);
890 return ERR_PTR(error);
894 * This code is common to create, mkdir, and mknod.
896 static int ncp_instantiate(struct inode *dir, struct dentry *dentry,
897 struct ncp_entry_info *finfo)
902 finfo->ino = iunique(dir->i_sb, 2);
903 inode = ncp_iget(dir->i_sb, finfo);
906 d_instantiate(dentry,inode);
912 PPRINTK("ncp_instantiate: %pd2 failed, closing file\n", dentry);
913 ncp_close_file(NCP_SERVER(dir), finfo->file_handle);
917 int ncp_create_new(struct inode *dir, struct dentry *dentry, umode_t mode,
918 dev_t rdev, __le32 attributes)
920 struct ncp_server *server = NCP_SERVER(dir);
921 struct ncp_entry_info finfo;
922 int error, result, len;
924 __u8 __name[NCP_MAXPATHLEN + 1];
926 PPRINTK("ncp_create_new: creating %pd2, mode=%hx\n", dentry, mode);
928 ncp_age_dentry(server, dentry);
929 len = sizeof(__name);
930 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
931 dentry->d_name.len, !ncp_preserve_case(dir));
938 (server->m.flags & NCP_MOUNT_EXTRAS) &&
940 attributes |= aSYSTEM | aSHARED;
942 result = ncp_open_create_file_or_subdir(server, dir, __name,
943 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
944 attributes, AR_READ | AR_WRITE, &finfo);
947 result = ncp_open_create_file_or_subdir(server, dir, __name,
948 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
949 attributes, AR_WRITE, &finfo);
952 error = -ENAMETOOLONG;
955 DPRINTK("ncp_create: %pd2 failed\n", dentry);
960 finfo.access = opmode;
961 if (ncp_is_nfs_extras(server, finfo.volume)) {
962 finfo.i.nfs.mode = mode;
963 finfo.i.nfs.rdev = new_encode_dev(rdev);
964 if (ncp_modify_nfs_info(server, finfo.volume,
966 mode, new_encode_dev(rdev)) != 0)
970 error = ncp_instantiate(dir, dentry, &finfo);
975 static int ncp_create(struct inode *dir, struct dentry *dentry, umode_t mode,
978 return ncp_create_new(dir, dentry, mode, 0, 0);
981 static int ncp_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
983 struct ncp_entry_info finfo;
984 struct ncp_server *server = NCP_SERVER(dir);
986 __u8 __name[NCP_MAXPATHLEN + 1];
988 DPRINTK("ncp_mkdir: making %pd2\n", dentry);
990 ncp_age_dentry(server, dentry);
991 len = sizeof(__name);
992 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
993 dentry->d_name.len, !ncp_preserve_case(dir));
997 error = ncp_open_create_file_or_subdir(server, dir, __name,
998 OC_MODE_CREATE, aDIR,
1002 if (ncp_is_nfs_extras(server, finfo.volume)) {
1004 finfo.i.nfs.mode = mode;
1005 if (ncp_modify_nfs_info(server,
1011 error = ncp_instantiate(dir, dentry, &finfo);
1012 } else if (error > 0) {
1019 static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
1021 struct ncp_server *server = NCP_SERVER(dir);
1022 int error, result, len;
1023 __u8 __name[NCP_MAXPATHLEN + 1];
1025 DPRINTK("ncp_rmdir: removing %pd2\n", dentry);
1027 len = sizeof(__name);
1028 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
1029 dentry->d_name.len, !ncp_preserve_case(dir));
1033 result = ncp_del_file_or_subdir(server, dir, __name);
1038 case 0x85: /* unauthorized to delete file */
1039 case 0x8A: /* unauthorized to delete file */
1043 case 0x90: /* read only */
1046 case 0x9F: /* in use by another client */
1049 case 0xA0: /* directory not empty */
1052 case 0xFF: /* someone deleted file */
1056 error = result < 0 ? result : -EACCES;
1063 static int ncp_unlink(struct inode *dir, struct dentry *dentry)
1065 struct inode *inode = dentry->d_inode;
1066 struct ncp_server *server;
1069 server = NCP_SERVER(dir);
1070 DPRINTK("ncp_unlink: unlinking %pd2\n", dentry);
1073 * Check whether to close the file ...
1076 PPRINTK("ncp_unlink: closing file\n");
1077 ncp_make_closed(inode);
1080 error = ncp_del_file_or_subdir2(server, dentry);
1081 #ifdef CONFIG_NCPFS_STRONG
1082 /* 9C is Invalid path.. It should be 8F, 90 - read only, but
1084 if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */
1085 error = ncp_force_unlink(dir, dentry);
1090 DPRINTK("ncp: removed %pd2\n", dentry);
1096 case 0x8D: /* some files in use */
1097 case 0x8E: /* all files in use */
1100 case 0x8F: /* some read only */
1101 case 0x90: /* all read only */
1102 case 0x9C: /* !!! returned when in-use or read-only by NW4 */
1109 error = error < 0 ? error : -EACCES;
1115 static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
1116 struct inode *new_dir, struct dentry *new_dentry)
1118 struct ncp_server *server = NCP_SERVER(old_dir);
1120 int old_len, new_len;
1121 __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1];
1123 DPRINTK("ncp_rename: %pd2 to %pd2\n", old_dentry, new_dentry);
1125 ncp_age_dentry(server, old_dentry);
1126 ncp_age_dentry(server, new_dentry);
1128 old_len = sizeof(__old_name);
1129 error = ncp_io2vol(server, __old_name, &old_len,
1130 old_dentry->d_name.name, old_dentry->d_name.len,
1131 !ncp_preserve_case(old_dir));
1135 new_len = sizeof(__new_name);
1136 error = ncp_io2vol(server, __new_name, &new_len,
1137 new_dentry->d_name.name, new_dentry->d_name.len,
1138 !ncp_preserve_case(new_dir));
1142 error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name,
1143 new_dir, __new_name);
1144 #ifdef CONFIG_NCPFS_STRONG
1145 if ((error == 0x90 || error == 0x8B || error == -EACCES) &&
1146 server->m.flags & NCP_MOUNT_STRONG) { /* RO */
1147 error = ncp_force_rename(old_dir, old_dentry, __old_name,
1148 new_dir, new_dentry, __new_name);
1153 DPRINTK("ncp renamed %pd -> %pd.\n",
1154 old_dentry, new_dentry);
1157 error = -ENAMETOOLONG;
1163 error = error < 0 ? error : -EACCES;
1170 static int ncp_mknod(struct inode * dir, struct dentry *dentry,
1171 umode_t mode, dev_t rdev)
1173 if (!new_valid_dev(rdev))
1175 if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) {
1176 DPRINTK(KERN_DEBUG "ncp_mknod: mode = 0%ho\n", mode);
1177 return ncp_create_new(dir, dentry, mode, rdev, 0);
1179 return -EPERM; /* Strange, but true */
1182 /* The following routines are taken directly from msdos-fs */
1184 /* Linear day numbers of the respective 1sts in non-leap years. */
1186 static int day_n[] =
1187 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
1188 /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
1191 extern struct timezone sys_tz;
1193 static int utc2local(int time)
1195 return time - sys_tz.tz_minuteswest * 60;
1198 static int local2utc(int time)
1200 return time + sys_tz.tz_minuteswest * 60;
1203 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
1205 ncp_date_dos2unix(__le16 t, __le16 d)
1207 unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d);
1208 int month, year, secs;
1210 /* first subtract and mask after that... Otherwise, if
1211 date == 0, bad things happen */
1212 month = ((date >> 5) - 1) & 15;
1214 secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
1215 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) +
1216 year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653);
1217 /* days since 1.1.70 plus 80's leap day */
1218 return local2utc(secs);
1222 /* Convert linear UNIX date to a MS-DOS time/date pair. */
1224 ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
1226 int day, year, nl_day, month;
1228 unix_date = utc2local(unix_date);
1229 *time = cpu_to_le16(
1230 (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
1231 (((unix_date / 3600) % 24) << 11));
1232 day = unix_date / 86400 - 3652;
1234 if ((year + 3) / 4 + 365 * year > day)
1236 day -= (year + 3) / 4 + 365 * year;
1237 if (day == 59 && !(year & 3)) {
1241 nl_day = (year & 3) || day <= 59 ? day : day - 1;
1242 for (month = 1; month < 12; month++)
1243 if (day_n[month] > nl_day)
1246 *date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));