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>
8 #include <linux/config.h>
10 #define __NO_VERSION__
11 #include <linux/module.h>
13 #include <linux/sched.h>
14 #include <linux/msdos_fs.h>
15 #include <linux/kernel.h>
16 #include <linux/errno.h>
17 #include <linux/string.h>
18 #include <linux/stat.h>
20 #include <asm/uaccess.h>
22 #include "../fat/msbuffer.h"
27 /* MS-DOS "device special files" */
29 static const char *reserved_names
[] = {
30 #ifndef CONFIG_ATARI /* GEMDOS is less stupid */
31 "CON ","PRN ","NUL ","AUX ",
32 "LPT1 ","LPT2 ","LPT3 ","LPT4 ",
33 "COM1 ","COM2 ","COM3 ","COM4 ",
38 /* Characters that are undesirable in an MS-DOS file name */
40 static char bad_chars
[] = "*?<>|\"";
42 /* GEMDOS is less restrictive */
43 static char bad_if_strict
[] = " ";
45 static char bad_if_strict
[] = "+=,; ";
48 void msdos_put_super(struct super_block
*sb
)
54 struct super_operations msdos_sops
= {
61 NULL
, /* added in 0.96c */
66 /***** Formats an MS-DOS file name. Rejects invalid names. */
67 static int msdos_format_name(char conv
,const char *name
,int len
,
68 char *res
,int dot_dirs
,char dotsOK
)
69 /* conv is relaxed/normal/strict, name is proposed name,
70 * len is the length of the proposed name, res is the result name,
71 * dot_dirs is . and .. are OK, dotsOK is if hidden files get dots.
75 const char **reserved
;
79 if (name
[0] == '.' && (len
== 1 || (len
== 2 && name
[1] == '.'))) {
80 if (!dot_dirs
) return -EEXIST
;
82 while (len
--) *res
++ = '.';
85 if (name
[0] == '.') { /* dotfile because . and .. already done */
86 if (!dotsOK
) return -EINVAL
;
87 /* Get rid of dot - test for it elsewhere */
91 space
= 1; /* disallow names that _really_ start with a dot */
93 space
= 0; /* GEMDOS does not care */
96 for (walk
= res
; len
&& walk
-res
< 8; walk
++) {
99 if (conv
!= 'r' && strchr(bad_chars
,c
)) return -EINVAL
;
100 if (conv
== 's' && strchr(bad_if_strict
,c
)) return -EINVAL
;
101 if (c
>= 'A' && c
<= 'Z' && conv
== 's') return -EINVAL
;
102 if (c
< ' ' || c
== ':' || c
== '\\') return -EINVAL
;
103 /* 0xE5 is legal as a first character, but we must substitute 0x05 */
104 /* because 0xE5 marks deleted files. Yes, DOS really does this. */
105 /* It seems that Microsoft hacked DOS to support non-US characters */
106 /* after the 0xE5 character was already in use to mark deleted files. */
107 if((res
==walk
) && (c
==0xE5)) c
=0x05;
110 *walk
= (c
>= 'a' && c
<= 'z') ? c
-32 : c
;
112 if (space
) return -EINVAL
;
113 if (conv
== 's' && len
&& c
!= '.') {
116 if (c
!= '.') return -EINVAL
;
118 while (c
!= '.' && len
--) c
= *name
++;
120 while (walk
-res
< 8) *walk
++ = ' ';
121 while (len
> 0 && walk
-res
< MSDOS_NAME
) {
124 if (conv
!= 'r' && strchr(bad_chars
,c
)) return -EINVAL
;
125 if (conv
== 's' && strchr(bad_if_strict
,c
))
127 if (c
< ' ' || c
== ':' || c
== '\\')
134 if (c
>= 'A' && c
<= 'Z' && conv
== 's') return -EINVAL
;
136 *walk
++ = c
>= 'a' && c
<= 'z' ? c
-32 : c
;
138 if (space
) return -EINVAL
;
139 if (conv
== 's' && len
) return -EINVAL
;
141 while (walk
-res
< MSDOS_NAME
) *walk
++ = ' ';
142 for (reserved
= reserved_names
; *reserved
; reserved
++)
143 if (!strncmp(res
,*reserved
,8)) return -EINVAL
;
148 /***** Locates a directory entry. Uses unformatted name. */
149 static int msdos_find(struct inode
*dir
,const char *name
,int len
,
150 struct buffer_head
**bh
,struct msdos_dir_entry
**de
,int *ino
)
152 char msdos_name
[MSDOS_NAME
];
157 dotsOK
= MSDOS_SB(dir
->i_sb
)->options
.dotsOK
;
158 res
= msdos_format_name(MSDOS_SB(dir
->i_sb
)->options
.name_check
,
159 name
,len
, msdos_name
,1,dotsOK
);
162 if((name
[0]=='.') && dotsOK
){
164 case 0: panic("Empty name in msdos_find!");
165 case 1: scantype
= SCAN_ANY
; break;
166 case 2: scantype
= ((name
[1]=='.')?SCAN_ANY
:SCAN_HID
); break;
167 default: scantype
= SCAN_HID
;
170 scantype
= (dotsOK
? SCAN_NOTHID
: SCAN_ANY
);
172 return fat_scan(dir
,msdos_name
,bh
,de
,ino
,scantype
);
176 * Compute the hash for the msdos name corresponding to the dentry.
177 * Note: if the name is invalid, we leave the hash code unchanged so
178 * that the existing dentry can be used. The msdos fs routines will
179 * return ENOENT or EINVAL as appropriate.
181 static int msdos_hash(struct dentry
*dentry
, struct qstr
*qstr
)
183 struct fat_mount_options
*options
= & (MSDOS_SB(dentry
->d_sb
)->options
);
185 char msdos_name
[MSDOS_NAME
];
187 error
= msdos_format_name(options
->name_check
, qstr
->name
, qstr
->len
,
188 msdos_name
, 1, options
->dotsOK
);
190 qstr
->hash
= full_name_hash(msdos_name
, MSDOS_NAME
);
195 * Compare two msdos names. If either of the names are invalid,
196 * we fall back to doing the standard name comparison.
198 static int msdos_cmp(struct dentry
*dentry
, struct qstr
*a
, struct qstr
*b
)
200 struct fat_mount_options
*options
= & (MSDOS_SB(dentry
->d_sb
)->options
);
202 char a_msdos_name
[MSDOS_NAME
], b_msdos_name
[MSDOS_NAME
];
204 error
= msdos_format_name(options
->name_check
, a
->name
, a
->len
,
205 a_msdos_name
, 1, options
->dotsOK
);
208 error
= msdos_format_name(options
->name_check
, b
->name
, b
->len
,
209 b_msdos_name
, 1, options
->dotsOK
);
212 error
= memcmp(a_msdos_name
, b_msdos_name
, MSDOS_NAME
);
218 if (a
->len
== b
->len
)
219 error
= memcmp(a
->name
, b
->name
, a
->len
);
224 static struct dentry_operations msdos_dentry_operations
= {
225 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
;
257 struct msdos_dir_entry
*de
;
258 struct buffer_head
*bh
;
261 PRINTK (("msdos_lookup\n"));
263 dentry
->d_op
= &msdos_dentry_operations
;
265 if(!dir
) { /* N.B. This test is bogus -- should never happen */
270 if ((res
= msdos_find(dir
,dentry
->d_name
.name
,dentry
->d_name
.len
,&bh
,&de
,&ino
)) < 0) {
277 PRINTK (("msdos_lookup 4\n"));
280 PRINTK (("msdos_lookup 4.5\n"));
281 if (!(inode
= iget(dir
->i_sb
,ino
)))
283 PRINTK (("msdos_lookup 5\n"));
285 (inode
->i_sb
->s_magic
!= MSDOS_SUPER_MAGIC
)) {
286 /* crossed a mount point into a non-msdos fs */
287 d_add(dentry
, inode
);
290 if (MSDOS_I(inode
)->i_busy
) { /* mkdir in progress */
292 d_add(dentry
, NULL
); /* N.B. Do we really want a negative? */
295 PRINTK (("msdos_lookup 6\n"));
296 d_add(dentry
, inode
);
297 PRINTK (("msdos_lookup 7\n"));
302 /***** Creates a directory entry (name is already formatted). */
303 static int msdos_create_entry(struct inode
*dir
, const char *name
,
304 int is_dir
, int is_hid
, struct inode
**result
)
306 struct super_block
*sb
= dir
->i_sb
;
307 struct buffer_head
*bh
;
308 struct msdos_dir_entry
*de
;
315 if ((res
= fat_scan(dir
,NULL
,&bh
,&de
,&ino
,SCAN_ANY
)) < 0) {
316 if (res
!= -ENOENT
) return res
;
317 if ((dir
->i_ino
== MSDOS_ROOT_INO
) &&
318 (MSDOS_SB(sb
)->fat_bits
!= 32))
320 if ((res
= fat_add_cluster(dir
)) < 0) return res
;
321 if ((res
= fat_scan(dir
,NULL
,&bh
,&de
,&ino
,SCAN_ANY
)) < 0) return res
;
324 * XXX all times should be set by caller upon successful completion.
326 dir
->i_ctime
= dir
->i_mtime
= CURRENT_TIME
;
327 mark_inode_dirty(dir
);
328 memcpy(de
->name
,name
,MSDOS_NAME
);
329 de
->attr
= is_dir
? ATTR_DIR
: ATTR_ARCH
;
330 de
->attr
= is_hid
? (de
->attr
|ATTR_HIDDEN
) : (de
->attr
&~ATTR_HIDDEN
);
333 fat_date_unix2dos(dir
->i_mtime
,&de
->time
,&de
->date
);
335 fat_mark_buffer_dirty(sb
, bh
, 1);
336 if ((*result
= iget(dir
->i_sb
,ino
)) != NULL
)
337 msdos_read_inode(*result
);
339 if (!*result
) return -EIO
;
340 (*result
)->i_mtime
= (*result
)->i_atime
= (*result
)->i_ctime
=
342 mark_inode_dirty(*result
);
346 /***** Create a file or directory */
347 int msdos_create(struct inode
*dir
,struct dentry
*dentry
,int mode
)
349 struct super_block
*sb
= dir
->i_sb
;
350 struct buffer_head
*bh
;
351 struct msdos_dir_entry
*de
;
353 char msdos_name
[MSDOS_NAME
];
356 if (!dir
) return -ENOENT
;
357 if ((res
= msdos_format_name(MSDOS_SB(dir
->i_sb
)->options
.name_check
,
358 dentry
->d_name
.name
,dentry
->d_name
.len
,
360 MSDOS_SB(dir
->i_sb
)->options
.dotsOK
)) < 0)
362 is_hid
= (dentry
->d_name
.name
[0]=='.') && (msdos_name
[0]!='.');
364 /* Scan for existing file twice, so that creating a file fails
365 * with -EINVAL if the other (dotfile/nondotfile) exists.
366 * Else SCAN_ANY would do. Maybe use EACCES, EBUSY, ENOSPC, ENFILE?
368 if (fat_scan(dir
,msdos_name
,&bh
,&de
,&ino
,SCAN_HID
) >= 0) {
369 fat_unlock_creation();
371 return is_hid
? -EEXIST
: -EINVAL
;
373 if (fat_scan(dir
,msdos_name
,&bh
,&de
,&ino
,SCAN_NOTHID
) >= 0) {
374 fat_unlock_creation();
376 return is_hid
? -EINVAL
: -EEXIST
;
378 res
= msdos_create_entry(dir
,msdos_name
,S_ISDIR(mode
),is_hid
,
380 fat_unlock_creation();
382 d_instantiate(dentry
, inode
);
389 static void dump_fat(struct super_block
*sb
,int start
)
394 start
= fat_access(sb
,start
,-1);
399 if (start
== -1) break;
406 /***** See if directory is empty */
407 static int msdos_empty(struct inode
*dir
)
410 struct buffer_head
*bh
;
411 struct msdos_dir_entry
*de
;
414 if (MSDOS_I(dir
)->i_start
) { /* may be zero in mkdir */
417 while (fat_get_entry(dir
,&pos
,&bh
,&de
) > -1) {
418 /* Ignore vfat longname entries */
419 if (de
->attr
== ATTR_EXT
)
421 if (!IS_FREE(de
->name
) &&
422 strncmp(de
->name
,MSDOS_DOT
, MSDOS_NAME
) &&
423 strncmp(de
->name
,MSDOS_DOTDOT
, MSDOS_NAME
)) {
429 fat_brelse(dir
->i_sb
, bh
);
434 /***** Remove a directory */
435 int msdos_rmdir(struct inode
*dir
, struct dentry
*dentry
)
437 struct inode
*inode
= dentry
->d_inode
;
438 struct super_block
*sb
= dir
->i_sb
;
440 struct buffer_head
*bh
;
441 struct msdos_dir_entry
*de
;
444 res
= msdos_find(dir
, dentry
->d_name
.name
, dentry
->d_name
.len
,
449 if (!S_ISDIR(inode
->i_mode
))
451 if (dir
->i_dev
!= inode
->i_dev
|| dir
== inode
)
452 printk("msdos_rmdir: impossible condition\n");
454 * Prune any child dentries, then verify that
455 * the directory is empty and not in use.
457 shrink_dcache_parent(dentry
);
458 res
= msdos_empty(inode
);
462 if (dentry
->d_count
> 1) {
464 printk("msdos_rmdir: %s/%s busy, d_count=%d\n",
465 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
, dentry
->d_count
);
471 inode
->i_ctime
= dir
->i_ctime
= dir
->i_mtime
= CURRENT_TIME
;
473 mark_inode_dirty(inode
);
474 mark_inode_dirty(dir
);
476 * Do the d_delete before any blocking operations.
477 * We must make a negative dentry, as the FAT code
478 * apparently relies on the inode being iput().
481 de
->name
[0] = DELETED_FLAG
;
482 fat_mark_buffer_dirty(sb
, bh
, 1);
489 /***** Make a directory */
490 int msdos_mkdir(struct inode
*dir
,struct dentry
*dentry
,int mode
)
492 struct super_block
*sb
= dir
->i_sb
;
493 struct buffer_head
*bh
;
494 struct msdos_dir_entry
*de
;
495 struct inode
*inode
,*dot
;
496 char msdos_name
[MSDOS_NAME
];
499 if ((res
= msdos_format_name(MSDOS_SB(dir
->i_sb
)->options
.name_check
,
500 dentry
->d_name
.name
,dentry
->d_name
.len
,
502 MSDOS_SB(dir
->i_sb
)->options
.dotsOK
)) < 0)
504 is_hid
= (dentry
->d_name
.name
[0]=='.') && (msdos_name
[0]!='.');
506 if (fat_scan(dir
,msdos_name
,&bh
,&de
,&ino
,SCAN_ANY
) >= 0) {
507 fat_unlock_creation();
508 /* N.B. does this need to be released on the other path? */
512 res
= msdos_create_entry(dir
,msdos_name
,1,is_hid
, &inode
);
516 inode
->i_nlink
= 2; /* no need to mark them dirty */
517 MSDOS_I(inode
)->i_busy
= 1; /* prevent lookups */
518 if ((res
= fat_add_cluster(inode
)) < 0)
520 if ((res
= msdos_create_entry(inode
,MSDOS_DOT
,1,0,&dot
)) < 0)
522 dot
->i_size
= inode
->i_size
; /* doesn't grow in the 2nd create_entry */
523 MSDOS_I(dot
)->i_start
= MSDOS_I(inode
)->i_start
;
524 MSDOS_I(dot
)->i_logstart
= MSDOS_I(inode
)->i_logstart
;
525 dot
->i_nlink
= inode
->i_nlink
;
526 mark_inode_dirty(dot
);
528 if ((res
= msdos_create_entry(inode
,MSDOS_DOTDOT
,1,0,&dot
)) < 0)
530 fat_unlock_creation();
531 dot
->i_size
= dir
->i_size
;
532 MSDOS_I(dot
)->i_start
= MSDOS_I(dir
)->i_start
;
533 MSDOS_I(dot
)->i_logstart
= MSDOS_I(dir
)->i_logstart
;
534 dot
->i_nlink
= dir
->i_nlink
;
535 mark_inode_dirty(dot
);
536 MSDOS_I(inode
)->i_busy
= 0;
538 d_instantiate(dentry
, inode
);
541 if (msdos_rmdir(dir
,dentry
) < 0)
542 fat_fs_panic(dir
->i_sb
,"rmdir in mkdir failed");
544 fat_unlock_creation();
548 /***** Unlink a file */
549 static int msdos_unlinkx(
551 struct dentry
*dentry
,
552 int nospc
) /* Flag special file ? */
554 struct super_block
*sb
= dir
->i_sb
;
555 struct inode
*inode
= dentry
->d_inode
;
557 struct buffer_head
*bh
;
558 struct msdos_dir_entry
*de
;
561 if ((res
= msdos_find(dir
,dentry
->d_name
.name
,dentry
->d_name
.len
,
565 if (!S_ISREG(inode
->i_mode
) && nospc
)
567 if (IS_IMMUTABLE(inode
))
570 inode
->i_ctime
= dir
->i_ctime
= dir
->i_mtime
= CURRENT_TIME
;
571 MSDOS_I(inode
)->i_busy
= 1;
572 mark_inode_dirty(inode
);
573 mark_inode_dirty(dir
);
574 de
->name
[0] = DELETED_FLAG
;
575 fat_mark_buffer_dirty(sb
, bh
, 1);
576 d_delete(dentry
); /* This also frees the inode */
583 /***** Unlink, as called for msdosfs */
584 int msdos_unlink(struct inode
*dir
,struct dentry
*dentry
)
586 return msdos_unlinkx (dir
,dentry
,1);
589 /***** Unlink, as called for umsdosfs */
590 int msdos_unlink_umsdos(struct inode
*dir
,struct dentry
*dentry
)
592 return msdos_unlinkx (dir
,dentry
,0);
595 /***** Rename within a directory */
596 static int rename_same_dir(struct inode
*old_dir
,char *old_name
,
597 struct dentry
*old_dentry
,
598 struct inode
*new_dir
,char *new_name
,struct dentry
*new_dentry
,
599 struct buffer_head
*old_bh
,
600 struct msdos_dir_entry
*old_de
,int old_ino
,int is_hid
)
602 struct super_block
*sb
= old_dir
->i_sb
;
603 struct buffer_head
*new_bh
;
604 struct msdos_dir_entry
*new_de
;
605 struct inode
*new_inode
,*old_inode
;
606 int new_ino
,exists
,error
;
608 if (!strncmp(old_name
,new_name
,MSDOS_NAME
)) goto set_hid
;
609 exists
= fat_scan(new_dir
,new_name
,&new_bh
,&new_de
,&new_ino
,SCAN_ANY
) >= 0;
610 if (*(unsigned char *) old_de
->name
== DELETED_FLAG
) {
612 fat_brelse(sb
, new_bh
);
616 new_inode
= new_dentry
->d_inode
;
617 error
= S_ISDIR(new_inode
->i_mode
)
618 ? (old_de
->attr
& ATTR_DIR
)
619 ? msdos_empty(new_inode
)
621 : (old_de
->attr
& ATTR_DIR
)
624 if (!error
&& (old_de
->attr
& ATTR_SYS
)) error
= -EPERM
;
626 fat_brelse(sb
, new_bh
);
629 if (S_ISDIR(new_inode
->i_mode
)) {
631 mark_inode_dirty(new_dir
);
633 new_inode
->i_nlink
= 0;
634 MSDOS_I(new_inode
)->i_busy
= 1;
635 mark_inode_dirty(new_inode
);
636 new_de
->name
[0] = DELETED_FLAG
;
637 fat_mark_buffer_dirty(sb
, new_bh
, 1);
638 fat_brelse(sb
, new_bh
);
640 memcpy(old_de
->name
,new_name
,MSDOS_NAME
);
641 /* Update the dcache */
642 d_move(old_dentry
, new_dentry
);
644 old_de
->attr
= is_hid
645 ? (old_de
->attr
| ATTR_HIDDEN
)
646 : (old_de
->attr
&~ ATTR_HIDDEN
);
647 fat_mark_buffer_dirty(sb
, old_bh
, 1);
648 /* update binary info for conversion, i_attrs */
649 old_inode
= old_dentry
->d_inode
;
650 MSDOS_I(old_inode
)->i_attrs
= is_hid
651 ? (MSDOS_I(old_inode
)->i_attrs
| ATTR_HIDDEN
)
652 : (MSDOS_I(old_inode
)->i_attrs
&~ ATTR_HIDDEN
);
656 /***** Rename across directories - a nonphysical move */
657 static int rename_diff_dir(struct inode
*old_dir
,char *old_name
,
658 struct dentry
*old_dentry
,
659 struct inode
*new_dir
,char *new_name
,struct dentry
*new_dentry
,
660 struct buffer_head
*old_bh
,
661 struct msdos_dir_entry
*old_de
,int old_ino
,int is_hid
)
663 struct super_block
*sb
= old_dir
->i_sb
;
664 struct buffer_head
*new_bh
,*free_bh
,*dotdot_bh
;
665 struct msdos_dir_entry
*new_de
,*free_de
,*dotdot_de
;
666 struct inode
*old_inode
,*new_inode
,*free_inode
,*dotdot_inode
;
668 int new_ino
,free_ino
,dotdot_ino
;
671 if (old_dir
->i_dev
!= new_dir
->i_dev
) return -EINVAL
;
672 if (old_ino
== new_dir
->i_ino
) return -EINVAL
;
674 /* prevent moving directory below itself */
676 if (walk
== old_dentry
) return -EINVAL
;
677 if (walk
== walk
->d_parent
) break;
678 walk
= walk
->d_parent
;
681 while ((error
= fat_scan(new_dir
,NULL
,&free_bh
,&free_de
,&free_ino
,
683 if (error
!= -ENOENT
) return error
;
684 error
= fat_add_cluster(new_dir
);
685 if (error
) return error
;
687 exists
= fat_scan(new_dir
,new_name
,&new_bh
,&new_de
,&new_ino
,SCAN_ANY
) >= 0;
688 old_inode
= old_dentry
->d_inode
;
689 if (*(unsigned char *) old_de
->name
== DELETED_FLAG
) {
690 fat_brelse(sb
, free_bh
);
692 fat_brelse(sb
, new_bh
);
695 new_inode
= NULL
; /* to make GCC happy */
696 if (exists
) { /* Trash the old file! */
697 new_inode
= new_dentry
->d_inode
;
698 error
= S_ISDIR(new_inode
->i_mode
)
699 ? (old_de
->attr
& ATTR_DIR
)
700 ? msdos_empty(new_inode
)
702 : (old_de
->attr
& ATTR_DIR
)
705 if (!error
&& (old_de
->attr
& ATTR_SYS
)) error
= -EPERM
;
707 fat_brelse(sb
, new_bh
);
710 new_inode
->i_nlink
= 0;
711 MSDOS_I(new_inode
)->i_busy
= 1;
712 mark_inode_dirty(new_inode
);
713 new_de
->name
[0] = DELETED_FLAG
;
714 fat_mark_buffer_dirty(sb
, new_bh
, 1);
716 memcpy(free_de
,old_de
,sizeof(struct msdos_dir_entry
));
717 memcpy(free_de
->name
,new_name
,MSDOS_NAME
);
718 free_de
->attr
= is_hid
719 ? (free_de
->attr
|ATTR_HIDDEN
)
720 : (free_de
->attr
&~ATTR_HIDDEN
);
721 if (!(free_inode
= iget(new_dir
->i_sb
,free_ino
))) {
722 free_de
->name
[0] = DELETED_FLAG
;
724 * Don't mark free_bh as dirty. Both states
725 * are supposed to be equivalent.
727 fat_brelse(sb
, free_bh
);
729 fat_brelse(sb
, new_bh
);
732 if (exists
&& S_ISDIR(new_inode
->i_mode
)) {
734 mark_inode_dirty(new_dir
);
736 msdos_read_inode(free_inode
);
738 free_inode
->i_mode
= old_inode
->i_mode
;
739 free_inode
->i_size
= old_inode
->i_size
;
740 free_inode
->i_blocks
= old_inode
->i_blocks
;
741 free_inode
->i_mtime
= old_inode
->i_mtime
;
742 free_inode
->i_atime
= old_inode
->i_atime
;
743 free_inode
->i_ctime
= old_inode
->i_ctime
;
744 MSDOS_I(free_inode
)->i_ctime_ms
= MSDOS_I(old_inode
)->i_ctime_ms
;
746 MSDOS_I(free_inode
)->i_start
= MSDOS_I(old_inode
)->i_start
;
747 MSDOS_I(free_inode
)->i_logstart
= MSDOS_I(old_inode
)->i_logstart
;
748 MSDOS_I(free_inode
)->i_attrs
= MSDOS_I(old_inode
)->i_attrs
;
750 /* Detach d_alias from old inode and attach to new inode */
751 list_del(&old_dentry
->d_alias
);
752 d_instantiate(old_dentry
, free_inode
);
755 fat_cache_inval_inode(old_inode
);
756 mark_inode_dirty(old_inode
);
757 old_de
->name
[0] = DELETED_FLAG
;
758 fat_mark_buffer_dirty(sb
, old_bh
, 1);
759 fat_mark_buffer_dirty(sb
, free_bh
, 1);
762 /* free_inode is put after putting new_inode and old_inode */
763 fat_brelse(sb
, new_bh
);
765 if (S_ISDIR(old_inode
->i_mode
)) {
766 if ((error
= fat_scan(old_inode
,MSDOS_DOTDOT
,&dotdot_bh
,
767 &dotdot_de
,&dotdot_ino
,SCAN_ANY
)) < 0) goto rename_done
;
768 if (!(dotdot_inode
= iget(old_inode
->i_sb
,dotdot_ino
))) {
769 fat_brelse(sb
, dotdot_bh
);
773 MSDOS_I(dotdot_inode
)->i_start
= MSDOS_I(new_dir
)->i_start
;
774 MSDOS_I(dotdot_inode
)->i_logstart
= MSDOS_I(new_dir
)->i_logstart
;
775 dotdot_de
->start
= CT_LE_W(MSDOS_I(new_dir
)->i_logstart
);
776 dotdot_de
->starthi
= CT_LE_W((MSDOS_I(new_dir
)->i_logstart
) >> 16);
777 mark_inode_dirty(dotdot_inode
);
778 fat_mark_buffer_dirty(sb
, dotdot_bh
, 1);
781 /* no need to mark them dirty */
782 dotdot_inode
->i_nlink
= new_dir
->i_nlink
;
784 fat_brelse(sb
, dotdot_bh
);
787 /* Update the dcache */
788 d_move(old_dentry
, new_dentry
);
791 fat_brelse(sb
, free_bh
);
795 /***** Rename, a wrapper for rename_same_dir & rename_diff_dir */
796 int msdos_rename(struct inode
*old_dir
,struct dentry
*old_dentry
,
797 struct inode
*new_dir
,struct dentry
*new_dentry
)
799 struct super_block
*sb
= old_dir
->i_sb
;
800 char old_msdos_name
[MSDOS_NAME
],new_msdos_name
[MSDOS_NAME
];
801 struct buffer_head
*old_bh
;
802 struct msdos_dir_entry
*old_de
;
804 int is_hid
,old_hid
; /* if new file and old file are hidden */
806 if ((error
= msdos_format_name(MSDOS_SB(old_dir
->i_sb
)->options
.name_check
,
807 old_dentry
->d_name
.name
,
808 old_dentry
->d_name
.len
,old_msdos_name
,1,
809 MSDOS_SB(old_dir
->i_sb
)->options
.dotsOK
))
810 < 0) goto rename_done
;
811 if ((error
= msdos_format_name(MSDOS_SB(new_dir
->i_sb
)->options
.name_check
,
812 new_dentry
->d_name
.name
,
813 new_dentry
->d_name
.len
,new_msdos_name
,0,
814 MSDOS_SB(new_dir
->i_sb
)->options
.dotsOK
))
815 < 0) goto rename_done
;
816 is_hid
= (new_dentry
->d_name
.name
[0]=='.') && (new_msdos_name
[0]!='.');
817 old_hid
= (old_dentry
->d_name
.name
[0]=='.') && (old_msdos_name
[0]!='.');
818 if ((error
= fat_scan(old_dir
,old_msdos_name
,&old_bh
,&old_de
,
819 &old_ino
,old_hid
?SCAN_HID
:SCAN_NOTHID
)) < 0) goto rename_done
;
821 if (old_dir
== new_dir
)
822 error
= rename_same_dir(old_dir
,old_msdos_name
,old_dentry
,
823 new_dir
,new_msdos_name
,new_dentry
,
824 old_bh
,old_de
,old_ino
,is_hid
);
825 else error
= rename_diff_dir(old_dir
,old_msdos_name
,old_dentry
,
826 new_dir
,new_msdos_name
,new_dentry
,
827 old_bh
,old_de
,old_ino
,is_hid
);
828 fat_unlock_creation();
829 fat_brelse(sb
, old_bh
);
835 /* The public inode operations for the msdos fs */
836 struct inode_operations msdos_dir_inode_operations
= {
837 &fat_dir_operations
, /* default directory file-ops */
838 msdos_create
, /* create */
839 msdos_lookup
, /* lookup */
841 msdos_unlink
, /* unlink */
843 msdos_mkdir
, /* mkdir */
844 msdos_rmdir
, /* rmdir */
846 msdos_rename
, /* rename */
848 NULL
, /* follow_link */
850 NULL
, /* writepage */
853 NULL
, /* permission */
855 NULL
, /* updatepage */
856 NULL
, /* revalidate */
860 void msdos_read_inode(struct inode
*inode
)
862 fat_read_inode(inode
, &msdos_dir_inode_operations
);
868 int init_module(void)
870 return init_msdos_fs();
874 void cleanup_module(void)
876 unregister_filesystem(&msdos_fs_type
);