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 DECLARE_MUTEX(c_sem
);
43 static int ncp_read_volume_list(struct ncp_server
*, int, int,
45 static int ncp_do_readdir(struct ncp_server
*, struct dentry
*, int, int,
48 static ssize_t
ncp_dir_read(struct file
*, char *, size_t, loff_t
*);
49 static int ncp_readdir(struct file
*, void *, filldir_t
);
51 static int ncp_create(struct inode
*, struct dentry
*, int);
52 static struct dentry
*ncp_lookup(struct inode
*, struct dentry
*);
53 static int ncp_unlink(struct inode
*, struct dentry
*);
54 static int ncp_mkdir(struct inode
*, struct dentry
*, int);
55 static int ncp_rmdir(struct inode
*, struct dentry
*);
56 static int ncp_rename(struct inode
*, struct dentry
*,
57 struct inode
*, struct dentry
*);
58 #ifdef CONFIG_NCPFS_EXTRAS
59 extern int ncp_symlink(struct inode
*, struct dentry
*, const char *);
62 static struct file_operations ncp_dir_operations
=
64 NULL
, /* lseek - default */
65 ncp_dir_read
, /* read - bad */
66 NULL
, /* write - bad */
67 ncp_readdir
, /* readdir */
68 NULL
, /* poll - default */
69 ncp_ioctl
, /* ioctl */
71 NULL
, /* no special open code */
73 NULL
, /* no special release code */
77 struct inode_operations ncp_dir_inode_operations
=
79 &ncp_dir_operations
, /* default directory file ops */
80 ncp_create
, /* create */
81 ncp_lookup
, /* lookup */
83 ncp_unlink
, /* unlink */
84 #ifdef CONFIG_NCPFS_EXTRAS
85 ncp_symlink
, /* symlink */
89 ncp_mkdir
, /* mkdir */
90 ncp_rmdir
, /* rmdir */
92 ncp_rename
, /* rename */
94 NULL
, /* follow link */
100 NULL
, /* permission */
102 NULL
, /* revalidate */
106 ncp_dir_read(struct file
*filp
, char *buf
, size_t count
, loff_t
*ppos
)
112 * Dentry operations routines
114 static int ncp_lookup_validate(struct dentry
*, int);
115 static int ncp_hash_dentry(struct dentry
*, struct qstr
*);
116 static int ncp_compare_dentry (struct dentry
*, struct qstr
*, struct qstr
*);
117 static void ncp_delete_dentry(struct dentry
*);
119 struct dentry_operations ncp_dentry_operations
=
121 ncp_lookup_validate
, /* d_revalidate(struct dentry *, int) */
122 ncp_hash_dentry
, /* d_hash */
123 ncp_compare_dentry
, /* d_compare */
124 ncp_delete_dentry
/* d_delete(struct dentry *) */
129 * XXX: It would be better to use the tolower from linux/ctype.h,
130 * but _ctype is needed and it is not exported.
132 #define tolower(c) (((c) >= 'A' && (c) <= 'Z') ? (c)-('A'-'a') : (c))
135 * Note: leave the hash unchanged if the directory
139 ncp_hash_dentry(struct dentry
*dentry
, struct qstr
*this)
144 if (!ncp_case_sensitive(dentry
->d_inode
)) {
145 hash
= init_name_hash();
146 for (i
=0; i
<this->len
; i
++)
147 hash
= partial_name_hash(tolower(this->name
[i
]),hash
);
148 this->hash
= end_name_hash(hash
);
154 ncp_compare_dentry(struct dentry
*dentry
, struct qstr
*a
, struct qstr
*b
)
158 if (a
->len
!= b
->len
) return 1;
160 if (ncp_case_sensitive(dentry
->d_inode
))
161 return strncmp(a
->name
, b
->name
, a
->len
);
163 for (i
=0; i
<a
->len
; i
++)
164 if (tolower(a
->name
[i
]) != tolower(b
->name
[i
]))
171 * This is the callback from dput() when d_count is going to 0.
172 * We use this to unhash dentries with bad inodes and close files.
175 ncp_delete_dentry(struct dentry
* dentry
)
177 struct inode
*inode
= dentry
->d_inode
;
181 if (is_bad_inode(inode
))
186 * Lock the superblock, then recheck the dentry count.
187 * (Somebody might have used it again ...)
189 if (dentry
->d_count
== 1 && NCP_FINFO(inode
)->opened
) {
190 #ifdef NCPFS_PARANOIA
191 printk(KERN_DEBUG
"ncp_delete_dentry: closing file %s/%s\n",
192 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
194 ncp_make_closed(inode
);
198 /* N.B. Unhash negative dentries? */
203 * Generate a unique inode number.
205 ino_t
ncp_invent_inos(unsigned long n
)
207 static ino_t ino
= 2;
219 ncp_single_volume(struct ncp_server
*server
)
221 return (server
->m
.mounted_vol
[0] != '\0');
224 static inline int ncp_is_server_root(struct inode
*inode
)
226 return (!ncp_single_volume(NCP_SERVER(inode
)) &&
227 inode
== inode
->i_sb
->s_root
->d_inode
);
230 static inline void ncp_lock_dircache(void)
235 static inline void ncp_unlock_dircache(void)
242 * This is the callback when the dcache has a lookup hit.
246 #ifdef CONFIG_NCPFS_STRONG
247 /* try to delete a readonly file (NW R bit set) */
250 ncp_force_unlink(struct inode
*dir
, struct dentry
* dentry
)
253 struct nw_modify_dos_info info
;
257 memset(&info
, 0, sizeof(info
));
259 /* remove the Read-Only flag on the NW server */
260 inode
= dentry
->d_inode
;
262 old_nwattr
= NCP_FINFO(inode
)->nwattr
;
263 info
.attributes
= old_nwattr
& ~(aRONLY
|aDELETEINHIBIT
|aRENAMEINHIBIT
);
264 res2
= ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode
), inode
, NULL
, DM_ATTRIBUTES
, &info
);
268 /* now try again the delete operation */
269 res
= ncp_del_file_or_subdir2(NCP_SERVER(dir
), dentry
);
271 if (res
) /* delete failed, set R bit again */
273 info
.attributes
= old_nwattr
;
274 res2
= ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode
), inode
, NULL
, DM_ATTRIBUTES
, &info
);
281 #endif /* CONFIG_NCPFS_STRONG */
283 #ifdef CONFIG_NCPFS_STRONG
285 ncp_force_rename(struct inode
*old_dir
, struct dentry
* old_dentry
, char *_old_name
,
286 struct inode
*new_dir
, struct dentry
* new_dentry
, char *_new_name
)
288 struct nw_modify_dos_info info
;
290 struct inode
*old_inode
= old_dentry
->d_inode
;
291 __u32 old_nwattr
= NCP_FINFO(old_inode
)->nwattr
;
292 __u32 new_nwattr
= 0; /* shut compiler warning */
293 int old_nwattr_changed
= 0;
294 int new_nwattr_changed
= 0;
296 memset(&info
, 0, sizeof(info
));
298 /* remove the Read-Only flag on the NW server */
300 info
.attributes
= old_nwattr
& ~(aRONLY
|aRENAMEINHIBIT
|aDELETEINHIBIT
);
301 res2
= ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode
), old_inode
, NULL
, DM_ATTRIBUTES
, &info
);
303 old_nwattr_changed
= 1;
304 if (new_dentry
&& new_dentry
->d_inode
) {
305 new_nwattr
= NCP_FINFO(new_dentry
->d_inode
)->nwattr
;
306 info
.attributes
= new_nwattr
& ~(aRONLY
|aRENAMEINHIBIT
|aDELETEINHIBIT
);
307 res2
= ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir
), new_dir
, _new_name
, DM_ATTRIBUTES
, &info
);
309 new_nwattr_changed
= 1;
311 /* now try again the rename operation */
312 /* but only if something really happened */
313 if (new_nwattr_changed
|| old_nwattr_changed
) {
314 res
= ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir
),
320 /* file was successfully renamed, so:
321 do not set attributes on old file - it no longer exists
322 copy attributes from old file to new */
323 new_nwattr_changed
= old_nwattr_changed
;
324 new_nwattr
= old_nwattr
;
325 old_nwattr_changed
= 0;
328 if (old_nwattr_changed
) {
329 info
.attributes
= old_nwattr
;
330 res2
= ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode
), old_inode
, NULL
, DM_ATTRIBUTES
, &info
);
333 if (new_nwattr_changed
) {
334 info
.attributes
= new_nwattr
;
335 res2
= ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir
), new_dir
, _new_name
, DM_ATTRIBUTES
, &info
);
340 #endif /* CONFIG_NCPFS_STRONG */
344 ncp_lookup_validate(struct dentry
* dentry
, int flags
)
346 struct ncp_server
*server
;
347 struct inode
*dir
= dentry
->d_parent
->d_inode
;
350 int len
= dentry
->d_name
.len
;
351 struct ncpfs_inode_info finfo
;
352 __u8 __name
[dentry
->d_name
.len
+ 1];
354 server
= NCP_SERVER(dir
);
356 if (!ncp_conn_valid(server
))
359 strncpy(__name
, dentry
->d_name
.name
, len
);
361 #ifdef NCPFS_PARANOIA
362 printk(KERN_DEBUG
"ncp_lookup_validate: %s, len %d\n", __name
, len
);
365 /* If the file is in the dir cache, we do not have to ask the
368 #ifdef NCPFS_PARANOIA
369 printk(KERN_DEBUG
"ncp_lookup_validate: server lookup for %s/%s\n",
370 dentry
->d_parent
->d_name
.name
, __name
);
372 if (ncp_is_server_root(dir
))
374 io2vol(server
, __name
, 1);
376 res
= ncp_lookup_volume(server
, __name
,
380 down_case
= !ncp_preserve_case(dir
);
381 io2vol(server
, __name
, down_case
);
382 res
= ncp_obtain_info(server
, dir
, __name
,
385 #ifdef NCPFS_PARANOIA
386 printk(KERN_DEBUG
"ncp_lookup_validate: looked for %s/%s, res=%d\n",
387 dentry
->d_parent
->d_name
.name
, __name
, res
);
390 * If we didn't find it, or if it has a different dirEntNum to
391 * what we remember, it's not valid any more.
394 if (finfo
.nw_info
.i
.dirEntNum
== NCP_FINFO(dentry
->d_inode
)->dirEntNum
)
396 #ifdef NCPFS_PARANOIA
398 printk(KERN_DEBUG
"ncp_lookup_validate: found, but dirEntNum changed\n");
400 vol2io(server
, finfo
.nw_info
.i
.entryName
,
401 !ncp_preserve_entry_case(dir
,
402 finfo
.nw_info
.i
.NSCreator
));
403 ncp_update_inode2(dentry
->d_inode
, &finfo
.nw_info
);
405 if (!val
) ncp_invalid_dir_cache(dir
);
408 #ifdef NCPFS_PARANOIA
409 printk(KERN_DEBUG
"ncp_lookup_validate: result=%d\n", val
);
416 static int ncp_readdir(struct file
*filp
, void *dirent
, filldir_t filldir
)
418 struct dentry
*dentry
= filp
->f_dentry
;
419 struct inode
*inode
= dentry
->d_inode
;
420 struct ncp_server
*server
= NCP_SERVER(inode
);
421 struct ncp_dirent
*entry
= NULL
;
422 int result
, i
, index
= 0;
424 DDPRINTK(KERN_DEBUG
"ncp_readdir: reading %s/%s, pos=%d\n",
425 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
,
427 DDPRINTK(KERN_DEBUG
"ncp_readdir: inode->i_ino = %ld, c_ino = %ld\n",
428 inode
->i_ino
, c_ino
);
431 if (!ncp_conn_valid(server
))
436 if (c_entry
== NULL
) {
437 i
= sizeof(struct ncp_dirent
) * NCP_READDIR_CACHE_SIZE
;
438 c_entry
= (struct ncp_dirent
*) vmalloc(i
);
439 if (c_entry
== NULL
) {
440 printk(KERN_WARNING
"ncp_readdir: no MEMORY for cache\n");
446 if (filp
->f_pos
== 0) {
447 ncp_invalid_dir_cache(inode
);
448 if (filldir(dirent
, ".", 1, 0, inode
->i_ino
) < 0) {
453 if (filp
->f_pos
== 1) {
454 if (filldir(dirent
, "..", 2, 1,
455 dentry
->d_parent
->d_inode
->i_ino
) < 0) {
461 if ((inode
->i_dev
== c_dev
) && (inode
->i_ino
== c_ino
)) {
462 for (i
= 0; i
< c_size
; i
++) {
463 if (filp
->f_pos
== c_entry
[i
].f_pos
) {
465 c_last_returned_index
= i
;
470 if ((entry
== NULL
) && c_seen_eof
) {
476 DDPRINTK(KERN_DEBUG
"ncp_readdir: Not found in cache.\n");
478 if (ncp_is_server_root(inode
)) {
479 entries
= ncp_read_volume_list(server
, filp
->f_pos
,
480 NCP_READDIR_CACHE_SIZE
, c_entry
);
481 DPRINTK(KERN_DEBUG
"ncp_read_volume_list returned %d\n", entries
);
484 entries
= ncp_do_readdir(server
, dentry
, filp
->f_pos
,
485 NCP_READDIR_CACHE_SIZE
, c_entry
);
486 DPRINTK(KERN_DEBUG
"ncp_readdir: returned %d\n", entries
);
496 c_seen_eof
= (entries
< NCP_READDIR_CACHE_SIZE
);
497 c_dev
= inode
->i_dev
;
498 c_ino
= inode
->i_ino
;
501 c_last_returned_index
= 0;
504 for (i
= 0; i
< c_size
; i
++)
506 vol2io(server
, c_entry
[i
].i
.entryName
,
507 !ncp_preserve_entry_case(inode
,
508 c_entry
[i
].i
.NSCreator
));
513 /* Nothing found, even from a ncp call */
517 while (index
< c_size
) {
521 DDPRINTK(KERN_DEBUG
"ncp_readdir: entry->path= %s\n", entry
->i
.entryName
);
522 DDPRINTK(KERN_DEBUG
"ncp_readdir: entry->f_pos = %ld\n", entry
->f_pos
);
524 /* For getwd() we have to return the correct
525 * inode in d_ino if the inode is currently in
526 * use. Otherwise the inode number does not
527 * matter. (You can argue a lot about this..)
529 qname
.name
= entry
->i
.entryName
;
530 qname
.len
= entry
->i
.nameLen
;
531 ino
= find_inode_number(dentry
, &qname
);
533 ino
= ncp_invent_inos(1);
535 if (filldir(dirent
, entry
->i
.entryName
, entry
->i
.nameLen
,
536 entry
->f_pos
, ino
) < 0) {
539 if ((inode
->i_dev
!= c_dev
)
540 || (inode
->i_ino
!= c_ino
)
541 || (entry
->f_pos
!= filp
->f_pos
)) {
542 /* Someone has destroyed the cache while we slept
551 ncp_unlock_dircache();
557 ncp_read_volume_list(struct ncp_server
*server
, int fpos
,
558 int cache_size
, struct ncp_dirent
*entry
)
560 int i
, total_count
= 2;
561 struct ncp_volume_info info
;
563 DPRINTK(KERN_DEBUG
"ncp_read_volume_list: pos=%d\n", fpos
);
566 printk(KERN_ERR
"OOPS, we expect fpos >= 2");
571 for (i
= 0; i
< NCP_NUMBER_OF_VOLUMES
; i
++) {
573 if (ncp_get_volume_info_with_number(server
, i
, &info
) != 0)
575 if (!strlen(info
.volume_name
))
578 if (total_count
< fpos
) {
579 DPRINTK(KERN_DEBUG
"ncp_read_volume_list: skipped vol: %s\n",
581 } else if (total_count
>= fpos
+ cache_size
) {
584 DPRINTK(KERN_DEBUG
"ncp_read_volume_list: found vol: %s\n",
587 if (ncp_lookup_volume(server
, info
.volume_name
,
589 DPRINTK(KERN_DEBUG
"ncpfs: could not lookup vol %s\n",
593 entry
->f_pos
= total_count
;
599 return (total_count
- fpos
);
602 static int ncp_do_readdir(struct ncp_server
*server
, struct dentry
*dentry
,
603 int fpos
, int cache_size
, struct ncp_dirent
*entry
)
605 struct inode
*dir
= dentry
->d_inode
;
606 static struct inode
*last_dir
;
607 static int total_count
;
608 static struct nw_search_sequence seq
;
613 printk(KERN_ERR
"OOPS, we expect fpos >= 2");
617 DPRINTK(KERN_DEBUG
"ncp_do_readdir: %s/%s, fpos=%d\n",
618 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
, fpos
);
624 if ((fpos
!= total_count
) || (dir
!= last_dir
))
629 #ifdef NCPFS_PARANOIA
630 printk(KERN_DEBUG
"ncp_do_readdir: init %s, volnum=%d, dirent=%u\n",
631 dentry
->d_name
.name
, NCP_FINFO(dir
)->volNumber
, NCP_FINFO(dir
)->dirEntNum
);
633 err
= ncp_initialize_search(server
, dir
, &seq
);
636 DPRINTK(KERN_DEBUG
"ncp_do_readdir: init failed, err=%d\n", err
);
641 while (total_count
< fpos
+ cache_size
) {
642 err
= ncp_search_for_file_or_subdir(server
, &seq
, &(entry
->i
));
644 DPRINTK(KERN_DEBUG
"ncp_do_readdir: search failed, err=%d\n", err
);
647 if (total_count
< fpos
) {
648 DPRINTK(KERN_DEBUG
"ncp_do_readdir: skipped file: %s/%s\n",
649 dentry
->d_name
.name
, entry
->i
.entryName
);
651 DDPRINTK(KERN_DEBUG
"ncp_do_r: file: %s, f_pos=%d,total_count=%d",
652 entry
->i
.entryName
, fpos
, total_count
);
654 entry
->f_pos
= total_count
;
660 return (total_count
- fpos
);
663 void ncp_init_dir_cache(void)
670 void ncp_invalid_dir_cache(struct inode
*ino
)
672 if ((ino
->i_dev
== c_dev
) && (ino
->i_ino
== c_ino
)) {
679 void ncp_free_dir_cache(void)
681 DPRINTK(KERN_DEBUG
"ncp_free_dir_cache: enter\n");
683 if (c_entry
== NULL
) {
689 DPRINTK(KERN_DEBUG
"ncp_free_dir_cache: exit\n");
692 int ncp_conn_logged_in(struct ncp_server
*server
)
696 if (ncp_single_volume(server
)) {
700 io2vol(server
, server
->m
.mounted_vol
, 1);
701 if (ncp_lookup_volume(server
, server
->m
.mounted_vol
,
702 &(server
->root
.finfo
.i
)) != 0) {
703 #ifdef NCPFS_PARANOIA
704 printk(KERN_DEBUG
"ncp_conn_logged_in: %s not found\n", server
->m
.mounted_vol
);
708 vol2io(server
, server
->root
.finfo
.i
.entryName
, 1);
709 dent
= server
->root_dentry
;
711 struct inode
* ino
= dent
->d_inode
;
713 NCP_FINFO(ino
)->volNumber
= server
->root
.finfo
.i
.volNumber
;
714 NCP_FINFO(ino
)->dirEntNum
= server
->root
.finfo
.i
.dirEntNum
;
715 NCP_FINFO(ino
)->DosDirNum
= server
->root
.finfo
.i
.DosDirNum
;
717 DPRINTK(KERN_DEBUG
"ncpfs: sb->root_dentry->d_inode == NULL!\n");
720 DPRINTK(KERN_DEBUG
"ncpfs: sb->root_dentry == NULL!\n");
729 static struct dentry
*ncp_lookup(struct inode
*dir
, struct dentry
*dentry
)
731 struct ncp_server
*server
;
732 struct inode
*inode
= NULL
;
733 int found_in_cache
, down_case
= 0;
735 int len
= dentry
->d_name
.len
;
736 struct ncpfs_inode_info finfo
;
737 __u8 __name
[dentry
->d_name
.len
+ 1];
739 server
= NCP_SERVER(dir
);
742 if (!ncp_conn_valid(server
))
745 strncpy(__name
, dentry
->d_name
.name
, len
);
747 #ifdef NCPFS_PARANOIA
748 printk(KERN_DEBUG
"ncp_lookup: %s, len %d\n", __name
, len
);
751 /* If the file is in the dir cache, we do not have to ask the
757 if ((dir
->i_dev
== c_dev
) && (dir
->i_ino
== c_ino
))
759 int first
= c_last_returned_index
;
764 #ifdef NCPFS_PARANOIA
765 printk(KERN_DEBUG
"ncp_lookup: trying index: %d, name: %s\n", i
, c_entry
[i
].i
.entryName
);
767 if (strcmp(c_entry
[i
].i
.entryName
, __name
) == 0) {
768 #ifdef NCPFS_PARANOIA
769 printk(KERN_DEBUG
"ncp_lookup: found in cache!\n");
771 finfo
.nw_info
.i
= c_entry
[i
].i
;
775 i
= (i
+ 1) % c_size
;
776 } while (i
!= first
);
778 ncp_unlock_dircache();
780 if (found_in_cache
== 0)
784 #ifdef NCPFS_PARANOIA
785 printk(KERN_DEBUG
"ncp_lookup: server lookup for %s/%s\n",
786 dentry
->d_parent
->d_name
.name
, __name
);
788 if (ncp_is_server_root(dir
))
790 io2vol(server
, __name
, 1);
792 res
= ncp_lookup_volume(server
, __name
,
796 down_case
= !ncp_preserve_case(dir
);
797 io2vol(server
, __name
, down_case
);
798 res
= ncp_obtain_info(server
, dir
, __name
,
801 #ifdef NCPFS_PARANOIA
802 printk(KERN_DEBUG
"ncp_lookup: looked for %s/%s, res=%d\n",
803 dentry
->d_parent
->d_name
.name
, __name
, res
);
806 * If we didn't find an entry, make a negative dentry.
810 } else vol2io(server
, finfo
.nw_info
.i
.entryName
,
811 !ncp_preserve_entry_case(dir
,
812 finfo
.nw_info
.i
.NSCreator
));
816 * Create an inode for the entry.
818 finfo
.nw_info
.opened
= 0;
819 finfo
.ino
= ncp_invent_inos(1);
821 inode
= ncp_iget(dir
->i_sb
, &finfo
);
825 dentry
->d_op
= &ncp_dentry_operations
;
826 d_add(dentry
, inode
);
831 #ifdef NCPFS_PARANOIA
832 printk(KERN_DEBUG
"ncp_lookup: result=%d\n", error
);
834 return ERR_PTR(error
);
838 * This code is common to create, mkdir, and mknod.
840 static int ncp_instantiate(struct inode
*dir
, struct dentry
*dentry
,
841 struct ncpfs_inode_info
*finfo
)
846 ncp_invalid_dir_cache(dir
);
848 finfo
->ino
= ncp_invent_inos(1);
849 inode
= ncp_iget(dir
->i_sb
, finfo
);
852 d_instantiate(dentry
,inode
);
858 #ifdef NCPFS_PARANOIA
859 printk(KERN_DEBUG
"ncp_instantiate: %s/%s failed, closing file\n",
860 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
862 ncp_close_file(NCP_SERVER(dir
), finfo
->nw_info
.file_handle
);
866 int ncp_create_new(struct inode
*dir
, struct dentry
*dentry
, int mode
,
870 struct ncpfs_inode_info finfo
;
871 __u8 _name
[dentry
->d_name
.len
+ 1];
873 #ifdef NCPFS_PARANOIA
874 printk(KERN_DEBUG
"ncp_create_new: creating %s/%s, mode=%x\n",
875 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
, mode
);
878 if (!ncp_conn_valid(NCP_SERVER(dir
)))
881 strncpy(_name
, dentry
->d_name
.name
, dentry
->d_name
.len
);
882 _name
[dentry
->d_name
.len
] = '\0';
884 io2vol(NCP_SERVER(dir
), _name
, !ncp_preserve_case(dir
));
887 result
= ncp_open_create_file_or_subdir(NCP_SERVER(dir
), dir
, _name
,
888 OC_MODE_CREATE
| OC_MODE_OPEN
| OC_MODE_REPLACE
,
889 attributes
, AR_READ
| AR_WRITE
, &finfo
.nw_info
);
891 finfo
.nw_info
.access
= O_RDWR
;
892 error
= ncp_instantiate(dir
, dentry
, &finfo
);
894 if (result
== 0x87) error
= -ENAMETOOLONG
;
895 DPRINTK(KERN_DEBUG
"ncp_create: %s/%s failed\n",
896 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
903 static int ncp_create(struct inode
*dir
, struct dentry
*dentry
, int mode
)
905 return ncp_create_new(dir
, dentry
, mode
, 0);
908 static int ncp_mkdir(struct inode
*dir
, struct dentry
*dentry
, int mode
)
911 struct ncpfs_inode_info finfo
;
912 __u8 _name
[dentry
->d_name
.len
+ 1];
914 DPRINTK(KERN_DEBUG
"ncp_mkdir: making %s/%s\n",
915 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
917 if (!ncp_conn_valid(NCP_SERVER(dir
)))
920 strncpy(_name
, dentry
->d_name
.name
, dentry
->d_name
.len
);
921 _name
[dentry
->d_name
.len
] = '\0';
922 io2vol(NCP_SERVER(dir
), _name
, !ncp_preserve_case(dir
));
925 if (ncp_open_create_file_or_subdir(NCP_SERVER(dir
), dir
, _name
,
926 OC_MODE_CREATE
, aDIR
, 0xffff,
927 &finfo
.nw_info
) == 0)
929 error
= ncp_instantiate(dir
, dentry
, &finfo
);
935 static int ncp_rmdir(struct inode
*dir
, struct dentry
*dentry
)
938 __u8 _name
[dentry
->d_name
.len
+ 1];
940 DPRINTK(KERN_DEBUG
"ncp_rmdir: removing %s/%s\n",
941 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
944 if (!ncp_conn_valid(NCP_SERVER(dir
)))
948 if (!list_empty(&dentry
->d_hash
))
951 strncpy(_name
, dentry
->d_name
.name
, dentry
->d_name
.len
);
952 _name
[dentry
->d_name
.len
] = '\0';
954 io2vol(NCP_SERVER(dir
), _name
, !ncp_preserve_case(dir
));
955 result
= ncp_del_file_or_subdir(NCP_SERVER(dir
), dir
, _name
);
958 ncp_invalid_dir_cache(dir
);
961 case 0x85: /* unauthorized to delete file */
962 case 0x8A: /* unauthorized to delete file */
966 case 0x90: /* read only */
969 case 0x9F: /* in use by another client */
972 case 0xA0: /* directory not empty */
975 case 0xFF: /* someone deleted file */
986 static int ncp_unlink(struct inode
*dir
, struct dentry
*dentry
)
988 struct inode
*inode
= dentry
->d_inode
;
991 DPRINTK(KERN_DEBUG
"ncp_unlink: unlinking %s/%s\n",
992 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
995 if (!ncp_conn_valid(NCP_SERVER(dir
)))
999 * Check whether to close the file ...
1001 if (inode
&& NCP_FINFO(inode
)->opened
) {
1002 #ifdef NCPFS_PARANOIA
1003 printk(KERN_DEBUG
"ncp_unlink: closing file\n");
1005 ncp_make_closed(inode
);
1008 error
= ncp_del_file_or_subdir2(NCP_SERVER(dir
), dentry
);
1009 #ifdef CONFIG_NCPFS_STRONG
1010 /* 9C is Invalid path.. It should be 8F, 90 - read only, but
1012 if (error
== 0x9C && NCP_SERVER(dir
)->m
.flags
& NCP_MOUNT_STRONG
) { /* R/O */
1013 error
= ncp_force_unlink(dir
, dentry
);
1018 DPRINTK(KERN_DEBUG
"ncp: removed %s/%s\n",
1019 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
1020 ncp_invalid_dir_cache(dir
);
1027 case 0x8D: /* some files in use */
1028 case 0x8E: /* all files in use */
1031 case 0x8F: /* some read only */
1032 case 0x90: /* all read only */
1033 case 0x9C: /* !!! returned when in-use or read-only by NW4 */
1048 static int ncp_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
1049 struct inode
*new_dir
, struct dentry
*new_dentry
)
1051 int old_len
= old_dentry
->d_name
.len
;
1052 int new_len
= new_dentry
->d_name
.len
;
1054 char _old_name
[old_dentry
->d_name
.len
+ 1];
1055 char _new_name
[new_dentry
->d_name
.len
+ 1];
1057 DPRINTK(KERN_DEBUG
"ncp_rename: %s/%s to %s/%s\n",
1058 old_dentry
->d_parent
->d_name
.name
, old_dentry
->d_name
.name
,
1059 new_dentry
->d_parent
->d_name
.name
, new_dentry
->d_name
.name
);
1062 if (!ncp_conn_valid(NCP_SERVER(old_dir
)))
1065 strncpy(_old_name
, old_dentry
->d_name
.name
, old_len
);
1066 _old_name
[old_len
] = '\0';
1067 io2vol(NCP_SERVER(old_dir
), _old_name
, !ncp_preserve_case(old_dir
));
1069 strncpy(_new_name
, new_dentry
->d_name
.name
, new_len
);
1070 _new_name
[new_len
] = '\0';
1071 io2vol(NCP_SERVER(new_dir
), _new_name
, !ncp_preserve_case(new_dir
));
1073 error
= ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir
),
1075 new_dir
, _new_name
);
1076 #ifdef CONFIG_NCPFS_STRONG
1077 if ((error
== 0x90 || error
== -EACCES
) && NCP_SERVER(old_dir
)->m
.flags
& NCP_MOUNT_STRONG
) { /* RO */
1078 error
= ncp_force_rename(old_dir
, old_dentry
, _old_name
,
1079 new_dir
, new_dentry
, _new_name
);
1084 DPRINTK(KERN_DEBUG
"ncp renamed %s -> %s.\n",
1085 old_dentry
->d_name
.name
,new_dentry
->d_name
.name
);
1086 ncp_invalid_dir_cache(old_dir
);
1087 ncp_invalid_dir_cache(new_dir
);
1088 /* d_move(old_dentry, new_dentry); */
1091 error
= -ENAMETOOLONG
;
1104 /* The following routines are taken directly from msdos-fs */
1106 /* Linear day numbers of the respective 1sts in non-leap years. */
1108 static int day_n
[] =
1109 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
1110 /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
1113 extern struct timezone sys_tz
;
1115 static int utc2local(int time
)
1117 return time
- sys_tz
.tz_minuteswest
* 60;
1120 static int local2utc(int time
)
1122 return time
+ sys_tz
.tz_minuteswest
* 60;
1125 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
1127 ncp_date_dos2unix(unsigned short time
, unsigned short date
)
1129 int month
, year
, secs
;
1131 /* first subtract and mask after that... Otherwise, if
1132 date == 0, bad things happen */
1133 month
= ((date
>> 5) - 1) & 15;
1135 secs
= (time
& 31) * 2 + 60 * ((time
>> 5) & 63) + (time
>> 11) * 3600 +
1136 86400 * ((date
& 31) - 1 + day_n
[month
] + (year
/ 4) +
1137 year
* 365 - ((year
& 3) == 0 && month
< 2 ? 1 : 0) + 3653);
1138 /* days since 1.1.70 plus 80's leap day */
1139 return local2utc(secs
);
1143 /* Convert linear UNIX date to a MS-DOS time/date pair. */
1145 ncp_date_unix2dos(int unix_date
, unsigned short *time
, unsigned short *date
)
1147 int day
, year
, nl_day
, month
;
1149 unix_date
= utc2local(unix_date
);
1150 *time
= (unix_date
% 60) / 2 + (((unix_date
/ 60) % 60) << 5) +
1151 (((unix_date
/ 3600) % 24) << 11);
1152 day
= unix_date
/ 86400 - 3652;
1154 if ((year
+ 3) / 4 + 365 * year
> day
)
1156 day
-= (year
+ 3) / 4 + 365 * year
;
1157 if (day
== 59 && !(year
& 3)) {
1161 nl_day
= (year
& 3) || day
<= 59 ? day
: day
- 1;
1162 for (month
= 0; month
< 12; month
++)
1163 if (day_n
[month
] > nl_day
)
1166 *date
= nl_day
- day_n
[month
- 1] + 1 + (month
<< 5) + (year
<< 9);