2 * linux/fs/vfat/namei.c
4 * Written 1992,1993 by Werner Almesberger
6 * Windows95/Windows NT compatible extended MSDOS filesystem
7 * by Gordon Chaffee Copyright (C) 1995. Send bug reports for the
8 * VFAT filesystem to <chaffee@cs.berkeley.edu>. Specify
9 * what file operation caused you trouble and if you can duplicate
10 * the problem, send a script that demonstrates it.
13 #define __NO_VERSION__
14 #include <linux/module.h>
16 #include <linux/sched.h>
17 #include <linux/msdos_fs.h>
18 #include <linux/nls.h>
19 #include <linux/kernel.h>
20 #include <linux/errno.h>
21 #include <linux/string.h>
22 #include <linux/ctype.h>
23 #include <linux/stat.h>
25 #include <linux/malloc.h>
27 #include "../fat/msbuffer.h"
30 #if (DEBUG_LEVEL >= 1)
31 # define PRINTK1(x) printk x
35 #if (DEBUG_LEVEL >= 2)
36 # define PRINTK2(x) printk x
40 #if (DEBUG_LEVEL >= 3)
41 # define PRINTK3(x) printk x
49 # define CHECK_STACK check_stack(__FILE__, __LINE__)
52 struct vfat_find_info
{
66 void vfat_read_inode(struct inode
*inode
);
67 static int vfat_valid_shortname(const char *,int, int, int);
68 static int vfat_format_name(const char *, int, char *, int, int);
69 static int vfat_valid_longname(const char *, int, int, int);
70 static int vfat_hashi(struct dentry
*parent
, struct qstr
*qstr
);
71 static int vfat_hash(struct dentry
*parent
, struct qstr
*qstr
);
72 static int vfat_cmpi(struct dentry
*dentry
, struct qstr
*a
, struct qstr
*b
);
73 static int vfat_cmp(struct dentry
*dentry
, struct qstr
*a
, struct qstr
*b
);
74 static int vfat_revalidate(struct dentry
*dentry
);
76 static struct dentry_operations vfat_dentry_ops
[4] = {
78 NULL
, /* d_revalidate */
90 NULL
, /* d_revalidate */
103 static int strnicmp(const char *s1
, const char *s2
, int len
)
106 while (*s1
&& *s2
&& (tolower(*s1
) == tolower(*s2
))) {
108 if (n
== len
) return 0;
110 if (*s1
== 0 && *s2
== 0) return 0;
112 if (*s1
> *s2
) return 1;
119 void vfat_put_super(struct super_block
*sb
)
125 static int vfat_revalidate(struct dentry
*dentry
)
127 PRINTK1(("vfat_revalidate: %s\n", dentry
->d_name
.name
));
128 if (dentry
->d_time
== dentry
->d_parent
->d_inode
->i_version
) {
134 static struct super_operations vfat_sops
= {
141 NULL
, /* write_super */
146 static int simple_getbool(char *s
, int *setval
)
149 if (!strcmp(s
,"1") || !strcmp(s
,"yes") || !strcmp(s
,"true")) {
151 } else if (!strcmp(s
,"0") || !strcmp(s
,"no") || !strcmp(s
,"false")) {
162 static int parse_options(char *options
, struct fat_mount_options
*opts
)
164 char *this_char
,*value
,save
,*savep
;
167 opts
->unicode_xlate
= opts
->posixfs
= 0;
171 if (!options
) return 1;
175 for (this_char
= strtok(options
,","); this_char
; this_char
= strtok(NULL
,",")) {
176 if ((value
= strchr(this_char
,'=')) != NULL
) {
181 if (!strcmp(this_char
,"utf8")) {
182 ret
= simple_getbool(value
, &val
);
183 if (ret
) opts
->utf8
= val
;
184 } else if (!strcmp(this_char
,"uni_xlate")) {
185 ret
= simple_getbool(value
, &val
);
186 if (ret
) opts
->unicode_xlate
= val
;
187 } else if (!strcmp(this_char
,"posix")) {
188 ret
= simple_getbool(value
, &val
);
189 if (ret
) opts
->posixfs
= val
;
190 } else if (!strcmp(this_char
,"nonumtail")) {
191 ret
= simple_getbool(value
, &val
);
193 opts
->numtail
= !val
;
196 if (this_char
!= options
)
197 *(this_char
-1) = ',';
205 if (opts
->unicode_xlate
) {
212 * Compute the hash for the vfat name corresponding to the dentry.
213 * Note: if the name is invalid, we leave the hash code unchanged so
214 * that the existing dentry can be used. The vfat fs routines will
215 * return ENOENT or EINVAL as appropriate.
217 static int vfat_hash(struct dentry
*dentry
, struct qstr
*qstr
)
224 while (len
&& name
[len
-1] == '.')
227 qstr
->hash
= full_name_hash(name
, len
);
233 * Compute the hash for the vfat name corresponding to the dentry.
234 * Note: if the name is invalid, we leave the hash code unchanged so
235 * that the existing dentry can be used. The vfat fs routines will
236 * return ENOENT or EINVAL as appropriate.
238 static int vfat_hashi(struct dentry
*dentry
, struct qstr
*qstr
)
247 while (len
&& name
[len
-1] == '.')
250 hash
= init_name_hash();
252 c
= tolower(*name
++);
253 hash
= partial_name_hash(tolower(c
), hash
);
255 qstr
->hash
= end_name_hash(hash
);
261 * Case insensitive compare of two vfat names.
263 static int vfat_cmpi(struct dentry
*dentry
, struct qstr
*a
, struct qstr
*b
)
267 /* A filename cannot end in '.' or we treat it like it has none */
270 while (alen
&& a
->name
[alen
-1] == '.')
272 while (blen
&& b
->name
[blen
-1] == '.')
275 if (strnicmp(a
->name
, b
->name
, alen
) == 0)
282 * Case sensitive compare of two vfat names.
284 static int vfat_cmp(struct dentry
*dentry
, struct qstr
*a
, struct qstr
*b
)
288 /* A filename cannot end in '.' or we treat it like it has none */
291 while (alen
&& a
->name
[alen
-1] == '.')
293 while (blen
&& b
->name
[blen
-1] == '.')
296 if (strncmp(a
->name
, b
->name
, alen
) == 0)
302 struct super_block
*vfat_read_super(struct super_block
*sb
,void *data
,
305 struct super_block
*res
;
309 MSDOS_SB(sb
)->options
.isvfat
= 1;
311 sb
->s_op
= &vfat_sops
;
312 res
= fat_read_super(sb
, data
, silent
);
319 if (!parse_options((char *) data
, &(MSDOS_SB(sb
)->options
))) {
322 MSDOS_SB(sb
)->options
.dotsOK
= 0;
323 if (MSDOS_SB(sb
)->options
.posixfs
) {
324 MSDOS_SB(sb
)->options
.name_check
= 's';
326 if (MSDOS_SB(sb
)->options
.name_check
!= 's') {
327 sb
->s_root
->d_op
= &vfat_dentry_ops
[0];
329 sb
->s_root
->d_op
= &vfat_dentry_ops
[2];
339 check_stack(const char *fname
, int lineno
)
344 stack_level
= (long)(&pg_dir
)-current
->kernel_stack_page
;
346 printk("*-*-*-* vfat kstack overflow in %s line %d: SL=%d\n",
347 fname
, lineno
, stack_level
);
348 else if (stack_level
< 500)
349 printk("*-*-*-* vfat kstack low in %s line %d: SL=%d\n",
350 fname
, lineno
, stack_level
);
353 printk("------- vfat kstack ok in %s line %d: SL=%d\n",
354 fname
, lineno
, stack_level
);
357 if (*(unsigned long *) current
->kernel_stack_page
!= STACK_MAGIC
) {
358 printk("******* vfat stack corruption detected in %s at line %d\n",
364 static int debug
= 0;
365 static void dump_fat(struct super_block
*sb
,int start
)
370 start
= fat_access(sb
,start
,-1);
375 if (start
== -1) break;
380 static void dump_de(struct msdos_dir_entry
*de
)
383 unsigned char *p
= (unsigned char *) de
;
386 for (i
= 0; i
< 32; i
++, p
++) {
394 /* MS-DOS "device special files" */
396 static const char *reserved3_names
[] = {
397 "con ", "prn ", "nul ", "aux ", NULL
400 static const char *reserved4_names
[] = {
401 "com1 ", "com2 ", "com3 ", "com4 ", "com5 ",
402 "com6 ", "com7 ", "com8 ", "com9 ",
403 "lpt1 ", "lpt2 ", "lpt3 ", "lpt4 ", "lpt5 ",
404 "lpt6 ", "lpt7 ", "lpt8 ", "lpt9 ",
408 /* Characters that are undesirable in an MS-DOS file name */
410 static char bad_chars
[] = "*?<>|\":/\\";
411 static char replace_chars
[] = "[];,+=";
413 static int vfat_find(struct inode
*dir
,struct qstr
* name
,
414 int find_long
,int new_filename
,int is_dir
,
415 struct vfat_slot_info
*sinfo_out
);
417 /* Checks the validity of a long MS-DOS filename */
418 /* Returns negative number on error, 0 for a normal
419 * return, and 1 for . or .. */
421 static int vfat_valid_longname(const char *name
, int len
, int dot_dirs
,
424 const char **reserved
, *walk
;
428 if (IS_FREE(name
)) return -EINVAL
;
429 if (name
[0] == '.' && (len
== 1 || (len
== 2 && name
[1] == '.'))) {
430 if (!dot_dirs
) return -EEXIST
;
434 if (len
&& name
[len
-1] == ' ') return -EINVAL
;
435 if (len
>= 256) return -EINVAL
;
436 for (i
= 0; i
< len
; i
++) {
438 if (xlate
&& c
== ':') continue;
439 if (strchr(bad_chars
,c
)) {
443 if (len
< 3) return 0;
445 for (walk
= name
; *walk
!= 0 && *walk
!= '.'; walk
++);
446 baselen
= walk
- name
;
449 for (reserved
= reserved3_names
; *reserved
; reserved
++) {
450 if (!strnicmp(name
,*reserved
,baselen
))
453 } else if (baselen
== 4) {
454 for (reserved
= reserved4_names
; *reserved
; reserved
++) {
455 if (!strnicmp(name
,*reserved
,baselen
))
462 static int vfat_valid_shortname(const char *name
,int len
,
463 int dot_dirs
, int utf8
)
465 const char *walk
, **reserved
;
470 if (IS_FREE(name
)) return -EINVAL
;
471 if (name
[0] == '.' && (len
== 1 || (len
== 2 && name
[1] == '.'))) {
472 if (!dot_dirs
) return -EEXIST
;
476 space
= 1; /* disallow names starting with a dot */
478 for (walk
= name
; len
&& walk
-name
< 8;) {
481 if (utf8
&& (c
& 0x80)) return -EINVAL
;
482 if (strchr(bad_chars
,c
)) return -EINVAL
;
483 if (strchr(replace_chars
,c
)) return -EINVAL
;
484 if (c
>= 'A' && c
<= 'Z') return -EINVAL
;
485 if (c
< ' ' || c
== ':' || c
== '\\') return -EINVAL
;
486 if ((walk
== name
) && (c
== 0xE5)) c
= 0x05;
490 if (space
) return -EINVAL
;
491 if (len
&& c
!= '.') {
494 if (c
!= '.') return -EINVAL
;
496 while (c
!= '.' && len
--) c
= *walk
++;
497 baselen
= walk
- name
;
500 if (len
>= 4) return -EINVAL
;
501 while (len
> 0 && walk
-name
< (MSDOS_NAME
+1)) {
504 if (utf8
&& (c
& 0x80)) return -EINVAL
;
505 if (strchr(bad_chars
,c
)) return -EINVAL
;
506 if (strchr(replace_chars
,c
))
508 if (c
< ' ' || c
== ':' || c
== '\\' || c
== '.')
510 if (c
>= 'A' && c
<= 'Z') return -EINVAL
;
513 if (space
) return -EINVAL
;
514 if (len
) return -EINVAL
;
517 for (reserved
= reserved3_names
; *reserved
; reserved
++)
518 if (!strnicmp(name
,*reserved
,baselen
)) return -EINVAL
;
519 } else if (baselen
== 4) {
520 for (reserved
= reserved4_names
; *reserved
; reserved
++)
521 if (!strnicmp(name
,*reserved
,baselen
)) return -EINVAL
;
527 /* Takes a short filename and converts it to a formatted MS-DOS filename.
528 * If the short filename is not a valid MS-DOS filename, an error is
529 * returned. The formatted short filename is returned in 'res'.
532 static int vfat_format_name(const char *name
,int len
,char *res
,
533 int dot_dirs
,int utf8
)
536 const char **reserved
;
540 if (IS_FREE(name
)) return -EINVAL
;
541 if (name
[0] == '.' && (len
== 1 || (len
== 2 && name
[1] == '.'))) {
542 if (!dot_dirs
) return -EEXIST
;
543 memset(res
+1,' ',10);
544 while (len
--) *res
++ = '.';
548 space
= 1; /* disallow names starting with a dot */
550 for (walk
= res
; len
&& walk
-res
< 8; walk
++) {
553 if (utf8
&& (c
& 0x80)) return -EINVAL
;
554 if (strchr(bad_chars
,c
)) return -EINVAL
;
555 if (strchr(replace_chars
,c
)) return -EINVAL
;
556 if (c
>= 'A' && c
<= 'Z') return -EINVAL
;
557 if (c
< ' ' || c
== ':' || c
== '\\') return -EINVAL
;
560 *walk
= c
>= 'a' && c
<= 'z' ? c
-32 : c
;
562 if (space
) return -EINVAL
;
563 if (len
&& c
!= '.') {
566 if (c
!= '.') return -EINVAL
;
568 while (c
!= '.' && len
--) c
= *name
++;
570 while (walk
-res
< 8) *walk
++ = ' ';
571 while (len
> 0 && walk
-res
< MSDOS_NAME
) {
574 if (utf8
&& (c
& 0x80)) return -EINVAL
;
575 if (strchr(bad_chars
,c
)) return -EINVAL
;
576 if (strchr(replace_chars
,c
))
578 if (c
< ' ' || c
== ':' || c
== '\\' || c
== '.')
580 if (c
>= 'A' && c
<= 'Z') return -EINVAL
;
582 *walk
++ = c
>= 'a' && c
<= 'z' ? c
-32 : c
;
584 if (space
) return -EINVAL
;
585 if (len
) return -EINVAL
;
587 while (walk
-res
< MSDOS_NAME
) *walk
++ = ' ';
588 for (reserved
= reserved3_names
; *reserved
; reserved
++)
589 if (!strnicmp(res
,*reserved
,8)) return -EINVAL
;
590 for (reserved
= reserved4_names
; *reserved
; reserved
++)
591 if (!strnicmp(res
,*reserved
,8)) return -EINVAL
;
596 static char skip_chars
[] = ".:\"?<>| ";
598 /* Given a valid longname, create a unique shortname. Make sure the
599 * shortname does not exist
601 static int vfat_create_shortname(struct inode
*dir
, const char *name
,
602 int len
, char *name_res
, int utf8
)
604 const char *ip
, *ext_start
, *end
;
606 int sz
, extlen
, baselen
, totlen
;
608 char base
[9], ext
[4];
613 struct vfat_slot_info sinfo
;
614 const char *name_start
;
617 PRINTK2(("Entering vfat_create_shortname: name=%s, len=%d\n", name
, len
));
618 sz
= 0; /* Make compiler happy */
619 if (len
&& name
[len
-1]==' ') return -EINVAL
;
621 /* Do a case insensitive search if the name would be a valid
622 * shortname if is were all capitalized. However, do not
623 * allow spaces in short names because Win95 scandisk does
626 for (i
= 0, p
= msdos_name
, ip
= name
; i
< len
; i
++, p
++, ip
++)
632 if (*ip
>= 'A' && *ip
<= 'Z') {
639 res
= vfat_format_name(msdos_name
, len
, name_res
, 1, utf8
);
642 PRINTK3(("vfat_create_shortname 1\n"));
643 qname
.name
=msdos_name
;
645 res
= vfat_find(dir
, &qname
, 0, 0, 0, &sinfo
);
646 PRINTK3(("vfat_create_shortname 2\n"));
647 if (res
> -1) return -EEXIST
;
652 PRINTK3(("vfat_create_shortname 3\n"));
653 /* Now, we need to create a shortname from the long name */
654 ext_start
= end
= &name
[len
];
655 while (--ext_start
>= name
) {
656 if (*ext_start
== '.') {
657 if (ext_start
== end
- 1) {
664 if (ext_start
== name
- 1) {
667 } else if (ext_start
) {
669 * Names which start with a dot could be just
670 * an extension eg. "...test". In this case Win95
671 * uses the extension as the name and sets no extension.
673 name_start
= &name
[0];
674 while (name_start
< ext_start
)
676 if (!strchr(skip_chars
,*name_start
)) break;
679 if (name_start
!= ext_start
) {
680 sz
= ext_start
- name
;
688 for (baselen
= i
= 0, p
= base
, ip
= name
; i
< sz
&& baselen
< 8; i
++)
690 if (utf8
&& (*ip
& 0x80)) {
693 } else if (!strchr(skip_chars
, *ip
)) {
694 if (*ip
>= 'A' && *ip
<= 'Z') {
699 if (strchr(replace_chars
, *p
)) *p
='_';
708 spaces
= 8 - baselen
;
712 for (p
= ext
, ip
= ext_start
; extlen
< 3 && ip
< end
; ip
++) {
713 if (utf8
&& (*ip
& 0x80)) {
716 } else if (!strchr(skip_chars
, *ip
)) {
717 if (*ip
>= 'A' && *ip
<= 'Z') {
722 if (strchr(replace_chars
, *p
)) *p
='_';
731 base
[baselen
] = '\0';
733 strcpy(msdos_name
, base
);
734 msdos_name
[baselen
] = '.';
735 strcpy(&msdos_name
[baselen
+1], ext
);
737 totlen
= baselen
+ extlen
+ (extlen
> 0);
739 if (MSDOS_SB(dir
->i_sb
)->options
.numtail
== 0) {
740 qname
.name
=msdos_name
;
742 res
= vfat_find(dir
, &qname
, 0, 0, 0, &sinfo
);
747 * Try to find a unique extension. This used to
748 * iterate through all possibilities sequentially,
749 * but that gave extremely bad performance. Windows
750 * only tries a few cases before using random
751 * values for part of the base.
755 baselen
= baselen
- (2 - spaces
);
758 msdos_name
[baselen
] = '~';
759 msdos_name
[baselen
+2] = '.';
760 strcpy(&msdos_name
[baselen
+3], ext
);
761 totlen
= baselen
+ 2 + extlen
+ (extlen
> 0);
762 qname
.name
=msdos_name
;
764 for (i
= 1; res
> -1 && i
< 10; i
++) {
765 strncpy(msdos_name
, base
, baselen
);
766 msdos_name
[baselen
+1] = i
+ '0';
767 res
= vfat_find(dir
, &qname
, 0, 0, 0, &sinfo
);
771 i
= jiffies
& 0xffff;
772 sz
= (jiffies
>> 16) & 0x7;
774 baselen
= baselen
- (6 - spaces
);
777 msdos_name
[baselen
+4] = '~';
778 msdos_name
[baselen
+5] = '1' + sz
;
779 msdos_name
[baselen
+6] = '.';
780 strcpy(&msdos_name
[baselen
+7], ext
);
781 totlen
= baselen
+ 6 + extlen
+ (extlen
> 0);
782 qname
.name
=msdos_name
;
785 sprintf(buf
, "%04x", i
);
786 memcpy(&msdos_name
[baselen
], buf
, 4);
788 res
= vfat_find(dir
, &qname
, 0, 0, 0, &sinfo
);
793 res
= vfat_format_name(msdos_name
, totlen
, name_res
, 1, utf8
);
797 static loff_t
vfat_find_free_slots(struct inode
*dir
,int slots
)
799 struct super_block
*sb
= dir
->i_sb
;
801 struct msdos_dir_entry
*de
;
802 struct buffer_head
*bh
;
810 PRINTK2(("vfat_find_free_slots: find %d free slots\n", slots
));
814 ino
= fat_get_entry(dir
,&curr
,&bh
,&de
);
816 for (added
= 0; added
< 2; added
++) {
818 done
= IS_FREE(de
->name
);
820 inode
= iget(sb
,ino
);
822 /* Directory slots of busy deleted files aren't available yet. */
823 done
= !MSDOS_I(inode
)->i_busy
;
824 /* PRINTK3(("inode %d still busy\n", ino)); */
832 /* printk("----- Free offset at %d\n", offset); */
839 ino
= fat_get_entry(dir
,&curr
,&bh
,&de
);
842 if ((dir
->i_ino
== MSDOS_ROOT_INO
) &&
843 (MSDOS_SB(sb
)->fat_bits
!= 32))
845 if ((res
= fat_add_cluster(dir
)) < 0) return res
;
846 ino
= fat_get_entry(dir
,&curr
,&bh
,&de
);
851 /* Translate a string, including coded sequences into Unicode */
853 xlate_to_uni(const char *name
, int len
, char *outname
, int *outlen
,
854 int escape
, int utf8
, struct nls_table
*nls
)
857 const unsigned char *ip
;
860 unsigned char c1
, c2
, c3
;
863 *outlen
= utf8_mbstowcs((__u16
*) outname
, name
, PAGE_SIZE
);
864 if (name
[len
-1] == '.')
866 op
= &outname
[*outlen
* sizeof(__u16
)];
868 if (name
[len
-1] == '.')
872 for (i
= 0, ip
= name
, op
= outname
, *outlen
= 0;
873 i
< len
&& *outlen
<= 260; i
++, *outlen
+= 1)
875 if (escape
&& (*ip
== ':')) {
876 if (i
> len
- 4) return -EINVAL
;
877 c1
= fat_esc2uni
[ip
[1]];
878 c2
= fat_esc2uni
[ip
[2]];
879 c3
= fat_esc2uni
[ip
[3]];
880 if (c1
== 255 || c2
== 255 || c3
== 255)
882 *op
++ = (c1
<< 4) + (c2
>> 2);
883 *op
++ = ((c2
& 0x3) << 6) + c3
;
886 *op
++ = nls
->charset2uni
[*ip
].uni1
;
887 *op
++ = nls
->charset2uni
[*ip
].uni2
;
892 for (i
= 0, ip
= name
, op
= outname
, *outlen
= 0;
893 i
< len
&& *outlen
<= 260; i
++, *outlen
+= 1)
901 return -ENAMETOOLONG
;
908 fill
= 13 - (*outlen
% 13);
909 for (i
= 0; i
< fill
; i
++) {
921 vfat_fill_long_slots(struct msdos_dir_slot
*ds
, const char *name
, int len
,
922 char *msdos_name
, int *slots
,
923 int uni_xlate
, int utf8
, struct nls_table
*nls
)
925 struct msdos_dir_slot
*ps
;
926 struct msdos_dir_entry
*de
;
937 if (name
[len
-1] == '.') len
--;
938 if(!(page
= __get_free_page(GFP_KERNEL
)))
940 uniname
= (char *) page
;
941 res
= xlate_to_uni(name
, len
, uniname
, &unilen
, uni_xlate
, utf8
, nls
);
947 *slots
= unilen
/ 13;
948 for (cksum
= i
= 0; i
< 11; i
++) {
949 cksum
= (((cksum
&1)<<7)|((cksum
&0xfe)>>1)) + msdos_name
[i
];
951 PRINTK3(("vfat_fill_long_slots 3: slots=%d\n",*slots
));
953 for (ps
= ds
, slot
= *slots
; slot
> 0; slot
--, ps
++) {
956 PRINTK3(("vfat_fill_long_slots 4\n"));
960 ps
->alias_checksum
= cksum
;
962 PRINTK3(("vfat_fill_long_slots 5: uniname=%s\n",uniname
));
963 offset
= (slot
- 1) * 26;
964 ip
= &uniname
[offset
];
967 for (i
= 0; i
< 10; i
+= 2) {
968 ps
->name0_4
[i
] = *ip
++;
969 ps
->name0_4
[i
+1] = *ip
++;
971 PRINTK3(("vfat_fill_long_slots 6\n"));
972 for (i
= 0; i
< 12; i
+= 2) {
973 ps
->name5_10
[i
] = *ip
++;
974 ps
->name5_10
[i
+1] = *ip
++;
976 PRINTK3(("vfat_fill_long_slots 7\n"));
977 for (i
= 0; i
< 4; i
+= 2) {
978 ps
->name11_12
[i
] = *ip
++;
979 ps
->name11_12
[i
+1] = *ip
++;
982 PRINTK3(("vfat_fill_long_slots 8\n"));
985 de
= (struct msdos_dir_entry
*) ps
;
986 PRINTK3(("vfat_fill_long_slots 9\n"));
987 strncpy(de
->name
, msdos_name
, MSDOS_NAME
);
993 static int vfat_build_slots(struct inode
*dir
,const char *name
,int len
,
994 struct msdos_dir_slot
*ds
, int *slots
, int *is_long
)
996 struct msdos_dir_entry
*de
;
997 char msdos_name
[MSDOS_NAME
];
998 int res
, xlate
, utf8
;
999 struct nls_table
*nls
;
1001 PRINTK2(("Entering vfat_build_slots: name=%s, len=%d\n", name
, len
));
1002 de
= (struct msdos_dir_entry
*) ds
;
1003 xlate
= MSDOS_SB(dir
->i_sb
)->options
.unicode_xlate
;
1004 utf8
= MSDOS_SB(dir
->i_sb
)->options
.utf8
;
1005 nls
= MSDOS_SB(dir
->i_sb
)->nls_io
;
1009 if (len
== 1 && name
[0] == '.') {
1010 strncpy(de
->name
, MSDOS_DOT
, MSDOS_NAME
);
1011 } else if (len
== 2 && name
[0] == '.' && name
[1] == '.') {
1012 strncpy(de
->name
, MSDOS_DOT
, MSDOS_NAME
);
1014 PRINTK3(("vfat_build_slots 4\n"));
1015 res
= vfat_valid_shortname(name
, len
, 1, utf8
);
1017 PRINTK3(("vfat_build_slots 5a\n"));
1018 res
= vfat_format_name(name
, len
, de
->name
, 1, utf8
);
1019 PRINTK3(("vfat_build_slots 5b\n"));
1021 res
= vfat_create_shortname(dir
, name
, len
, msdos_name
, utf8
);
1026 res
= vfat_valid_longname(name
, len
, 1, xlate
);
1033 return vfat_fill_long_slots(ds
, name
, len
, msdos_name
,
1034 slots
, xlate
, utf8
, nls
);
1040 static int vfat_readdir_cb(
1051 struct vfat_find_info
*vf
= (struct vfat_find_info
*) buf
;
1052 const char *s1
, *s2
;
1056 if (debug
) printk("cb: vf.name=%s, len=%d, name=%s, name_len=%d\n",
1057 vf
->name
, vf
->len
, name
, name_len
);
1060 if (vf
->len
!= name_len
) {
1064 s1
= name
; s2
= vf
->name
;
1065 for (i
= 0; i
< name_len
; i
++) {
1066 if (vf
->anycase
|| (vf
->new_filename
&& !vf
->posix
)) {
1067 if (tolower(*s1
) != tolower(*s2
))
1076 vf
->is_long
= is_long
;
1077 vf
->offset
= (offset
== 2) ? 0 : offset
;
1078 vf
->short_offset
= (short_offset
== 2) ? 0 : short_offset
;
1079 vf
->long_slots
= long_slots
;
1084 static int vfat_find(struct inode
*dir
,struct qstr
* qname
,
1085 int find_long
, int new_filename
,int is_dir
,struct vfat_slot_info
*sinfo_out
)
1087 struct super_block
*sb
= dir
->i_sb
;
1088 struct vfat_find_info vf
;
1090 struct buffer_head
*bh
;
1091 struct msdos_dir_entry
*de
;
1092 struct msdos_dir_slot
*ps
;
1094 struct msdos_dir_slot
*ds
;
1099 PRINTK2(("Entering vfat_find\n"));
1101 ds
= (struct msdos_dir_slot
*)
1102 kmalloc(sizeof(struct msdos_dir_slot
)*MSDOS_SLOTS
, GFP_KERNEL
);
1103 if (ds
== NULL
) return -ENOMEM
;
1106 vf
.name
= qname
->name
;
1107 vf
.len
= qname
->len
;
1108 while (vf
.len
&& vf
.name
[vf
.len
-1] == '.') {
1111 vf
.new_filename
= new_filename
;
1113 vf
.posix
= MSDOS_SB(sb
)->options
.posixfs
;
1114 vf
.anycase
= (MSDOS_SB(sb
)->options
.name_check
!= 's');
1115 res
= fat_readdirx(dir
,&fil
,(void *)&vf
,vfat_readdir_cb
,NULL
,1,find_long
,0);
1116 PRINTK3(("vfat_find: Debug 1\n"));
1117 if (res
< 0) goto cleanup
;
1123 sinfo_out
->longname_offset
= vf
.offset
;
1124 sinfo_out
->shortname_offset
= vf
.short_offset
;
1125 sinfo_out
->is_long
= vf
.is_long
;
1126 sinfo_out
->long_slots
= vf
.long_slots
;
1127 sinfo_out
->total_slots
= vf
.long_slots
+ 1;
1128 sinfo_out
->ino
= vf
.ino
;
1130 PRINTK3(("vfat_find: Debug 2\n"));
1135 PRINTK3(("vfat_find: Debug 3\n"));
1136 if (!vf
.found
&& !new_filename
) {
1141 res
= vfat_build_slots(dir
, qname
->name
, vf
.len
, ds
,
1143 if (res
< 0) goto cleanup
;
1145 de
= (struct msdos_dir_entry
*) ds
;
1149 PRINTK3(("vfat_find: create file 1\n"));
1150 if (is_long
) slots
++;
1151 offset
= vfat_find_free_slots(dir
, slots
);
1157 PRINTK3(("vfat_find: create file 2\n"));
1158 /* Now create the new entry */
1160 for (slot
= 0, ps
= ds
; slot
< slots
; slot
++, ps
++) {
1161 PRINTK3(("vfat_find: create file 3, slot=%d\n",slot
));
1162 sinfo_out
->ino
= fat_get_entry(dir
,&offset
,&bh
,&de
);
1163 if (sinfo_out
->ino
< 0) {
1164 PRINTK3(("vfat_find: problem\n"));
1165 res
= sinfo_out
->ino
;
1168 memcpy(de
, ps
, sizeof(struct msdos_dir_slot
));
1169 fat_mark_buffer_dirty(sb
, bh
, 1);
1172 PRINTK3(("vfat_find: create file 4\n"));
1173 dir
->i_ctime
= dir
->i_mtime
= dir
->i_atime
= CURRENT_TIME
;
1174 mark_inode_dirty(dir
);
1176 PRINTK3(("vfat_find: create file 5\n"));
1178 fat_date_unix2dos(dir
->i_mtime
,&de
->time
,&de
->date
);
1180 de
->ctime
= de
->time
;
1181 de
->adate
= de
->cdate
= de
->date
;
1185 de
->attr
= is_dir
? ATTR_DIR
: ATTR_ARCH
;
1186 de
->lcase
= CASE_LOWER_BASE
| CASE_LOWER_EXT
;
1189 fat_mark_buffer_dirty(sb
, bh
, 1);
1192 sinfo_out
->is_long
= (slots
> 1) ? 1 : 0;
1193 if (sinfo_out
->is_long
) {
1194 sinfo_out
->long_slots
= slots
- 1;
1196 sinfo_out
->long_slots
= 0;
1198 sinfo_out
->total_slots
= slots
;
1199 sinfo_out
->shortname_offset
= offset
- sizeof(struct msdos_dir_slot
);
1200 sinfo_out
->longname_offset
= offset
- sizeof(struct msdos_dir_slot
) * slots
;
1211 int vfat_lookup(struct inode
*dir
,struct dentry
*dentry
)
1214 struct vfat_slot_info sinfo
;
1215 struct inode
*result
;
1218 PRINTK2(("vfat_lookup: name=%s, len=%d\n",
1219 dentry
->d_name
.name
, dentry
->d_name
.len
));
1221 table
= (MSDOS_SB(dir
->i_sb
)->options
.name_check
== 's') ? 2 : 0;
1222 dentry
->d_op
= &vfat_dentry_ops
[table
];
1225 if ((res
= vfat_find(dir
,&dentry
->d_name
,1,0,0,&sinfo
)) < 0) {
1230 PRINTK3(("vfat_lookup 4.5\n"));
1231 if (!(result
= iget(dir
->i_sb
,sinfo
.ino
)))
1233 PRINTK3(("vfat_lookup 5\n"));
1234 if (MSDOS_I(result
)->i_busy
) { /* mkdir in progress */
1240 PRINTK3(("vfat_lookup 6\n"));
1242 dentry
->d_op
= &vfat_dentry_ops
[table
];
1243 dentry
->d_time
= dentry
->d_parent
->d_inode
->i_version
;
1244 d_add(dentry
,result
);
1249 static int vfat_create_entry(struct inode
*dir
,struct qstr
* qname
,
1250 int is_dir
, struct inode
**result
)
1252 struct super_block
*sb
= dir
->i_sb
;
1255 struct buffer_head
*bh
;
1256 struct msdos_dir_entry
*de
;
1257 struct vfat_slot_info sinfo
;
1260 PRINTK1(("vfat_create_entry: Entering\n"));
1261 res
= vfat_find(dir
, qname
, 1, 1, is_dir
, &sinfo
);
1266 offset
= sinfo
.shortname_offset
;
1268 PRINTK3(("vfat_create_entry 2\n"));
1270 ino
= fat_get_entry(dir
, &offset
, &bh
, &de
);
1272 PRINTK3(("vfat_mkdir problem\n"));
1277 PRINTK3(("vfat_create_entry 3\n"));
1279 if ((*result
= iget(dir
->i_sb
,ino
)) != NULL
)
1280 vfat_read_inode(*result
);
1284 (*result
)->i_mtime
= (*result
)->i_atime
= (*result
)->i_ctime
=
1286 mark_inode_dirty(*result
);
1287 (*result
)->i_version
= ++event
;
1288 dir
->i_version
= event
;
1293 int vfat_create(struct inode
*dir
,struct dentry
* dentry
,int mode
)
1296 struct inode
*result
;
1299 fat_lock_creation();
1300 res
= vfat_create_entry(dir
,&dentry
->d_name
,0,&result
);
1301 fat_unlock_creation();
1303 PRINTK3(("vfat_create: unable to get new entry\n"));
1305 dentry
->d_time
= dentry
->d_parent
->d_inode
->i_version
;
1306 d_instantiate(dentry
,result
);
1311 static int vfat_create_a_dotdir(struct inode
*dir
,struct inode
*parent
,
1312 struct buffer_head
*bh
,
1313 struct msdos_dir_entry
*de
,int ino
,const char *name
, int isdot
)
1315 struct super_block
*sb
= dir
->i_sb
;
1318 PRINTK2(("vfat_create_a_dotdir: Entering\n"));
1321 * XXX all times should be set by caller upon successful completion.
1323 dir
->i_atime
= dir
->i_ctime
= dir
->i_mtime
= CURRENT_TIME
;
1324 mark_inode_dirty(dir
);
1325 memcpy(de
->name
,name
,MSDOS_NAME
);
1327 de
->attr
= ATTR_DIR
;
1330 fat_date_unix2dos(dir
->i_mtime
,&de
->time
,&de
->date
);
1332 de
->ctime
= de
->time
;
1333 de
->adate
= de
->cdate
= de
->date
;
1335 fat_mark_buffer_dirty(sb
, bh
, 1);
1336 dot
= iget(dir
->i_sb
,ino
);
1339 vfat_read_inode(dot
);
1340 dot
->i_mtime
= dot
->i_atime
= CURRENT_TIME
;
1341 mark_inode_dirty(dot
);
1343 dot
->i_size
= dir
->i_size
;
1344 MSDOS_I(dot
)->i_start
= MSDOS_I(dir
)->i_start
;
1345 MSDOS_I(dot
)->i_logstart
= MSDOS_I(dir
)->i_logstart
;
1346 dot
->i_nlink
= dir
->i_nlink
;
1348 dot
->i_size
= parent
->i_size
;
1349 MSDOS_I(dot
)->i_start
= MSDOS_I(parent
)->i_start
;
1350 MSDOS_I(dot
)->i_logstart
= MSDOS_I(parent
)->i_logstart
;
1351 dot
->i_nlink
= parent
->i_nlink
;
1356 PRINTK3(("vfat_create_a_dotdir 2\n"));
1360 static int vfat_create_dotdirs(struct inode
*dir
, struct inode
*parent
)
1362 struct super_block
*sb
= dir
->i_sb
;
1364 struct buffer_head
*bh
;
1365 struct msdos_dir_entry
*de
;
1368 PRINTK2(("vfat_create_dotdirs: Entering\n"));
1369 if ((res
= fat_add_cluster(dir
)) < 0) return res
;
1371 PRINTK3(("vfat_create_dotdirs 2\n"));
1374 if ((res
= fat_get_entry(dir
,&offset
,&bh
,&de
)) < 0) return res
;
1376 PRINTK3(("vfat_create_dotdirs 3\n"));
1377 res
= vfat_create_a_dotdir(dir
, parent
, bh
, de
, res
, MSDOS_DOT
, 1);
1378 PRINTK3(("vfat_create_dotdirs 4\n"));
1383 PRINTK3(("vfat_create_dotdirs 5\n"));
1385 if ((res
= fat_get_entry(dir
,&offset
,&bh
,&de
)) < 0) {
1389 PRINTK3(("vfat_create_dotdirs 6\n"));
1391 res
= vfat_create_a_dotdir(dir
, parent
, bh
, de
, res
, MSDOS_DOTDOT
, 0);
1392 PRINTK3(("vfat_create_dotdirs 7\n"));
1398 /***** See if directory is empty */
1399 static int vfat_empty(struct inode
*dir
)
1401 struct super_block
*sb
= dir
->i_sb
;
1403 struct buffer_head
*bh
;
1404 struct msdos_dir_entry
*de
;
1406 if (dir
->i_count
> 1) {
1409 if (MSDOS_I(dir
)->i_start
) { /* may be zero in mkdir */
1412 while (fat_get_entry(dir
,&pos
,&bh
,&de
) > -1) {
1413 /* Skip extended filename entries */
1414 if (de
->attr
== ATTR_EXT
) continue;
1416 if (!IS_FREE(de
->name
) && strncmp(de
->name
,MSDOS_DOT
,
1417 MSDOS_NAME
) && strncmp(de
->name
,MSDOS_DOTDOT
,
1429 static int vfat_rmdir_free_ino(struct inode
*dir
,struct buffer_head
*bh
,
1430 struct msdos_dir_entry
*de
,struct dentry
* dentry
)
1432 struct super_block
*sb
= dir
->i_sb
;
1435 if (!S_ISDIR(dentry
->d_inode
->i_mode
)) {
1438 if (dir
->i_dev
!= dentry
->d_inode
->i_dev
|| dir
== dentry
->d_inode
) {
1442 res
= vfat_empty(dentry
->d_inode
);
1446 dentry
->d_inode
->i_nlink
= 0;
1447 dentry
->d_inode
->i_mtime
= dir
->i_mtime
= CURRENT_TIME
;
1448 dentry
->d_inode
->i_atime
= dir
->i_atime
= CURRENT_TIME
;
1450 mark_inode_dirty(dir
);
1451 mark_inode_dirty(dentry
->d_inode
);
1452 de
->name
[0] = DELETED_FLAG
;
1453 fat_mark_buffer_dirty(sb
, bh
, 1);
1458 static int vfat_unlink_free_ino(struct inode
*dir
,struct buffer_head
*bh
,
1459 struct msdos_dir_entry
*de
,struct dentry
* dentry
,int nospc
)
1461 struct super_block
*sb
= dir
->i_sb
;
1462 if ((!S_ISREG(dentry
->d_inode
->i_mode
) && nospc
) ||
1463 IS_IMMUTABLE(dentry
->d_inode
)) {
1466 dentry
->d_inode
->i_nlink
= 0;
1467 dentry
->d_inode
->i_mtime
= dir
->i_mtime
= CURRENT_TIME
;
1468 dentry
->d_inode
->i_atime
= dir
->i_atime
= CURRENT_TIME
;
1469 dir
->i_version
= ++event
;
1470 MSDOS_I(dentry
->d_inode
)->i_busy
= 1;
1471 mark_inode_dirty(dir
);
1472 mark_inode_dirty(dentry
->d_inode
);
1473 de
->name
[0] = DELETED_FLAG
;
1474 fat_mark_buffer_dirty(sb
, bh
, 1);
1479 static int vfat_remove_entry(struct inode
*dir
,struct vfat_slot_info
*sinfo
,
1480 struct buffer_head
**bh
,struct dentry
* dentry
,
1481 int is_dir
,int nospc
)
1483 struct super_block
*sb
= dir
->i_sb
;
1485 struct msdos_dir_entry
*de
;
1488 /* remove the shortname */
1489 offset
= sinfo
->shortname_offset
;
1490 res
= fat_get_entry(dir
, &offset
, bh
, &de
);
1491 if (res
< 0) return res
;
1493 res
= vfat_rmdir_free_ino(dir
,*bh
,de
,dentry
);
1495 res
= vfat_unlink_free_ino(dir
,*bh
,de
,dentry
,nospc
);
1497 if (res
< 0) return res
;
1499 /* remove the longname */
1500 offset
= sinfo
->longname_offset
;
1501 for (i
= sinfo
->long_slots
; i
> 0; --i
) {
1502 res
= fat_get_entry(dir
, &offset
, bh
, &de
);
1506 de
->name
[0] = DELETED_FLAG
;
1508 fat_mark_buffer_dirty(sb
, *bh
, 1);
1513 /* Replace inodes in alias dentries and drop all but the initial dentry */
1514 static void drop_replace_inodes(struct dentry
*dentry
, struct inode
*inode
)
1516 struct list_head
*head
, *next
, *tmp
;
1517 struct dentry
*alias
;
1519 PRINTK1(("drop_replace_inodes: dentry=%p, inode=%p\n", dentry
, inode
));
1520 head
= &dentry
->d_inode
->i_dentry
;
1521 if (dentry
->d_inode
) {
1522 next
= dentry
->d_inode
->i_dentry
.next
;
1523 while (next
!= head
) {
1526 alias
= list_entry(tmp
, struct dentry
, d_alias
);
1528 list_del(&alias
->d_alias
);
1529 iput(alias
->d_inode
);
1530 d_instantiate(alias
, inode
);
1531 /* dentry is already accounted for */
1532 if (alias
!= dentry
) {
1536 if (alias
!= dentry
) {
1543 static int vfat_rmdirx(struct inode
*dir
,struct dentry
* dentry
)
1545 struct super_block
*sb
= dir
->i_sb
;
1547 struct buffer_head
*bh
;
1548 struct vfat_slot_info sinfo
;
1550 PRINTK1(("vfat_rmdirx: dentry=%p\n", dentry
));
1551 res
= vfat_find(dir
,&dentry
->d_name
,1,0,0,&sinfo
);
1553 if (res
>= 0 && sinfo
.total_slots
> 0) {
1555 res
= vfat_remove_entry(dir
,&sinfo
,&bh
,dentry
,1,0);
1559 dir
->i_version
= ++event
;
1560 if (bh
) fat_brelse(sb
, bh
);
1565 /***** Remove a directory */
1566 int vfat_rmdir(struct inode
*dir
,struct dentry
* dentry
)
1569 PRINTK1(("vfat_rmdir: dentry=%p, inode=%p\n", dentry
, dentry
->d_inode
));
1570 res
= vfat_rmdirx(dir
, dentry
);
1572 drop_replace_inodes(dentry
, NULL
);
1578 static int vfat_unlinkx(
1580 struct dentry
* dentry
,
1581 int nospc
) /* Flag special file ? */
1583 struct super_block
*sb
= dir
->i_sb
;
1585 struct buffer_head
*bh
;
1586 struct vfat_slot_info sinfo
;
1588 PRINTK1(("vfat_unlinkx: dentry=%p, inode=%p\n", dentry
, dentry
->d_inode
));
1590 res
= vfat_find(dir
,&dentry
->d_name
,1,0,0,&sinfo
);
1592 if (res
>= 0 && sinfo
.total_slots
> 0) {
1593 res
= vfat_remove_entry(dir
,&sinfo
,&bh
,dentry
,0,nospc
);
1599 if (bh
) fat_brelse(sb
, bh
);
1604 int vfat_mkdir(struct inode
*dir
,struct dentry
* dentry
,int mode
)
1606 struct inode
*inode
;
1609 PRINTK1(("vfat_mkdir: dentry=%p, inode=%p\n", dentry
, dentry
->d_inode
));
1610 fat_lock_creation();
1611 if ((res
= vfat_create_entry(dir
,&dentry
->d_name
,1,&inode
)) < 0) {
1612 fat_unlock_creation();
1617 inode
->i_nlink
= 2; /* no need to mark them dirty */
1618 MSDOS_I(inode
)->i_busy
= 1; /* prevent lookups */
1620 res
= vfat_create_dotdirs(inode
, dir
);
1621 fat_unlock_creation();
1622 MSDOS_I(inode
)->i_busy
= 0;
1623 dentry
->d_time
= dentry
->d_parent
->d_inode
->i_version
;
1624 d_instantiate(dentry
,inode
);
1626 if (vfat_rmdir(dir
,dentry
) < 0)
1627 fat_fs_panic(dir
->i_sb
,"rmdir in mkdir failed");
1632 /***** Unlink, as called for msdosfs */
1633 int vfat_unlink(struct inode
*dir
,struct dentry
* dentry
)
1637 PRINTK1(("vfat_unlink: dentry=%p, inode=%p\n", dentry
, dentry
->d_inode
));
1638 res
= vfat_unlinkx (dir
,dentry
,1);
1640 drop_replace_inodes(dentry
, NULL
);
1646 /***** Unlink, as called for uvfatfs */
1647 int vfat_unlink_uvfat(struct inode
*dir
,struct dentry
*dentry
)
1651 res
= vfat_unlinkx (dir
,dentry
,0);
1656 int vfat_rename(struct inode
*old_dir
,struct dentry
*old_dentry
,
1657 struct inode
*new_dir
,struct dentry
*new_dentry
)
1659 struct super_block
*sb
= old_dir
->i_sb
;
1660 struct buffer_head
*old_bh
,*new_bh
,*dotdot_bh
;
1661 struct msdos_dir_entry
*old_de
,*new_de
,*dotdot_de
;
1662 loff_t old_offset
,new_offset
,old_longname_offset
;
1663 int old_slots
,old_ino
,new_ino
,dotdot_ino
;
1664 struct inode
*old_inode
, *new_inode
, *dotdot_inode
;
1665 struct dentry
*walk
;
1668 struct vfat_slot_info sinfo
;
1669 int put_new_inode
= 0;
1671 PRINTK1(("vfat_rename: Entering: old_dentry=%p, old_inode=%p, old ino=%ld, new_dentry=%p, new_inode=%p, new ino=%ld\n",
1672 old_dentry
, old_dentry
->d_inode
, old_dentry
->d_inode
->i_ino
,
1673 new_dentry
, new_dentry
->d_inode
,
1674 new_dentry
->d_inode
? new_dentry
->d_inode
->i_ino
: 0));
1675 if (old_dir
== new_dir
&&
1676 old_dentry
->d_name
.len
== new_dentry
->d_name
.len
&&
1677 strncmp(old_dentry
->d_name
.name
, new_dentry
->d_name
.name
,
1678 old_dentry
->d_name
.len
) == 0)
1681 old_bh
= new_bh
= NULL
;
1682 old_inode
= new_inode
= NULL
;
1683 res
= vfat_find(old_dir
,&old_dentry
->d_name
,1,0,0,&sinfo
);
1684 PRINTK3(("vfat_rename 2\n"));
1685 if (res
< 0) goto rename_done
;
1687 old_slots
= sinfo
.total_slots
;
1688 old_longname_offset
= sinfo
.longname_offset
;
1689 old_offset
= sinfo
.shortname_offset
;
1690 old_ino
= sinfo
.ino
;
1691 res
= fat_get_entry(old_dir
, &old_offset
, &old_bh
, &old_de
);
1692 PRINTK3(("vfat_rename 3\n"));
1693 if (res
< 0) goto rename_done
;
1696 old_inode
= old_dentry
->d_inode
;
1697 is_dir
= S_ISDIR(old_inode
->i_mode
);
1699 if ((old_dir
->i_dev
!= new_dir
->i_dev
) ||
1700 (old_ino
== new_dir
->i_ino
)) {
1705 /* prevent moving directory below itself */
1707 if (walk
== old_dentry
) return -EINVAL
;
1708 if (walk
== walk
->d_parent
) break;
1709 walk
= walk
->d_parent
;
1713 res
= vfat_find(new_dir
,&new_dentry
->d_name
,1,0,is_dir
,&sinfo
);
1715 PRINTK3(("vfat_rename 4\n"));
1719 PRINTK3(("vfat_rename 5\n"));
1720 /* Filename currently exists. Need to delete it */
1721 new_offset
= sinfo
.shortname_offset
;
1722 res
= fat_get_entry(new_dir
, &new_offset
, &new_bh
, &new_de
);
1723 PRINTK3(("vfat_rename 6\n"));
1724 if (res
< 0) goto rename_done
;
1726 if (!(new_inode
= iget(new_dir
->i_sb
,res
)))
1728 new_is_dir
= S_ISDIR(new_inode
->i_mode
);
1731 PRINTK3(("vfat_rename 7\n"));
1732 res
= vfat_rmdirx(new_dir
,new_dentry
);
1733 PRINTK3(("vfat_rename 8\n"));
1734 if (res
< 0) goto rename_done
;
1736 /* Is this the same file, different case? */
1737 if (new_inode
!= old_inode
) {
1738 PRINTK3(("vfat_rename 9\n"));
1739 res
= vfat_unlink(new_dir
,new_dentry
);
1740 PRINTK3(("vfat_rename 10\n"));
1741 if (res
< 0) goto rename_done
;
1746 PRINTK3(("vfat_rename 11\n"));
1747 fat_lock_creation(); locked
= 1;
1748 res
= vfat_find(new_dir
,&new_dentry
->d_name
,1,1,is_dir
,&sinfo
);
1750 PRINTK3(("vfat_rename 12\n"));
1751 if (res
< 0) goto rename_done
;
1753 new_offset
= sinfo
.shortname_offset
;
1754 new_ino
= sinfo
.ino
;
1755 PRINTK3(("vfat_rename 13: new_ino=%d\n", new_ino
));
1757 if (!(new_inode
= iget(new_dir
->i_sb
,new_ino
))) goto rename_done
;
1760 new_inode
->i_mode
= old_inode
->i_mode
;
1761 new_inode
->i_size
= old_inode
->i_size
;
1762 new_inode
->i_blocks
= old_inode
->i_blocks
;
1763 new_inode
->i_mtime
= old_inode
->i_mtime
;
1764 new_inode
->i_atime
= old_inode
->i_atime
;
1765 new_inode
->i_ctime
= old_inode
->i_ctime
;
1766 new_inode
->i_nlink
= old_inode
->i_nlink
;
1767 new_inode
->i_op
= old_inode
->i_op
;
1768 MSDOS_I(new_inode
)->i_ctime_ms
= MSDOS_I(old_inode
)->i_ctime_ms
;
1770 MSDOS_I(new_inode
)->i_start
= MSDOS_I(old_inode
)->i_start
;
1771 MSDOS_I(new_inode
)->i_logstart
= MSDOS_I(old_inode
)->i_logstart
;
1772 MSDOS_I(new_inode
)->i_attrs
= MSDOS_I(old_inode
)->i_attrs
;
1774 old_inode
->i_nlink
= 0;
1776 fat_cache_inval_inode(old_inode
);
1777 mark_inode_dirty(new_inode
);
1779 old_dir
->i_version
= ++event
;
1780 new_dir
->i_version
= ++event
;
1782 PRINTK3(("vfat_rename 14: old_slots=%d\n",old_slots
));
1784 /* remove the old entry */
1785 for (i
= old_slots
; i
> 0; --i
) {
1786 res
= fat_get_entry(old_dir
, &old_longname_offset
, &old_bh
, &old_de
);
1788 printk("vfat_rename: problem 1\n");
1791 old_de
->name
[0] = DELETED_FLAG
;
1793 fat_mark_buffer_dirty(sb
, old_bh
, 1);
1795 PRINTK3(("vfat_rename 15b\n"));
1797 if (S_ISDIR(old_inode
->i_mode
)) {
1798 if ((res
= fat_scan(old_inode
,MSDOS_DOTDOT
,&dotdot_bh
,
1799 &dotdot_de
,&dotdot_ino
,SCAN_ANY
)) < 0) goto rename_done
;
1800 if (!(dotdot_inode
= iget(old_inode
->i_sb
,dotdot_ino
))) {
1801 fat_brelse(sb
, dotdot_bh
);
1805 MSDOS_I(dotdot_inode
)->i_start
= MSDOS_I(new_dir
)->i_start
;
1806 MSDOS_I(dotdot_inode
)->i_logstart
= MSDOS_I(new_dir
)->i_logstart
;
1807 dotdot_de
->start
= CT_LE_W(MSDOS_I(new_dir
)->i_logstart
);
1808 dotdot_de
->starthi
= CT_LE_W((MSDOS_I(new_dir
)->i_logstart
) >> 16);
1809 mark_inode_dirty(dotdot_inode
);
1810 fat_mark_buffer_dirty(sb
, dotdot_bh
, 1);
1813 /* no need to mark them dirty */
1814 dotdot_inode
->i_nlink
= new_dir
->i_nlink
;
1816 fat_brelse(sb
, dotdot_bh
);
1819 if (res
> 0) res
= 0;
1822 drop_replace_inodes(old_dentry
, new_inode
);
1823 d_move(old_dentry
, new_dentry
);
1829 fat_unlock_creation();
1831 fat_brelse(sb
, old_bh
);
1833 fat_brelse(sb
, new_bh
);
1841 /* Public inode operations for the VFAT fs */
1842 struct inode_operations vfat_dir_inode_operations
= {
1843 &fat_dir_operations
, /* default directory file-ops */
1844 vfat_create
, /* create */
1845 vfat_lookup
, /* lookup */
1847 vfat_unlink
, /* unlink */
1849 vfat_mkdir
, /* mkdir */
1850 vfat_rmdir
, /* rmdir */
1852 vfat_rename
, /* rename */
1853 NULL
, /* readlink */
1854 NULL
, /* followlink */
1855 NULL
, /* readpage */
1856 NULL
, /* writepage */
1857 fat_bmap
, /* bmap */
1858 NULL
, /* truncate */
1859 NULL
/* permission */
1863 void vfat_read_inode(struct inode
*inode
)
1865 fat_read_inode(inode
, &vfat_dir_inode_operations
);
1869 int init_module(void)
1871 return init_vfat_fs();
1874 void cleanup_module(void)
1876 unregister_filesystem(&vfat_fs_type
);
1879 #endif /* ifdef MODULE */