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
*, void *, filldir_t
,
27 struct ncp_cache_control
*);
28 static void ncp_do_readdir(struct file
*, void *, filldir_t
,
29 struct ncp_cache_control
*);
31 static int ncp_readdir(struct file
*, void *, filldir_t
);
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 .readdir
= 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
*, const struct inode
*,
78 static int ncp_compare_dentry(const struct dentry
*, const struct inode
*,
79 const struct dentry
*, const struct inode
*,
80 unsigned int, const char *, const struct qstr
*);
81 static int ncp_delete_dentry(const struct 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
,
91 #define ncp_namespace(i) (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber])
93 static inline int ncp_preserve_entry_case(struct inode
*i
, __u32 nscreator
)
95 #ifdef CONFIG_NCPFS_SMALLDOS
96 int ns
= ncp_namespace(i
);
99 #ifdef CONFIG_NCPFS_OS2_NS
100 || ((ns
== NW_NS_OS2
) && (nscreator
== NW_NS_DOS
))
101 #endif /* CONFIG_NCPFS_OS2_NS */
104 #endif /* CONFIG_NCPFS_SMALLDOS */
108 #define ncp_preserve_case(i) (ncp_namespace(i) != NW_NS_DOS)
110 static inline int ncp_case_sensitive(const struct inode
*i
)
112 #ifdef CONFIG_NCPFS_NFS_NS
113 return ncp_namespace(i
) == NW_NS_NFS
;
116 #endif /* CONFIG_NCPFS_NFS_NS */
120 * Note: leave the hash unchanged if the directory
124 ncp_hash_dentry(const struct dentry
*dentry
, const struct inode
*inode
,
127 if (!ncp_case_sensitive(inode
)) {
128 struct super_block
*sb
= dentry
->d_sb
;
133 t
= NCP_IO_TABLE(sb
);
134 hash
= init_name_hash();
135 for (i
=0; i
<this->len
; i
++)
136 hash
= partial_name_hash(ncp_tolower(t
, this->name
[i
]),
138 this->hash
= end_name_hash(hash
);
144 ncp_compare_dentry(const struct dentry
*parent
, const struct inode
*pinode
,
145 const struct dentry
*dentry
, const struct inode
*inode
,
146 unsigned int len
, const char *str
, const struct qstr
*name
)
148 if (len
!= name
->len
)
151 if (ncp_case_sensitive(pinode
))
152 return strncmp(str
, name
->name
, len
);
154 return ncp_strnicmp(NCP_IO_TABLE(pinode
->i_sb
), str
, name
->name
, len
);
158 * This is the callback from dput() when d_count is going to 0.
159 * We use this to unhash dentries with bad inodes.
160 * Closing files can be safely postponed until iput() - it's done there anyway.
163 ncp_delete_dentry(const struct dentry
* dentry
)
165 struct inode
*inode
= dentry
->d_inode
;
168 if (is_bad_inode(inode
))
172 /* N.B. Unhash negative dentries? */
178 ncp_single_volume(struct ncp_server
*server
)
180 return (server
->m
.mounted_vol
[0] != '\0');
183 static inline int ncp_is_server_root(struct inode
*inode
)
185 return (!ncp_single_volume(NCP_SERVER(inode
)) &&
186 inode
== inode
->i_sb
->s_root
->d_inode
);
191 * This is the callback when the dcache has a lookup hit.
195 #ifdef CONFIG_NCPFS_STRONG
196 /* try to delete a readonly file (NW R bit set) */
199 ncp_force_unlink(struct inode
*dir
, struct dentry
* dentry
)
202 struct nw_modify_dos_info info
;
206 memset(&info
, 0, sizeof(info
));
208 /* remove the Read-Only flag on the NW server */
209 inode
= dentry
->d_inode
;
211 old_nwattr
= NCP_FINFO(inode
)->nwattr
;
212 info
.attributes
= old_nwattr
& ~(aRONLY
|aDELETEINHIBIT
|aRENAMEINHIBIT
);
213 res2
= ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode
), inode
, NULL
, DM_ATTRIBUTES
, &info
);
217 /* now try again the delete operation */
218 res
= ncp_del_file_or_subdir2(NCP_SERVER(dir
), dentry
);
220 if (res
) /* delete failed, set R bit again */
222 info
.attributes
= old_nwattr
;
223 res2
= ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode
), inode
, NULL
, DM_ATTRIBUTES
, &info
);
230 #endif /* CONFIG_NCPFS_STRONG */
232 #ifdef CONFIG_NCPFS_STRONG
234 ncp_force_rename(struct inode
*old_dir
, struct dentry
* old_dentry
, char *_old_name
,
235 struct inode
*new_dir
, struct dentry
* new_dentry
, char *_new_name
)
237 struct nw_modify_dos_info info
;
239 struct inode
*old_inode
= old_dentry
->d_inode
;
240 __le32 old_nwattr
= NCP_FINFO(old_inode
)->nwattr
;
241 __le32 new_nwattr
= 0; /* shut compiler warning */
242 int old_nwattr_changed
= 0;
243 int new_nwattr_changed
= 0;
245 memset(&info
, 0, sizeof(info
));
247 /* remove the Read-Only flag on the NW server */
249 info
.attributes
= old_nwattr
& ~(aRONLY
|aRENAMEINHIBIT
|aDELETEINHIBIT
);
250 res2
= ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode
), old_inode
, NULL
, DM_ATTRIBUTES
, &info
);
252 old_nwattr_changed
= 1;
253 if (new_dentry
&& new_dentry
->d_inode
) {
254 new_nwattr
= NCP_FINFO(new_dentry
->d_inode
)->nwattr
;
255 info
.attributes
= new_nwattr
& ~(aRONLY
|aRENAMEINHIBIT
|aDELETEINHIBIT
);
256 res2
= ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir
), new_dir
, _new_name
, DM_ATTRIBUTES
, &info
);
258 new_nwattr_changed
= 1;
260 /* now try again the rename operation */
261 /* but only if something really happened */
262 if (new_nwattr_changed
|| old_nwattr_changed
) {
263 res
= ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir
),
269 /* file was successfully renamed, so:
270 do not set attributes on old file - it no longer exists
271 copy attributes from old file to new */
272 new_nwattr_changed
= old_nwattr_changed
;
273 new_nwattr
= old_nwattr
;
274 old_nwattr_changed
= 0;
277 if (old_nwattr_changed
) {
278 info
.attributes
= old_nwattr
;
279 res2
= ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode
), old_inode
, NULL
, DM_ATTRIBUTES
, &info
);
282 if (new_nwattr_changed
) {
283 info
.attributes
= new_nwattr
;
284 res2
= ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir
), new_dir
, _new_name
, DM_ATTRIBUTES
, &info
);
289 #endif /* CONFIG_NCPFS_STRONG */
293 ncp_lookup_validate(struct dentry
*dentry
, unsigned int flags
)
295 struct ncp_server
*server
;
296 struct dentry
*parent
;
298 struct ncp_entry_info finfo
;
299 int res
, val
= 0, len
;
300 __u8 __name
[NCP_MAXPATHLEN
+ 1];
302 if (dentry
== dentry
->d_sb
->s_root
)
305 if (flags
& LOOKUP_RCU
)
308 parent
= dget_parent(dentry
);
309 dir
= parent
->d_inode
;
311 if (!dentry
->d_inode
)
314 server
= NCP_SERVER(dir
);
318 * The default validation is based on dentry age:
319 * We set the max age at mount time. (But each
320 * successful server lookup renews the timestamp.)
322 val
= NCP_TEST_AGE(server
, dentry
);
326 DDPRINTK("ncp_lookup_validate: %s/%s not valid, age=%ld, server lookup\n",
327 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
,
328 NCP_GET_AGE(dentry
));
330 len
= sizeof(__name
);
331 if (ncp_is_server_root(dir
)) {
332 res
= ncp_io2vol(server
, __name
, &len
, dentry
->d_name
.name
,
333 dentry
->d_name
.len
, 1);
335 res
= ncp_lookup_volume(server
, __name
, &(finfo
.i
));
337 ncp_update_known_namespace(server
, finfo
.i
.volNumber
, NULL
);
340 res
= ncp_io2vol(server
, __name
, &len
, dentry
->d_name
.name
,
341 dentry
->d_name
.len
, !ncp_preserve_case(dir
));
343 res
= ncp_obtain_info(server
, dir
, __name
, &(finfo
.i
));
345 finfo
.volume
= finfo
.i
.volNumber
;
346 DDPRINTK("ncp_lookup_validate: looked for %s/%s, res=%d\n",
347 dentry
->d_parent
->d_name
.name
, __name
, res
);
349 * If we didn't find it, or if it has a different dirEntNum to
350 * what we remember, it's not valid any more.
353 struct inode
*inode
= dentry
->d_inode
;
355 mutex_lock(&inode
->i_mutex
);
356 if (finfo
.i
.dirEntNum
== NCP_FINFO(inode
)->dirEntNum
) {
357 ncp_new_dentry(dentry
);
360 DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");
362 ncp_update_inode2(inode
, &finfo
);
363 mutex_unlock(&inode
->i_mutex
);
367 DDPRINTK("ncp_lookup_validate: result=%d\n", val
);
372 static struct dentry
*
373 ncp_dget_fpos(struct dentry
*dentry
, struct dentry
*parent
, unsigned long fpos
)
375 struct dentry
*dent
= dentry
;
376 struct list_head
*next
;
378 if (d_validate(dent
, parent
)) {
379 if (dent
->d_name
.len
<= NCP_MAXPATHLEN
&&
380 (unsigned long)dent
->d_fsdata
== fpos
) {
381 if (!dent
->d_inode
) {
390 /* If a pointer is invalid, we search the dentry. */
391 spin_lock(&parent
->d_lock
);
392 next
= parent
->d_subdirs
.next
;
393 while (next
!= &parent
->d_subdirs
) {
394 dent
= list_entry(next
, struct dentry
, d_u
.d_child
);
395 if ((unsigned long)dent
->d_fsdata
== fpos
) {
400 spin_unlock(&parent
->d_lock
);
405 spin_unlock(&parent
->d_lock
);
412 static time_t ncp_obtain_mtime(struct dentry
*dentry
)
414 struct inode
*inode
= dentry
->d_inode
;
415 struct ncp_server
*server
= NCP_SERVER(inode
);
416 struct nw_info_struct i
;
418 if (!ncp_conn_valid(server
) || ncp_is_server_root(inode
))
421 if (ncp_obtain_info(server
, inode
, NULL
, &i
))
424 return ncp_date_dos2unix(i
.modifyTime
, i
.modifyDate
);
427 static int ncp_readdir(struct file
*filp
, void *dirent
, filldir_t filldir
)
429 struct dentry
*dentry
= filp
->f_path
.dentry
;
430 struct inode
*inode
= dentry
->d_inode
;
431 struct page
*page
= NULL
;
432 struct ncp_server
*server
= NCP_SERVER(inode
);
433 union ncp_dir_cache
*cache
= NULL
;
434 struct ncp_cache_control ctl
;
435 int result
, mtime_valid
= 0;
441 DDPRINTK("ncp_readdir: reading %s/%s, pos=%d\n",
442 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
,
446 /* Do not generate '.' and '..' when server is dead. */
447 if (!ncp_conn_valid(server
))
451 if (filp
->f_pos
== 0) {
452 if (filldir(dirent
, ".", 1, 0, inode
->i_ino
, DT_DIR
))
456 if (filp
->f_pos
== 1) {
457 if (filldir(dirent
, "..", 2, 1, parent_ino(dentry
), DT_DIR
))
462 page
= grab_cache_page(&inode
->i_data
, 0);
466 ctl
.cache
= cache
= kmap(page
);
467 ctl
.head
= cache
->head
;
469 if (!PageUptodate(page
) || !ctl
.head
.eof
)
472 if (filp
->f_pos
== 2) {
473 if (jiffies
- ctl
.head
.time
>= NCP_MAX_AGE(server
))
476 mtime
= ncp_obtain_mtime(dentry
);
478 if ((!mtime
) || (mtime
!= ctl
.head
.mtime
))
482 if (filp
->f_pos
> ctl
.head
.end
)
485 ctl
.fpos
= filp
->f_pos
+ (NCP_DIRCACHE_START
- 2);
486 ctl
.ofs
= ctl
.fpos
/ NCP_DIRCACHE_SIZE
;
487 ctl
.idx
= ctl
.fpos
% NCP_DIRCACHE_SIZE
;
491 ctl
.page
= find_lock_page(&inode
->i_data
, ctl
.ofs
);
494 ctl
.cache
= kmap(ctl
.page
);
495 if (!PageUptodate(ctl
.page
))
498 while (ctl
.idx
< NCP_DIRCACHE_SIZE
) {
502 dent
= ncp_dget_fpos(ctl
.cache
->dentry
[ctl
.idx
],
503 dentry
, filp
->f_pos
);
506 res
= filldir(dirent
, dent
->d_name
.name
,
507 dent
->d_name
.len
, filp
->f_pos
,
508 dent
->d_inode
->i_ino
, DT_UNKNOWN
);
514 if (filp
->f_pos
> ctl
.head
.end
)
519 SetPageUptodate(ctl
.page
);
520 unlock_page(ctl
.page
);
521 page_cache_release(ctl
.page
);
530 unlock_page(ctl
.page
);
531 page_cache_release(ctl
.page
);
536 ncp_invalidate_dircache_entries(dentry
);
538 mtime
= ncp_obtain_mtime(dentry
);
541 ctl
.head
.mtime
= mtime
;
542 ctl
.head
.time
= jiffies
;
546 ctl
.idx
= NCP_DIRCACHE_START
;
550 if (ncp_is_server_root(inode
)) {
551 ncp_read_volume_list(filp
, dirent
, filldir
, &ctl
);
553 ncp_do_readdir(filp
, dirent
, filldir
, &ctl
);
555 ctl
.head
.end
= ctl
.fpos
- 1;
556 ctl
.head
.eof
= ctl
.valid
;
560 SetPageUptodate(ctl
.page
);
561 unlock_page(ctl
.page
);
562 page_cache_release(ctl
.page
);
565 cache
->head
= ctl
.head
;
567 SetPageUptodate(page
);
569 page_cache_release(page
);
576 ncp_fill_cache(struct file
*filp
, void *dirent
, filldir_t filldir
,
577 struct ncp_cache_control
*ctrl
, struct ncp_entry_info
*entry
,
580 struct dentry
*newdent
, *dentry
= filp
->f_path
.dentry
;
581 struct inode
*dir
= dentry
->d_inode
;
582 struct ncp_cache_control ctl
= *ctrl
;
587 __u8 __name
[NCP_MAXPATHLEN
+ 1];
589 qname
.len
= sizeof(__name
);
590 if (ncp_vol2io(NCP_SERVER(dir
), __name
, &qname
.len
,
591 entry
->i
.entryName
, entry
->i
.nameLen
,
592 !ncp_preserve_entry_case(dir
, entry
->i
.NSCreator
)))
593 return 1; /* I'm not sure */
597 newdent
= d_hash_and_lookup(dentry
, &qname
);
598 if (unlikely(IS_ERR(newdent
)))
601 newdent
= d_alloc(dentry
, &qname
);
607 /* If case sensitivity changed for this volume, all entries below this one
608 should be thrown away. This entry itself is not affected, as its case
609 sensitivity is controlled by its own parent. */
611 shrink_dcache_parent(newdent
);
614 * NetWare's OS2 namespace is case preserving yet case
615 * insensitive. So we update dentry's name as received from
616 * server. Parent dir's i_mutex is locked because we're in
619 dentry_update_name_case(newdent
, &qname
);
622 if (!newdent
->d_inode
) {
626 entry
->ino
= iunique(dir
->i_sb
, 2);
627 inode
= ncp_iget(dir
->i_sb
, entry
);
629 d_instantiate(newdent
, inode
);
634 struct inode
*inode
= newdent
->d_inode
;
636 mutex_lock_nested(&inode
->i_mutex
, I_MUTEX_CHILD
);
637 ncp_update_inode2(inode
, entry
);
638 mutex_unlock(&inode
->i_mutex
);
641 if (newdent
->d_inode
) {
642 ino
= newdent
->d_inode
->i_ino
;
643 newdent
->d_fsdata
= (void *) ctl
.fpos
;
644 ncp_new_dentry(newdent
);
647 if (ctl
.idx
>= NCP_DIRCACHE_SIZE
) {
650 SetPageUptodate(ctl
.page
);
651 unlock_page(ctl
.page
);
652 page_cache_release(ctl
.page
);
655 ctl
.idx
-= NCP_DIRCACHE_SIZE
;
657 ctl
.page
= grab_cache_page(&dir
->i_data
, ctl
.ofs
);
659 ctl
.cache
= kmap(ctl
.page
);
662 ctl
.cache
->dentry
[ctl
.idx
] = newdent
;
669 if (!ctl
.filled
&& (ctl
.fpos
== filp
->f_pos
)) {
671 ino
= find_inode_number(dentry
, &qname
);
673 ino
= iunique(dir
->i_sb
, 2);
674 ctl
.filled
= filldir(dirent
, qname
.name
, qname
.len
,
675 filp
->f_pos
, ino
, DT_UNKNOWN
);
682 return (ctl
.valid
|| !ctl
.filled
);
686 ncp_read_volume_list(struct file
*filp
, void *dirent
, filldir_t filldir
,
687 struct ncp_cache_control
*ctl
)
689 struct dentry
*dentry
= filp
->f_path
.dentry
;
690 struct inode
*inode
= dentry
->d_inode
;
691 struct ncp_server
*server
= NCP_SERVER(inode
);
692 struct ncp_volume_info info
;
693 struct ncp_entry_info entry
;
696 DPRINTK("ncp_read_volume_list: pos=%ld\n",
697 (unsigned long) filp
->f_pos
);
699 for (i
= 0; i
< NCP_NUMBER_OF_VOLUMES
; i
++) {
702 if (ncp_get_volume_info_with_number(server
, i
, &info
) != 0)
704 if (!strlen(info
.volume_name
))
707 DPRINTK("ncp_read_volume_list: found vol: %s\n",
710 if (ncp_lookup_volume(server
, info
.volume_name
,
712 DPRINTK("ncpfs: could not lookup vol %s\n",
716 inval_dentry
= ncp_update_known_namespace(server
, entry
.i
.volNumber
, NULL
);
717 entry
.volume
= entry
.i
.volNumber
;
718 if (!ncp_fill_cache(filp
, dirent
, filldir
, ctl
, &entry
, inval_dentry
))
724 ncp_do_readdir(struct file
*filp
, void *dirent
, filldir_t filldir
,
725 struct ncp_cache_control
*ctl
)
727 struct dentry
*dentry
= filp
->f_path
.dentry
;
728 struct inode
*dir
= dentry
->d_inode
;
729 struct ncp_server
*server
= NCP_SERVER(dir
);
730 struct nw_search_sequence seq
;
731 struct ncp_entry_info entry
;
737 DPRINTK("ncp_do_readdir: %s/%s, fpos=%ld\n",
738 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
,
739 (unsigned long) filp
->f_pos
);
740 PPRINTK("ncp_do_readdir: init %s, volnum=%d, dirent=%u\n",
741 dentry
->d_name
.name
, NCP_FINFO(dir
)->volNumber
,
742 NCP_FINFO(dir
)->dirEntNum
);
744 err
= ncp_initialize_search(server
, dir
, &seq
);
746 DPRINTK("ncp_do_readdir: init failed, err=%d\n", err
);
749 /* We MUST NOT use server->buffer_size handshaked with server if we are
750 using UDP, as for UDP server uses max. buffer size determined by
751 MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes).
752 So we use 128KB, just to be sure, as there is no way how to know
753 this value in advance. */
755 buf
= vmalloc(bufsize
);
763 err
= ncp_search_for_fileset(server
, &seq
, &more
, &cnt
, buf
, bufsize
, &rpl
, &rpls
);
766 if (!cnt
) /* prevent endless loop */
771 if (rpls
< offsetof(struct nw_info_struct
, entryName
))
772 break; /* short packet */
773 ncp_extract_file_info(rpl
, &entry
.i
);
774 onerpl
= offsetof(struct nw_info_struct
, entryName
) + entry
.i
.nameLen
;
776 break; /* short packet */
777 (void)ncp_obtain_nfs_info(server
, &entry
.i
);
780 entry
.volume
= entry
.i
.volNumber
;
781 if (!ncp_fill_cache(filp
, dirent
, filldir
, ctl
, &entry
, 0))
789 int ncp_conn_logged_in(struct super_block
*sb
)
791 struct ncp_server
* server
= NCP_SBP(sb
);
794 if (ncp_single_volume(server
)) {
800 __u8 __name
[NCP_MAXPATHLEN
+ 1];
802 len
= sizeof(__name
);
803 result
= ncp_io2vol(server
, __name
, &len
, server
->m
.mounted_vol
,
804 strlen(server
->m
.mounted_vol
), 1);
808 if (ncp_get_volume_root(server
, __name
, &volNumber
, &dirEntNum
, &DosDirNum
)) {
809 PPRINTK("ncp_conn_logged_in: %s not found\n",
810 server
->m
.mounted_vol
);
815 struct inode
* ino
= dent
->d_inode
;
817 ncp_update_known_namespace(server
, volNumber
, NULL
);
818 NCP_FINFO(ino
)->volNumber
= volNumber
;
819 NCP_FINFO(ino
)->dirEntNum
= dirEntNum
;
820 NCP_FINFO(ino
)->DosDirNum
= DosDirNum
;
823 DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n");
826 DPRINTK("ncpfs: sb->s_root == NULL!\n");
835 static struct dentry
*ncp_lookup(struct inode
*dir
, struct dentry
*dentry
, unsigned int flags
)
837 struct ncp_server
*server
= NCP_SERVER(dir
);
838 struct inode
*inode
= NULL
;
839 struct ncp_entry_info finfo
;
841 __u8 __name
[NCP_MAXPATHLEN
+ 1];
844 if (!ncp_conn_valid(server
))
847 PPRINTK("ncp_lookup: server lookup for %s/%s\n",
848 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
850 len
= sizeof(__name
);
851 if (ncp_is_server_root(dir
)) {
852 res
= ncp_io2vol(server
, __name
, &len
, dentry
->d_name
.name
,
853 dentry
->d_name
.len
, 1);
855 res
= ncp_lookup_volume(server
, __name
, &(finfo
.i
));
857 ncp_update_known_namespace(server
, finfo
.i
.volNumber
, NULL
);
859 res
= ncp_io2vol(server
, __name
, &len
, dentry
->d_name
.name
,
860 dentry
->d_name
.len
, !ncp_preserve_case(dir
));
862 res
= ncp_obtain_info(server
, dir
, __name
, &(finfo
.i
));
864 PPRINTK("ncp_lookup: looked for %s/%s, res=%d\n",
865 dentry
->d_parent
->d_name
.name
, __name
, 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: %s/%s failed, closing file\n",
913 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
914 ncp_close_file(NCP_SERVER(dir
), finfo
->file_handle
);
918 int ncp_create_new(struct inode
*dir
, struct dentry
*dentry
, umode_t mode
,
919 dev_t rdev
, __le32 attributes
)
921 struct ncp_server
*server
= NCP_SERVER(dir
);
922 struct ncp_entry_info finfo
;
923 int error
, result
, len
;
925 __u8 __name
[NCP_MAXPATHLEN
+ 1];
927 PPRINTK("ncp_create_new: creating %s/%s, mode=%hx\n",
928 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
, mode
);
930 ncp_age_dentry(server
, dentry
);
931 len
= sizeof(__name
);
932 error
= ncp_io2vol(server
, __name
, &len
, dentry
->d_name
.name
,
933 dentry
->d_name
.len
, !ncp_preserve_case(dir
));
940 (server
->m
.flags
& NCP_MOUNT_EXTRAS
) &&
942 attributes
|= aSYSTEM
| aSHARED
;
944 result
= ncp_open_create_file_or_subdir(server
, dir
, __name
,
945 OC_MODE_CREATE
| OC_MODE_OPEN
| OC_MODE_REPLACE
,
946 attributes
, AR_READ
| AR_WRITE
, &finfo
);
949 result
= ncp_open_create_file_or_subdir(server
, dir
, __name
,
950 OC_MODE_CREATE
| OC_MODE_OPEN
| OC_MODE_REPLACE
,
951 attributes
, AR_WRITE
, &finfo
);
954 error
= -ENAMETOOLONG
;
957 DPRINTK("ncp_create: %s/%s failed\n",
958 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
963 finfo
.access
= opmode
;
964 if (ncp_is_nfs_extras(server
, finfo
.volume
)) {
965 finfo
.i
.nfs
.mode
= mode
;
966 finfo
.i
.nfs
.rdev
= new_encode_dev(rdev
);
967 if (ncp_modify_nfs_info(server
, finfo
.volume
,
969 mode
, new_encode_dev(rdev
)) != 0)
973 error
= ncp_instantiate(dir
, dentry
, &finfo
);
978 static int ncp_create(struct inode
*dir
, struct dentry
*dentry
, umode_t mode
,
981 return ncp_create_new(dir
, dentry
, mode
, 0, 0);
984 static int ncp_mkdir(struct inode
*dir
, struct dentry
*dentry
, umode_t mode
)
986 struct ncp_entry_info finfo
;
987 struct ncp_server
*server
= NCP_SERVER(dir
);
989 __u8 __name
[NCP_MAXPATHLEN
+ 1];
991 DPRINTK("ncp_mkdir: making %s/%s\n",
992 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
994 ncp_age_dentry(server
, dentry
);
995 len
= sizeof(__name
);
996 error
= ncp_io2vol(server
, __name
, &len
, dentry
->d_name
.name
,
997 dentry
->d_name
.len
, !ncp_preserve_case(dir
));
1001 error
= ncp_open_create_file_or_subdir(server
, dir
, __name
,
1002 OC_MODE_CREATE
, aDIR
,
1003 cpu_to_le16(0xffff),
1006 if (ncp_is_nfs_extras(server
, finfo
.volume
)) {
1008 finfo
.i
.nfs
.mode
= mode
;
1009 if (ncp_modify_nfs_info(server
,
1015 error
= ncp_instantiate(dir
, dentry
, &finfo
);
1016 } else if (error
> 0) {
1023 static int ncp_rmdir(struct inode
*dir
, struct dentry
*dentry
)
1025 struct ncp_server
*server
= NCP_SERVER(dir
);
1026 int error
, result
, len
;
1027 __u8 __name
[NCP_MAXPATHLEN
+ 1];
1029 DPRINTK("ncp_rmdir: removing %s/%s\n",
1030 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
1033 * fail with EBUSY if there are still references to this
1036 dentry_unhash(dentry
);
1038 if (!d_unhashed(dentry
))
1041 len
= sizeof(__name
);
1042 error
= ncp_io2vol(server
, __name
, &len
, dentry
->d_name
.name
,
1043 dentry
->d_name
.len
, !ncp_preserve_case(dir
));
1047 result
= ncp_del_file_or_subdir(server
, dir
, __name
);
1052 case 0x85: /* unauthorized to delete file */
1053 case 0x8A: /* unauthorized to delete file */
1057 case 0x90: /* read only */
1060 case 0x9F: /* in use by another client */
1063 case 0xA0: /* directory not empty */
1066 case 0xFF: /* someone deleted file */
1070 error
= result
< 0 ? result
: -EACCES
;
1077 static int ncp_unlink(struct inode
*dir
, struct dentry
*dentry
)
1079 struct inode
*inode
= dentry
->d_inode
;
1080 struct ncp_server
*server
;
1083 server
= NCP_SERVER(dir
);
1084 DPRINTK("ncp_unlink: unlinking %s/%s\n",
1085 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
1088 * Check whether to close the file ...
1091 PPRINTK("ncp_unlink: closing file\n");
1092 ncp_make_closed(inode
);
1095 error
= ncp_del_file_or_subdir2(server
, dentry
);
1096 #ifdef CONFIG_NCPFS_STRONG
1097 /* 9C is Invalid path.. It should be 8F, 90 - read only, but
1099 if ((error
== 0x9C || error
== 0x90) && server
->m
.flags
& NCP_MOUNT_STRONG
) { /* R/O */
1100 error
= ncp_force_unlink(dir
, dentry
);
1105 DPRINTK("ncp: removed %s/%s\n",
1106 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
1112 case 0x8D: /* some files in use */
1113 case 0x8E: /* all files in use */
1116 case 0x8F: /* some read only */
1117 case 0x90: /* all read only */
1118 case 0x9C: /* !!! returned when in-use or read-only by NW4 */
1125 error
= error
< 0 ? error
: -EACCES
;
1131 static int ncp_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
1132 struct inode
*new_dir
, struct dentry
*new_dentry
)
1134 struct ncp_server
*server
= NCP_SERVER(old_dir
);
1136 int old_len
, new_len
;
1137 __u8 __old_name
[NCP_MAXPATHLEN
+ 1], __new_name
[NCP_MAXPATHLEN
+ 1];
1139 DPRINTK("ncp_rename: %s/%s to %s/%s\n",
1140 old_dentry
->d_parent
->d_name
.name
, old_dentry
->d_name
.name
,
1141 new_dentry
->d_parent
->d_name
.name
, new_dentry
->d_name
.name
);
1143 if (new_dentry
->d_inode
&& S_ISDIR(new_dentry
->d_inode
->i_mode
)) {
1145 * fail with EBUSY if there are still references to this
1148 dentry_unhash(new_dentry
);
1150 if (!d_unhashed(new_dentry
))
1154 ncp_age_dentry(server
, old_dentry
);
1155 ncp_age_dentry(server
, new_dentry
);
1157 old_len
= sizeof(__old_name
);
1158 error
= ncp_io2vol(server
, __old_name
, &old_len
,
1159 old_dentry
->d_name
.name
, old_dentry
->d_name
.len
,
1160 !ncp_preserve_case(old_dir
));
1164 new_len
= sizeof(__new_name
);
1165 error
= ncp_io2vol(server
, __new_name
, &new_len
,
1166 new_dentry
->d_name
.name
, new_dentry
->d_name
.len
,
1167 !ncp_preserve_case(new_dir
));
1171 error
= ncp_ren_or_mov_file_or_subdir(server
, old_dir
, __old_name
,
1172 new_dir
, __new_name
);
1173 #ifdef CONFIG_NCPFS_STRONG
1174 if ((error
== 0x90 || error
== 0x8B || error
== -EACCES
) &&
1175 server
->m
.flags
& NCP_MOUNT_STRONG
) { /* RO */
1176 error
= ncp_force_rename(old_dir
, old_dentry
, __old_name
,
1177 new_dir
, new_dentry
, __new_name
);
1182 DPRINTK("ncp renamed %s -> %s.\n",
1183 old_dentry
->d_name
.name
,new_dentry
->d_name
.name
);
1186 error
= -ENAMETOOLONG
;
1192 error
= error
< 0 ? error
: -EACCES
;
1199 static int ncp_mknod(struct inode
* dir
, struct dentry
*dentry
,
1200 umode_t mode
, dev_t rdev
)
1202 if (!new_valid_dev(rdev
))
1204 if (ncp_is_nfs_extras(NCP_SERVER(dir
), NCP_FINFO(dir
)->volNumber
)) {
1205 DPRINTK(KERN_DEBUG
"ncp_mknod: mode = 0%ho\n", mode
);
1206 return ncp_create_new(dir
, dentry
, mode
, rdev
, 0);
1208 return -EPERM
; /* Strange, but true */
1211 /* The following routines are taken directly from msdos-fs */
1213 /* Linear day numbers of the respective 1sts in non-leap years. */
1215 static int day_n
[] =
1216 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
1217 /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
1220 extern struct timezone sys_tz
;
1222 static int utc2local(int time
)
1224 return time
- sys_tz
.tz_minuteswest
* 60;
1227 static int local2utc(int time
)
1229 return time
+ sys_tz
.tz_minuteswest
* 60;
1232 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
1234 ncp_date_dos2unix(__le16 t
, __le16 d
)
1236 unsigned short time
= le16_to_cpu(t
), date
= le16_to_cpu(d
);
1237 int month
, year
, secs
;
1239 /* first subtract and mask after that... Otherwise, if
1240 date == 0, bad things happen */
1241 month
= ((date
>> 5) - 1) & 15;
1243 secs
= (time
& 31) * 2 + 60 * ((time
>> 5) & 63) + (time
>> 11) * 3600 +
1244 86400 * ((date
& 31) - 1 + day_n
[month
] + (year
/ 4) +
1245 year
* 365 - ((year
& 3) == 0 && month
< 2 ? 1 : 0) + 3653);
1246 /* days since 1.1.70 plus 80's leap day */
1247 return local2utc(secs
);
1251 /* Convert linear UNIX date to a MS-DOS time/date pair. */
1253 ncp_date_unix2dos(int unix_date
, __le16
*time
, __le16
*date
)
1255 int day
, year
, nl_day
, month
;
1257 unix_date
= utc2local(unix_date
);
1258 *time
= cpu_to_le16(
1259 (unix_date
% 60) / 2 + (((unix_date
/ 60) % 60) << 5) +
1260 (((unix_date
/ 3600) % 24) << 11));
1261 day
= unix_date
/ 86400 - 3652;
1263 if ((year
+ 3) / 4 + 365 * year
> day
)
1265 day
-= (year
+ 3) / 4 + 365 * year
;
1266 if (day
== 59 && !(year
& 3)) {
1270 nl_day
= (year
& 3) || day
<= 59 ? day
: day
- 1;
1271 for (month
= 1; month
< 12; month
++)
1272 if (day_n
[month
] > nl_day
)
1275 *date
= cpu_to_le16(nl_day
- day_n
[month
- 1] + 1 + (month
<< 5) + (year
<< 9));