2 * linux/fs/msdos/namei.c
4 * Written 1992,1993 by Werner Almesberger
5 * Hidden files 1995 by Albert Cahalan <albert@ccs.neu.edu> <adc@coe.neu.edu>
10 #include <linux/config.h>
11 #include <linux/module.h>
13 #include <linux/sched.h>
14 #include <linux/msdos_fs.h>
15 #include <linux/errno.h>
16 #include <linux/string.h>
18 #include <asm/uaccess.h>
20 #include "../fat/msbuffer.h"
25 /* MS-DOS "device special files" */
27 static const char *reserved_names
[] = {
28 #ifndef CONFIG_ATARI /* GEMDOS is less stupid */
29 "CON ","PRN ","NUL ","AUX ",
30 "LPT1 ","LPT2 ","LPT3 ","LPT4 ",
31 "COM1 ","COM2 ","COM3 ","COM4 ",
36 /* Characters that are undesirable in an MS-DOS file name */
38 static char bad_chars
[] = "*?<>|\"";
40 /* GEMDOS is less restrictive */
41 static char bad_if_strict
[] = " ";
43 static char bad_if_strict
[] = "+=,; ";
46 void msdos_put_super(struct super_block
*sb
)
52 struct super_operations msdos_sops
= {
59 NULL
, /* added in 0.96c */
64 /***** Formats an MS-DOS file name. Rejects invalid names. */
65 static int msdos_format_name(char conv
,const char *name
,int len
,
66 char *res
,int dot_dirs
,char dotsOK
)
67 /* conv is relaxed/normal/strict, name is proposed name,
68 * len is the length of the proposed name, res is the result name,
69 * dot_dirs is . and .. are OK, dotsOK is if hidden files get dots.
73 const char **reserved
;
77 if (name
[0] == '.' && (len
== 1 || (len
== 2 && name
[1] == '.'))) {
78 if (!dot_dirs
) return -EEXIST
;
80 while (len
--) *res
++ = '.';
83 if (name
[0] == '.') { /* dotfile because . and .. already done */
84 if (!dotsOK
) return -EINVAL
;
85 /* Get rid of dot - test for it elsewhere */
89 space
= 1; /* disallow names that _really_ start with a dot */
91 space
= 0; /* GEMDOS does not care */
94 for (walk
= res
; len
&& walk
-res
< 8; walk
++) {
97 if (conv
!= 'r' && strchr(bad_chars
,c
)) return -EINVAL
;
98 if (conv
== 's' && strchr(bad_if_strict
,c
)) return -EINVAL
;
99 if (c
>= 'A' && c
<= 'Z' && conv
== 's') return -EINVAL
;
100 if (c
< ' ' || c
== ':' || c
== '\\') return -EINVAL
;
101 /* 0xE5 is legal as a first character, but we must substitute 0x05 */
102 /* because 0xE5 marks deleted files. Yes, DOS really does this. */
103 /* It seems that Microsoft hacked DOS to support non-US characters */
104 /* after the 0xE5 character was already in use to mark deleted files. */
105 if((res
==walk
) && (c
==0xE5)) c
=0x05;
108 *walk
= (c
>= 'a' && c
<= 'z') ? c
-32 : c
;
110 if (space
) return -EINVAL
;
111 if (conv
== 's' && len
&& c
!= '.') {
114 if (c
!= '.') return -EINVAL
;
116 while (c
!= '.' && len
--) c
= *name
++;
118 while (walk
-res
< 8) *walk
++ = ' ';
119 while (len
> 0 && walk
-res
< MSDOS_NAME
) {
122 if (conv
!= 'r' && strchr(bad_chars
,c
)) return -EINVAL
;
123 if (conv
== 's' && strchr(bad_if_strict
,c
))
125 if (c
< ' ' || c
== ':' || c
== '\\')
132 if (c
>= 'A' && c
<= 'Z' && conv
== 's') return -EINVAL
;
134 *walk
++ = c
>= 'a' && c
<= 'z' ? c
-32 : c
;
136 if (space
) return -EINVAL
;
137 if (conv
== 's' && len
) return -EINVAL
;
139 while (walk
-res
< MSDOS_NAME
) *walk
++ = ' ';
140 for (reserved
= reserved_names
; *reserved
; reserved
++)
141 if (!strncmp(res
,*reserved
,8)) return -EINVAL
;
146 /***** Locates a directory entry. Uses unformatted name. */
147 static int msdos_find(struct inode
*dir
,const char *name
,int len
,
148 struct buffer_head
**bh
,struct msdos_dir_entry
**de
,int *ino
)
153 char msdos_name
[MSDOS_NAME
];
155 dotsOK
= MSDOS_SB(dir
->i_sb
)->options
.dotsOK
;
156 res
= msdos_format_name(MSDOS_SB(dir
->i_sb
)->options
.name_check
,
157 name
,len
, msdos_name
,1,dotsOK
);
160 if((name
[0]=='.') && dotsOK
){
162 case 0: panic("Empty name in msdos_find!");
163 case 1: scantype
= SCAN_ANY
; break;
164 case 2: scantype
= ((name
[1]=='.')?SCAN_ANY
:SCAN_HID
); break;
165 default: scantype
= SCAN_HID
;
168 scantype
= (dotsOK
? SCAN_NOTHID
: SCAN_ANY
);
170 return fat_scan(dir
,msdos_name
,bh
,de
,ino
,scantype
);
174 * Compute the hash for the msdos name corresponding to the dentry.
175 * Note: if the name is invalid, we leave the hash code unchanged so
176 * that the existing dentry can be used. The msdos fs routines will
177 * return ENOENT or EINVAL as appropriate.
179 static int msdos_hash(struct dentry
*dentry
, struct qstr
*qstr
)
181 struct fat_mount_options
*options
= & (MSDOS_SB(dentry
->d_sb
)->options
);
183 char msdos_name
[MSDOS_NAME
];
185 error
= msdos_format_name(options
->name_check
, qstr
->name
, qstr
->len
,
186 msdos_name
, 1, options
->dotsOK
);
188 qstr
->hash
= full_name_hash(msdos_name
, MSDOS_NAME
);
193 * Compare two msdos names. If either of the names are invalid,
194 * we fall back to doing the standard name comparison.
196 static int msdos_cmp(struct dentry
*dentry
, struct qstr
*a
, struct qstr
*b
)
198 struct fat_mount_options
*options
= & (MSDOS_SB(dentry
->d_sb
)->options
);
200 char a_msdos_name
[MSDOS_NAME
], b_msdos_name
[MSDOS_NAME
];
202 error
= msdos_format_name(options
->name_check
, a
->name
, a
->len
,
203 a_msdos_name
, 1, options
->dotsOK
);
206 error
= msdos_format_name(options
->name_check
, b
->name
, b
->len
,
207 b_msdos_name
, 1, options
->dotsOK
);
210 error
= memcmp(a_msdos_name
, b_msdos_name
, MSDOS_NAME
);
216 if (a
->len
== b
->len
)
217 error
= memcmp(a
->name
, b
->name
, a
->len
);
222 static struct dentry_operations msdos_dentry_operations
= {
223 NULL
, /* d_revalidate */
231 struct super_block
*msdos_read_super(struct super_block
*sb
,void *data
, int silent
)
233 struct super_block
*res
;
237 MSDOS_SB(sb
)->options
.isvfat
= 0;
238 sb
->s_op
= &msdos_sops
;
239 res
= fat_read_super(sb
, data
, silent
);
242 sb
->s_root
->d_op
= &msdos_dentry_operations
;
252 /***** Get inode using directory and name */
253 int msdos_lookup(struct inode
*dir
,struct dentry
*dentry
)
255 struct super_block
*sb
= dir
->i_sb
;
256 struct inode
*inode
= NULL
;
257 struct msdos_dir_entry
*de
;
258 struct buffer_head
*bh
;
261 PRINTK (("msdos_lookup\n"));
263 dentry
->d_op
= &msdos_dentry_operations
;
265 res
= msdos_find(dir
, dentry
->d_name
.name
, dentry
->d_name
.len
, &bh
,
275 /* try to get the inode */
277 inode
= iget(sb
, ino
);
281 (inode
->i_sb
->s_magic
!= MSDOS_SUPER_MAGIC
)) {
282 printk(KERN_WARNING
"msdos_lookup: foreign inode??\n");
284 /* mkdir in progress? */
285 if (MSDOS_I(inode
)->i_busy
) {
286 printk(KERN_WARNING
"msdos_lookup: %s/%s busy\n",
287 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
292 d_add(dentry
, inode
);
299 /***** Creates a directory entry (name is already formatted). */
300 static int msdos_create_entry(struct inode
*dir
, const char *name
,
301 int is_dir
, int is_hid
, struct inode
**result
)
303 struct super_block
*sb
= dir
->i_sb
;
304 struct buffer_head
*bh
;
305 struct msdos_dir_entry
*de
;
309 if ((res
= fat_scan(dir
,NULL
,&bh
,&de
,&ino
,SCAN_ANY
)) < 0) {
310 if (res
!= -ENOENT
) return res
;
311 if ((dir
->i_ino
== MSDOS_ROOT_INO
) &&
312 (MSDOS_SB(sb
)->fat_bits
!= 32))
314 if ((res
= fat_add_cluster(dir
)) < 0) return res
;
315 if ((res
= fat_scan(dir
,NULL
,&bh
,&de
,&ino
,SCAN_ANY
)) < 0) return res
;
318 * XXX all times should be set by caller upon successful completion.
320 dir
->i_ctime
= dir
->i_mtime
= CURRENT_TIME
;
321 mark_inode_dirty(dir
);
322 memcpy(de
->name
,name
,MSDOS_NAME
);
323 de
->attr
= is_dir
? ATTR_DIR
: ATTR_ARCH
;
324 de
->attr
= is_hid
? (de
->attr
|ATTR_HIDDEN
) : (de
->attr
&~ATTR_HIDDEN
);
327 fat_date_unix2dos(dir
->i_mtime
,&de
->time
,&de
->date
);
329 fat_mark_buffer_dirty(sb
, bh
, 1);
330 if ((*result
= iget(dir
->i_sb
,ino
)) != NULL
)
331 msdos_read_inode(*result
);
333 if (!*result
) return -EIO
;
334 (*result
)->i_mtime
= (*result
)->i_atime
= (*result
)->i_ctime
=
336 mark_inode_dirty(*result
);
340 /***** Create a file or directory */
341 int msdos_create(struct inode
*dir
,struct dentry
*dentry
,int mode
)
343 struct super_block
*sb
= dir
->i_sb
;
344 struct buffer_head
*bh
;
345 struct msdos_dir_entry
*de
;
348 char msdos_name
[MSDOS_NAME
];
350 res
= msdos_format_name(MSDOS_SB(sb
)->options
.name_check
,
351 dentry
->d_name
.name
,dentry
->d_name
.len
,
353 MSDOS_SB(sb
)->options
.dotsOK
);
356 is_hid
= (dentry
->d_name
.name
[0]=='.') && (msdos_name
[0]!='.');
358 /* Scan for existing file twice, so that creating a file fails
359 * with -EINVAL if the other (dotfile/nondotfile) exists.
360 * Else SCAN_ANY would do. Maybe use EACCES, EBUSY, ENOSPC, ENFILE?
362 if (fat_scan(dir
,msdos_name
,&bh
,&de
,&ino
,SCAN_HID
) >= 0) {
363 fat_unlock_creation();
365 return is_hid
? -EEXIST
: -EINVAL
;
367 if (fat_scan(dir
,msdos_name
,&bh
,&de
,&ino
,SCAN_NOTHID
) >= 0) {
368 fat_unlock_creation();
370 return is_hid
? -EINVAL
: -EEXIST
;
372 res
= msdos_create_entry(dir
,msdos_name
,S_ISDIR(mode
),is_hid
,
374 fat_unlock_creation();
376 d_instantiate(dentry
, inode
);
383 static void dump_fat(struct super_block
*sb
,int start
)
388 start
= fat_access(sb
,start
,-1);
393 if (start
== -1) break;
400 /***** See if directory is empty */
401 static int msdos_empty(struct inode
*dir
)
404 struct buffer_head
*bh
;
405 struct msdos_dir_entry
*de
;
408 if (MSDOS_I(dir
)->i_start
) { /* may be zero in mkdir */
411 while (fat_get_entry(dir
,&pos
,&bh
,&de
) > -1) {
412 /* Ignore vfat longname entries */
413 if (de
->attr
== ATTR_EXT
)
415 if (!IS_FREE(de
->name
) &&
416 strncmp(de
->name
,MSDOS_DOT
, MSDOS_NAME
) &&
417 strncmp(de
->name
,MSDOS_DOTDOT
, MSDOS_NAME
)) {
423 fat_brelse(dir
->i_sb
, bh
);
428 /***** Remove a directory */
429 int msdos_rmdir(struct inode
*dir
, struct dentry
*dentry
)
431 struct super_block
*sb
= dir
->i_sb
;
432 struct inode
*inode
= dentry
->d_inode
;
434 struct buffer_head
*bh
;
435 struct msdos_dir_entry
*de
;
438 res
= msdos_find(dir
, dentry
->d_name
.name
, dentry
->d_name
.len
,
443 * Check whether the directory is not in use, then check
444 * whether it is empty.
447 if (!list_empty(&dentry
->d_hash
)) {
449 printk("msdos_rmdir: %s/%s busy, d_count=%d\n",
450 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
, dentry
->d_count
);
454 res
= msdos_empty(inode
);
459 inode
->i_ctime
= dir
->i_ctime
= dir
->i_mtime
= CURRENT_TIME
;
461 mark_inode_dirty(inode
);
462 mark_inode_dirty(dir
);
464 * Do the d_delete before any blocking operations.
465 * We must make a negative dentry, as the FAT code
466 * apparently relies on the inode being iput().
469 de
->name
[0] = DELETED_FLAG
;
470 fat_mark_buffer_dirty(sb
, bh
, 1);
478 /***** Make a directory */
479 int msdos_mkdir(struct inode
*dir
,struct dentry
*dentry
,int mode
)
481 struct super_block
*sb
= dir
->i_sb
;
482 struct buffer_head
*bh
;
483 struct msdos_dir_entry
*de
;
484 struct inode
*inode
,*dot
;
486 char msdos_name
[MSDOS_NAME
];
488 res
= msdos_format_name(MSDOS_SB(sb
)->options
.name_check
,
489 dentry
->d_name
.name
,dentry
->d_name
.len
,
491 MSDOS_SB(sb
)->options
.dotsOK
);
494 is_hid
= (dentry
->d_name
.name
[0]=='.') && (msdos_name
[0]!='.');
496 if (fat_scan(dir
,msdos_name
,&bh
,&de
,&ino
,SCAN_ANY
) >= 0)
499 res
= msdos_create_entry(dir
,msdos_name
,1,is_hid
, &inode
);
504 inode
->i_nlink
= 2; /* no need to mark them dirty */
508 * He's dead, Jim. We don't d_instantiate anymore. Should do it
509 * from the very beginning, actually.
511 MSDOS_I(inode
)->i_busy
= 1; /* prevent lookups */
514 if ((res
= fat_add_cluster(inode
)) < 0)
516 if ((res
= msdos_create_entry(inode
,MSDOS_DOT
,1,0,&dot
)) < 0)
518 dot
->i_size
= inode
->i_size
; /* doesn't grow in the 2nd create_entry */
519 MSDOS_I(dot
)->i_start
= MSDOS_I(inode
)->i_start
;
520 MSDOS_I(dot
)->i_logstart
= MSDOS_I(inode
)->i_logstart
;
521 dot
->i_nlink
= inode
->i_nlink
;
522 mark_inode_dirty(dot
);
525 if ((res
= msdos_create_entry(inode
,MSDOS_DOTDOT
,1,0,&dot
)) < 0)
527 dot
->i_size
= dir
->i_size
;
528 MSDOS_I(dot
)->i_start
= MSDOS_I(dir
)->i_start
;
529 MSDOS_I(dot
)->i_logstart
= MSDOS_I(dir
)->i_logstart
;
530 dot
->i_nlink
= dir
->i_nlink
;
531 mark_inode_dirty(dot
);
533 MSDOS_I(inode
)->i_busy
= 0;
536 d_instantiate(dentry
, inode
);
540 fat_unlock_creation();
544 printk("msdos_mkdir: error=%d, attempting cleanup\n", res
);
546 fat_scan(dir
,msdos_name
,&bh
,&de
,&ino
,SCAN_ANY
);
548 inode
->i_ctime
= dir
->i_ctime
= dir
->i_mtime
= CURRENT_TIME
;
550 mark_inode_dirty(inode
);
551 mark_inode_dirty(dir
);
553 de
->name
[0] = DELETED_FLAG
;
554 fat_mark_buffer_dirty(sb
, bh
, 1);
564 /***** Unlink a file */
565 static int msdos_unlinkx( struct inode
*dir
, struct dentry
*dentry
, int nospc
)
567 struct super_block
*sb
= dir
->i_sb
;
568 struct inode
*inode
= dentry
->d_inode
;
570 struct buffer_head
*bh
;
571 struct msdos_dir_entry
*de
;
574 res
= msdos_find(dir
, dentry
->d_name
.name
, dentry
->d_name
.len
,
579 if (!S_ISREG(inode
->i_mode
) && nospc
)
581 /* N.B. check for busy files? */
584 inode
->i_ctime
= dir
->i_ctime
= dir
->i_mtime
= CURRENT_TIME
;
585 MSDOS_I(inode
)->i_busy
= 1;
586 mark_inode_dirty(inode
);
587 mark_inode_dirty(dir
);
588 d_delete(dentry
); /* This also frees the inode */
589 de
->name
[0] = DELETED_FLAG
;
590 fat_mark_buffer_dirty(sb
, bh
, 1);
597 /***** Unlink, as called for msdosfs */
598 int msdos_unlink(struct inode
*dir
,struct dentry
*dentry
)
600 return msdos_unlinkx (dir
,dentry
,1);
603 /***** Unlink, as called for umsdosfs */
604 int msdos_unlink_umsdos(struct inode
*dir
,struct dentry
*dentry
)
606 return msdos_unlinkx (dir
,dentry
,0);
609 #define MSDOS_CHECK_BUSY 1
611 /***** Rename within a directory */
612 static int msdos_rename_same(struct inode
*old_dir
,char *old_name
,
613 struct dentry
*old_dentry
,
614 struct inode
*new_dir
,char *new_name
,struct dentry
*new_dentry
,
615 struct buffer_head
*old_bh
,
616 struct msdos_dir_entry
*old_de
, int old_ino
, int is_hid
)
618 struct super_block
*sb
= old_dir
->i_sb
;
619 struct buffer_head
*new_bh
;
620 struct msdos_dir_entry
*new_de
;
621 struct inode
*new_inode
,*old_inode
;
622 int new_ino
, exists
, error
;
624 if (!strncmp(old_name
, new_name
, MSDOS_NAME
))
627 if (*(unsigned char *) old_de
->name
== DELETED_FLAG
)
630 exists
= fat_scan(new_dir
,new_name
,&new_bh
,&new_de
,&new_ino
,SCAN_ANY
) >= 0;
633 new_inode
= new_dentry
->d_inode
;
634 /* Make sure it really exists ... */
637 "msdos_rename_same: %s/%s inode NULL, ino=%d\n",
638 new_dentry
->d_parent
->d_name
.name
,
639 new_dentry
->d_name
.name
, new_ino
);
643 error
= S_ISDIR(new_inode
->i_mode
)
644 ? (old_de
->attr
& ATTR_DIR
)
645 ? msdos_empty(new_inode
)
647 : (old_de
->attr
& ATTR_DIR
)
653 if ((old_de
->attr
& ATTR_SYS
))
656 if (S_ISDIR(new_inode
->i_mode
)) {
657 /* make sure it's empty */
658 error
= msdos_empty(new_inode
);
661 #ifdef MSDOS_CHECK_BUSY
662 /* check for a busy dentry */
664 shrink_dcache_parent(new_dentry
);
665 if (new_dentry
->d_count
> 1) {
666 printk("msdos_rename_same: %s/%s busy, count=%d\n",
667 new_dentry
->d_parent
->d_name
.name
, new_dentry
->d_name
.name
,
668 new_dentry
->d_count
);
673 mark_inode_dirty(new_dir
);
675 new_inode
->i_nlink
= 0;
676 MSDOS_I(new_inode
)->i_busy
= 1;
677 mark_inode_dirty(new_inode
);
679 * Make it negative if it's not busy;
680 * otherwise let d_move() drop it.
682 if (new_dentry
->d_count
== 1)
683 d_delete(new_dentry
);
685 new_de
->name
[0] = DELETED_FLAG
;
686 fat_mark_buffer_dirty(sb
, new_bh
, 1);
687 fat_brelse(sb
, new_bh
);
689 memcpy(old_de
->name
, new_name
, MSDOS_NAME
);
690 /* Update the dcache */
691 d_move(old_dentry
, new_dentry
);
693 old_de
->attr
= is_hid
694 ? (old_de
->attr
| ATTR_HIDDEN
)
695 : (old_de
->attr
&~ ATTR_HIDDEN
);
696 fat_mark_buffer_dirty(sb
, old_bh
, 1);
697 /* update binary info for conversion, i_attrs */
698 old_inode
= old_dentry
->d_inode
;
699 MSDOS_I(old_inode
)->i_attrs
= is_hid
700 ? (MSDOS_I(old_inode
)->i_attrs
| ATTR_HIDDEN
)
701 : (MSDOS_I(old_inode
)->i_attrs
&~ ATTR_HIDDEN
);
707 fat_brelse(sb
, new_bh
);
711 /***** Rename across directories - a nonphysical move */
712 static int msdos_rename_diff(struct inode
*old_dir
, char *old_name
,
713 struct dentry
*old_dentry
,
714 struct inode
*new_dir
,char *new_name
, struct dentry
*new_dentry
,
715 struct buffer_head
*old_bh
,
716 struct msdos_dir_entry
*old_de
, int old_ino
, int is_hid
)
718 struct super_block
*sb
= old_dir
->i_sb
;
719 struct buffer_head
*new_bh
,*free_bh
,*dotdot_bh
;
720 struct msdos_dir_entry
*new_de
,*free_de
,*dotdot_de
;
721 struct inode
*old_inode
,*new_inode
,*free_inode
,*dotdot_inode
;
722 int new_ino
,free_ino
,dotdot_ino
;
726 if (old_ino
== new_dir
->i_ino
)
728 /* prevent moving directory below itself */
729 if (is_subdir(new_dentry
, old_dentry
))
733 if (*(unsigned char *) old_de
->name
== DELETED_FLAG
)
737 while ((error
= fat_scan(new_dir
, NULL
, &free_bh
, &free_de
, &free_ino
,
739 if (error
!= -ENOENT
)
741 error
= fat_add_cluster(new_dir
);
746 exists
= fat_scan(new_dir
,new_name
,&new_bh
,&new_de
,&new_ino
,SCAN_ANY
) >= 0;
747 if (exists
) { /* Trash the old file! */
749 new_inode
= new_dentry
->d_inode
;
750 /* Make sure it really exists ... */
753 "msdos_rename_diff: %s/%s inode NULL, ino=%d\n",
754 new_dentry
->d_parent
->d_name
.name
,
755 new_dentry
->d_name
.name
, new_ino
);
759 error
= S_ISDIR(new_inode
->i_mode
)
760 ? (old_de
->attr
& ATTR_DIR
)
761 ? msdos_empty(new_inode
)
763 : (old_de
->attr
& ATTR_DIR
)
769 if ((old_de
->attr
& ATTR_SYS
))
772 #ifdef MSDOS_CHECK_BUSY
773 /* check for a busy dentry */
775 if (new_dentry
->d_count
> 1) {
776 shrink_dcache_parent(new_dentry
);
777 if (new_dentry
->d_count
> 1) {
778 printk("msdos_rename_diff: target %s/%s busy, count=%d\n",
779 new_dentry
->d_parent
->d_name
.name
, new_dentry
->d_name
.name
,
780 new_dentry
->d_count
);
785 if (S_ISDIR(new_inode
->i_mode
)) {
786 /* make sure it's empty */
787 error
= msdos_empty(new_inode
);
791 mark_inode_dirty(new_dir
);
793 new_inode
->i_nlink
= 0;
794 MSDOS_I(new_inode
)->i_busy
= 1;
795 mark_inode_dirty(new_inode
);
797 * Make it negative if it's not busy;
798 * otherwise let d_move() drop it.
800 if (new_dentry
->d_count
== 1)
801 d_delete(new_dentry
);
802 new_de
->name
[0] = DELETED_FLAG
;
803 fat_mark_buffer_dirty(sb
, new_bh
, 1);
804 fat_brelse(sb
, new_bh
);
807 old_inode
= old_dentry
->d_inode
;
808 /* Get the dotdot inode if we'll need it ... */
811 if (S_ISDIR(old_inode
->i_mode
)) {
812 error
= fat_scan(old_inode
, MSDOS_DOTDOT
, &dotdot_bh
,
813 &dotdot_de
, &dotdot_ino
, SCAN_ANY
);
816 "MSDOS: %s/%s, get dotdot failed, ret=%d\n",
817 old_dentry
->d_parent
->d_name
.name
,
818 old_dentry
->d_name
.name
, error
);
822 dotdot_inode
= iget(sb
, dotdot_ino
);
827 /* get an inode for the new name */
828 memcpy(free_de
, old_de
, sizeof(struct msdos_dir_entry
));
829 memcpy(free_de
->name
, new_name
, MSDOS_NAME
);
830 free_de
->attr
= is_hid
831 ? (free_de
->attr
|ATTR_HIDDEN
)
832 : (free_de
->attr
&~ATTR_HIDDEN
);
835 free_inode
= iget(sb
, free_ino
);
838 /* make sure it's not busy! */
839 if (MSDOS_I(free_inode
)->i_busy
)
840 printk(KERN_ERR
"msdos_rename_diff: new inode %ld busy!\n",
842 if (!list_empty(&free_inode
->i_dentry
))
843 printk("msdos_rename_diff: free inode has aliases??\n");
844 msdos_read_inode(free_inode
);
847 * Make sure the old dentry isn't busy,
848 * as we need to change inodes ...
851 if (old_dentry
->d_count
> 1) {
852 shrink_dcache_parent(old_dentry
);
853 if (old_dentry
->d_count
> 1) {
854 printk("msdos_rename_diff: source %s/%s busy, count=%d\n",
855 old_dentry
->d_parent
->d_name
.name
, old_dentry
->d_name
.name
,
856 old_dentry
->d_count
);
861 /* keep the inode for a bit ... */
862 old_inode
->i_count
++;
863 d_delete(old_dentry
);
865 free_inode
->i_mode
= old_inode
->i_mode
;
866 free_inode
->i_nlink
= old_inode
->i_nlink
;
867 free_inode
->i_size
= old_inode
->i_size
;
868 free_inode
->i_blocks
= old_inode
->i_blocks
;
869 free_inode
->i_mtime
= old_inode
->i_mtime
;
870 free_inode
->i_atime
= old_inode
->i_atime
;
871 free_inode
->i_ctime
= old_inode
->i_ctime
;
872 MSDOS_I(free_inode
)->i_ctime_ms
= MSDOS_I(old_inode
)->i_ctime_ms
;
874 MSDOS_I(free_inode
)->i_start
= MSDOS_I(old_inode
)->i_start
;
875 MSDOS_I(free_inode
)->i_logstart
= MSDOS_I(old_inode
)->i_logstart
;
876 MSDOS_I(free_inode
)->i_attrs
= MSDOS_I(old_inode
)->i_attrs
;
878 /* release the old inode's resources */
879 MSDOS_I(old_inode
)->i_start
= 0;
880 MSDOS_I(old_inode
)->i_logstart
= 0;
881 old_inode
->i_nlink
= 0;
884 * Install the new inode ...
886 d_instantiate(old_dentry
, free_inode
);
888 fat_mark_buffer_dirty(sb
, free_bh
, 1);
889 fat_cache_inval_inode(old_inode
);
890 mark_inode_dirty(old_inode
);
891 old_de
->name
[0] = DELETED_FLAG
;
892 fat_mark_buffer_dirty(sb
, old_bh
, 1);
897 MSDOS_I(dotdot_inode
)->i_start
= MSDOS_I(new_dir
)->i_start
;
898 MSDOS_I(dotdot_inode
)->i_logstart
= MSDOS_I(new_dir
)->i_logstart
;
899 dotdot_de
->start
= CT_LE_W(MSDOS_I(new_dir
)->i_logstart
);
900 dotdot_de
->starthi
= CT_LE_W((MSDOS_I(new_dir
)->i_logstart
) >> 16);
903 /* no need to mark them dirty */
904 dotdot_inode
->i_nlink
= new_dir
->i_nlink
;
905 mark_inode_dirty(dotdot_inode
);
907 fat_mark_buffer_dirty(sb
, dotdot_bh
, 1);
908 fat_brelse(sb
, dotdot_bh
);
911 /* Update the dcache */
912 d_move(old_dentry
, new_dentry
);
916 fat_brelse(sb
, free_bh
);
921 free_de
->name
[0] = DELETED_FLAG
;
923 * Don't mark free_bh as dirty. Both states
924 * are supposed to be equivalent.
926 iput(free_inode
); /* may be NULL */
929 fat_brelse(sb
, dotdot_bh
);
932 fat_brelse(sb
, new_bh
);
936 /***** Rename, a wrapper for rename_same_dir & rename_diff_dir */
937 int msdos_rename(struct inode
*old_dir
,struct dentry
*old_dentry
,
938 struct inode
*new_dir
,struct dentry
*new_dentry
)
940 struct super_block
*sb
= old_dir
->i_sb
;
941 struct buffer_head
*old_bh
;
942 struct msdos_dir_entry
*old_de
;
944 int is_hid
,old_hid
; /* if new file and old file are hidden */
945 char old_msdos_name
[MSDOS_NAME
], new_msdos_name
[MSDOS_NAME
];
948 if (sb
!= new_dir
->i_sb
)
950 error
= msdos_format_name(MSDOS_SB(sb
)->options
.name_check
,
951 old_dentry
->d_name
.name
, old_dentry
->d_name
.len
,
952 old_msdos_name
, 1,MSDOS_SB(sb
)->options
.dotsOK
);
955 error
= msdos_format_name(MSDOS_SB(sb
)->options
.name_check
,
956 new_dentry
->d_name
.name
, new_dentry
->d_name
.len
,
957 new_msdos_name
, 0,MSDOS_SB(sb
)->options
.dotsOK
);
961 is_hid
= (new_dentry
->d_name
.name
[0]=='.') && (new_msdos_name
[0]!='.');
962 old_hid
= (old_dentry
->d_name
.name
[0]=='.') && (old_msdos_name
[0]!='.');
963 error
= fat_scan(old_dir
, old_msdos_name
, &old_bh
, &old_de
,
964 &old_ino
, old_hid
?SCAN_HID
:SCAN_NOTHID
);
969 if (old_dir
== new_dir
)
970 error
= msdos_rename_same(old_dir
, old_msdos_name
, old_dentry
,
971 new_dir
, new_msdos_name
, new_dentry
,
972 old_bh
, old_de
, (ino_t
)old_ino
, is_hid
);
974 error
= msdos_rename_diff(old_dir
, old_msdos_name
, old_dentry
,
975 new_dir
, new_msdos_name
, new_dentry
,
976 old_bh
, old_de
, (ino_t
)old_ino
, is_hid
);
977 fat_unlock_creation();
978 fat_brelse(sb
, old_bh
);
985 /* The public inode operations for the msdos fs */
986 struct inode_operations msdos_dir_inode_operations
= {
987 &fat_dir_operations
, /* default directory file-ops */
988 msdos_create
, /* create */
989 msdos_lookup
, /* lookup */
991 msdos_unlink
, /* unlink */
993 msdos_mkdir
, /* mkdir */
994 msdos_rmdir
, /* rmdir */
996 msdos_rename
, /* rename */
998 NULL
, /* follow_link */
1000 NULL
, /* writepage */
1002 NULL
, /* truncate */
1003 NULL
, /* permission */
1005 NULL
, /* updatepage */
1006 NULL
, /* revalidate */
1010 void msdos_read_inode(struct inode
*inode
)
1012 fat_read_inode(inode
, &msdos_dir_inode_operations
);
1018 int init_module(void)
1020 return init_msdos_fs();
1024 void cleanup_module(void)
1026 unregister_filesystem(&msdos_fs_type
);