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>
24 #include <linux/ncp_fs.h>
26 #include "ncplib_kernel.h"
28 static void ncp_read_volume_list(struct file
*, void *, filldir_t
,
29 struct ncp_cache_control
*);
30 static void ncp_do_readdir(struct file
*, void *, filldir_t
,
31 struct ncp_cache_control
*);
33 static int ncp_readdir(struct file
*, void *, filldir_t
);
35 static int ncp_create(struct inode
*, struct dentry
*, int, struct nameidata
*);
36 static struct dentry
*ncp_lookup(struct inode
*, struct dentry
*, struct nameidata
*);
37 static int ncp_unlink(struct inode
*, struct dentry
*);
38 static int ncp_mkdir(struct inode
*, struct dentry
*, int);
39 static int ncp_rmdir(struct inode
*, struct dentry
*);
40 static int ncp_rename(struct inode
*, struct dentry
*,
41 struct inode
*, struct dentry
*);
42 static int ncp_mknod(struct inode
* dir
, struct dentry
*dentry
,
43 int mode
, dev_t rdev
);
44 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
45 extern int ncp_symlink(struct inode
*, struct dentry
*, const char *);
47 #define ncp_symlink NULL
50 const struct file_operations ncp_dir_operations
=
52 .llseek
= generic_file_llseek
,
53 .read
= generic_read_dir
,
54 .readdir
= ncp_readdir
,
55 .unlocked_ioctl
= ncp_ioctl
,
57 .compat_ioctl
= ncp_compat_ioctl
,
61 const struct inode_operations ncp_dir_inode_operations
=
66 .symlink
= ncp_symlink
,
71 .setattr
= ncp_notify_change
,
75 * Dentry operations routines
77 static int ncp_lookup_validate(struct dentry
*, struct nameidata
*);
78 static int ncp_hash_dentry(const struct dentry
*, const struct inode
*,
80 static int ncp_compare_dentry(const struct dentry
*, const struct inode
*,
81 const struct dentry
*, const struct inode
*,
82 unsigned int, const char *, const struct qstr
*);
83 static int ncp_delete_dentry(const struct dentry
*);
85 const struct dentry_operations ncp_dentry_operations
=
87 .d_revalidate
= ncp_lookup_validate
,
88 .d_hash
= ncp_hash_dentry
,
89 .d_compare
= ncp_compare_dentry
,
90 .d_delete
= ncp_delete_dentry
,
93 #define ncp_namespace(i) (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber])
95 static inline int ncp_preserve_entry_case(struct inode
*i
, __u32 nscreator
)
97 #ifdef CONFIG_NCPFS_SMALLDOS
98 int ns
= ncp_namespace(i
);
100 if ((ns
== NW_NS_DOS
)
101 #ifdef CONFIG_NCPFS_OS2_NS
102 || ((ns
== NW_NS_OS2
) && (nscreator
== NW_NS_DOS
))
103 #endif /* CONFIG_NCPFS_OS2_NS */
106 #endif /* CONFIG_NCPFS_SMALLDOS */
110 #define ncp_preserve_case(i) (ncp_namespace(i) != NW_NS_DOS)
112 static inline int ncp_case_sensitive(const struct inode
*i
)
114 #ifdef CONFIG_NCPFS_NFS_NS
115 return ncp_namespace(i
) == NW_NS_NFS
;
118 #endif /* CONFIG_NCPFS_NFS_NS */
122 * Note: leave the hash unchanged if the directory
126 ncp_hash_dentry(const struct dentry
*dentry
, const struct inode
*inode
,
129 if (!ncp_case_sensitive(inode
)) {
130 struct super_block
*sb
= dentry
->d_sb
;
135 t
= NCP_IO_TABLE(sb
);
136 hash
= init_name_hash();
137 for (i
=0; i
<this->len
; i
++)
138 hash
= partial_name_hash(ncp_tolower(t
, this->name
[i
]),
140 this->hash
= end_name_hash(hash
);
146 ncp_compare_dentry(const struct dentry
*parent
, const struct inode
*pinode
,
147 const struct dentry
*dentry
, const struct inode
*inode
,
148 unsigned int len
, const char *str
, const struct qstr
*name
)
150 if (len
!= name
->len
)
153 if (ncp_case_sensitive(pinode
))
154 return strncmp(str
, name
->name
, len
);
156 return ncp_strnicmp(NCP_IO_TABLE(pinode
->i_sb
), str
, name
->name
, len
);
160 * This is the callback from dput() when d_count is going to 0.
161 * We use this to unhash dentries with bad inodes.
162 * Closing files can be safely postponed until iput() - it's done there anyway.
165 ncp_delete_dentry(const struct dentry
* dentry
)
167 struct inode
*inode
= dentry
->d_inode
;
170 if (is_bad_inode(inode
))
174 /* N.B. Unhash negative dentries? */
180 ncp_single_volume(struct ncp_server
*server
)
182 return (server
->m
.mounted_vol
[0] != '\0');
185 static inline int ncp_is_server_root(struct inode
*inode
)
187 return (!ncp_single_volume(NCP_SERVER(inode
)) &&
188 inode
== inode
->i_sb
->s_root
->d_inode
);
193 * This is the callback when the dcache has a lookup hit.
197 #ifdef CONFIG_NCPFS_STRONG
198 /* try to delete a readonly file (NW R bit set) */
201 ncp_force_unlink(struct inode
*dir
, struct dentry
* dentry
)
204 struct nw_modify_dos_info info
;
208 memset(&info
, 0, sizeof(info
));
210 /* remove the Read-Only flag on the NW server */
211 inode
= dentry
->d_inode
;
213 old_nwattr
= NCP_FINFO(inode
)->nwattr
;
214 info
.attributes
= old_nwattr
& ~(aRONLY
|aDELETEINHIBIT
|aRENAMEINHIBIT
);
215 res2
= ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode
), inode
, NULL
, DM_ATTRIBUTES
, &info
);
219 /* now try again the delete operation */
220 res
= ncp_del_file_or_subdir2(NCP_SERVER(dir
), dentry
);
222 if (res
) /* delete failed, set R bit again */
224 info
.attributes
= old_nwattr
;
225 res2
= ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode
), inode
, NULL
, DM_ATTRIBUTES
, &info
);
232 #endif /* CONFIG_NCPFS_STRONG */
234 #ifdef CONFIG_NCPFS_STRONG
236 ncp_force_rename(struct inode
*old_dir
, struct dentry
* old_dentry
, char *_old_name
,
237 struct inode
*new_dir
, struct dentry
* new_dentry
, char *_new_name
)
239 struct nw_modify_dos_info info
;
241 struct inode
*old_inode
= old_dentry
->d_inode
;
242 __le32 old_nwattr
= NCP_FINFO(old_inode
)->nwattr
;
243 __le32 new_nwattr
= 0; /* shut compiler warning */
244 int old_nwattr_changed
= 0;
245 int new_nwattr_changed
= 0;
247 memset(&info
, 0, sizeof(info
));
249 /* remove the Read-Only flag on the NW server */
251 info
.attributes
= old_nwattr
& ~(aRONLY
|aRENAMEINHIBIT
|aDELETEINHIBIT
);
252 res2
= ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode
), old_inode
, NULL
, DM_ATTRIBUTES
, &info
);
254 old_nwattr_changed
= 1;
255 if (new_dentry
&& new_dentry
->d_inode
) {
256 new_nwattr
= NCP_FINFO(new_dentry
->d_inode
)->nwattr
;
257 info
.attributes
= new_nwattr
& ~(aRONLY
|aRENAMEINHIBIT
|aDELETEINHIBIT
);
258 res2
= ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir
), new_dir
, _new_name
, DM_ATTRIBUTES
, &info
);
260 new_nwattr_changed
= 1;
262 /* now try again the rename operation */
263 /* but only if something really happened */
264 if (new_nwattr_changed
|| old_nwattr_changed
) {
265 res
= ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir
),
271 /* file was successfully renamed, so:
272 do not set attributes on old file - it no longer exists
273 copy attributes from old file to new */
274 new_nwattr_changed
= old_nwattr_changed
;
275 new_nwattr
= old_nwattr
;
276 old_nwattr_changed
= 0;
279 if (old_nwattr_changed
) {
280 info
.attributes
= old_nwattr
;
281 res2
= ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode
), old_inode
, NULL
, DM_ATTRIBUTES
, &info
);
284 if (new_nwattr_changed
) {
285 info
.attributes
= new_nwattr
;
286 res2
= ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir
), new_dir
, _new_name
, DM_ATTRIBUTES
, &info
);
291 #endif /* CONFIG_NCPFS_STRONG */
295 ncp_lookup_validate(struct dentry
*dentry
, struct nameidata
*nd
)
297 struct ncp_server
*server
;
298 struct dentry
*parent
;
300 struct ncp_entry_info finfo
;
301 int res
, val
= 0, len
;
302 __u8 __name
[NCP_MAXPATHLEN
+ 1];
304 if (dentry
== dentry
->d_sb
->s_root
)
307 if (nd
->flags
& LOOKUP_RCU
)
310 parent
= dget_parent(dentry
);
311 dir
= parent
->d_inode
;
313 if (!dentry
->d_inode
)
316 server
= NCP_SERVER(dir
);
320 * The default validation is based on dentry age:
321 * We set the max age at mount time. (But each
322 * successful server lookup renews the timestamp.)
324 val
= NCP_TEST_AGE(server
, dentry
);
328 DDPRINTK("ncp_lookup_validate: %s/%s not valid, age=%ld, server lookup\n",
329 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
,
330 NCP_GET_AGE(dentry
));
332 len
= sizeof(__name
);
333 if (ncp_is_server_root(dir
)) {
334 res
= ncp_io2vol(server
, __name
, &len
, dentry
->d_name
.name
,
335 dentry
->d_name
.len
, 1);
337 res
= ncp_lookup_volume(server
, __name
, &(finfo
.i
));
339 ncp_update_known_namespace(server
, finfo
.i
.volNumber
, NULL
);
342 res
= ncp_io2vol(server
, __name
, &len
, dentry
->d_name
.name
,
343 dentry
->d_name
.len
, !ncp_preserve_case(dir
));
345 res
= ncp_obtain_info(server
, dir
, __name
, &(finfo
.i
));
347 finfo
.volume
= finfo
.i
.volNumber
;
348 DDPRINTK("ncp_lookup_validate: looked for %s/%s, res=%d\n",
349 dentry
->d_parent
->d_name
.name
, __name
, res
);
351 * If we didn't find it, or if it has a different dirEntNum to
352 * what we remember, it's not valid any more.
355 struct inode
*inode
= dentry
->d_inode
;
357 mutex_lock(&inode
->i_mutex
);
358 if (finfo
.i
.dirEntNum
== NCP_FINFO(inode
)->dirEntNum
) {
359 ncp_new_dentry(dentry
);
362 DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");
364 ncp_update_inode2(inode
, &finfo
);
365 mutex_unlock(&inode
->i_mutex
);
369 DDPRINTK("ncp_lookup_validate: result=%d\n", val
);
374 static struct dentry
*
375 ncp_dget_fpos(struct dentry
*dentry
, struct dentry
*parent
, unsigned long fpos
)
377 struct dentry
*dent
= dentry
;
378 struct list_head
*next
;
380 if (d_validate(dent
, parent
)) {
381 if (dent
->d_name
.len
<= NCP_MAXPATHLEN
&&
382 (unsigned long)dent
->d_fsdata
== fpos
) {
383 if (!dent
->d_inode
) {
392 /* If a pointer is invalid, we search the dentry. */
393 spin_lock(&parent
->d_lock
);
394 next
= parent
->d_subdirs
.next
;
395 while (next
!= &parent
->d_subdirs
) {
396 dent
= list_entry(next
, struct dentry
, d_u
.d_child
);
397 if ((unsigned long)dent
->d_fsdata
== fpos
) {
402 spin_unlock(&parent
->d_lock
);
407 spin_unlock(&parent
->d_lock
);
414 static time_t ncp_obtain_mtime(struct dentry
*dentry
)
416 struct inode
*inode
= dentry
->d_inode
;
417 struct ncp_server
*server
= NCP_SERVER(inode
);
418 struct nw_info_struct i
;
420 if (!ncp_conn_valid(server
) || ncp_is_server_root(inode
))
423 if (ncp_obtain_info(server
, inode
, NULL
, &i
))
426 return ncp_date_dos2unix(i
.modifyTime
, i
.modifyDate
);
429 static int ncp_readdir(struct file
*filp
, void *dirent
, filldir_t filldir
)
431 struct dentry
*dentry
= filp
->f_path
.dentry
;
432 struct inode
*inode
= dentry
->d_inode
;
433 struct page
*page
= NULL
;
434 struct ncp_server
*server
= NCP_SERVER(inode
);
435 union ncp_dir_cache
*cache
= NULL
;
436 struct ncp_cache_control ctl
;
437 int result
, mtime_valid
= 0;
443 DDPRINTK("ncp_readdir: reading %s/%s, pos=%d\n",
444 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
,
448 /* Do not generate '.' and '..' when server is dead. */
449 if (!ncp_conn_valid(server
))
453 if (filp
->f_pos
== 0) {
454 if (filldir(dirent
, ".", 1, 0, inode
->i_ino
, DT_DIR
))
458 if (filp
->f_pos
== 1) {
459 if (filldir(dirent
, "..", 2, 1, parent_ino(dentry
), DT_DIR
))
464 page
= grab_cache_page(&inode
->i_data
, 0);
468 ctl
.cache
= cache
= kmap(page
);
469 ctl
.head
= cache
->head
;
471 if (!PageUptodate(page
) || !ctl
.head
.eof
)
474 if (filp
->f_pos
== 2) {
475 if (jiffies
- ctl
.head
.time
>= NCP_MAX_AGE(server
))
478 mtime
= ncp_obtain_mtime(dentry
);
480 if ((!mtime
) || (mtime
!= ctl
.head
.mtime
))
484 if (filp
->f_pos
> ctl
.head
.end
)
487 ctl
.fpos
= filp
->f_pos
+ (NCP_DIRCACHE_START
- 2);
488 ctl
.ofs
= ctl
.fpos
/ NCP_DIRCACHE_SIZE
;
489 ctl
.idx
= ctl
.fpos
% NCP_DIRCACHE_SIZE
;
493 ctl
.page
= find_lock_page(&inode
->i_data
, ctl
.ofs
);
496 ctl
.cache
= kmap(ctl
.page
);
497 if (!PageUptodate(ctl
.page
))
500 while (ctl
.idx
< NCP_DIRCACHE_SIZE
) {
504 dent
= ncp_dget_fpos(ctl
.cache
->dentry
[ctl
.idx
],
505 dentry
, filp
->f_pos
);
508 res
= filldir(dirent
, dent
->d_name
.name
,
509 dent
->d_name
.len
, filp
->f_pos
,
510 dent
->d_inode
->i_ino
, DT_UNKNOWN
);
516 if (filp
->f_pos
> ctl
.head
.end
)
521 SetPageUptodate(ctl
.page
);
522 unlock_page(ctl
.page
);
523 page_cache_release(ctl
.page
);
532 unlock_page(ctl
.page
);
533 page_cache_release(ctl
.page
);
538 ncp_invalidate_dircache_entries(dentry
);
540 mtime
= ncp_obtain_mtime(dentry
);
543 ctl
.head
.mtime
= mtime
;
544 ctl
.head
.time
= jiffies
;
548 ctl
.idx
= NCP_DIRCACHE_START
;
552 if (ncp_is_server_root(inode
)) {
553 ncp_read_volume_list(filp
, dirent
, filldir
, &ctl
);
555 ncp_do_readdir(filp
, dirent
, filldir
, &ctl
);
557 ctl
.head
.end
= ctl
.fpos
- 1;
558 ctl
.head
.eof
= ctl
.valid
;
562 SetPageUptodate(ctl
.page
);
563 unlock_page(ctl
.page
);
564 page_cache_release(ctl
.page
);
567 cache
->head
= ctl
.head
;
569 SetPageUptodate(page
);
571 page_cache_release(page
);
578 ncp_fill_cache(struct file
*filp
, void *dirent
, filldir_t filldir
,
579 struct ncp_cache_control
*ctrl
, struct ncp_entry_info
*entry
,
582 struct dentry
*newdent
, *dentry
= filp
->f_path
.dentry
;
583 struct inode
*dir
= dentry
->d_inode
;
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 */
598 qname
.hash
= full_name_hash(qname
.name
, qname
.len
);
600 if (dentry
->d_op
&& dentry
->d_op
->d_hash
)
601 if (dentry
->d_op
->d_hash(dentry
, dentry
->d_inode
, &qname
) != 0)
604 newdent
= d_lookup(dentry
, &qname
);
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
== filp
->f_pos
)) {
677 ino
= find_inode_number(dentry
, &qname
);
679 ino
= iunique(dir
->i_sb
, 2);
680 ctl
.filled
= filldir(dirent
, qname
.name
, qname
.len
,
681 filp
->f_pos
, ino
, DT_UNKNOWN
);
688 return (ctl
.valid
|| !ctl
.filled
);
692 ncp_read_volume_list(struct file
*filp
, void *dirent
, filldir_t filldir
,
693 struct ncp_cache_control
*ctl
)
695 struct dentry
*dentry
= filp
->f_path
.dentry
;
696 struct inode
*inode
= dentry
->d_inode
;
697 struct ncp_server
*server
= NCP_SERVER(inode
);
698 struct ncp_volume_info info
;
699 struct ncp_entry_info entry
;
702 DPRINTK("ncp_read_volume_list: pos=%ld\n",
703 (unsigned long) filp
->f_pos
);
705 for (i
= 0; i
< NCP_NUMBER_OF_VOLUMES
; i
++) {
708 if (ncp_get_volume_info_with_number(server
, i
, &info
) != 0)
710 if (!strlen(info
.volume_name
))
713 DPRINTK("ncp_read_volume_list: found vol: %s\n",
716 if (ncp_lookup_volume(server
, info
.volume_name
,
718 DPRINTK("ncpfs: could not lookup vol %s\n",
722 inval_dentry
= ncp_update_known_namespace(server
, entry
.i
.volNumber
, NULL
);
723 entry
.volume
= entry
.i
.volNumber
;
724 if (!ncp_fill_cache(filp
, dirent
, filldir
, ctl
, &entry
, inval_dentry
))
730 ncp_do_readdir(struct file
*filp
, void *dirent
, filldir_t filldir
,
731 struct ncp_cache_control
*ctl
)
733 struct dentry
*dentry
= filp
->f_path
.dentry
;
734 struct inode
*dir
= dentry
->d_inode
;
735 struct ncp_server
*server
= NCP_SERVER(dir
);
736 struct nw_search_sequence seq
;
737 struct ncp_entry_info entry
;
743 DPRINTK("ncp_do_readdir: %s/%s, fpos=%ld\n",
744 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
,
745 (unsigned long) filp
->f_pos
);
746 PPRINTK("ncp_do_readdir: init %s, volnum=%d, dirent=%u\n",
747 dentry
->d_name
.name
, NCP_FINFO(dir
)->volNumber
,
748 NCP_FINFO(dir
)->dirEntNum
);
750 err
= ncp_initialize_search(server
, dir
, &seq
);
752 DPRINTK("ncp_do_readdir: init failed, err=%d\n", err
);
755 /* We MUST NOT use server->buffer_size handshaked with server if we are
756 using UDP, as for UDP server uses max. buffer size determined by
757 MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes).
758 So we use 128KB, just to be sure, as there is no way how to know
759 this value in advance. */
761 buf
= vmalloc(bufsize
);
769 err
= ncp_search_for_fileset(server
, &seq
, &more
, &cnt
, buf
, bufsize
, &rpl
, &rpls
);
772 if (!cnt
) /* prevent endless loop */
777 if (rpls
< offsetof(struct nw_info_struct
, entryName
))
778 break; /* short packet */
779 ncp_extract_file_info(rpl
, &entry
.i
);
780 onerpl
= offsetof(struct nw_info_struct
, entryName
) + entry
.i
.nameLen
;
782 break; /* short packet */
783 (void)ncp_obtain_nfs_info(server
, &entry
.i
);
786 entry
.volume
= entry
.i
.volNumber
;
787 if (!ncp_fill_cache(filp
, dirent
, filldir
, ctl
, &entry
, 0))
795 int ncp_conn_logged_in(struct super_block
*sb
)
797 struct ncp_server
* server
= NCP_SBP(sb
);
800 if (ncp_single_volume(server
)) {
806 __u8 __name
[NCP_MAXPATHLEN
+ 1];
808 len
= sizeof(__name
);
809 result
= ncp_io2vol(server
, __name
, &len
, server
->m
.mounted_vol
,
810 strlen(server
->m
.mounted_vol
), 1);
814 if (ncp_get_volume_root(server
, __name
, &volNumber
, &dirEntNum
, &DosDirNum
)) {
815 PPRINTK("ncp_conn_logged_in: %s not found\n",
816 server
->m
.mounted_vol
);
821 struct inode
* ino
= dent
->d_inode
;
823 ncp_update_known_namespace(server
, volNumber
, NULL
);
824 NCP_FINFO(ino
)->volNumber
= volNumber
;
825 NCP_FINFO(ino
)->dirEntNum
= dirEntNum
;
826 NCP_FINFO(ino
)->DosDirNum
= DosDirNum
;
829 DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n");
832 DPRINTK("ncpfs: sb->s_root == NULL!\n");
841 static struct dentry
*ncp_lookup(struct inode
*dir
, struct dentry
*dentry
, struct nameidata
*nd
)
843 struct ncp_server
*server
= NCP_SERVER(dir
);
844 struct inode
*inode
= NULL
;
845 struct ncp_entry_info finfo
;
847 __u8 __name
[NCP_MAXPATHLEN
+ 1];
850 if (!ncp_conn_valid(server
))
853 PPRINTK("ncp_lookup: server lookup for %s/%s\n",
854 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
856 len
= sizeof(__name
);
857 if (ncp_is_server_root(dir
)) {
858 res
= ncp_io2vol(server
, __name
, &len
, dentry
->d_name
.name
,
859 dentry
->d_name
.len
, 1);
861 res
= ncp_lookup_volume(server
, __name
, &(finfo
.i
));
863 ncp_update_known_namespace(server
, finfo
.i
.volNumber
, NULL
);
865 res
= ncp_io2vol(server
, __name
, &len
, dentry
->d_name
.name
,
866 dentry
->d_name
.len
, !ncp_preserve_case(dir
));
868 res
= ncp_obtain_info(server
, dir
, __name
, &(finfo
.i
));
870 PPRINTK("ncp_lookup: looked for %s/%s, res=%d\n",
871 dentry
->d_parent
->d_name
.name
, __name
, res
);
873 * If we didn't find an entry, make a negative dentry.
879 * Create an inode for the entry.
882 finfo
.ino
= iunique(dir
->i_sb
, 2);
883 finfo
.volume
= finfo
.i
.volNumber
;
885 inode
= ncp_iget(dir
->i_sb
, &finfo
);
888 ncp_new_dentry(dentry
);
890 d_add(dentry
, inode
);
895 PPRINTK("ncp_lookup: result=%d\n", error
);
896 return ERR_PTR(error
);
900 * This code is common to create, mkdir, and mknod.
902 static int ncp_instantiate(struct inode
*dir
, struct dentry
*dentry
,
903 struct ncp_entry_info
*finfo
)
908 finfo
->ino
= iunique(dir
->i_sb
, 2);
909 inode
= ncp_iget(dir
->i_sb
, finfo
);
912 d_instantiate(dentry
,inode
);
918 PPRINTK("ncp_instantiate: %s/%s failed, closing file\n",
919 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
920 ncp_close_file(NCP_SERVER(dir
), finfo
->file_handle
);
924 int ncp_create_new(struct inode
*dir
, struct dentry
*dentry
, int mode
,
925 dev_t rdev
, __le32 attributes
)
927 struct ncp_server
*server
= NCP_SERVER(dir
);
928 struct ncp_entry_info finfo
;
929 int error
, result
, len
;
931 __u8 __name
[NCP_MAXPATHLEN
+ 1];
933 PPRINTK("ncp_create_new: creating %s/%s, mode=%x\n",
934 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
, mode
);
936 ncp_age_dentry(server
, dentry
);
937 len
= sizeof(__name
);
938 error
= ncp_io2vol(server
, __name
, &len
, dentry
->d_name
.name
,
939 dentry
->d_name
.len
, !ncp_preserve_case(dir
));
946 (server
->m
.flags
& NCP_MOUNT_EXTRAS
) &&
948 attributes
|= aSYSTEM
| aSHARED
;
950 result
= ncp_open_create_file_or_subdir(server
, dir
, __name
,
951 OC_MODE_CREATE
| OC_MODE_OPEN
| OC_MODE_REPLACE
,
952 attributes
, AR_READ
| AR_WRITE
, &finfo
);
955 result
= ncp_open_create_file_or_subdir(server
, dir
, __name
,
956 OC_MODE_CREATE
| OC_MODE_OPEN
| OC_MODE_REPLACE
,
957 attributes
, AR_WRITE
, &finfo
);
960 error
= -ENAMETOOLONG
;
963 DPRINTK("ncp_create: %s/%s failed\n",
964 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
969 finfo
.access
= opmode
;
970 if (ncp_is_nfs_extras(server
, finfo
.volume
)) {
971 finfo
.i
.nfs
.mode
= mode
;
972 finfo
.i
.nfs
.rdev
= new_encode_dev(rdev
);
973 if (ncp_modify_nfs_info(server
, finfo
.volume
,
975 mode
, new_encode_dev(rdev
)) != 0)
979 error
= ncp_instantiate(dir
, dentry
, &finfo
);
984 static int ncp_create(struct inode
*dir
, struct dentry
*dentry
, int mode
,
985 struct nameidata
*nd
)
987 return ncp_create_new(dir
, dentry
, mode
, 0, 0);
990 static int ncp_mkdir(struct inode
*dir
, struct dentry
*dentry
, int mode
)
992 struct ncp_entry_info finfo
;
993 struct ncp_server
*server
= NCP_SERVER(dir
);
995 __u8 __name
[NCP_MAXPATHLEN
+ 1];
997 DPRINTK("ncp_mkdir: making %s/%s\n",
998 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
1000 ncp_age_dentry(server
, dentry
);
1001 len
= sizeof(__name
);
1002 error
= ncp_io2vol(server
, __name
, &len
, dentry
->d_name
.name
,
1003 dentry
->d_name
.len
, !ncp_preserve_case(dir
));
1007 error
= ncp_open_create_file_or_subdir(server
, dir
, __name
,
1008 OC_MODE_CREATE
, aDIR
,
1009 cpu_to_le16(0xffff),
1012 if (ncp_is_nfs_extras(server
, finfo
.volume
)) {
1014 finfo
.i
.nfs
.mode
= mode
;
1015 if (ncp_modify_nfs_info(server
,
1021 error
= ncp_instantiate(dir
, dentry
, &finfo
);
1022 } else if (error
> 0) {
1029 static int ncp_rmdir(struct inode
*dir
, struct dentry
*dentry
)
1031 struct ncp_server
*server
= NCP_SERVER(dir
);
1032 int error
, result
, len
;
1033 __u8 __name
[NCP_MAXPATHLEN
+ 1];
1035 DPRINTK("ncp_rmdir: removing %s/%s\n",
1036 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
1039 if (!d_unhashed(dentry
))
1042 len
= sizeof(__name
);
1043 error
= ncp_io2vol(server
, __name
, &len
, dentry
->d_name
.name
,
1044 dentry
->d_name
.len
, !ncp_preserve_case(dir
));
1048 result
= ncp_del_file_or_subdir(server
, dir
, __name
);
1053 case 0x85: /* unauthorized to delete file */
1054 case 0x8A: /* unauthorized to delete file */
1058 case 0x90: /* read only */
1061 case 0x9F: /* in use by another client */
1064 case 0xA0: /* directory not empty */
1067 case 0xFF: /* someone deleted file */
1071 error
= result
< 0 ? result
: -EACCES
;
1078 static int ncp_unlink(struct inode
*dir
, struct dentry
*dentry
)
1080 struct inode
*inode
= dentry
->d_inode
;
1081 struct ncp_server
*server
;
1084 server
= NCP_SERVER(dir
);
1085 DPRINTK("ncp_unlink: unlinking %s/%s\n",
1086 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
1089 * Check whether to close the file ...
1092 PPRINTK("ncp_unlink: closing file\n");
1093 ncp_make_closed(inode
);
1096 error
= ncp_del_file_or_subdir2(server
, dentry
);
1097 #ifdef CONFIG_NCPFS_STRONG
1098 /* 9C is Invalid path.. It should be 8F, 90 - read only, but
1100 if ((error
== 0x9C || error
== 0x90) && server
->m
.flags
& NCP_MOUNT_STRONG
) { /* R/O */
1101 error
= ncp_force_unlink(dir
, dentry
);
1106 DPRINTK("ncp: removed %s/%s\n",
1107 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
1113 case 0x8D: /* some files in use */
1114 case 0x8E: /* all files in use */
1117 case 0x8F: /* some read only */
1118 case 0x90: /* all read only */
1119 case 0x9C: /* !!! returned when in-use or read-only by NW4 */
1126 error
= error
< 0 ? error
: -EACCES
;
1132 static int ncp_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
1133 struct inode
*new_dir
, struct dentry
*new_dentry
)
1135 struct ncp_server
*server
= NCP_SERVER(old_dir
);
1137 int old_len
, new_len
;
1138 __u8 __old_name
[NCP_MAXPATHLEN
+ 1], __new_name
[NCP_MAXPATHLEN
+ 1];
1140 DPRINTK("ncp_rename: %s/%s to %s/%s\n",
1141 old_dentry
->d_parent
->d_name
.name
, old_dentry
->d_name
.name
,
1142 new_dentry
->d_parent
->d_name
.name
, new_dentry
->d_name
.name
);
1144 ncp_age_dentry(server
, old_dentry
);
1145 ncp_age_dentry(server
, new_dentry
);
1147 old_len
= sizeof(__old_name
);
1148 error
= ncp_io2vol(server
, __old_name
, &old_len
,
1149 old_dentry
->d_name
.name
, old_dentry
->d_name
.len
,
1150 !ncp_preserve_case(old_dir
));
1154 new_len
= sizeof(__new_name
);
1155 error
= ncp_io2vol(server
, __new_name
, &new_len
,
1156 new_dentry
->d_name
.name
, new_dentry
->d_name
.len
,
1157 !ncp_preserve_case(new_dir
));
1161 error
= ncp_ren_or_mov_file_or_subdir(server
, old_dir
, __old_name
,
1162 new_dir
, __new_name
);
1163 #ifdef CONFIG_NCPFS_STRONG
1164 if ((error
== 0x90 || error
== 0x8B || error
== -EACCES
) &&
1165 server
->m
.flags
& NCP_MOUNT_STRONG
) { /* RO */
1166 error
= ncp_force_rename(old_dir
, old_dentry
, __old_name
,
1167 new_dir
, new_dentry
, __new_name
);
1172 DPRINTK("ncp renamed %s -> %s.\n",
1173 old_dentry
->d_name
.name
,new_dentry
->d_name
.name
);
1176 error
= -ENAMETOOLONG
;
1182 error
= error
< 0 ? error
: -EACCES
;
1189 static int ncp_mknod(struct inode
* dir
, struct dentry
*dentry
,
1190 int mode
, dev_t rdev
)
1192 if (!new_valid_dev(rdev
))
1194 if (ncp_is_nfs_extras(NCP_SERVER(dir
), NCP_FINFO(dir
)->volNumber
)) {
1195 DPRINTK(KERN_DEBUG
"ncp_mknod: mode = 0%o\n", mode
);
1196 return ncp_create_new(dir
, dentry
, mode
, rdev
, 0);
1198 return -EPERM
; /* Strange, but true */
1201 /* The following routines are taken directly from msdos-fs */
1203 /* Linear day numbers of the respective 1sts in non-leap years. */
1205 static int day_n
[] =
1206 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
1207 /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
1210 extern struct timezone sys_tz
;
1212 static int utc2local(int time
)
1214 return time
- sys_tz
.tz_minuteswest
* 60;
1217 static int local2utc(int time
)
1219 return time
+ sys_tz
.tz_minuteswest
* 60;
1222 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
1224 ncp_date_dos2unix(__le16 t
, __le16 d
)
1226 unsigned short time
= le16_to_cpu(t
), date
= le16_to_cpu(d
);
1227 int month
, year
, secs
;
1229 /* first subtract and mask after that... Otherwise, if
1230 date == 0, bad things happen */
1231 month
= ((date
>> 5) - 1) & 15;
1233 secs
= (time
& 31) * 2 + 60 * ((time
>> 5) & 63) + (time
>> 11) * 3600 +
1234 86400 * ((date
& 31) - 1 + day_n
[month
] + (year
/ 4) +
1235 year
* 365 - ((year
& 3) == 0 && month
< 2 ? 1 : 0) + 3653);
1236 /* days since 1.1.70 plus 80's leap day */
1237 return local2utc(secs
);
1241 /* Convert linear UNIX date to a MS-DOS time/date pair. */
1243 ncp_date_unix2dos(int unix_date
, __le16
*time
, __le16
*date
)
1245 int day
, year
, nl_day
, month
;
1247 unix_date
= utc2local(unix_date
);
1248 *time
= cpu_to_le16(
1249 (unix_date
% 60) / 2 + (((unix_date
/ 60) % 60) << 5) +
1250 (((unix_date
/ 3600) % 24) << 11));
1251 day
= unix_date
/ 86400 - 3652;
1253 if ((year
+ 3) / 4 + 365 * year
> day
)
1255 day
-= (year
+ 3) / 4 + 365 * year
;
1256 if (day
== 59 && !(year
& 3)) {
1260 nl_day
= (year
& 3) || day
<= 59 ? day
: day
- 1;
1261 for (month
= 1; month
< 12; month
++)
1262 if (day_n
[month
] > nl_day
)
1265 *date
= cpu_to_le16(nl_day
- day_n
[month
- 1] + 1 + (month
<< 5) + (year
<< 9));