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 struct dentry
*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);
331 if ((*result
= iget(dir
->i_sb
,ino
)) != NULL
)
332 msdos_read_inode(*result
);
334 if (!*result
) return -EIO
;
335 (*result
)->i_mtime
= (*result
)->i_atime
= (*result
)->i_ctime
=
337 mark_inode_dirty(*result
);
341 /***** Create a file or directory */
342 int msdos_create(struct inode
*dir
,struct dentry
*dentry
,int mode
)
344 struct super_block
*sb
= dir
->i_sb
;
345 struct buffer_head
*bh
;
346 struct msdos_dir_entry
*de
;
349 char msdos_name
[MSDOS_NAME
];
351 res
= msdos_format_name(MSDOS_SB(sb
)->options
.name_check
,
352 dentry
->d_name
.name
,dentry
->d_name
.len
,
354 MSDOS_SB(sb
)->options
.dotsOK
);
357 is_hid
= (dentry
->d_name
.name
[0]=='.') && (msdos_name
[0]!='.');
359 /* Scan for existing file twice, so that creating a file fails
360 * with -EINVAL if the other (dotfile/nondotfile) exists.
361 * Else SCAN_ANY would do. Maybe use EACCES, EBUSY, ENOSPC, ENFILE?
363 if (fat_scan(dir
,msdos_name
,&bh
,&de
,&ino
,SCAN_HID
) >= 0) {
364 fat_unlock_creation();
366 return is_hid
? -EEXIST
: -EINVAL
;
368 if (fat_scan(dir
,msdos_name
,&bh
,&de
,&ino
,SCAN_NOTHID
) >= 0) {
369 fat_unlock_creation();
371 return is_hid
? -EINVAL
: -EEXIST
;
373 res
= msdos_create_entry(dir
,msdos_name
,S_ISDIR(mode
),is_hid
,
375 fat_unlock_creation();
377 d_instantiate(dentry
, inode
);
384 static void dump_fat(struct super_block
*sb
,int start
)
389 start
= fat_access(sb
,start
,-1);
394 if (start
== -1) break;
401 /***** See if directory is empty */
402 static int msdos_empty(struct inode
*dir
)
405 struct buffer_head
*bh
;
406 struct msdos_dir_entry
*de
;
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 res
= msdos_empty(inode
);
454 inode
->i_ctime
= dir
->i_ctime
= dir
->i_mtime
= CURRENT_TIME
;
456 mark_inode_dirty(inode
);
457 mark_inode_dirty(dir
);
459 * Do the d_delete before any blocking operations.
460 * We must make a negative dentry, as the FAT code
461 * apparently relies on the inode being iput().
464 de
->name
[0] = DELETED_FLAG
;
465 fat_mark_buffer_dirty(sb
, bh
, 1);
473 /***** Make a directory */
474 int msdos_mkdir(struct inode
*dir
,struct dentry
*dentry
,int mode
)
476 struct super_block
*sb
= dir
->i_sb
;
477 struct buffer_head
*bh
;
478 struct msdos_dir_entry
*de
;
479 struct inode
*inode
,*dot
;
481 char msdos_name
[MSDOS_NAME
];
483 res
= msdos_format_name(MSDOS_SB(sb
)->options
.name_check
,
484 dentry
->d_name
.name
,dentry
->d_name
.len
,
486 MSDOS_SB(sb
)->options
.dotsOK
);
489 is_hid
= (dentry
->d_name
.name
[0]=='.') && (msdos_name
[0]!='.');
491 if (fat_scan(dir
,msdos_name
,&bh
,&de
,&ino
,SCAN_ANY
) >= 0)
494 res
= msdos_create_entry(dir
,msdos_name
,1,is_hid
, &inode
);
499 inode
->i_nlink
= 2; /* no need to mark them dirty */
501 if ((res
= fat_add_cluster(inode
)) < 0)
503 if ((res
= msdos_create_entry(inode
,MSDOS_DOT
,1,0,&dot
)) < 0)
505 dot
->i_size
= inode
->i_size
; /* doesn't grow in the 2nd create_entry */
506 MSDOS_I(dot
)->i_start
= MSDOS_I(inode
)->i_start
;
507 MSDOS_I(dot
)->i_logstart
= MSDOS_I(inode
)->i_logstart
;
508 dot
->i_nlink
= inode
->i_nlink
;
509 mark_inode_dirty(dot
);
512 if ((res
= msdos_create_entry(inode
,MSDOS_DOTDOT
,1,0,&dot
)) < 0)
514 dot
->i_size
= dir
->i_size
;
515 MSDOS_I(dot
)->i_start
= MSDOS_I(dir
)->i_start
;
516 MSDOS_I(dot
)->i_logstart
= MSDOS_I(dir
)->i_logstart
;
517 dot
->i_nlink
= dir
->i_nlink
;
518 mark_inode_dirty(dot
);
520 d_instantiate(dentry
, inode
);
524 fat_unlock_creation();
528 printk("msdos_mkdir: error=%d, attempting cleanup\n", res
);
530 fat_scan(dir
,msdos_name
,&bh
,&de
,&ino
,SCAN_ANY
);
532 inode
->i_ctime
= dir
->i_ctime
= dir
->i_mtime
= CURRENT_TIME
;
534 mark_inode_dirty(inode
);
535 mark_inode_dirty(dir
);
537 de
->name
[0] = DELETED_FLAG
;
538 fat_mark_buffer_dirty(sb
, bh
, 1);
548 /***** Unlink a file */
549 static int msdos_unlinkx( struct inode
*dir
, struct dentry
*dentry
, int nospc
)
551 struct super_block
*sb
= dir
->i_sb
;
552 struct inode
*inode
= dentry
->d_inode
;
554 struct buffer_head
*bh
;
555 struct msdos_dir_entry
*de
;
558 res
= msdos_find(dir
, dentry
->d_name
.name
, dentry
->d_name
.len
,
563 if (!S_ISREG(inode
->i_mode
) && nospc
)
565 /* N.B. check for busy files? */
568 inode
->i_ctime
= dir
->i_ctime
= dir
->i_mtime
= CURRENT_TIME
;
569 MSDOS_I(inode
)->i_busy
= 1;
570 mark_inode_dirty(inode
);
571 mark_inode_dirty(dir
);
572 d_delete(dentry
); /* This also frees the inode */
573 de
->name
[0] = DELETED_FLAG
;
574 fat_mark_buffer_dirty(sb
, bh
, 1);
581 /***** Unlink, as called for msdosfs */
582 int msdos_unlink(struct inode
*dir
,struct dentry
*dentry
)
584 return msdos_unlinkx (dir
,dentry
,1);
587 /***** Unlink, as called for umsdosfs */
588 int msdos_unlink_umsdos(struct inode
*dir
,struct dentry
*dentry
)
590 return msdos_unlinkx (dir
,dentry
,0);
593 /* Now we could merge it with msdos_rename_same. Later */
594 /***** Rename across directories - a nonphysical move */
595 static int do_msdos_rename(struct inode
*old_dir
, char *old_name
,
596 struct dentry
*old_dentry
,
597 struct inode
*new_dir
,char *new_name
, struct dentry
*new_dentry
,
598 struct buffer_head
*old_bh
,
599 struct msdos_dir_entry
*old_de
, int old_ino
, int is_hid
)
601 struct super_block
*sb
= old_dir
->i_sb
;
602 struct buffer_head
*new_bh
,*free_bh
,*dotdot_bh
;
603 struct msdos_dir_entry
*new_de
,*free_de
,*dotdot_de
;
604 struct inode
*old_inode
,*new_inode
,*dotdot_inode
;
605 int new_ino
,free_ino
,dotdot_ino
;
608 old_inode
= old_dentry
->d_inode
;
609 if (old_dir
==new_dir
&& !strncmp(old_name
, new_name
, MSDOS_NAME
))
612 if (*(unsigned char *) old_de
->name
== DELETED_FLAG
)
616 if (new_dir
!=old_dir
)
617 while ((error
= fat_scan(new_dir
, NULL
, &free_bh
, &free_de
,
618 &free_ino
, SCAN_ANY
)) < 0) {
619 if (error
!= -ENOENT
)
621 error
= fat_add_cluster(new_dir
);
626 exists
= fat_scan(new_dir
,new_name
,&new_bh
,&new_de
,&new_ino
,SCAN_ANY
) >= 0;
627 if (exists
) { /* Trash the old file! */
629 new_inode
= new_dentry
->d_inode
;
630 /* Make sure it really exists ... */
633 "msdos_rename: %s/%s inode NULL, ino=%d\n",
634 new_dentry
->d_parent
->d_name
.name
,
635 new_dentry
->d_name
.name
, new_ino
);
640 if ((old_de
->attr
& ATTR_SYS
))
643 if (S_ISDIR(new_inode
->i_mode
)) {
644 error
= msdos_empty(new_inode
);
648 mark_inode_dirty(new_dir
);
650 new_inode
->i_nlink
= 0;
651 MSDOS_I(new_inode
)->i_busy
= 1;
652 mark_inode_dirty(new_inode
);
654 new_de
->name
[0] = DELETED_FLAG
;
655 fat_mark_buffer_dirty(sb
, new_bh
, 1);
656 fat_brelse(sb
, new_bh
);
659 if (old_dir
==new_dir
) {
660 memcpy(old_de
->name
, new_name
, MSDOS_NAME
);
662 old_de
->attr
= is_hid
663 ? (old_de
->attr
| ATTR_HIDDEN
)
664 : (old_de
->attr
&~ ATTR_HIDDEN
);
665 fat_mark_buffer_dirty(sb
, old_bh
, 1);
666 MSDOS_I(old_inode
)->i_attrs
= is_hid
667 ? (MSDOS_I(old_inode
)->i_attrs
| ATTR_HIDDEN
)
668 : (MSDOS_I(old_inode
)->i_attrs
&~ ATTR_HIDDEN
);
673 /* Get the dotdot inode if we'll need it ... */
676 if (S_ISDIR(old_inode
->i_mode
)) {
677 error
= fat_scan(old_inode
, MSDOS_DOTDOT
, &dotdot_bh
,
678 &dotdot_de
, &dotdot_ino
, SCAN_ANY
);
681 "MSDOS: %s/%s, get dotdot failed, ret=%d\n",
682 old_dentry
->d_parent
->d_name
.name
,
683 old_dentry
->d_name
.name
, error
);
687 dotdot_inode
= iget(sb
, dotdot_ino
);
693 * Potential race here. It will go away when we'll switch to
694 * sane inumbers (along with a frigging lot of other races).
698 memcpy(free_de
, old_de
, sizeof(struct msdos_dir_entry
));
699 memcpy(free_de
->name
, new_name
, MSDOS_NAME
);
700 free_de
->attr
= is_hid
701 ? (free_de
->attr
|ATTR_HIDDEN
)
702 : (free_de
->attr
&~ATTR_HIDDEN
);
705 * Now the tricky part. We need to change i_ino. icache ignores
706 * i_ino for unhashed inodes, so we'll remove inode from hash,
707 * change what we want to change and reinsert it back. NB: we
708 * don't have to invalidate FAT cache here - all we need is to
709 * flip i_ino in relevant cache entries. Later.
711 remove_inode_hash(old_inode
);
713 fat_cache_inval_inode(old_inode
);
714 old_inode
->i_version
= ++event
;
715 MSDOS_I(old_inode
)->i_binary
=
716 fat_is_binary(MSDOS_SB(sb
)->options
.conversion
, free_de
->ext
);
717 old_inode
->i_ino
= free_ino
;
718 fat_mark_buffer_dirty(sb
, free_bh
, 1);
719 old_de
->name
[0] = DELETED_FLAG
;
720 fat_mark_buffer_dirty(sb
, old_bh
, 1);
722 insert_inode_hash(old_inode
);
726 MSDOS_I(dotdot_inode
)->i_start
= MSDOS_I(new_dir
)->i_start
;
727 MSDOS_I(dotdot_inode
)->i_logstart
= MSDOS_I(new_dir
)->i_logstart
;
728 dotdot_de
->start
= CT_LE_W(MSDOS_I(new_dir
)->i_logstart
);
729 dotdot_de
->starthi
= CT_LE_W((MSDOS_I(new_dir
)->i_logstart
) >> 16);
732 /* no need to mark them dirty */
733 dotdot_inode
->i_nlink
= new_dir
->i_nlink
;
734 mark_inode_dirty(dotdot_inode
);
736 fat_mark_buffer_dirty(sb
, dotdot_bh
, 1);
737 fat_brelse(sb
, dotdot_bh
);
743 fat_brelse(sb
, free_bh
);
748 fat_brelse(sb
, dotdot_bh
);
751 fat_brelse(sb
, new_bh
);
755 /***** Rename, a wrapper for rename_same_dir & rename_diff_dir */
756 int msdos_rename(struct inode
*old_dir
,struct dentry
*old_dentry
,
757 struct inode
*new_dir
,struct dentry
*new_dentry
)
759 struct super_block
*sb
= old_dir
->i_sb
;
760 struct buffer_head
*old_bh
;
761 struct msdos_dir_entry
*old_de
;
763 int is_hid
,old_hid
; /* if new file and old file are hidden */
764 char old_msdos_name
[MSDOS_NAME
], new_msdos_name
[MSDOS_NAME
];
766 error
= msdos_format_name(MSDOS_SB(sb
)->options
.name_check
,
767 old_dentry
->d_name
.name
, old_dentry
->d_name
.len
,
768 old_msdos_name
, 1,MSDOS_SB(sb
)->options
.dotsOK
);
771 error
= msdos_format_name(MSDOS_SB(sb
)->options
.name_check
,
772 new_dentry
->d_name
.name
, new_dentry
->d_name
.len
,
773 new_msdos_name
, 0,MSDOS_SB(sb
)->options
.dotsOK
);
777 is_hid
= (new_dentry
->d_name
.name
[0]=='.') && (new_msdos_name
[0]!='.');
778 old_hid
= (old_dentry
->d_name
.name
[0]=='.') && (old_msdos_name
[0]!='.');
779 error
= fat_scan(old_dir
, old_msdos_name
, &old_bh
, &old_de
,
780 &old_ino
, old_hid
?SCAN_HID
:SCAN_NOTHID
);
785 error
= do_msdos_rename(old_dir
, old_msdos_name
, old_dentry
,
786 new_dir
, new_msdos_name
, new_dentry
,
787 old_bh
, old_de
, (ino_t
)old_ino
, is_hid
);
788 fat_unlock_creation();
789 fat_brelse(sb
, old_bh
);
796 /* The public inode operations for the msdos fs */
797 struct inode_operations msdos_dir_inode_operations
= {
798 &fat_dir_operations
, /* default directory file-ops */
799 msdos_create
, /* create */
800 msdos_lookup
, /* lookup */
802 msdos_unlink
, /* unlink */
804 msdos_mkdir
, /* mkdir */
805 msdos_rmdir
, /* rmdir */
807 msdos_rename
, /* rename */
809 NULL
, /* follow_link */
811 NULL
, /* writepage */
814 NULL
, /* permission */
816 NULL
, /* updatepage */
817 NULL
, /* revalidate */
821 void msdos_read_inode(struct inode
*inode
)
823 fat_read_inode(inode
, &msdos_dir_inode_operations
);
829 int init_module(void)
831 return init_msdos_fs();
835 void cleanup_module(void)
837 unregister_filesystem(&msdos_fs_type
);