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 is_root_inode(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 ncp_dbg(2, "%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 ncp_dbg(2, "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 ncp_dbg(2, "found, but dirEntNum changed\n");
377 ncp_update_inode2(inode
, &finfo
);
378 mutex_unlock(&inode
->i_mutex
);
382 ncp_dbg(2, "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
;
392 if (d_validate(dent
, parent
)) {
393 if (dent
->d_name
.len
<= NCP_MAXPATHLEN
&&
394 (unsigned long)dent
->d_fsdata
== fpos
) {
395 if (!dent
->d_inode
) {
404 /* If a pointer is invalid, we search the dentry. */
405 spin_lock(&parent
->d_lock
);
406 list_for_each_entry(dent
, &parent
->d_subdirs
, d_child
) {
407 if ((unsigned long)dent
->d_fsdata
== fpos
) {
412 spin_unlock(&parent
->d_lock
);
416 spin_unlock(&parent
->d_lock
);
423 static time_t ncp_obtain_mtime(struct dentry
*dentry
)
425 struct inode
*inode
= dentry
->d_inode
;
426 struct ncp_server
*server
= NCP_SERVER(inode
);
427 struct nw_info_struct i
;
429 if (!ncp_conn_valid(server
) || ncp_is_server_root(inode
))
432 if (ncp_obtain_info(server
, inode
, NULL
, &i
))
435 return ncp_date_dos2unix(i
.modifyTime
, i
.modifyDate
);
438 static int ncp_readdir(struct file
*file
, struct dir_context
*ctx
)
440 struct dentry
*dentry
= file
->f_path
.dentry
;
441 struct inode
*inode
= dentry
->d_inode
;
442 struct page
*page
= NULL
;
443 struct ncp_server
*server
= NCP_SERVER(inode
);
444 union ncp_dir_cache
*cache
= NULL
;
445 struct ncp_cache_control ctl
;
446 int result
, mtime_valid
= 0;
452 ncp_dbg(2, "reading %pD2, pos=%d\n", file
, (int)ctx
->pos
);
455 /* Do not generate '.' and '..' when server is dead. */
456 if (!ncp_conn_valid(server
))
460 if (!dir_emit_dots(file
, ctx
))
463 page
= grab_cache_page(&inode
->i_data
, 0);
467 ctl
.cache
= cache
= kmap(page
);
468 ctl
.head
= cache
->head
;
470 if (!PageUptodate(page
) || !ctl
.head
.eof
)
474 if (jiffies
- ctl
.head
.time
>= NCP_MAX_AGE(server
))
477 mtime
= ncp_obtain_mtime(dentry
);
479 if ((!mtime
) || (mtime
!= ctl
.head
.mtime
))
483 if (ctx
->pos
> ctl
.head
.end
)
486 ctl
.fpos
= ctx
->pos
+ (NCP_DIRCACHE_START
- 2);
487 ctl
.ofs
= ctl
.fpos
/ NCP_DIRCACHE_SIZE
;
488 ctl
.idx
= ctl
.fpos
% NCP_DIRCACHE_SIZE
;
492 ctl
.page
= find_lock_page(&inode
->i_data
, ctl
.ofs
);
495 ctl
.cache
= kmap(ctl
.page
);
496 if (!PageUptodate(ctl
.page
))
499 while (ctl
.idx
< NCP_DIRCACHE_SIZE
) {
503 dent
= ncp_dget_fpos(ctl
.cache
->dentry
[ctl
.idx
],
507 over
= !dir_emit(ctx
, dent
->d_name
.name
,
509 dent
->d_inode
->i_ino
, DT_UNKNOWN
);
515 if (ctx
->pos
> ctl
.head
.end
)
520 SetPageUptodate(ctl
.page
);
521 unlock_page(ctl
.page
);
522 page_cache_release(ctl
.page
);
531 unlock_page(ctl
.page
);
532 page_cache_release(ctl
.page
);
537 ncp_invalidate_dircache_entries(dentry
);
539 mtime
= ncp_obtain_mtime(dentry
);
542 ctl
.head
.mtime
= mtime
;
543 ctl
.head
.time
= jiffies
;
547 ctl
.idx
= NCP_DIRCACHE_START
;
551 if (ncp_is_server_root(inode
)) {
552 ncp_read_volume_list(file
, ctx
, &ctl
);
554 ncp_do_readdir(file
, ctx
, &ctl
);
556 ctl
.head
.end
= ctl
.fpos
- 1;
557 ctl
.head
.eof
= ctl
.valid
;
561 SetPageUptodate(ctl
.page
);
562 unlock_page(ctl
.page
);
563 page_cache_release(ctl
.page
);
566 cache
->head
= ctl
.head
;
568 SetPageUptodate(page
);
570 page_cache_release(page
);
577 ncp_fill_cache(struct file
*file
, struct dir_context
*ctx
,
578 struct ncp_cache_control
*ctrl
, struct ncp_entry_info
*entry
,
581 struct dentry
*newdent
, *dentry
= file
->f_path
.dentry
;
582 struct inode
*dir
= dentry
->d_inode
;
583 struct ncp_cache_control ctl
= *ctrl
;
588 __u8 __name
[NCP_MAXPATHLEN
+ 1];
590 qname
.len
= sizeof(__name
);
591 if (ncp_vol2io(NCP_SERVER(dir
), __name
, &qname
.len
,
592 entry
->i
.entryName
, entry
->i
.nameLen
,
593 !ncp_preserve_entry_case(dir
, entry
->i
.NSCreator
)))
594 return 1; /* I'm not sure */
598 newdent
= d_hash_and_lookup(dentry
, &qname
);
599 if (unlikely(IS_ERR(newdent
)))
602 newdent
= d_alloc(dentry
, &qname
);
608 /* If case sensitivity changed for this volume, all entries below this one
609 should be thrown away. This entry itself is not affected, as its case
610 sensitivity is controlled by its own parent. */
612 shrink_dcache_parent(newdent
);
615 * NetWare's OS2 namespace is case preserving yet case
616 * insensitive. So we update dentry's name as received from
617 * server. Parent dir's i_mutex is locked because we're in
620 dentry_update_name_case(newdent
, &qname
);
623 if (!newdent
->d_inode
) {
627 entry
->ino
= iunique(dir
->i_sb
, 2);
628 inode
= ncp_iget(dir
->i_sb
, entry
);
630 d_instantiate(newdent
, inode
);
635 struct inode
*inode
= newdent
->d_inode
;
637 mutex_lock_nested(&inode
->i_mutex
, I_MUTEX_CHILD
);
638 ncp_update_inode2(inode
, entry
);
639 mutex_unlock(&inode
->i_mutex
);
642 if (newdent
->d_inode
) {
643 ino
= newdent
->d_inode
->i_ino
;
644 newdent
->d_fsdata
= (void *) ctl
.fpos
;
645 ncp_new_dentry(newdent
);
648 if (ctl
.idx
>= NCP_DIRCACHE_SIZE
) {
651 SetPageUptodate(ctl
.page
);
652 unlock_page(ctl
.page
);
653 page_cache_release(ctl
.page
);
656 ctl
.idx
-= NCP_DIRCACHE_SIZE
;
658 ctl
.page
= grab_cache_page(&dir
->i_data
, ctl
.ofs
);
660 ctl
.cache
= kmap(ctl
.page
);
663 ctl
.cache
->dentry
[ctl
.idx
] = newdent
;
670 if (!ctl
.filled
&& (ctl
.fpos
== ctx
->pos
)) {
672 ino
= iunique(dir
->i_sb
, 2);
673 ctl
.filled
= !dir_emit(ctx
, qname
.name
, qname
.len
,
681 return (ctl
.valid
|| !ctl
.filled
);
685 ncp_read_volume_list(struct file
*file
, struct dir_context
*ctx
,
686 struct ncp_cache_control
*ctl
)
688 struct inode
*inode
= file_inode(file
);
689 struct ncp_server
*server
= NCP_SERVER(inode
);
690 struct ncp_volume_info info
;
691 struct ncp_entry_info entry
;
694 ncp_dbg(1, "pos=%ld\n", (unsigned long)ctx
->pos
);
696 for (i
= 0; i
< NCP_NUMBER_OF_VOLUMES
; i
++) {
699 if (ncp_get_volume_info_with_number(server
, i
, &info
) != 0)
701 if (!strlen(info
.volume_name
))
704 ncp_dbg(1, "found vol: %s\n", info
.volume_name
);
706 if (ncp_lookup_volume(server
, info
.volume_name
,
708 ncp_dbg(1, "could not lookup vol %s\n",
712 inval_dentry
= ncp_update_known_namespace(server
, entry
.i
.volNumber
, NULL
);
713 entry
.volume
= entry
.i
.volNumber
;
714 if (!ncp_fill_cache(file
, ctx
, ctl
, &entry
, inval_dentry
))
720 ncp_do_readdir(struct file
*file
, struct dir_context
*ctx
,
721 struct ncp_cache_control
*ctl
)
723 struct inode
*dir
= file_inode(file
);
724 struct ncp_server
*server
= NCP_SERVER(dir
);
725 struct nw_search_sequence seq
;
726 struct ncp_entry_info entry
;
732 ncp_dbg(1, "%pD2, fpos=%ld\n", file
, (unsigned long)ctx
->pos
);
733 ncp_vdbg("init %pD, volnum=%d, dirent=%u\n",
734 file
, NCP_FINFO(dir
)->volNumber
, NCP_FINFO(dir
)->dirEntNum
);
736 err
= ncp_initialize_search(server
, dir
, &seq
);
738 ncp_dbg(1, "init failed, err=%d\n", err
);
741 /* We MUST NOT use server->buffer_size handshaked with server if we are
742 using UDP, as for UDP server uses max. buffer size determined by
743 MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes).
744 So we use 128KB, just to be sure, as there is no way how to know
745 this value in advance. */
747 buf
= vmalloc(bufsize
);
755 err
= ncp_search_for_fileset(server
, &seq
, &more
, &cnt
, buf
, bufsize
, &rpl
, &rpls
);
758 if (!cnt
) /* prevent endless loop */
763 if (rpls
< offsetof(struct nw_info_struct
, entryName
))
764 break; /* short packet */
765 ncp_extract_file_info(rpl
, &entry
.i
);
766 onerpl
= offsetof(struct nw_info_struct
, entryName
) + entry
.i
.nameLen
;
768 break; /* short packet */
769 (void)ncp_obtain_nfs_info(server
, &entry
.i
);
772 entry
.volume
= entry
.i
.volNumber
;
773 if (!ncp_fill_cache(file
, ctx
, ctl
, &entry
, 0))
781 int ncp_conn_logged_in(struct super_block
*sb
)
783 struct ncp_server
* server
= NCP_SBP(sb
);
786 if (ncp_single_volume(server
)) {
792 __u8 __name
[NCP_MAXPATHLEN
+ 1];
794 len
= sizeof(__name
);
795 result
= ncp_io2vol(server
, __name
, &len
, server
->m
.mounted_vol
,
796 strlen(server
->m
.mounted_vol
), 1);
800 if (ncp_get_volume_root(server
, __name
, &volNumber
, &dirEntNum
, &DosDirNum
)) {
801 ncp_vdbg("%s not found\n", server
->m
.mounted_vol
);
806 struct inode
* ino
= dent
->d_inode
;
808 ncp_update_known_namespace(server
, volNumber
, NULL
);
809 NCP_FINFO(ino
)->volNumber
= volNumber
;
810 NCP_FINFO(ino
)->dirEntNum
= dirEntNum
;
811 NCP_FINFO(ino
)->DosDirNum
= DosDirNum
;
814 ncp_dbg(1, "sb->s_root->d_inode == NULL!\n");
817 ncp_dbg(1, "sb->s_root == NULL!\n");
826 static struct dentry
*ncp_lookup(struct inode
*dir
, struct dentry
*dentry
, unsigned int flags
)
828 struct ncp_server
*server
= NCP_SERVER(dir
);
829 struct inode
*inode
= NULL
;
830 struct ncp_entry_info finfo
;
832 __u8 __name
[NCP_MAXPATHLEN
+ 1];
835 if (!ncp_conn_valid(server
))
838 ncp_vdbg("server lookup for %pd2\n", dentry
);
840 len
= sizeof(__name
);
841 if (ncp_is_server_root(dir
)) {
842 res
= ncp_io2vol(server
, __name
, &len
, dentry
->d_name
.name
,
843 dentry
->d_name
.len
, 1);
845 res
= ncp_lookup_volume(server
, __name
, &(finfo
.i
));
847 ncp_update_known_namespace(server
, finfo
.i
.volNumber
, NULL
);
849 res
= ncp_io2vol(server
, __name
, &len
, dentry
->d_name
.name
,
850 dentry
->d_name
.len
, !ncp_preserve_case(dir
));
852 res
= ncp_obtain_info(server
, dir
, __name
, &(finfo
.i
));
854 ncp_vdbg("looked for %pd2, res=%d\n", dentry
, res
);
856 * If we didn't find an entry, make a negative dentry.
862 * Create an inode for the entry.
865 finfo
.ino
= iunique(dir
->i_sb
, 2);
866 finfo
.volume
= finfo
.i
.volNumber
;
868 inode
= ncp_iget(dir
->i_sb
, &finfo
);
871 ncp_new_dentry(dentry
);
873 d_add(dentry
, inode
);
878 ncp_vdbg("result=%d\n", error
);
879 return ERR_PTR(error
);
883 * This code is common to create, mkdir, and mknod.
885 static int ncp_instantiate(struct inode
*dir
, struct dentry
*dentry
,
886 struct ncp_entry_info
*finfo
)
891 finfo
->ino
= iunique(dir
->i_sb
, 2);
892 inode
= ncp_iget(dir
->i_sb
, finfo
);
895 d_instantiate(dentry
,inode
);
901 ncp_vdbg("%pd2 failed, closing file\n", dentry
);
902 ncp_close_file(NCP_SERVER(dir
), finfo
->file_handle
);
906 int ncp_create_new(struct inode
*dir
, struct dentry
*dentry
, umode_t mode
,
907 dev_t rdev
, __le32 attributes
)
909 struct ncp_server
*server
= NCP_SERVER(dir
);
910 struct ncp_entry_info finfo
;
911 int error
, result
, len
;
913 __u8 __name
[NCP_MAXPATHLEN
+ 1];
915 ncp_vdbg("creating %pd2, mode=%hx\n", dentry
, mode
);
917 ncp_age_dentry(server
, dentry
);
918 len
= sizeof(__name
);
919 error
= ncp_io2vol(server
, __name
, &len
, dentry
->d_name
.name
,
920 dentry
->d_name
.len
, !ncp_preserve_case(dir
));
927 (server
->m
.flags
& NCP_MOUNT_EXTRAS
) &&
929 attributes
|= aSYSTEM
| aSHARED
;
931 result
= ncp_open_create_file_or_subdir(server
, dir
, __name
,
932 OC_MODE_CREATE
| OC_MODE_OPEN
| OC_MODE_REPLACE
,
933 attributes
, AR_READ
| AR_WRITE
, &finfo
);
936 result
= ncp_open_create_file_or_subdir(server
, dir
, __name
,
937 OC_MODE_CREATE
| OC_MODE_OPEN
| OC_MODE_REPLACE
,
938 attributes
, AR_WRITE
, &finfo
);
941 error
= -ENAMETOOLONG
;
944 ncp_dbg(1, "%pd2 failed\n", dentry
);
949 finfo
.access
= opmode
;
950 if (ncp_is_nfs_extras(server
, finfo
.volume
)) {
951 finfo
.i
.nfs
.mode
= mode
;
952 finfo
.i
.nfs
.rdev
= new_encode_dev(rdev
);
953 if (ncp_modify_nfs_info(server
, finfo
.volume
,
955 mode
, new_encode_dev(rdev
)) != 0)
959 error
= ncp_instantiate(dir
, dentry
, &finfo
);
964 static int ncp_create(struct inode
*dir
, struct dentry
*dentry
, umode_t mode
,
967 return ncp_create_new(dir
, dentry
, mode
, 0, 0);
970 static int ncp_mkdir(struct inode
*dir
, struct dentry
*dentry
, umode_t mode
)
972 struct ncp_entry_info finfo
;
973 struct ncp_server
*server
= NCP_SERVER(dir
);
975 __u8 __name
[NCP_MAXPATHLEN
+ 1];
977 ncp_dbg(1, "making %pd2\n", dentry
);
979 ncp_age_dentry(server
, dentry
);
980 len
= sizeof(__name
);
981 error
= ncp_io2vol(server
, __name
, &len
, dentry
->d_name
.name
,
982 dentry
->d_name
.len
, !ncp_preserve_case(dir
));
986 error
= ncp_open_create_file_or_subdir(server
, dir
, __name
,
987 OC_MODE_CREATE
, aDIR
,
991 if (ncp_is_nfs_extras(server
, finfo
.volume
)) {
993 finfo
.i
.nfs
.mode
= mode
;
994 if (ncp_modify_nfs_info(server
,
1000 error
= ncp_instantiate(dir
, dentry
, &finfo
);
1001 } else if (error
> 0) {
1008 static int ncp_rmdir(struct inode
*dir
, struct dentry
*dentry
)
1010 struct ncp_server
*server
= NCP_SERVER(dir
);
1011 int error
, result
, len
;
1012 __u8 __name
[NCP_MAXPATHLEN
+ 1];
1014 ncp_dbg(1, "removing %pd2\n", dentry
);
1016 len
= sizeof(__name
);
1017 error
= ncp_io2vol(server
, __name
, &len
, dentry
->d_name
.name
,
1018 dentry
->d_name
.len
, !ncp_preserve_case(dir
));
1022 result
= ncp_del_file_or_subdir(server
, dir
, __name
);
1027 case 0x85: /* unauthorized to delete file */
1028 case 0x8A: /* unauthorized to delete file */
1032 case 0x90: /* read only */
1035 case 0x9F: /* in use by another client */
1038 case 0xA0: /* directory not empty */
1041 case 0xFF: /* someone deleted file */
1045 error
= result
< 0 ? result
: -EACCES
;
1052 static int ncp_unlink(struct inode
*dir
, struct dentry
*dentry
)
1054 struct inode
*inode
= dentry
->d_inode
;
1055 struct ncp_server
*server
;
1058 server
= NCP_SERVER(dir
);
1059 ncp_dbg(1, "unlinking %pd2\n", dentry
);
1062 * Check whether to close the file ...
1065 ncp_vdbg("closing file\n");
1066 ncp_make_closed(inode
);
1069 error
= ncp_del_file_or_subdir2(server
, dentry
);
1070 #ifdef CONFIG_NCPFS_STRONG
1071 /* 9C is Invalid path.. It should be 8F, 90 - read only, but
1073 if ((error
== 0x9C || error
== 0x90) && server
->m
.flags
& NCP_MOUNT_STRONG
) { /* R/O */
1074 error
= ncp_force_unlink(dir
, dentry
);
1079 ncp_dbg(1, "removed %pd2\n", dentry
);
1085 case 0x8D: /* some files in use */
1086 case 0x8E: /* all files in use */
1089 case 0x8F: /* some read only */
1090 case 0x90: /* all read only */
1091 case 0x9C: /* !!! returned when in-use or read-only by NW4 */
1098 error
= error
< 0 ? error
: -EACCES
;
1104 static int ncp_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
1105 struct inode
*new_dir
, struct dentry
*new_dentry
)
1107 struct ncp_server
*server
= NCP_SERVER(old_dir
);
1109 int old_len
, new_len
;
1110 __u8 __old_name
[NCP_MAXPATHLEN
+ 1], __new_name
[NCP_MAXPATHLEN
+ 1];
1112 ncp_dbg(1, "%pd2 to %pd2\n", old_dentry
, new_dentry
);
1114 ncp_age_dentry(server
, old_dentry
);
1115 ncp_age_dentry(server
, new_dentry
);
1117 old_len
= sizeof(__old_name
);
1118 error
= ncp_io2vol(server
, __old_name
, &old_len
,
1119 old_dentry
->d_name
.name
, old_dentry
->d_name
.len
,
1120 !ncp_preserve_case(old_dir
));
1124 new_len
= sizeof(__new_name
);
1125 error
= ncp_io2vol(server
, __new_name
, &new_len
,
1126 new_dentry
->d_name
.name
, new_dentry
->d_name
.len
,
1127 !ncp_preserve_case(new_dir
));
1131 error
= ncp_ren_or_mov_file_or_subdir(server
, old_dir
, __old_name
,
1132 new_dir
, __new_name
);
1133 #ifdef CONFIG_NCPFS_STRONG
1134 if ((error
== 0x90 || error
== 0x8B || error
== -EACCES
) &&
1135 server
->m
.flags
& NCP_MOUNT_STRONG
) { /* RO */
1136 error
= ncp_force_rename(old_dir
, old_dentry
, __old_name
,
1137 new_dir
, new_dentry
, __new_name
);
1142 ncp_dbg(1, "renamed %pd -> %pd\n",
1143 old_dentry
, new_dentry
);
1146 error
= -ENAMETOOLONG
;
1152 error
= error
< 0 ? error
: -EACCES
;
1159 static int ncp_mknod(struct inode
* dir
, struct dentry
*dentry
,
1160 umode_t mode
, dev_t rdev
)
1162 if (!new_valid_dev(rdev
))
1164 if (ncp_is_nfs_extras(NCP_SERVER(dir
), NCP_FINFO(dir
)->volNumber
)) {
1165 ncp_dbg(1, "mode = 0%ho\n", mode
);
1166 return ncp_create_new(dir
, dentry
, mode
, rdev
, 0);
1168 return -EPERM
; /* Strange, but true */
1171 /* The following routines are taken directly from msdos-fs */
1173 /* Linear day numbers of the respective 1sts in non-leap years. */
1175 static int day_n
[] =
1176 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
1177 /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
1179 static int utc2local(int time
)
1181 return time
- sys_tz
.tz_minuteswest
* 60;
1184 static int local2utc(int time
)
1186 return time
+ sys_tz
.tz_minuteswest
* 60;
1189 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
1191 ncp_date_dos2unix(__le16 t
, __le16 d
)
1193 unsigned short time
= le16_to_cpu(t
), date
= le16_to_cpu(d
);
1194 int month
, year
, secs
;
1196 /* first subtract and mask after that... Otherwise, if
1197 date == 0, bad things happen */
1198 month
= ((date
>> 5) - 1) & 15;
1200 secs
= (time
& 31) * 2 + 60 * ((time
>> 5) & 63) + (time
>> 11) * 3600 +
1201 86400 * ((date
& 31) - 1 + day_n
[month
] + (year
/ 4) +
1202 year
* 365 - ((year
& 3) == 0 && month
< 2 ? 1 : 0) + 3653);
1203 /* days since 1.1.70 plus 80's leap day */
1204 return local2utc(secs
);
1208 /* Convert linear UNIX date to a MS-DOS time/date pair. */
1210 ncp_date_unix2dos(int unix_date
, __le16
*time
, __le16
*date
)
1212 int day
, year
, nl_day
, month
;
1214 unix_date
= utc2local(unix_date
);
1215 *time
= cpu_to_le16(
1216 (unix_date
% 60) / 2 + (((unix_date
/ 60) % 60) << 5) +
1217 (((unix_date
/ 3600) % 24) << 11));
1218 day
= unix_date
/ 86400 - 3652;
1220 if ((year
+ 3) / 4 + 365 * year
> day
)
1222 day
-= (year
+ 3) / 4 + 365 * year
;
1223 if (day
== 59 && !(year
& 3)) {
1227 nl_day
= (year
& 3) || day
<= 59 ? day
: day
- 1;
1228 for (month
= 1; month
< 12; month
++)
1229 if (day_n
[month
] > nl_day
)
1232 *date
= cpu_to_le16(nl_day
- day_n
[month
- 1] + 1 + (month
<< 5) + (year
<< 9));