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: %s/%s not valid, age=%ld, server lookup\n",
343 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
,
344 NCP_GET_AGE(dentry
));
346 len
= sizeof(__name
);
347 if (ncp_is_server_root(dir
)) {
348 res
= ncp_io2vol(server
, __name
, &len
, dentry
->d_name
.name
,
349 dentry
->d_name
.len
, 1);
351 res
= ncp_lookup_volume(server
, __name
, &(finfo
.i
));
353 ncp_update_known_namespace(server
, finfo
.i
.volNumber
, NULL
);
356 res
= ncp_io2vol(server
, __name
, &len
, dentry
->d_name
.name
,
357 dentry
->d_name
.len
, !ncp_preserve_case(dir
));
359 res
= ncp_obtain_info(server
, dir
, __name
, &(finfo
.i
));
361 finfo
.volume
= finfo
.i
.volNumber
;
362 DDPRINTK("ncp_lookup_validate: looked for %s/%s, res=%d\n",
363 dentry
->d_parent
->d_name
.name
, __name
, res
);
365 * If we didn't find it, or if it has a different dirEntNum to
366 * what we remember, it's not valid any more.
369 struct inode
*inode
= dentry
->d_inode
;
371 mutex_lock(&inode
->i_mutex
);
372 if (finfo
.i
.dirEntNum
== NCP_FINFO(inode
)->dirEntNum
) {
373 ncp_new_dentry(dentry
);
376 DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");
378 ncp_update_inode2(inode
, &finfo
);
379 mutex_unlock(&inode
->i_mutex
);
383 DDPRINTK("ncp_lookup_validate: result=%d\n", val
);
388 static struct dentry
*
389 ncp_dget_fpos(struct dentry
*dentry
, struct dentry
*parent
, unsigned long fpos
)
391 struct dentry
*dent
= dentry
;
392 struct list_head
*next
;
394 if (d_validate(dent
, parent
)) {
395 if (dent
->d_name
.len
<= NCP_MAXPATHLEN
&&
396 (unsigned long)dent
->d_fsdata
== fpos
) {
397 if (!dent
->d_inode
) {
406 /* If a pointer is invalid, we search the dentry. */
407 spin_lock(&parent
->d_lock
);
408 next
= parent
->d_subdirs
.next
;
409 while (next
!= &parent
->d_subdirs
) {
410 dent
= list_entry(next
, struct dentry
, d_u
.d_child
);
411 if ((unsigned long)dent
->d_fsdata
== fpos
) {
416 spin_unlock(&parent
->d_lock
);
421 spin_unlock(&parent
->d_lock
);
428 static time_t ncp_obtain_mtime(struct dentry
*dentry
)
430 struct inode
*inode
= dentry
->d_inode
;
431 struct ncp_server
*server
= NCP_SERVER(inode
);
432 struct nw_info_struct i
;
434 if (!ncp_conn_valid(server
) || ncp_is_server_root(inode
))
437 if (ncp_obtain_info(server
, inode
, NULL
, &i
))
440 return ncp_date_dos2unix(i
.modifyTime
, i
.modifyDate
);
443 static int ncp_readdir(struct file
*file
, struct dir_context
*ctx
)
445 struct dentry
*dentry
= file
->f_path
.dentry
;
446 struct inode
*inode
= dentry
->d_inode
;
447 struct page
*page
= NULL
;
448 struct ncp_server
*server
= NCP_SERVER(inode
);
449 union ncp_dir_cache
*cache
= NULL
;
450 struct ncp_cache_control ctl
;
451 int result
, mtime_valid
= 0;
457 DDPRINTK("ncp_readdir: reading %s/%s, pos=%d\n",
458 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
,
462 /* Do not generate '.' and '..' when server is dead. */
463 if (!ncp_conn_valid(server
))
467 if (!dir_emit_dots(file
, ctx
))
470 page
= grab_cache_page(&inode
->i_data
, 0);
474 ctl
.cache
= cache
= kmap(page
);
475 ctl
.head
= cache
->head
;
477 if (!PageUptodate(page
) || !ctl
.head
.eof
)
481 if (jiffies
- ctl
.head
.time
>= NCP_MAX_AGE(server
))
484 mtime
= ncp_obtain_mtime(dentry
);
486 if ((!mtime
) || (mtime
!= ctl
.head
.mtime
))
490 if (ctx
->pos
> ctl
.head
.end
)
493 ctl
.fpos
= ctx
->pos
+ (NCP_DIRCACHE_START
- 2);
494 ctl
.ofs
= ctl
.fpos
/ NCP_DIRCACHE_SIZE
;
495 ctl
.idx
= ctl
.fpos
% NCP_DIRCACHE_SIZE
;
499 ctl
.page
= find_lock_page(&inode
->i_data
, ctl
.ofs
);
502 ctl
.cache
= kmap(ctl
.page
);
503 if (!PageUptodate(ctl
.page
))
506 while (ctl
.idx
< NCP_DIRCACHE_SIZE
) {
510 dent
= ncp_dget_fpos(ctl
.cache
->dentry
[ctl
.idx
],
514 over
= !dir_emit(ctx
, dent
->d_name
.name
,
516 dent
->d_inode
->i_ino
, DT_UNKNOWN
);
522 if (ctx
->pos
> ctl
.head
.end
)
527 SetPageUptodate(ctl
.page
);
528 unlock_page(ctl
.page
);
529 page_cache_release(ctl
.page
);
538 unlock_page(ctl
.page
);
539 page_cache_release(ctl
.page
);
544 ncp_invalidate_dircache_entries(dentry
);
546 mtime
= ncp_obtain_mtime(dentry
);
549 ctl
.head
.mtime
= mtime
;
550 ctl
.head
.time
= jiffies
;
554 ctl
.idx
= NCP_DIRCACHE_START
;
558 if (ncp_is_server_root(inode
)) {
559 ncp_read_volume_list(file
, ctx
, &ctl
);
561 ncp_do_readdir(file
, ctx
, &ctl
);
563 ctl
.head
.end
= ctl
.fpos
- 1;
564 ctl
.head
.eof
= ctl
.valid
;
568 SetPageUptodate(ctl
.page
);
569 unlock_page(ctl
.page
);
570 page_cache_release(ctl
.page
);
573 cache
->head
= ctl
.head
;
575 SetPageUptodate(page
);
577 page_cache_release(page
);
584 ncp_fill_cache(struct file
*file
, struct dir_context
*ctx
,
585 struct ncp_cache_control
*ctrl
, struct ncp_entry_info
*entry
,
588 struct dentry
*newdent
, *dentry
= file
->f_path
.dentry
;
589 struct inode
*dir
= dentry
->d_inode
;
590 struct ncp_cache_control ctl
= *ctrl
;
595 __u8 __name
[NCP_MAXPATHLEN
+ 1];
597 qname
.len
= sizeof(__name
);
598 if (ncp_vol2io(NCP_SERVER(dir
), __name
, &qname
.len
,
599 entry
->i
.entryName
, entry
->i
.nameLen
,
600 !ncp_preserve_entry_case(dir
, entry
->i
.NSCreator
)))
601 return 1; /* I'm not sure */
605 newdent
= d_hash_and_lookup(dentry
, &qname
);
606 if (unlikely(IS_ERR(newdent
)))
609 newdent
= d_alloc(dentry
, &qname
);
615 /* If case sensitivity changed for this volume, all entries below this one
616 should be thrown away. This entry itself is not affected, as its case
617 sensitivity is controlled by its own parent. */
619 shrink_dcache_parent(newdent
);
622 * NetWare's OS2 namespace is case preserving yet case
623 * insensitive. So we update dentry's name as received from
624 * server. Parent dir's i_mutex is locked because we're in
627 dentry_update_name_case(newdent
, &qname
);
630 if (!newdent
->d_inode
) {
634 entry
->ino
= iunique(dir
->i_sb
, 2);
635 inode
= ncp_iget(dir
->i_sb
, entry
);
637 d_instantiate(newdent
, inode
);
642 struct inode
*inode
= newdent
->d_inode
;
644 mutex_lock_nested(&inode
->i_mutex
, I_MUTEX_CHILD
);
645 ncp_update_inode2(inode
, entry
);
646 mutex_unlock(&inode
->i_mutex
);
649 if (newdent
->d_inode
) {
650 ino
= newdent
->d_inode
->i_ino
;
651 newdent
->d_fsdata
= (void *) ctl
.fpos
;
652 ncp_new_dentry(newdent
);
655 if (ctl
.idx
>= NCP_DIRCACHE_SIZE
) {
658 SetPageUptodate(ctl
.page
);
659 unlock_page(ctl
.page
);
660 page_cache_release(ctl
.page
);
663 ctl
.idx
-= NCP_DIRCACHE_SIZE
;
665 ctl
.page
= grab_cache_page(&dir
->i_data
, ctl
.ofs
);
667 ctl
.cache
= kmap(ctl
.page
);
670 ctl
.cache
->dentry
[ctl
.idx
] = newdent
;
677 if (!ctl
.filled
&& (ctl
.fpos
== ctx
->pos
)) {
679 ino
= iunique(dir
->i_sb
, 2);
680 ctl
.filled
= !dir_emit(ctx
, qname
.name
, qname
.len
,
688 return (ctl
.valid
|| !ctl
.filled
);
692 ncp_read_volume_list(struct file
*file
, struct dir_context
*ctx
,
693 struct ncp_cache_control
*ctl
)
695 struct dentry
*dentry
= file
->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) ctx
->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(file
, ctx
, ctl
, &entry
, inval_dentry
))
730 ncp_do_readdir(struct file
*file
, struct dir_context
*ctx
,
731 struct ncp_cache_control
*ctl
)
733 struct dentry
*dentry
= file
->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) ctx
->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(file
, ctx
, 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
, unsigned int flags
)
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
, umode_t 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=%hx\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
, umode_t mode
,
987 return ncp_create_new(dir
, dentry
, mode
, 0, 0);
990 static int ncp_mkdir(struct inode
*dir
, struct dentry
*dentry
, umode_t 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
);
1038 len
= sizeof(__name
);
1039 error
= ncp_io2vol(server
, __name
, &len
, dentry
->d_name
.name
,
1040 dentry
->d_name
.len
, !ncp_preserve_case(dir
));
1044 result
= ncp_del_file_or_subdir(server
, dir
, __name
);
1049 case 0x85: /* unauthorized to delete file */
1050 case 0x8A: /* unauthorized to delete file */
1054 case 0x90: /* read only */
1057 case 0x9F: /* in use by another client */
1060 case 0xA0: /* directory not empty */
1063 case 0xFF: /* someone deleted file */
1067 error
= result
< 0 ? result
: -EACCES
;
1074 static int ncp_unlink(struct inode
*dir
, struct dentry
*dentry
)
1076 struct inode
*inode
= dentry
->d_inode
;
1077 struct ncp_server
*server
;
1080 server
= NCP_SERVER(dir
);
1081 DPRINTK("ncp_unlink: unlinking %s/%s\n",
1082 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
1085 * Check whether to close the file ...
1088 PPRINTK("ncp_unlink: closing file\n");
1089 ncp_make_closed(inode
);
1092 error
= ncp_del_file_or_subdir2(server
, dentry
);
1093 #ifdef CONFIG_NCPFS_STRONG
1094 /* 9C is Invalid path.. It should be 8F, 90 - read only, but
1096 if ((error
== 0x9C || error
== 0x90) && server
->m
.flags
& NCP_MOUNT_STRONG
) { /* R/O */
1097 error
= ncp_force_unlink(dir
, dentry
);
1102 DPRINTK("ncp: removed %s/%s\n",
1103 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
1109 case 0x8D: /* some files in use */
1110 case 0x8E: /* all files in use */
1113 case 0x8F: /* some read only */
1114 case 0x90: /* all read only */
1115 case 0x9C: /* !!! returned when in-use or read-only by NW4 */
1122 error
= error
< 0 ? error
: -EACCES
;
1128 static int ncp_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
1129 struct inode
*new_dir
, struct dentry
*new_dentry
)
1131 struct ncp_server
*server
= NCP_SERVER(old_dir
);
1133 int old_len
, new_len
;
1134 __u8 __old_name
[NCP_MAXPATHLEN
+ 1], __new_name
[NCP_MAXPATHLEN
+ 1];
1136 DPRINTK("ncp_rename: %s/%s to %s/%s\n",
1137 old_dentry
->d_parent
->d_name
.name
, old_dentry
->d_name
.name
,
1138 new_dentry
->d_parent
->d_name
.name
, new_dentry
->d_name
.name
);
1140 ncp_age_dentry(server
, old_dentry
);
1141 ncp_age_dentry(server
, new_dentry
);
1143 old_len
= sizeof(__old_name
);
1144 error
= ncp_io2vol(server
, __old_name
, &old_len
,
1145 old_dentry
->d_name
.name
, old_dentry
->d_name
.len
,
1146 !ncp_preserve_case(old_dir
));
1150 new_len
= sizeof(__new_name
);
1151 error
= ncp_io2vol(server
, __new_name
, &new_len
,
1152 new_dentry
->d_name
.name
, new_dentry
->d_name
.len
,
1153 !ncp_preserve_case(new_dir
));
1157 error
= ncp_ren_or_mov_file_or_subdir(server
, old_dir
, __old_name
,
1158 new_dir
, __new_name
);
1159 #ifdef CONFIG_NCPFS_STRONG
1160 if ((error
== 0x90 || error
== 0x8B || error
== -EACCES
) &&
1161 server
->m
.flags
& NCP_MOUNT_STRONG
) { /* RO */
1162 error
= ncp_force_rename(old_dir
, old_dentry
, __old_name
,
1163 new_dir
, new_dentry
, __new_name
);
1168 DPRINTK("ncp renamed %s -> %s.\n",
1169 old_dentry
->d_name
.name
,new_dentry
->d_name
.name
);
1172 error
= -ENAMETOOLONG
;
1178 error
= error
< 0 ? error
: -EACCES
;
1185 static int ncp_mknod(struct inode
* dir
, struct dentry
*dentry
,
1186 umode_t mode
, dev_t rdev
)
1188 if (!new_valid_dev(rdev
))
1190 if (ncp_is_nfs_extras(NCP_SERVER(dir
), NCP_FINFO(dir
)->volNumber
)) {
1191 DPRINTK(KERN_DEBUG
"ncp_mknod: mode = 0%ho\n", mode
);
1192 return ncp_create_new(dir
, dentry
, mode
, rdev
, 0);
1194 return -EPERM
; /* Strange, but true */
1197 /* The following routines are taken directly from msdos-fs */
1199 /* Linear day numbers of the respective 1sts in non-leap years. */
1201 static int day_n
[] =
1202 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
1203 /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
1206 extern struct timezone sys_tz
;
1208 static int utc2local(int time
)
1210 return time
- sys_tz
.tz_minuteswest
* 60;
1213 static int local2utc(int time
)
1215 return time
+ sys_tz
.tz_minuteswest
* 60;
1218 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
1220 ncp_date_dos2unix(__le16 t
, __le16 d
)
1222 unsigned short time
= le16_to_cpu(t
), date
= le16_to_cpu(d
);
1223 int month
, year
, secs
;
1225 /* first subtract and mask after that... Otherwise, if
1226 date == 0, bad things happen */
1227 month
= ((date
>> 5) - 1) & 15;
1229 secs
= (time
& 31) * 2 + 60 * ((time
>> 5) & 63) + (time
>> 11) * 3600 +
1230 86400 * ((date
& 31) - 1 + day_n
[month
] + (year
/ 4) +
1231 year
* 365 - ((year
& 3) == 0 && month
< 2 ? 1 : 0) + 3653);
1232 /* days since 1.1.70 plus 80's leap day */
1233 return local2utc(secs
);
1237 /* Convert linear UNIX date to a MS-DOS time/date pair. */
1239 ncp_date_unix2dos(int unix_date
, __le16
*time
, __le16
*date
)
1241 int day
, year
, nl_day
, month
;
1243 unix_date
= utc2local(unix_date
);
1244 *time
= cpu_to_le16(
1245 (unix_date
% 60) / 2 + (((unix_date
/ 60) % 60) << 5) +
1246 (((unix_date
/ 3600) % 24) << 11));
1247 day
= unix_date
/ 86400 - 3652;
1249 if ((year
+ 3) / 4 + 365 * year
> day
)
1251 day
-= (year
+ 3) / 4 + 365 * year
;
1252 if (day
== 59 && !(year
& 3)) {
1256 nl_day
= (year
& 3) || day
<= 59 ? day
: day
- 1;
1257 for (month
= 1; month
< 12; month
++)
1258 if (day_n
[month
] > nl_day
)
1261 *date
= cpu_to_le16(nl_day
- day_n
[month
- 1] + 1 + (month
<< 5) + (year
<< 9));