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 Wolfram Pienkoss for NLS
11 #include <linux/config.h>
13 #include <linux/sched.h>
14 #include <linux/errno.h>
15 #include <linux/stat.h>
16 #include <linux/kernel.h>
17 #include <linux/malloc.h>
18 #include <linux/vmalloc.h>
20 #include <asm/uaccess.h>
21 #include <asm/byteorder.h>
22 #include <linux/errno.h>
23 #include <linux/locks.h>
25 #include <linux/ncp_fs.h>
27 #include "ncplib_kernel.h"
30 struct nw_info_struct i
;
31 struct nw_search_sequence s
; /* given back for i */
35 static kdev_t c_dev
= 0;
36 static unsigned long c_ino
= 0;
38 static int c_seen_eof
;
39 static int c_last_returned_index
;
40 static struct ncp_dirent
*c_entry
= NULL
;
41 static int c_lock
= 0;
42 static DECLARE_WAIT_QUEUE_HEAD(c_wait
);
44 static int ncp_read_volume_list(struct ncp_server
*, int, int,
46 static int ncp_do_readdir(struct ncp_server
*, struct dentry
*, int, int,
49 static ssize_t
ncp_dir_read(struct file
*, char *, size_t, loff_t
*);
50 static int ncp_readdir(struct file
*, void *, filldir_t
);
52 static int ncp_create(struct inode
*, struct dentry
*, int);
53 static struct dentry
*ncp_lookup(struct inode
*, struct dentry
*);
54 static int ncp_unlink(struct inode
*, struct dentry
*);
55 static int ncp_mkdir(struct inode
*, struct dentry
*, int);
56 static int ncp_rmdir(struct inode
*, struct dentry
*);
57 static int ncp_rename(struct inode
*, struct dentry
*,
58 struct inode
*, struct dentry
*);
59 #ifdef CONFIG_NCPFS_EXTRAS
60 extern int ncp_symlink(struct inode
*, struct dentry
*, const char *);
63 static struct file_operations ncp_dir_operations
=
65 NULL
, /* lseek - default */
66 ncp_dir_read
, /* read - bad */
67 NULL
, /* write - bad */
68 ncp_readdir
, /* readdir */
69 NULL
, /* poll - default */
70 ncp_ioctl
, /* ioctl */
72 NULL
, /* no special open code */
74 NULL
, /* no special release code */
78 struct inode_operations ncp_dir_inode_operations
=
80 &ncp_dir_operations
, /* default directory file ops */
81 ncp_create
, /* create */
82 ncp_lookup
, /* lookup */
84 ncp_unlink
, /* unlink */
85 #ifdef CONFIG_NCPFS_EXTRAS
86 ncp_symlink
, /* symlink */
90 ncp_mkdir
, /* mkdir */
91 ncp_rmdir
, /* rmdir */
93 ncp_rename
, /* rename */
95 NULL
, /* follow link */
100 NULL
, /* permission */
102 NULL
, /* updatepage */
103 NULL
, /* revalidate */
107 ncp_dir_read(struct file
*filp
, char *buf
, size_t count
, loff_t
*ppos
)
113 * Dentry operations routines
115 static int ncp_lookup_validate(struct dentry
*, int);
116 static int ncp_hash_dentry(struct dentry
*, struct qstr
*);
117 static int ncp_compare_dentry (struct dentry
*, struct qstr
*, struct qstr
*);
118 static void ncp_delete_dentry(struct dentry
*);
120 struct dentry_operations ncp_dentry_operations
=
122 ncp_lookup_validate
, /* d_revalidate(struct dentry *, int) */
123 ncp_hash_dentry
, /* d_hash */
124 ncp_compare_dentry
, /* d_compare */
125 ncp_delete_dentry
/* d_delete(struct dentry *) */
130 * XXX: It would be better to use the tolower from linux/ctype.h,
131 * but _ctype is needed and it is not exported.
133 #define tolower(c) (((c) >= 'A' && (c) <= 'Z') ? (c)-('A'-'a') : (c))
136 * Note: leave the hash unchanged if the directory
140 ncp_hash_dentry(struct dentry
*dentry
, struct qstr
*this)
145 if (!ncp_case_sensitive(dentry
->d_inode
)) {
146 hash
= init_name_hash();
147 for (i
=0; i
<this->len
; i
++)
148 hash
= partial_name_hash(tolower(this->name
[i
]),hash
);
149 this->hash
= end_name_hash(hash
);
155 ncp_compare_dentry(struct dentry
*dentry
, struct qstr
*a
, struct qstr
*b
)
159 if (a
->len
!= b
->len
) return 1;
161 if (ncp_case_sensitive(dentry
->d_inode
))
162 return strncmp(a
->name
, b
->name
, a
->len
);
164 for (i
=0; i
<a
->len
; i
++)
165 if (tolower(a
->name
[i
]) != tolower(b
->name
[i
]))
172 * This is the callback from dput() when d_count is going to 0.
173 * We use this to unhash dentries with bad inodes and close files.
176 ncp_delete_dentry(struct dentry
* dentry
)
178 struct inode
*inode
= dentry
->d_inode
;
182 if (is_bad_inode(inode
))
187 * Lock the superblock, then recheck the dentry count.
188 * (Somebody might have used it again ...)
190 if (dentry
->d_count
== 1 && NCP_FINFO(inode
)->opened
) {
191 #ifdef NCPFS_PARANOIA
192 printk(KERN_DEBUG
"ncp_delete_dentry: closing file %s/%s\n",
193 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
195 ncp_make_closed(inode
);
199 /* N.B. Unhash negative dentries? */
204 * Generate a unique inode number.
206 ino_t
ncp_invent_inos(unsigned long n
)
208 static ino_t ino
= 2;
220 ncp_single_volume(struct ncp_server
*server
)
222 return (server
->m
.mounted_vol
[0] != '\0');
225 static inline int ncp_is_server_root(struct inode
*inode
)
227 return (!ncp_single_volume(NCP_SERVER(inode
)) &&
228 inode
== inode
->i_sb
->s_root
->d_inode
);
231 static inline void ncp_lock_dircache(void)
238 static inline void ncp_unlock_dircache(void)
246 * This is the callback when the dcache has a lookup hit.
250 #ifdef CONFIG_NCPFS_STRONG
251 /* try to delete a readonly file (NW R bit set) */
254 ncp_force_unlink(struct inode
*dir
, struct dentry
* dentry
)
257 struct nw_modify_dos_info info
;
261 memset(&info
, 0, sizeof(info
));
263 /* remove the Read-Only flag on the NW server */
264 inode
= dentry
->d_inode
;
266 old_nwattr
= NCP_FINFO(inode
)->nwattr
;
267 info
.attributes
= old_nwattr
& ~(aRONLY
|aDELETEINHIBIT
|aRENAMEINHIBIT
);
268 res2
= ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode
), inode
, NULL
, DM_ATTRIBUTES
, &info
);
272 /* now try again the delete operation */
273 res
= ncp_del_file_or_subdir2(NCP_SERVER(dir
), dentry
);
275 if (res
) /* delete failed, set R bit again */
277 info
.attributes
= old_nwattr
;
278 res2
= ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode
), inode
, NULL
, DM_ATTRIBUTES
, &info
);
285 #endif /* CONFIG_NCPFS_STRONG */
287 #ifdef CONFIG_NCPFS_STRONG
289 ncp_force_rename(struct inode
*old_dir
, struct dentry
* old_dentry
, char *_old_name
,
290 struct inode
*new_dir
, struct dentry
* new_dentry
, char *_new_name
)
292 struct nw_modify_dos_info info
;
294 struct inode
*old_inode
= old_dentry
->d_inode
;
295 __u32 old_nwattr
= NCP_FINFO(old_inode
)->nwattr
;
296 __u32 new_nwattr
= 0; /* shut compiler warning */
297 int old_nwattr_changed
= 0;
298 int new_nwattr_changed
= 0;
300 memset(&info
, 0, sizeof(info
));
302 /* remove the Read-Only flag on the NW server */
304 info
.attributes
= old_nwattr
& ~(aRONLY
|aRENAMEINHIBIT
|aDELETEINHIBIT
);
305 res2
= ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode
), old_inode
, NULL
, DM_ATTRIBUTES
, &info
);
307 old_nwattr_changed
= 1;
308 if (new_dentry
&& new_dentry
->d_inode
) {
309 new_nwattr
= NCP_FINFO(new_dentry
->d_inode
)->nwattr
;
310 info
.attributes
= new_nwattr
& ~(aRONLY
|aRENAMEINHIBIT
|aDELETEINHIBIT
);
311 res2
= ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir
), new_dir
, _new_name
, DM_ATTRIBUTES
, &info
);
313 new_nwattr_changed
= 1;
315 /* now try again the rename operation */
316 /* but only if something really happened */
317 if (new_nwattr_changed
|| old_nwattr_changed
) {
318 res
= ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir
),
324 /* file was successfully renamed, so:
325 do not set attributes on old file - it no longer exists
326 copy attributes from old file to new */
327 new_nwattr_changed
= old_nwattr_changed
;
328 new_nwattr
= old_nwattr
;
329 old_nwattr_changed
= 0;
332 if (old_nwattr_changed
) {
333 info
.attributes
= old_nwattr
;
334 res2
= ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode
), old_inode
, NULL
, DM_ATTRIBUTES
, &info
);
337 if (new_nwattr_changed
) {
338 info
.attributes
= new_nwattr
;
339 res2
= ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir
), new_dir
, _new_name
, DM_ATTRIBUTES
, &info
);
344 #endif /* CONFIG_NCPFS_STRONG */
348 ncp_lookup_validate(struct dentry
* dentry
, int flags
)
350 struct ncp_server
*server
;
351 struct inode
*dir
= dentry
->d_parent
->d_inode
;
354 int len
= dentry
->d_name
.len
;
355 struct ncpfs_inode_info finfo
;
356 __u8 __name
[dentry
->d_name
.len
+ 1];
358 if (!dentry
->d_inode
) {
359 DPRINTK(KERN_DEBUG
"ncp_lookup_validate: called with dentry->d_inode already NULL.\n");
363 if (!dir
|| !S_ISDIR(dir
->i_mode
)) {
364 printk(KERN_WARNING
"ncp_lookup_validate: inode is NULL or not a directory.\n");
367 server
= NCP_SERVER(dir
);
369 if (!ncp_conn_valid(server
))
372 strncpy(__name
, dentry
->d_name
.name
, len
);
374 #ifdef NCPFS_PARANOIA
375 printk(KERN_DEBUG
"ncp_lookup_validate: %s, len %d\n", __name
, len
);
378 /* If the file is in the dir cache, we do not have to ask the
381 #ifdef NCPFS_PARANOIA
382 printk(KERN_DEBUG
"ncp_lookup_validate: server lookup for %s/%s\n",
383 dentry
->d_parent
->d_name
.name
, __name
);
385 if (ncp_is_server_root(dir
))
387 io2vol(server
, __name
, 1);
389 res
= ncp_lookup_volume(server
, __name
,
393 down_case
= !ncp_preserve_case(dir
);
394 io2vol(server
, __name
, down_case
);
395 res
= ncp_obtain_info(server
, dir
, __name
,
398 #ifdef NCPFS_PARANOIA
399 printk(KERN_DEBUG
"ncp_lookup_validate: looked for %s/%s, res=%d\n",
400 dentry
->d_parent
->d_name
.name
, __name
, res
);
403 * If we didn't find it, or if it has a different dirEntNum to
404 * what we remember, it's not valid any more.
407 if (finfo
.nw_info
.i
.dirEntNum
== NCP_FINFO(dentry
->d_inode
)->dirEntNum
)
409 #ifdef NCPFS_PARANOIA
411 printk(KERN_DEBUG
"ncp_lookup_validate: found, but dirEntNum changed\n");
413 vol2io(server
, finfo
.nw_info
.i
.entryName
,
414 !ncp_preserve_entry_case(dir
,
415 finfo
.nw_info
.i
.NSCreator
));
416 ncp_update_inode2(dentry
->d_inode
, &finfo
.nw_info
);
418 if (!val
) ncp_invalid_dir_cache(dir
);
421 #ifdef NCPFS_PARANOIA
422 printk(KERN_DEBUG
"ncp_lookup_validate: result=%d\n", val
);
429 static int ncp_readdir(struct file
*filp
, void *dirent
, filldir_t filldir
)
431 struct dentry
*dentry
= filp
->f_dentry
;
432 struct inode
*inode
= dentry
->d_inode
;
433 struct ncp_server
*server
= NCP_SERVER(inode
);
434 struct ncp_dirent
*entry
= NULL
;
435 int result
, i
, index
= 0;
437 DDPRINTK(KERN_DEBUG
"ncp_readdir: reading %s/%s, pos=%d\n",
438 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
,
440 DDPRINTK(KERN_DEBUG
"ncp_readdir: inode->i_ino = %ld, c_ino = %ld\n",
441 inode
->i_ino
, c_ino
);
444 if (!ncp_conn_valid(server
))
449 if (c_entry
== NULL
) {
450 i
= sizeof(struct ncp_dirent
) * NCP_READDIR_CACHE_SIZE
;
451 c_entry
= (struct ncp_dirent
*) vmalloc(i
);
452 if (c_entry
== NULL
) {
453 printk(KERN_WARNING
"ncp_readdir: no MEMORY for cache\n");
459 if (filp
->f_pos
== 0) {
460 ncp_invalid_dir_cache(inode
);
461 if (filldir(dirent
, ".", 1, 0, inode
->i_ino
) < 0) {
466 if (filp
->f_pos
== 1) {
467 if (filldir(dirent
, "..", 2, 1,
468 dentry
->d_parent
->d_inode
->i_ino
) < 0) {
474 if ((inode
->i_dev
== c_dev
) && (inode
->i_ino
== c_ino
)) {
475 for (i
= 0; i
< c_size
; i
++) {
476 if (filp
->f_pos
== c_entry
[i
].f_pos
) {
478 c_last_returned_index
= i
;
483 if ((entry
== NULL
) && c_seen_eof
) {
489 DDPRINTK(KERN_DEBUG
"ncp_readdir: Not found in cache.\n");
491 if (ncp_is_server_root(inode
)) {
492 entries
= ncp_read_volume_list(server
, filp
->f_pos
,
493 NCP_READDIR_CACHE_SIZE
, c_entry
);
494 DPRINTK(KERN_DEBUG
"ncp_read_volume_list returned %d\n", entries
);
497 entries
= ncp_do_readdir(server
, dentry
, filp
->f_pos
,
498 NCP_READDIR_CACHE_SIZE
, c_entry
);
499 DPRINTK(KERN_DEBUG
"ncp_readdir: returned %d\n", entries
);
509 c_seen_eof
= (entries
< NCP_READDIR_CACHE_SIZE
);
510 c_dev
= inode
->i_dev
;
511 c_ino
= inode
->i_ino
;
514 c_last_returned_index
= 0;
517 for (i
= 0; i
< c_size
; i
++)
519 vol2io(server
, c_entry
[i
].i
.entryName
,
520 !ncp_preserve_entry_case(inode
,
521 c_entry
[i
].i
.NSCreator
));
526 /* Nothing found, even from a ncp call */
530 while (index
< c_size
) {
534 DDPRINTK(KERN_DEBUG
"ncp_readdir: entry->path= %s\n", entry
->i
.entryName
);
535 DDPRINTK(KERN_DEBUG
"ncp_readdir: entry->f_pos = %ld\n", entry
->f_pos
);
537 /* For getwd() we have to return the correct
538 * inode in d_ino if the inode is currently in
539 * use. Otherwise the inode number does not
540 * matter. (You can argue a lot about this..)
542 qname
.name
= entry
->i
.entryName
;
543 qname
.len
= entry
->i
.nameLen
;
544 ino
= find_inode_number(dentry
, &qname
);
546 ino
= ncp_invent_inos(1);
548 if (filldir(dirent
, entry
->i
.entryName
, entry
->i
.nameLen
,
549 entry
->f_pos
, ino
) < 0) {
552 if ((inode
->i_dev
!= c_dev
)
553 || (inode
->i_ino
!= c_ino
)
554 || (entry
->f_pos
!= filp
->f_pos
)) {
555 /* Someone has destroyed the cache while we slept
564 ncp_unlock_dircache();
570 ncp_read_volume_list(struct ncp_server
*server
, int fpos
,
571 int cache_size
, struct ncp_dirent
*entry
)
573 int i
, total_count
= 2;
574 struct ncp_volume_info info
;
576 DPRINTK(KERN_DEBUG
"ncp_read_volume_list: pos=%d\n", fpos
);
579 printk(KERN_ERR
"OOPS, we expect fpos >= 2");
584 for (i
= 0; i
< NCP_NUMBER_OF_VOLUMES
; i
++) {
586 if (ncp_get_volume_info_with_number(server
, i
, &info
) != 0)
588 if (!strlen(info
.volume_name
))
591 if (total_count
< fpos
) {
592 DPRINTK(KERN_DEBUG
"ncp_read_volume_list: skipped vol: %s\n",
594 } else if (total_count
>= fpos
+ cache_size
) {
597 DPRINTK(KERN_DEBUG
"ncp_read_volume_list: found vol: %s\n",
600 if (ncp_lookup_volume(server
, info
.volume_name
,
602 DPRINTK(KERN_DEBUG
"ncpfs: could not lookup vol %s\n",
606 entry
->f_pos
= total_count
;
612 return (total_count
- fpos
);
615 static int ncp_do_readdir(struct ncp_server
*server
, struct dentry
*dentry
,
616 int fpos
, int cache_size
, struct ncp_dirent
*entry
)
618 struct inode
*dir
= dentry
->d_inode
;
619 static struct inode
*last_dir
;
620 static int total_count
;
621 static struct nw_search_sequence seq
;
626 printk(KERN_ERR
"OOPS, we expect fpos >= 2");
630 DPRINTK(KERN_DEBUG
"ncp_do_readdir: %s/%s, fpos=%d\n",
631 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
, fpos
);
637 if ((fpos
!= total_count
) || (dir
!= last_dir
))
642 #ifdef NCPFS_PARANOIA
643 printk(KERN_DEBUG
"ncp_do_readdir: init %s, volnum=%d, dirent=%u\n",
644 dentry
->d_name
.name
, NCP_FINFO(dir
)->volNumber
, NCP_FINFO(dir
)->dirEntNum
);
646 err
= ncp_initialize_search(server
, dir
, &seq
);
649 DPRINTK(KERN_DEBUG
"ncp_do_readdir: init failed, err=%d\n", err
);
654 while (total_count
< fpos
+ cache_size
) {
655 err
= ncp_search_for_file_or_subdir(server
, &seq
, &(entry
->i
));
657 DPRINTK(KERN_DEBUG
"ncp_do_readdir: search failed, err=%d\n", err
);
660 if (total_count
< fpos
) {
661 DPRINTK(KERN_DEBUG
"ncp_do_readdir: skipped file: %s/%s\n",
662 dentry
->d_name
.name
, entry
->i
.entryName
);
664 DDPRINTK(KERN_DEBUG
"ncp_do_r: file: %s, f_pos=%d,total_count=%d",
665 entry
->i
.entryName
, fpos
, total_count
);
667 entry
->f_pos
= total_count
;
673 return (total_count
- fpos
);
676 void ncp_init_dir_cache(void)
683 void ncp_invalid_dir_cache(struct inode
*ino
)
685 if ((ino
->i_dev
== c_dev
) && (ino
->i_ino
== c_ino
)) {
692 void ncp_free_dir_cache(void)
694 DPRINTK(KERN_DEBUG
"ncp_free_dir_cache: enter\n");
696 if (c_entry
== NULL
) {
702 DPRINTK(KERN_DEBUG
"ncp_free_dir_cache: exit\n");
705 int ncp_conn_logged_in(struct ncp_server
*server
)
709 if (ncp_single_volume(server
)) {
713 io2vol(server
, server
->m
.mounted_vol
, 1);
714 if (ncp_lookup_volume(server
, server
->m
.mounted_vol
,
715 &(server
->root
.finfo
.i
)) != 0) {
716 #ifdef NCPFS_PARANOIA
717 printk(KERN_DEBUG
"ncp_conn_logged_in: %s not found\n", server
->m
.mounted_vol
);
721 vol2io(server
, server
->root
.finfo
.i
.entryName
, 1);
722 dent
= server
->root_dentry
;
724 struct inode
* ino
= dent
->d_inode
;
726 NCP_FINFO(ino
)->volNumber
= server
->root
.finfo
.i
.volNumber
;
727 NCP_FINFO(ino
)->dirEntNum
= server
->root
.finfo
.i
.dirEntNum
;
728 NCP_FINFO(ino
)->DosDirNum
= server
->root
.finfo
.i
.DosDirNum
;
730 DPRINTK(KERN_DEBUG
"ncpfs: sb->root_dentry->d_inode == NULL!\n");
733 DPRINTK(KERN_DEBUG
"ncpfs: sb->root_dentry == NULL!\n");
742 static struct dentry
*ncp_lookup(struct inode
*dir
, struct dentry
*dentry
)
744 struct ncp_server
*server
;
745 struct inode
*inode
= NULL
;
746 int found_in_cache
, down_case
= 0;
748 int len
= dentry
->d_name
.len
;
749 struct ncpfs_inode_info finfo
;
750 __u8 __name
[dentry
->d_name
.len
+ 1];
752 server
= NCP_SERVER(dir
);
755 if (!ncp_conn_valid(server
))
758 strncpy(__name
, dentry
->d_name
.name
, len
);
760 #ifdef NCPFS_PARANOIA
761 printk(KERN_DEBUG
"ncp_lookup: %s, len %d\n", __name
, len
);
764 /* If the file is in the dir cache, we do not have to ask the
770 if ((dir
->i_dev
== c_dev
) && (dir
->i_ino
== c_ino
))
772 int first
= c_last_returned_index
;
777 #ifdef NCPFS_PARANOIA
778 printk(KERN_DEBUG
"ncp_lookup: trying index: %d, name: %s\n", i
, c_entry
[i
].i
.entryName
);
780 if (strcmp(c_entry
[i
].i
.entryName
, __name
) == 0) {
781 #ifdef NCPFS_PARANOIA
782 printk(KERN_DEBUG
"ncp_lookup: found in cache!\n");
784 finfo
.nw_info
.i
= c_entry
[i
].i
;
788 i
= (i
+ 1) % c_size
;
789 } while (i
!= first
);
791 ncp_unlock_dircache();
793 if (found_in_cache
== 0)
797 #ifdef NCPFS_PARANOIA
798 printk(KERN_DEBUG
"ncp_lookup: server lookup for %s/%s\n",
799 dentry
->d_parent
->d_name
.name
, __name
);
801 if (ncp_is_server_root(dir
))
803 io2vol(server
, __name
, 1);
805 res
= ncp_lookup_volume(server
, __name
,
809 down_case
= !ncp_preserve_case(dir
);
810 io2vol(server
, __name
, down_case
);
811 res
= ncp_obtain_info(server
, dir
, __name
,
814 #ifdef NCPFS_PARANOIA
815 printk(KERN_DEBUG
"ncp_lookup: looked for %s/%s, res=%d\n",
816 dentry
->d_parent
->d_name
.name
, __name
, res
);
819 * If we didn't find an entry, make a negative dentry.
823 } else vol2io(server
, finfo
.nw_info
.i
.entryName
,
824 !ncp_preserve_entry_case(dir
,
825 finfo
.nw_info
.i
.NSCreator
));
829 * Create an inode for the entry.
831 finfo
.nw_info
.opened
= 0;
832 finfo
.ino
= ncp_invent_inos(1);
834 inode
= ncp_iget(dir
->i_sb
, &finfo
);
838 dentry
->d_op
= &ncp_dentry_operations
;
839 d_add(dentry
, inode
);
844 #ifdef NCPFS_PARANOIA
845 printk(KERN_DEBUG
"ncp_lookup: result=%d\n", error
);
847 return ERR_PTR(error
);
851 * This code is common to create, mkdir, and mknod.
853 static int ncp_instantiate(struct inode
*dir
, struct dentry
*dentry
,
854 struct ncpfs_inode_info
*finfo
)
859 ncp_invalid_dir_cache(dir
);
861 finfo
->ino
= ncp_invent_inos(1);
862 inode
= ncp_iget(dir
->i_sb
, finfo
);
865 d_instantiate(dentry
,inode
);
871 #ifdef NCPFS_PARANOIA
872 printk(KERN_DEBUG
"ncp_instantiate: %s/%s failed, closing file\n",
873 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
875 ncp_close_file(NCP_SERVER(dir
), finfo
->nw_info
.file_handle
);
879 int ncp_create_new(struct inode
*dir
, struct dentry
*dentry
, int mode
,
883 struct ncpfs_inode_info finfo
;
884 __u8 _name
[dentry
->d_name
.len
+ 1];
886 #ifdef NCPFS_PARANOIA
887 printk(KERN_DEBUG
"ncp_create_new: creating %s/%s, mode=%x\n",
888 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
, mode
);
891 if (!ncp_conn_valid(NCP_SERVER(dir
)))
894 strncpy(_name
, dentry
->d_name
.name
, dentry
->d_name
.len
);
895 _name
[dentry
->d_name
.len
] = '\0';
897 io2vol(NCP_SERVER(dir
), _name
, !ncp_preserve_case(dir
));
900 result
= ncp_open_create_file_or_subdir(NCP_SERVER(dir
), dir
, _name
,
901 OC_MODE_CREATE
| OC_MODE_OPEN
| OC_MODE_REPLACE
,
902 attributes
, AR_READ
| AR_WRITE
, &finfo
.nw_info
);
904 finfo
.nw_info
.access
= O_RDWR
;
905 error
= ncp_instantiate(dir
, dentry
, &finfo
);
907 if (result
== 0x87) error
= -ENAMETOOLONG
;
908 DPRINTK(KERN_DEBUG
"ncp_create: %s/%s failed\n",
909 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
916 static int ncp_create(struct inode
*dir
, struct dentry
*dentry
, int mode
)
918 return ncp_create_new(dir
, dentry
, mode
, 0);
921 static int ncp_mkdir(struct inode
*dir
, struct dentry
*dentry
, int mode
)
924 struct ncpfs_inode_info finfo
;
925 __u8 _name
[dentry
->d_name
.len
+ 1];
927 DPRINTK(KERN_DEBUG
"ncp_mkdir: making %s/%s\n",
928 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
930 if (!ncp_conn_valid(NCP_SERVER(dir
)))
933 strncpy(_name
, dentry
->d_name
.name
, dentry
->d_name
.len
);
934 _name
[dentry
->d_name
.len
] = '\0';
935 io2vol(NCP_SERVER(dir
), _name
, !ncp_preserve_case(dir
));
938 if (ncp_open_create_file_or_subdir(NCP_SERVER(dir
), dir
, _name
,
939 OC_MODE_CREATE
, aDIR
, 0xffff,
940 &finfo
.nw_info
) == 0)
942 error
= ncp_instantiate(dir
, dentry
, &finfo
);
948 static int ncp_rmdir(struct inode
*dir
, struct dentry
*dentry
)
951 __u8 _name
[dentry
->d_name
.len
+ 1];
953 DPRINTK(KERN_DEBUG
"ncp_rmdir: removing %s/%s\n",
954 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
957 if (!ncp_conn_valid(NCP_SERVER(dir
)))
961 if (!list_empty(&dentry
->d_hash
))
964 strncpy(_name
, dentry
->d_name
.name
, dentry
->d_name
.len
);
965 _name
[dentry
->d_name
.len
] = '\0';
967 io2vol(NCP_SERVER(dir
), _name
, !ncp_preserve_case(dir
));
968 result
= ncp_del_file_or_subdir(NCP_SERVER(dir
), dir
, _name
);
971 ncp_invalid_dir_cache(dir
);
974 case 0x85: /* unauthorized to delete file */
975 case 0x8A: /* unauthorized to delete file */
979 case 0x90: /* read only */
982 case 0x9F: /* in use by another client */
985 case 0xA0: /* directory not empty */
988 case 0xFF: /* someone deleted file */
999 static int ncp_unlink(struct inode
*dir
, struct dentry
*dentry
)
1001 struct inode
*inode
= dentry
->d_inode
;
1004 DPRINTK(KERN_DEBUG
"ncp_unlink: unlinking %s/%s\n",
1005 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
1008 if (!ncp_conn_valid(NCP_SERVER(dir
)))
1012 * Check whether to close the file ...
1014 if (inode
&& NCP_FINFO(inode
)->opened
) {
1015 #ifdef NCPFS_PARANOIA
1016 printk(KERN_DEBUG
"ncp_unlink: closing file\n");
1018 ncp_make_closed(inode
);
1021 error
= ncp_del_file_or_subdir2(NCP_SERVER(dir
), dentry
);
1022 #ifdef CONFIG_NCPFS_STRONG
1023 /* 9C is Invalid path.. It should be 8F, 90 - read only, but
1025 if (error
== 0x9C && NCP_SERVER(dir
)->m
.flags
& NCP_MOUNT_STRONG
) { /* R/O */
1026 error
= ncp_force_unlink(dir
, dentry
);
1031 DPRINTK(KERN_DEBUG
"ncp: removed %s/%s\n",
1032 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
1033 ncp_invalid_dir_cache(dir
);
1040 case 0x8D: /* some files in use */
1041 case 0x8E: /* all files in use */
1044 case 0x8F: /* some read only */
1045 case 0x90: /* all read only */
1046 case 0x9C: /* !!! returned when in-use or read-only by NW4 */
1061 static int ncp_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
1062 struct inode
*new_dir
, struct dentry
*new_dentry
)
1064 int old_len
= old_dentry
->d_name
.len
;
1065 int new_len
= new_dentry
->d_name
.len
;
1067 char _old_name
[old_dentry
->d_name
.len
+ 1];
1068 char _new_name
[new_dentry
->d_name
.len
+ 1];
1070 DPRINTK(KERN_DEBUG
"ncp_rename: %s/%s to %s/%s\n",
1071 old_dentry
->d_parent
->d_name
.name
, old_dentry
->d_name
.name
,
1072 new_dentry
->d_parent
->d_name
.name
, new_dentry
->d_name
.name
);
1075 if (!ncp_conn_valid(NCP_SERVER(old_dir
)))
1078 strncpy(_old_name
, old_dentry
->d_name
.name
, old_len
);
1079 _old_name
[old_len
] = '\0';
1080 io2vol(NCP_SERVER(old_dir
), _old_name
, !ncp_preserve_case(old_dir
));
1082 strncpy(_new_name
, new_dentry
->d_name
.name
, new_len
);
1083 _new_name
[new_len
] = '\0';
1084 io2vol(NCP_SERVER(new_dir
), _new_name
, !ncp_preserve_case(new_dir
));
1086 error
= ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir
),
1088 new_dir
, _new_name
);
1089 #ifdef CONFIG_NCPFS_STRONG
1090 if ((error
== 0x90 || error
== -EACCES
) && NCP_SERVER(old_dir
)->m
.flags
& NCP_MOUNT_STRONG
) { /* RO */
1091 error
= ncp_force_rename(old_dir
, old_dentry
, _old_name
,
1092 new_dir
, new_dentry
, _new_name
);
1097 DPRINTK(KERN_DEBUG
"ncp renamed %s -> %s.\n",
1098 old_dentry
->d_name
.name
,new_dentry
->d_name
.name
);
1099 ncp_invalid_dir_cache(old_dir
);
1100 ncp_invalid_dir_cache(new_dir
);
1101 /* d_move(old_dentry, new_dentry); */
1104 error
= -ENAMETOOLONG
;
1117 /* The following routines are taken directly from msdos-fs */
1119 /* Linear day numbers of the respective 1sts in non-leap years. */
1121 static int day_n
[] =
1122 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
1123 /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
1126 extern struct timezone sys_tz
;
1128 static int utc2local(int time
)
1130 return time
- sys_tz
.tz_minuteswest
* 60;
1133 static int local2utc(int time
)
1135 return time
+ sys_tz
.tz_minuteswest
* 60;
1138 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
1140 ncp_date_dos2unix(unsigned short time
, unsigned short date
)
1142 int month
, year
, secs
;
1144 /* first subtract and mask after that... Otherwise, if
1145 date == 0, bad things happen */
1146 month
= ((date
>> 5) - 1) & 15;
1148 secs
= (time
& 31) * 2 + 60 * ((time
>> 5) & 63) + (time
>> 11) * 3600 +
1149 86400 * ((date
& 31) - 1 + day_n
[month
] + (year
/ 4) +
1150 year
* 365 - ((year
& 3) == 0 && month
< 2 ? 1 : 0) + 3653);
1151 /* days since 1.1.70 plus 80's leap day */
1152 return local2utc(secs
);
1156 /* Convert linear UNIX date to a MS-DOS time/date pair. */
1158 ncp_date_unix2dos(int unix_date
, unsigned short *time
, unsigned short *date
)
1160 int day
, year
, nl_day
, month
;
1162 unix_date
= utc2local(unix_date
);
1163 *time
= (unix_date
% 60) / 2 + (((unix_date
/ 60) % 60) << 5) +
1164 (((unix_date
/ 3600) % 24) << 11);
1165 day
= unix_date
/ 86400 - 3652;
1167 if ((year
+ 3) / 4 + 365 * year
> day
)
1169 day
-= (year
+ 3) / 4 + 365 * year
;
1170 if (day
== 59 && !(year
& 3)) {
1174 nl_day
= (year
& 3) || day
<= 59 ? day
: day
- 1;
1175 for (month
= 0; month
< 12; month
++)
1176 if (day_n
[month
] > nl_day
)
1179 *date
= nl_day
- day_n
[month
- 1] + 1 + (month
<< 5) + (year
<< 9);