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 #include <linux/config.h>
14 #define __NO_VERSION__
15 #include <linux/module.h>
17 #include <linux/sched.h>
18 #include <linux/msdos_fs.h>
19 #include <linux/nls.h>
20 #include <linux/kernel.h>
21 #include <linux/errno.h>
22 #include <linux/string.h>
23 #include <linux/ctype.h>
24 #include <linux/stat.h>
26 #include <linux/malloc.h>
28 #include "../fat/msbuffer.h"
31 #if (DEBUG_LEVEL >= 1)
32 # define PRINTK1(x) printk x
36 #if (DEBUG_LEVEL >= 2)
37 # define PRINTK2(x) printk x
41 #if (DEBUG_LEVEL >= 3)
42 # define PRINTK3(x) printk x
50 # define CHECK_STACK check_stack(__FILE__, __LINE__)
53 struct vfat_find_info
{
67 void vfat_read_inode(struct inode
*inode
);
68 static int vfat_valid_shortname(const char *,int, int, int);
69 static int vfat_format_name(const char *, int, char *, int, int);
70 static int vfat_valid_longname(const char *, int, int, int);
71 static int vfat_hashi(struct dentry
*parent
, struct qstr
*qstr
);
72 static int vfat_hash(struct dentry
*parent
, struct qstr
*qstr
);
73 static int vfat_cmpi(struct dentry
*dentry
, struct qstr
*a
, struct qstr
*b
);
74 static int vfat_cmp(struct dentry
*dentry
, struct qstr
*a
, struct qstr
*b
);
75 static int vfat_revalidate(struct dentry
*dentry
);
77 static struct dentry_operations vfat_dentry_ops
[4] = {
79 NULL
, /* d_revalidate */
91 NULL
, /* d_revalidate */
104 static int strnicmp(const char *s1
, const char *s2
, int len
)
107 while (*s1
&& *s2
&& (tolower(*s1
) == tolower(*s2
))) {
109 if (n
== len
) return 0;
111 if (*s1
== 0 && *s2
== 0) return 0;
113 if (*s1
> *s2
) return 1;
120 void vfat_put_super(struct super_block
*sb
)
126 static int vfat_revalidate(struct dentry
*dentry
)
128 PRINTK1(("vfat_revalidate: %s\n", dentry
->d_name
.name
));
129 if (dentry
->d_time
== dentry
->d_parent
->d_inode
->i_version
) {
135 static struct super_operations vfat_sops
= {
142 NULL
, /* write_super */
147 static int simple_getbool(char *s
, int *setval
)
150 if (!strcmp(s
,"1") || !strcmp(s
,"yes") || !strcmp(s
,"true")) {
152 } else if (!strcmp(s
,"0") || !strcmp(s
,"no") || !strcmp(s
,"false")) {
163 static int parse_options(char *options
, struct fat_mount_options
*opts
)
165 char *this_char
,*value
,save
,*savep
;
168 opts
->unicode_xlate
= opts
->posixfs
= 0;
172 if (!options
) return 1;
176 for (this_char
= strtok(options
,","); this_char
; this_char
= strtok(NULL
,",")) {
177 if ((value
= strchr(this_char
,'=')) != NULL
) {
182 if (!strcmp(this_char
,"utf8")) {
183 ret
= simple_getbool(value
, &val
);
184 if (ret
) opts
->utf8
= val
;
185 } else if (!strcmp(this_char
,"uni_xlate")) {
186 ret
= simple_getbool(value
, &val
);
187 if (ret
) opts
->unicode_xlate
= val
;
188 } else if (!strcmp(this_char
,"posix")) {
189 ret
= simple_getbool(value
, &val
);
190 if (ret
) opts
->posixfs
= val
;
191 } else if (!strcmp(this_char
,"nonumtail")) {
192 ret
= simple_getbool(value
, &val
);
194 opts
->numtail
= !val
;
197 if (this_char
!= options
)
198 *(this_char
-1) = ',';
206 if (opts
->unicode_xlate
) {
213 * Compute the hash for the vfat name corresponding to the dentry.
214 * Note: if the name is invalid, we leave the hash code unchanged so
215 * that the existing dentry can be used. The vfat fs routines will
216 * return ENOENT or EINVAL as appropriate.
218 static int vfat_hash(struct dentry
*dentry
, struct qstr
*qstr
)
225 while (len
&& name
[len
-1] == '.')
228 qstr
->hash
= full_name_hash(name
, len
);
234 * Compute the hash for the vfat name corresponding to the dentry.
235 * Note: if the name is invalid, we leave the hash code unchanged so
236 * that the existing dentry can be used. The vfat fs routines will
237 * return ENOENT or EINVAL as appropriate.
239 static int vfat_hashi(struct dentry
*dentry
, struct qstr
*qstr
)
248 while (len
&& name
[len
-1] == '.')
251 hash
= init_name_hash();
253 c
= tolower(*name
++);
254 hash
= partial_name_hash(tolower(c
), hash
);
256 qstr
->hash
= end_name_hash(hash
);
262 * Case insensitive compare of two vfat names.
264 static int vfat_cmpi(struct dentry
*dentry
, struct qstr
*a
, struct qstr
*b
)
268 /* A filename cannot end in '.' or we treat it like it has none */
271 while (alen
&& a
->name
[alen
-1] == '.')
273 while (blen
&& b
->name
[blen
-1] == '.')
276 if (strnicmp(a
->name
, b
->name
, alen
) == 0)
283 * Case sensitive compare of two vfat names.
285 static int vfat_cmp(struct dentry
*dentry
, struct qstr
*a
, struct qstr
*b
)
289 /* A filename cannot end in '.' or we treat it like it has none */
292 while (alen
&& a
->name
[alen
-1] == '.')
294 while (blen
&& b
->name
[blen
-1] == '.')
297 if (strncmp(a
->name
, b
->name
, alen
) == 0)
303 struct super_block
*vfat_read_super(struct super_block
*sb
,void *data
,
306 struct super_block
*res
;
310 MSDOS_SB(sb
)->options
.isvfat
= 1;
312 sb
->s_op
= &vfat_sops
;
313 res
= fat_read_super(sb
, data
, silent
);
320 if (!parse_options((char *) data
, &(MSDOS_SB(sb
)->options
))) {
323 MSDOS_SB(sb
)->options
.dotsOK
= 0;
324 if (MSDOS_SB(sb
)->options
.posixfs
) {
325 MSDOS_SB(sb
)->options
.name_check
= 's';
327 if (MSDOS_SB(sb
)->options
.name_check
!= 's') {
328 sb
->s_root
->d_op
= &vfat_dentry_ops
[0];
330 sb
->s_root
->d_op
= &vfat_dentry_ops
[2];
340 check_stack(const char *fname
, int lineno
)
345 stack_level
= (long)(&pg_dir
)-current
->kernel_stack_page
;
347 printk("*-*-*-* vfat kstack overflow in %s line %d: SL=%d\n",
348 fname
, lineno
, stack_level
);
349 else if (stack_level
< 500)
350 printk("*-*-*-* vfat kstack low in %s line %d: SL=%d\n",
351 fname
, lineno
, stack_level
);
354 printk("------- vfat kstack ok in %s line %d: SL=%d\n",
355 fname
, lineno
, stack_level
);
358 if (*(unsigned long *) current
->kernel_stack_page
!= STACK_MAGIC
) {
359 printk("******* vfat stack corruption detected in %s at line %d\n",
365 static int debug
= 0;
366 static void dump_fat(struct super_block
*sb
,int start
)
371 start
= fat_access(sb
,start
,-1);
376 if (start
== -1) break;
381 static void dump_de(struct msdos_dir_entry
*de
)
384 unsigned char *p
= (unsigned char *) de
;
387 for (i
= 0; i
< 32; i
++, p
++) {
395 /* MS-DOS "device special files" */
397 static const char *reserved3_names
[] = {
398 "con ", "prn ", "nul ", "aux ", NULL
401 static const char *reserved4_names
[] = {
402 "com1 ", "com2 ", "com3 ", "com4 ", "com5 ",
403 "com6 ", "com7 ", "com8 ", "com9 ",
404 "lpt1 ", "lpt2 ", "lpt3 ", "lpt4 ", "lpt5 ",
405 "lpt6 ", "lpt7 ", "lpt8 ", "lpt9 ",
409 /* Characters that are undesirable in an MS-DOS file name */
411 static char bad_chars
[] = "*?<>|\":/\\";
412 static char replace_chars
[] = "[];,+=";
414 static int vfat_find(struct inode
*dir
,struct qstr
* name
,
415 int find_long
,int new_filename
,int is_dir
,
416 struct vfat_slot_info
*sinfo_out
);
418 /* Checks the validity of a long MS-DOS filename */
419 /* Returns negative number on error, 0 for a normal
420 * return, and 1 for . or .. */
422 static int vfat_valid_longname(const char *name
, int len
, int dot_dirs
,
425 const char **reserved
, *walk
;
429 if (IS_FREE(name
)) return -EINVAL
;
430 if (name
[0] == '.' && (len
== 1 || (len
== 2 && name
[1] == '.'))) {
431 if (!dot_dirs
) return -EEXIST
;
435 if (len
&& name
[len
-1] == ' ') return -EINVAL
;
436 if (len
>= 256) return -EINVAL
;
437 for (i
= 0; i
< len
; i
++) {
439 if (xlate
&& c
== ':') continue;
440 if (strchr(bad_chars
,c
)) {
444 if (len
< 3) return 0;
446 for (walk
= name
; *walk
!= 0 && *walk
!= '.'; walk
++);
447 baselen
= walk
- name
;
450 for (reserved
= reserved3_names
; *reserved
; reserved
++) {
451 if (!strnicmp(name
,*reserved
,baselen
))
454 } else if (baselen
== 4) {
455 for (reserved
= reserved4_names
; *reserved
; reserved
++) {
456 if (!strnicmp(name
,*reserved
,baselen
))
463 static int vfat_valid_shortname(const char *name
,int len
,
464 int dot_dirs
, int utf8
)
466 const char *walk
, **reserved
;
471 if (IS_FREE(name
)) return -EINVAL
;
472 if (name
[0] == '.' && (len
== 1 || (len
== 2 && name
[1] == '.'))) {
473 if (!dot_dirs
) return -EEXIST
;
477 space
= 1; /* disallow names starting with a dot */
479 for (walk
= name
; len
&& walk
-name
< 8;) {
482 if (utf8
&& (c
& 0x80)) return -EINVAL
;
483 if (strchr(bad_chars
,c
)) return -EINVAL
;
484 if (strchr(replace_chars
,c
)) return -EINVAL
;
485 if (c
>= 'A' && c
<= 'Z') return -EINVAL
;
486 if (c
< ' ' || c
== ':' || c
== '\\') return -EINVAL
;
487 if ((walk
== name
) && (c
== 0xE5)) c
= 0x05;
491 if (space
) return -EINVAL
;
492 if (len
&& c
!= '.') {
495 if (c
!= '.') return -EINVAL
;
497 while (c
!= '.' && len
--) c
= *walk
++;
498 baselen
= walk
- name
;
501 if (len
>= 4) return -EINVAL
;
502 while (len
> 0 && walk
-name
< (MSDOS_NAME
+1)) {
505 if (utf8
&& (c
& 0x80)) return -EINVAL
;
506 if (strchr(bad_chars
,c
)) return -EINVAL
;
507 if (strchr(replace_chars
,c
))
509 if (c
< ' ' || c
== ':' || c
== '\\' || c
== '.')
511 if (c
>= 'A' && c
<= 'Z') return -EINVAL
;
514 if (space
) return -EINVAL
;
515 if (len
) return -EINVAL
;
518 for (reserved
= reserved3_names
; *reserved
; reserved
++)
519 if (!strnicmp(name
,*reserved
,baselen
)) return -EINVAL
;
520 } else if (baselen
== 4) {
521 for (reserved
= reserved4_names
; *reserved
; reserved
++)
522 if (!strnicmp(name
,*reserved
,baselen
)) return -EINVAL
;
528 /* Takes a short filename and converts it to a formatted MS-DOS filename.
529 * If the short filename is not a valid MS-DOS filename, an error is
530 * returned. The formatted short filename is returned in 'res'.
533 static int vfat_format_name(const char *name
,int len
,char *res
,
534 int dot_dirs
,int utf8
)
537 const char **reserved
;
541 if (IS_FREE(name
)) return -EINVAL
;
542 if (name
[0] == '.' && (len
== 1 || (len
== 2 && name
[1] == '.'))) {
543 if (!dot_dirs
) return -EEXIST
;
544 memset(res
+1,' ',10);
545 while (len
--) *res
++ = '.';
549 space
= 1; /* disallow names starting with a dot */
551 for (walk
= res
; len
&& walk
-res
< 8; walk
++) {
554 if (utf8
&& (c
& 0x80)) return -EINVAL
;
555 if (strchr(bad_chars
,c
)) return -EINVAL
;
556 if (strchr(replace_chars
,c
)) return -EINVAL
;
557 if (c
>= 'A' && c
<= 'Z') return -EINVAL
;
558 if (c
< ' ' || c
== ':' || c
== '\\') return -EINVAL
;
561 *walk
= c
>= 'a' && c
<= 'z' ? c
-32 : c
;
563 if (space
) return -EINVAL
;
564 if (len
&& c
!= '.') {
567 if (c
!= '.') return -EINVAL
;
569 while (c
!= '.' && len
--) c
= *name
++;
571 while (walk
-res
< 8) *walk
++ = ' ';
572 while (len
> 0 && walk
-res
< MSDOS_NAME
) {
575 if (utf8
&& (c
& 0x80)) return -EINVAL
;
576 if (strchr(bad_chars
,c
)) return -EINVAL
;
577 if (strchr(replace_chars
,c
))
579 if (c
< ' ' || c
== ':' || c
== '\\' || c
== '.')
581 if (c
>= 'A' && c
<= 'Z') return -EINVAL
;
583 *walk
++ = c
>= 'a' && c
<= 'z' ? c
-32 : c
;
585 if (space
) return -EINVAL
;
586 if (len
) return -EINVAL
;
588 while (walk
-res
< MSDOS_NAME
) *walk
++ = ' ';
589 for (reserved
= reserved3_names
; *reserved
; reserved
++)
590 if (!strnicmp(res
,*reserved
,8)) return -EINVAL
;
591 for (reserved
= reserved4_names
; *reserved
; reserved
++)
592 if (!strnicmp(res
,*reserved
,8)) return -EINVAL
;
597 static char skip_chars
[] = ".:\"?<>| ";
599 /* Given a valid longname, create a unique shortname. Make sure the
600 * shortname does not exist
602 static int vfat_create_shortname(struct inode
*dir
, const char *name
,
603 int len
, char *name_res
, int utf8
)
605 const char *ip
, *ext_start
, *end
;
607 int sz
, extlen
, baselen
, totlen
;
609 char base
[9], ext
[4];
614 struct vfat_slot_info sinfo
;
615 const char *name_start
;
618 PRINTK2(("Entering vfat_create_shortname: name=%s, len=%d\n", name
, len
));
619 sz
= 0; /* Make compiler happy */
620 if (len
&& name
[len
-1]==' ') return -EINVAL
;
622 /* Do a case insensitive search if the name would be a valid
623 * shortname if is were all capitalized. However, do not
624 * allow spaces in short names because Win95 scandisk does
627 for (i
= 0, p
= msdos_name
, ip
= name
; i
< len
; i
++, p
++, ip
++)
633 if (*ip
>= 'A' && *ip
<= 'Z') {
640 res
= vfat_format_name(msdos_name
, len
, name_res
, 1, utf8
);
643 PRINTK3(("vfat_create_shortname 1\n"));
644 qname
.name
=msdos_name
;
646 res
= vfat_find(dir
, &qname
, 0, 0, 0, &sinfo
);
647 PRINTK3(("vfat_create_shortname 2\n"));
648 if (res
> -1) return -EEXIST
;
653 PRINTK3(("vfat_create_shortname 3\n"));
654 /* Now, we need to create a shortname from the long name */
655 ext_start
= end
= &name
[len
];
656 while (--ext_start
>= name
) {
657 if (*ext_start
== '.') {
658 if (ext_start
== end
- 1) {
665 if (ext_start
== name
- 1) {
668 } else if (ext_start
) {
670 * Names which start with a dot could be just
671 * an extension eg. "...test". In this case Win95
672 * uses the extension as the name and sets no extension.
674 name_start
= &name
[0];
675 while (name_start
< ext_start
)
677 if (!strchr(skip_chars
,*name_start
)) break;
680 if (name_start
!= ext_start
) {
681 sz
= ext_start
- name
;
689 for (baselen
= i
= 0, p
= base
, ip
= name
; i
< sz
&& baselen
< 8; i
++)
691 if (utf8
&& (*ip
& 0x80)) {
694 } else if (!strchr(skip_chars
, *ip
)) {
695 if (*ip
>= 'A' && *ip
<= 'Z') {
700 if (strchr(replace_chars
, *p
)) *p
='_';
709 spaces
= 8 - baselen
;
713 for (p
= ext
, ip
= ext_start
; extlen
< 3 && ip
< end
; ip
++) {
714 if (utf8
&& (*ip
& 0x80)) {
717 } else if (!strchr(skip_chars
, *ip
)) {
718 if (*ip
>= 'A' && *ip
<= 'Z') {
723 if (strchr(replace_chars
, *p
)) *p
='_';
732 base
[baselen
] = '\0';
734 strcpy(msdos_name
, base
);
735 msdos_name
[baselen
] = '.';
736 strcpy(&msdos_name
[baselen
+1], ext
);
738 totlen
= baselen
+ extlen
+ (extlen
> 0);
740 if (MSDOS_SB(dir
->i_sb
)->options
.numtail
== 0) {
741 qname
.name
=msdos_name
;
743 res
= vfat_find(dir
, &qname
, 0, 0, 0, &sinfo
);
748 * Try to find a unique extension. This used to
749 * iterate through all possibilities sequentially,
750 * but that gave extremely bad performance. Windows
751 * only tries a few cases before using random
752 * values for part of the base.
756 baselen
= baselen
- (2 - spaces
);
759 msdos_name
[baselen
] = '~';
760 msdos_name
[baselen
+2] = '.';
761 strcpy(&msdos_name
[baselen
+3], ext
);
762 totlen
= baselen
+ 2 + extlen
+ (extlen
> 0);
763 qname
.name
=msdos_name
;
765 for (i
= 1; res
> -1 && i
< 10; i
++) {
766 strncpy(msdos_name
, base
, baselen
);
767 msdos_name
[baselen
+1] = i
+ '0';
768 res
= vfat_find(dir
, &qname
, 0, 0, 0, &sinfo
);
772 i
= jiffies
& 0xffff;
773 sz
= (jiffies
>> 16) & 0x7;
775 baselen
= baselen
- (6 - spaces
);
778 msdos_name
[baselen
+4] = '~';
779 msdos_name
[baselen
+5] = '1' + sz
;
780 msdos_name
[baselen
+6] = '.';
781 strcpy(&msdos_name
[baselen
+7], ext
);
782 totlen
= baselen
+ 6 + extlen
+ (extlen
> 0);
783 qname
.name
=msdos_name
;
786 sprintf(buf
, "%04x", i
);
787 memcpy(&msdos_name
[baselen
], buf
, 4);
789 res
= vfat_find(dir
, &qname
, 0, 0, 0, &sinfo
);
794 res
= vfat_format_name(msdos_name
, totlen
, name_res
, 1, utf8
);
798 static loff_t
vfat_find_free_slots(struct inode
*dir
,int slots
)
800 struct super_block
*sb
= dir
->i_sb
;
802 struct msdos_dir_entry
*de
;
803 struct buffer_head
*bh
;
811 PRINTK2(("vfat_find_free_slots: find %d free slots\n", slots
));
815 ino
= fat_get_entry(dir
,&curr
,&bh
,&de
);
817 for (added
= 0; added
< 2; added
++) {
819 done
= IS_FREE(de
->name
);
821 inode
= iget(sb
,ino
);
823 /* Directory slots of busy deleted files aren't available yet. */
824 done
= !MSDOS_I(inode
)->i_busy
;
825 /* PRINTK3(("inode %d still busy\n", ino)); */
833 /* printk("----- Free offset at %d\n", offset); */
840 ino
= fat_get_entry(dir
,&curr
,&bh
,&de
);
843 if ((dir
->i_ino
== MSDOS_ROOT_INO
) &&
844 (MSDOS_SB(sb
)->fat_bits
!= 32))
846 if ((res
= fat_add_cluster(dir
)) < 0) return res
;
847 ino
= fat_get_entry(dir
,&curr
,&bh
,&de
);
852 /* Translate a string, including coded sequences into Unicode */
854 xlate_to_uni(const char *name
, int len
, char *outname
, int *outlen
,
855 int escape
, int utf8
, struct nls_table
*nls
)
858 const unsigned char *ip
;
861 unsigned char c1
, c2
, c3
;
864 *outlen
= utf8_mbstowcs((__u16
*) outname
, name
, PAGE_SIZE
);
865 if (name
[len
-1] == '.')
867 op
= &outname
[*outlen
* sizeof(__u16
)];
869 if (name
[len
-1] == '.')
873 for (i
= 0, ip
= name
, op
= outname
, *outlen
= 0;
874 i
< len
&& *outlen
<= 260; i
++, *outlen
+= 1)
876 if (escape
&& (*ip
== ':')) {
877 if (i
> len
- 4) return -EINVAL
;
878 c1
= fat_esc2uni
[ip
[1]];
879 c2
= fat_esc2uni
[ip
[2]];
880 c3
= fat_esc2uni
[ip
[3]];
881 if (c1
== 255 || c2
== 255 || c3
== 255)
883 *op
++ = (c1
<< 4) + (c2
>> 2);
884 *op
++ = ((c2
& 0x3) << 6) + c3
;
887 *op
++ = nls
->charset2uni
[*ip
].uni1
;
888 *op
++ = nls
->charset2uni
[*ip
].uni2
;
893 for (i
= 0, ip
= name
, op
= outname
, *outlen
= 0;
894 i
< len
&& *outlen
<= 260; i
++, *outlen
+= 1)
902 return -ENAMETOOLONG
;
909 fill
= 13 - (*outlen
% 13);
910 for (i
= 0; i
< fill
; i
++) {
922 vfat_fill_long_slots(struct msdos_dir_slot
*ds
, const char *name
, int len
,
923 char *msdos_name
, int *slots
,
924 int uni_xlate
, int utf8
, struct nls_table
*nls
)
926 struct msdos_dir_slot
*ps
;
927 struct msdos_dir_entry
*de
;
938 if (name
[len
-1] == '.') len
--;
939 if(!(page
= __get_free_page(GFP_KERNEL
)))
941 uniname
= (char *) page
;
942 res
= xlate_to_uni(name
, len
, uniname
, &unilen
, uni_xlate
, utf8
, nls
);
948 *slots
= unilen
/ 13;
949 for (cksum
= i
= 0; i
< 11; i
++) {
950 cksum
= (((cksum
&1)<<7)|((cksum
&0xfe)>>1)) + msdos_name
[i
];
952 PRINTK3(("vfat_fill_long_slots 3: slots=%d\n",*slots
));
954 for (ps
= ds
, slot
= *slots
; slot
> 0; slot
--, ps
++) {
957 PRINTK3(("vfat_fill_long_slots 4\n"));
961 ps
->alias_checksum
= cksum
;
963 PRINTK3(("vfat_fill_long_slots 5: uniname=%s\n",uniname
));
964 offset
= (slot
- 1) * 26;
965 ip
= &uniname
[offset
];
968 for (i
= 0; i
< 10; i
+= 2) {
969 ps
->name0_4
[i
] = *ip
++;
970 ps
->name0_4
[i
+1] = *ip
++;
972 PRINTK3(("vfat_fill_long_slots 6\n"));
973 for (i
= 0; i
< 12; i
+= 2) {
974 ps
->name5_10
[i
] = *ip
++;
975 ps
->name5_10
[i
+1] = *ip
++;
977 PRINTK3(("vfat_fill_long_slots 7\n"));
978 for (i
= 0; i
< 4; i
+= 2) {
979 ps
->name11_12
[i
] = *ip
++;
980 ps
->name11_12
[i
+1] = *ip
++;
983 PRINTK3(("vfat_fill_long_slots 8\n"));
986 de
= (struct msdos_dir_entry
*) ps
;
987 PRINTK3(("vfat_fill_long_slots 9\n"));
988 strncpy(de
->name
, msdos_name
, MSDOS_NAME
);
994 static int vfat_build_slots(struct inode
*dir
,const char *name
,int len
,
995 struct msdos_dir_slot
*ds
, int *slots
, int *is_long
)
997 struct msdos_dir_entry
*de
;
998 char msdos_name
[MSDOS_NAME
];
999 int res
, xlate
, utf8
;
1000 struct nls_table
*nls
;
1002 PRINTK2(("Entering vfat_build_slots: name=%s, len=%d\n", name
, len
));
1003 de
= (struct msdos_dir_entry
*) ds
;
1004 xlate
= MSDOS_SB(dir
->i_sb
)->options
.unicode_xlate
;
1005 utf8
= MSDOS_SB(dir
->i_sb
)->options
.utf8
;
1006 nls
= MSDOS_SB(dir
->i_sb
)->nls_io
;
1010 if (len
== 1 && name
[0] == '.') {
1011 strncpy(de
->name
, MSDOS_DOT
, MSDOS_NAME
);
1012 } else if (len
== 2 && name
[0] == '.' && name
[1] == '.') {
1013 strncpy(de
->name
, MSDOS_DOT
, MSDOS_NAME
);
1015 PRINTK3(("vfat_build_slots 4\n"));
1016 res
= vfat_valid_shortname(name
, len
, 1, utf8
);
1018 PRINTK3(("vfat_build_slots 5a\n"));
1019 res
= vfat_format_name(name
, len
, de
->name
, 1, utf8
);
1020 PRINTK3(("vfat_build_slots 5b\n"));
1022 res
= vfat_create_shortname(dir
, name
, len
, msdos_name
, utf8
);
1027 res
= vfat_valid_longname(name
, len
, 1, xlate
);
1034 return vfat_fill_long_slots(ds
, name
, len
, msdos_name
,
1035 slots
, xlate
, utf8
, nls
);
1041 static int vfat_readdir_cb(
1052 struct vfat_find_info
*vf
= (struct vfat_find_info
*) buf
;
1053 const char *s1
, *s2
;
1057 if (debug
) printk("cb: vf.name=%s, len=%d, name=%s, name_len=%d\n",
1058 vf
->name
, vf
->len
, name
, name_len
);
1061 if (vf
->len
!= name_len
) {
1065 s1
= name
; s2
= vf
->name
;
1066 for (i
= 0; i
< name_len
; i
++) {
1067 if (vf
->anycase
|| (vf
->new_filename
&& !vf
->posix
)) {
1068 if (tolower(*s1
) != tolower(*s2
))
1077 vf
->is_long
= is_long
;
1078 vf
->offset
= (offset
== 2) ? 0 : offset
;
1079 vf
->short_offset
= (short_offset
== 2) ? 0 : short_offset
;
1080 vf
->long_slots
= long_slots
;
1085 static int vfat_find(struct inode
*dir
,struct qstr
* qname
,
1086 int find_long
, int new_filename
,int is_dir
,struct vfat_slot_info
*sinfo_out
)
1088 struct super_block
*sb
= dir
->i_sb
;
1089 struct vfat_find_info vf
;
1091 struct buffer_head
*bh
;
1092 struct msdos_dir_entry
*de
;
1093 struct msdos_dir_slot
*ps
;
1095 struct msdos_dir_slot
*ds
;
1100 PRINTK2(("Entering vfat_find\n"));
1102 ds
= (struct msdos_dir_slot
*)
1103 kmalloc(sizeof(struct msdos_dir_slot
)*MSDOS_SLOTS
, GFP_KERNEL
);
1104 if (ds
== NULL
) return -ENOMEM
;
1107 vf
.name
= qname
->name
;
1108 vf
.len
= qname
->len
;
1109 vf
.new_filename
= new_filename
;
1111 vf
.posix
= MSDOS_SB(sb
)->options
.posixfs
;
1112 vf
.anycase
= (MSDOS_SB(sb
)->options
.name_check
!= 's');
1113 res
= fat_readdirx(dir
,&fil
,(void *)&vf
,vfat_readdir_cb
,NULL
,1,find_long
,0);
1114 PRINTK3(("vfat_find: Debug 1\n"));
1115 if (res
< 0) goto cleanup
;
1121 sinfo_out
->longname_offset
= vf
.offset
;
1122 sinfo_out
->shortname_offset
= vf
.short_offset
;
1123 sinfo_out
->is_long
= vf
.is_long
;
1124 sinfo_out
->long_slots
= vf
.long_slots
;
1125 sinfo_out
->total_slots
= vf
.long_slots
+ 1;
1126 sinfo_out
->ino
= vf
.ino
;
1128 PRINTK3(("vfat_find: Debug 2\n"));
1133 PRINTK3(("vfat_find: Debug 3\n"));
1134 if (!vf
.found
&& !new_filename
) {
1139 res
= vfat_build_slots(dir
, qname
->name
, qname
->len
, ds
,
1141 if (res
< 0) goto cleanup
;
1143 de
= (struct msdos_dir_entry
*) ds
;
1147 PRINTK3(("vfat_find: create file 1\n"));
1148 if (is_long
) slots
++;
1149 offset
= vfat_find_free_slots(dir
, slots
);
1155 PRINTK3(("vfat_find: create file 2\n"));
1156 /* Now create the new entry */
1158 for (slot
= 0, ps
= ds
; slot
< slots
; slot
++, ps
++) {
1159 PRINTK3(("vfat_find: create file 3, slot=%d\n",slot
));
1160 sinfo_out
->ino
= fat_get_entry(dir
,&offset
,&bh
,&de
);
1161 if (sinfo_out
->ino
< 0) {
1162 PRINTK3(("vfat_find: problem\n"));
1163 res
= sinfo_out
->ino
;
1166 memcpy(de
, ps
, sizeof(struct msdos_dir_slot
));
1167 fat_mark_buffer_dirty(sb
, bh
, 1);
1170 PRINTK3(("vfat_find: create file 4\n"));
1171 dir
->i_ctime
= dir
->i_mtime
= dir
->i_atime
= CURRENT_TIME
;
1172 mark_inode_dirty(dir
);
1174 PRINTK3(("vfat_find: create file 5\n"));
1176 fat_date_unix2dos(dir
->i_mtime
,&de
->time
,&de
->date
);
1178 de
->ctime
= de
->time
;
1179 de
->adate
= de
->cdate
= de
->date
;
1183 de
->attr
= is_dir
? ATTR_DIR
: ATTR_ARCH
;
1184 de
->lcase
= CASE_LOWER_BASE
| CASE_LOWER_EXT
;
1187 fat_mark_buffer_dirty(sb
, bh
, 1);
1190 sinfo_out
->is_long
= (slots
> 1) ? 1 : 0;
1191 if (sinfo_out
->is_long
) {
1192 sinfo_out
->long_slots
= slots
- 1;
1194 sinfo_out
->long_slots
= 0;
1196 sinfo_out
->total_slots
= slots
;
1197 sinfo_out
->shortname_offset
= offset
- sizeof(struct msdos_dir_slot
);
1198 sinfo_out
->longname_offset
= offset
- sizeof(struct msdos_dir_slot
) * slots
;
1209 int vfat_lookup(struct inode
*dir
,struct dentry
*dentry
)
1212 struct vfat_slot_info sinfo
;
1213 struct inode
*result
;
1216 PRINTK2(("vfat_lookup: name=%s, len=%d\n",
1217 dentry
->d_name
.name
, dentry
->d_name
.len
));
1219 table
= (MSDOS_SB(dir
->i_sb
)->options
.name_check
== 's') ? 2 : 0;
1220 dentry
->d_op
= &vfat_dentry_ops
[table
];
1223 if ((res
= vfat_find(dir
,&dentry
->d_name
,1,0,0,&sinfo
)) < 0) {
1228 PRINTK3(("vfat_lookup 4.5\n"));
1229 if (!(result
= iget(dir
->i_sb
,sinfo
.ino
)))
1231 PRINTK3(("vfat_lookup 5\n"));
1232 if (MSDOS_I(result
)->i_busy
) { /* mkdir in progress */
1238 PRINTK3(("vfat_lookup 6\n"));
1240 dentry
->d_op
= &vfat_dentry_ops
[table
];
1241 dentry
->d_time
= dentry
->d_parent
->d_inode
->i_version
;
1242 d_add(dentry
,result
);
1247 static int vfat_create_entry(struct inode
*dir
,struct qstr
* qname
,
1248 int is_dir
, struct inode
**result
)
1250 struct super_block
*sb
= dir
->i_sb
;
1253 struct buffer_head
*bh
;
1254 struct msdos_dir_entry
*de
;
1255 struct vfat_slot_info sinfo
;
1258 PRINTK1(("vfat_create_entry: Entering\n"));
1259 res
= vfat_find(dir
, qname
, 1, 1, is_dir
, &sinfo
);
1264 offset
= sinfo
.shortname_offset
;
1266 PRINTK3(("vfat_create_entry 2\n"));
1268 ino
= fat_get_entry(dir
, &offset
, &bh
, &de
);
1270 PRINTK3(("vfat_mkdir problem\n"));
1275 PRINTK3(("vfat_create_entry 3\n"));
1277 if ((*result
= iget(dir
->i_sb
,ino
)) != NULL
)
1278 vfat_read_inode(*result
);
1282 (*result
)->i_mtime
= (*result
)->i_atime
= (*result
)->i_ctime
=
1284 mark_inode_dirty(*result
);
1285 (*result
)->i_version
= ++event
;
1286 dir
->i_version
= event
;
1291 int vfat_create(struct inode
*dir
,struct dentry
* dentry
,int mode
)
1294 struct inode
*result
;
1297 fat_lock_creation();
1298 res
= vfat_create_entry(dir
,&dentry
->d_name
,0,&result
);
1299 fat_unlock_creation();
1301 PRINTK3(("vfat_create: unable to get new entry\n"));
1303 dentry
->d_time
= dentry
->d_parent
->d_inode
->i_version
;
1304 d_instantiate(dentry
,result
);
1309 static int vfat_create_a_dotdir(struct inode
*dir
,struct inode
*parent
,
1310 struct buffer_head
*bh
,
1311 struct msdos_dir_entry
*de
,int ino
,const char *name
, int isdot
)
1313 struct super_block
*sb
= dir
->i_sb
;
1316 PRINTK2(("vfat_create_a_dotdir: Entering\n"));
1319 * XXX all times should be set by caller upon successful completion.
1321 dir
->i_atime
= dir
->i_ctime
= dir
->i_mtime
= CURRENT_TIME
;
1322 mark_inode_dirty(dir
);
1323 memcpy(de
->name
,name
,MSDOS_NAME
);
1325 de
->attr
= ATTR_DIR
;
1328 fat_date_unix2dos(dir
->i_mtime
,&de
->time
,&de
->date
);
1330 de
->ctime
= de
->time
;
1331 de
->adate
= de
->cdate
= de
->date
;
1333 fat_mark_buffer_dirty(sb
, bh
, 1);
1334 dot
= iget(dir
->i_sb
,ino
);
1337 vfat_read_inode(dot
);
1338 dot
->i_mtime
= dot
->i_atime
= CURRENT_TIME
;
1339 mark_inode_dirty(dot
);
1341 dot
->i_size
= dir
->i_size
;
1342 MSDOS_I(dot
)->i_start
= MSDOS_I(dir
)->i_start
;
1343 MSDOS_I(dot
)->i_logstart
= MSDOS_I(dir
)->i_logstart
;
1344 dot
->i_nlink
= dir
->i_nlink
;
1346 dot
->i_size
= parent
->i_size
;
1347 MSDOS_I(dot
)->i_start
= MSDOS_I(parent
)->i_start
;
1348 MSDOS_I(dot
)->i_logstart
= MSDOS_I(parent
)->i_logstart
;
1349 dot
->i_nlink
= parent
->i_nlink
;
1354 PRINTK3(("vfat_create_a_dotdir 2\n"));
1358 static int vfat_create_dotdirs(struct inode
*dir
, struct inode
*parent
)
1360 struct super_block
*sb
= dir
->i_sb
;
1362 struct buffer_head
*bh
;
1363 struct msdos_dir_entry
*de
;
1366 PRINTK2(("vfat_create_dotdirs: Entering\n"));
1367 if ((res
= fat_add_cluster(dir
)) < 0) return res
;
1369 PRINTK3(("vfat_create_dotdirs 2\n"));
1372 if ((res
= fat_get_entry(dir
,&offset
,&bh
,&de
)) < 0) return res
;
1374 PRINTK3(("vfat_create_dotdirs 3\n"));
1375 res
= vfat_create_a_dotdir(dir
, parent
, bh
, de
, res
, MSDOS_DOT
, 1);
1376 PRINTK3(("vfat_create_dotdirs 4\n"));
1381 PRINTK3(("vfat_create_dotdirs 5\n"));
1383 if ((res
= fat_get_entry(dir
,&offset
,&bh
,&de
)) < 0) {
1387 PRINTK3(("vfat_create_dotdirs 6\n"));
1389 res
= vfat_create_a_dotdir(dir
, parent
, bh
, de
, res
, MSDOS_DOTDOT
, 0);
1390 PRINTK3(("vfat_create_dotdirs 7\n"));
1396 /***** See if directory is empty */
1397 static int vfat_empty(struct inode
*dir
)
1399 struct super_block
*sb
= dir
->i_sb
;
1401 struct buffer_head
*bh
;
1402 struct msdos_dir_entry
*de
;
1404 if (dir
->i_count
> 1) {
1407 if (MSDOS_I(dir
)->i_start
) { /* may be zero in mkdir */
1410 while (fat_get_entry(dir
,&pos
,&bh
,&de
) > -1) {
1411 /* Skip extended filename entries */
1412 if (de
->attr
== ATTR_EXT
) continue;
1414 if (!IS_FREE(de
->name
) && strncmp(de
->name
,MSDOS_DOT
,
1415 MSDOS_NAME
) && strncmp(de
->name
,MSDOS_DOTDOT
,
1427 static int vfat_rmdir_free_ino(struct inode
*dir
,struct buffer_head
*bh
,
1428 struct msdos_dir_entry
*de
,struct dentry
* dentry
)
1430 struct super_block
*sb
= dir
->i_sb
;
1433 if (!S_ISDIR(dentry
->d_inode
->i_mode
)) {
1436 if (dir
->i_dev
!= dentry
->d_inode
->i_dev
|| dir
== dentry
->d_inode
) {
1440 res
= vfat_empty(dentry
->d_inode
);
1444 dentry
->d_inode
->i_nlink
= 0;
1445 dentry
->d_inode
->i_mtime
= dir
->i_mtime
= CURRENT_TIME
;
1446 dentry
->d_inode
->i_atime
= dir
->i_atime
= CURRENT_TIME
;
1448 mark_inode_dirty(dir
);
1449 mark_inode_dirty(dentry
->d_inode
);
1450 de
->name
[0] = DELETED_FLAG
;
1451 fat_mark_buffer_dirty(sb
, bh
, 1);
1456 static int vfat_unlink_free_ino(struct inode
*dir
,struct buffer_head
*bh
,
1457 struct msdos_dir_entry
*de
,struct dentry
* dentry
,int nospc
)
1459 struct super_block
*sb
= dir
->i_sb
;
1460 if ((!S_ISREG(dentry
->d_inode
->i_mode
) && nospc
) ||
1461 IS_IMMUTABLE(dentry
->d_inode
)) {
1464 dentry
->d_inode
->i_nlink
= 0;
1465 dentry
->d_inode
->i_mtime
= dir
->i_mtime
= CURRENT_TIME
;
1466 dentry
->d_inode
->i_atime
= dir
->i_atime
= CURRENT_TIME
;
1467 dir
->i_version
= ++event
;
1468 MSDOS_I(dentry
->d_inode
)->i_busy
= 1;
1469 mark_inode_dirty(dir
);
1470 mark_inode_dirty(dentry
->d_inode
);
1471 de
->name
[0] = DELETED_FLAG
;
1472 fat_mark_buffer_dirty(sb
, bh
, 1);
1477 static int vfat_remove_entry(struct inode
*dir
,struct vfat_slot_info
*sinfo
,
1478 struct buffer_head
**bh
,struct dentry
* dentry
,
1479 int is_dir
,int nospc
)
1481 struct super_block
*sb
= dir
->i_sb
;
1483 struct msdos_dir_entry
*de
;
1486 /* remove the shortname */
1487 offset
= sinfo
->shortname_offset
;
1488 res
= fat_get_entry(dir
, &offset
, bh
, &de
);
1489 if (res
< 0) return res
;
1491 res
= vfat_rmdir_free_ino(dir
,*bh
,de
,dentry
);
1493 res
= vfat_unlink_free_ino(dir
,*bh
,de
,dentry
,nospc
);
1495 if (res
< 0) return res
;
1497 /* remove the longname */
1498 offset
= sinfo
->longname_offset
;
1499 for (i
= sinfo
->long_slots
; i
> 0; --i
) {
1500 res
= fat_get_entry(dir
, &offset
, bh
, &de
);
1504 de
->name
[0] = DELETED_FLAG
;
1506 fat_mark_buffer_dirty(sb
, *bh
, 1);
1511 /* Replace inodes in alias dentries and drop all but the initial dentry */
1512 static void drop_replace_inodes(struct dentry
*dentry
, struct inode
*inode
)
1514 struct list_head
*head
, *next
, *tmp
;
1515 struct dentry
*alias
;
1517 PRINTK1(("drop_replace_inodes: dentry=%p, inode=%p\n", dentry
, inode
));
1518 head
= &dentry
->d_inode
->i_dentry
;
1519 if (dentry
->d_inode
) {
1520 next
= dentry
->d_inode
->i_dentry
.next
;
1521 while (next
!= head
) {
1524 alias
= list_entry(tmp
, struct dentry
, d_alias
);
1526 list_del(&alias
->d_alias
);
1527 iput(alias
->d_inode
);
1528 d_instantiate(alias
, inode
);
1529 /* dentry is already accounted for */
1530 if (alias
!= dentry
) {
1534 if (alias
!= dentry
) {
1541 static int vfat_rmdirx(struct inode
*dir
,struct dentry
* dentry
)
1543 struct super_block
*sb
= dir
->i_sb
;
1545 struct buffer_head
*bh
;
1546 struct vfat_slot_info sinfo
;
1548 PRINTK1(("vfat_rmdirx: dentry=%p\n", dentry
));
1549 res
= vfat_find(dir
,&dentry
->d_name
,1,0,0,&sinfo
);
1551 if (res
>= 0 && sinfo
.total_slots
> 0) {
1553 res
= vfat_remove_entry(dir
,&sinfo
,&bh
,dentry
,1,0);
1557 dir
->i_version
= ++event
;
1558 if (bh
) fat_brelse(sb
, bh
);
1563 /***** Remove a directory */
1564 int vfat_rmdir(struct inode
*dir
,struct dentry
* dentry
)
1567 PRINTK1(("vfat_rmdir: dentry=%p, inode=%p\n", dentry
, dentry
->d_inode
));
1568 res
= vfat_rmdirx(dir
, dentry
);
1570 drop_replace_inodes(dentry
, NULL
);
1576 static int vfat_unlinkx(
1578 struct dentry
* dentry
,
1579 int nospc
) /* Flag special file ? */
1581 struct super_block
*sb
= dir
->i_sb
;
1583 struct buffer_head
*bh
;
1584 struct vfat_slot_info sinfo
;
1586 PRINTK1(("vfat_unlinkx: dentry=%p, inode=%p\n", dentry
, dentry
->d_inode
));
1588 res
= vfat_find(dir
,&dentry
->d_name
,1,0,0,&sinfo
);
1590 if (res
>= 0 && sinfo
.total_slots
> 0) {
1591 res
= vfat_remove_entry(dir
,&sinfo
,&bh
,dentry
,0,nospc
);
1597 if (bh
) fat_brelse(sb
, bh
);
1602 int vfat_mkdir(struct inode
*dir
,struct dentry
* dentry
,int mode
)
1604 struct inode
*inode
;
1607 PRINTK1(("vfat_mkdir: dentry=%p, inode=%p\n", dentry
, dentry
->d_inode
));
1608 fat_lock_creation();
1609 if ((res
= vfat_create_entry(dir
,&dentry
->d_name
,1,&inode
)) < 0) {
1610 fat_unlock_creation();
1615 inode
->i_nlink
= 2; /* no need to mark them dirty */
1616 MSDOS_I(inode
)->i_busy
= 1; /* prevent lookups */
1618 res
= vfat_create_dotdirs(inode
, dir
);
1619 fat_unlock_creation();
1620 MSDOS_I(inode
)->i_busy
= 0;
1621 dentry
->d_time
= dentry
->d_parent
->d_inode
->i_version
;
1622 d_instantiate(dentry
,inode
);
1624 if (vfat_rmdir(dir
,dentry
) < 0)
1625 fat_fs_panic(dir
->i_sb
,"rmdir in mkdir failed");
1630 /***** Unlink, as called for msdosfs */
1631 int vfat_unlink(struct inode
*dir
,struct dentry
* dentry
)
1635 PRINTK1(("vfat_unlink: dentry=%p, inode=%p\n", dentry
, dentry
->d_inode
));
1636 res
= vfat_unlinkx (dir
,dentry
,1);
1638 drop_replace_inodes(dentry
, NULL
);
1644 /***** Unlink, as called for uvfatfs */
1645 int vfat_unlink_uvfat(struct inode
*dir
,struct dentry
*dentry
)
1649 res
= vfat_unlinkx (dir
,dentry
,0);
1654 int vfat_rename(struct inode
*old_dir
,struct dentry
*old_dentry
,
1655 struct inode
*new_dir
,struct dentry
*new_dentry
)
1657 struct super_block
*sb
= old_dir
->i_sb
;
1658 struct buffer_head
*old_bh
,*new_bh
,*dotdot_bh
;
1659 struct msdos_dir_entry
*old_de
,*new_de
,*dotdot_de
;
1660 loff_t old_offset
,new_offset
,old_longname_offset
;
1661 int old_slots
,old_ino
,new_ino
,dotdot_ino
;
1662 struct inode
*old_inode
, *new_inode
, *dotdot_inode
;
1663 struct dentry
*walk
;
1666 struct vfat_slot_info sinfo
;
1667 int put_new_inode
= 0;
1669 PRINTK1(("vfat_rename: Entering: old_dentry=%p, old_inode=%p, old ino=%ld, new_dentry=%p, new_inode=%p, new ino=%ld\n",
1670 old_dentry
, old_dentry
->d_inode
, old_dentry
->d_inode
->i_ino
,
1671 new_dentry
, new_dentry
->d_inode
,
1672 new_dentry
->d_inode
? new_dentry
->d_inode
->i_ino
: 0));
1673 if (old_dir
== new_dir
&&
1674 old_dentry
->d_name
.len
== new_dentry
->d_name
.len
&&
1675 strncmp(old_dentry
->d_name
.name
, new_dentry
->d_name
.name
,
1676 old_dentry
->d_name
.len
) == 0)
1679 old_bh
= new_bh
= NULL
;
1680 old_inode
= new_inode
= NULL
;
1681 res
= vfat_find(old_dir
,&old_dentry
->d_name
,1,0,0,&sinfo
);
1682 PRINTK3(("vfat_rename 2\n"));
1683 if (res
< 0) goto rename_done
;
1685 old_slots
= sinfo
.total_slots
;
1686 old_longname_offset
= sinfo
.longname_offset
;
1687 old_offset
= sinfo
.shortname_offset
;
1688 old_ino
= sinfo
.ino
;
1689 res
= fat_get_entry(old_dir
, &old_offset
, &old_bh
, &old_de
);
1690 PRINTK3(("vfat_rename 3\n"));
1691 if (res
< 0) goto rename_done
;
1694 old_inode
= old_dentry
->d_inode
;
1695 is_dir
= S_ISDIR(old_inode
->i_mode
);
1697 if ((old_dir
->i_dev
!= new_dir
->i_dev
) ||
1698 (old_ino
== new_dir
->i_ino
)) {
1703 /* prevent moving directory below itself */
1705 if (walk
== old_dentry
) return -EINVAL
;
1706 if (walk
== walk
->d_parent
) break;
1707 walk
= walk
->d_parent
;
1711 res
= vfat_find(new_dir
,&new_dentry
->d_name
,1,0,is_dir
,&sinfo
);
1713 PRINTK3(("vfat_rename 4\n"));
1717 PRINTK3(("vfat_rename 5\n"));
1718 /* Filename currently exists. Need to delete it */
1719 new_offset
= sinfo
.shortname_offset
;
1720 res
= fat_get_entry(new_dir
, &new_offset
, &new_bh
, &new_de
);
1721 PRINTK3(("vfat_rename 6\n"));
1722 if (res
< 0) goto rename_done
;
1724 if (!(new_inode
= iget(new_dir
->i_sb
,res
)))
1726 new_is_dir
= S_ISDIR(new_inode
->i_mode
);
1729 PRINTK3(("vfat_rename 7\n"));
1730 res
= vfat_rmdirx(new_dir
,new_dentry
);
1731 PRINTK3(("vfat_rename 8\n"));
1732 if (res
< 0) goto rename_done
;
1734 /* Is this the same file, different case? */
1735 if (new_inode
!= old_inode
) {
1736 PRINTK3(("vfat_rename 9\n"));
1737 res
= vfat_unlink(new_dir
,new_dentry
);
1738 PRINTK3(("vfat_rename 10\n"));
1739 if (res
< 0) goto rename_done
;
1744 PRINTK3(("vfat_rename 11\n"));
1745 fat_lock_creation(); locked
= 1;
1746 res
= vfat_find(new_dir
,&new_dentry
->d_name
,1,1,is_dir
,&sinfo
);
1748 PRINTK3(("vfat_rename 12\n"));
1749 if (res
< 0) goto rename_done
;
1751 new_offset
= sinfo
.shortname_offset
;
1752 new_ino
= sinfo
.ino
;
1753 PRINTK3(("vfat_rename 13: new_ino=%d\n", new_ino
));
1755 if (!(new_inode
= iget(new_dir
->i_sb
,new_ino
))) goto rename_done
;
1758 new_inode
->i_mode
= old_inode
->i_mode
;
1759 new_inode
->i_size
= old_inode
->i_size
;
1760 new_inode
->i_blocks
= old_inode
->i_blocks
;
1761 new_inode
->i_mtime
= old_inode
->i_mtime
;
1762 new_inode
->i_atime
= old_inode
->i_atime
;
1763 new_inode
->i_ctime
= old_inode
->i_ctime
;
1764 MSDOS_I(new_inode
)->i_ctime_ms
= MSDOS_I(old_inode
)->i_ctime_ms
;
1766 MSDOS_I(new_inode
)->i_start
= MSDOS_I(old_inode
)->i_start
;
1767 MSDOS_I(new_inode
)->i_logstart
= MSDOS_I(old_inode
)->i_logstart
;
1768 MSDOS_I(new_inode
)->i_attrs
= MSDOS_I(old_inode
)->i_attrs
;
1770 mark_inode_dirty(new_inode
);
1772 old_dir
->i_version
= ++event
;
1773 new_dir
->i_version
= ++event
;
1775 PRINTK3(("vfat_rename 14: old_slots=%d\n",old_slots
));
1777 /* remove the old entry */
1778 for (i
= old_slots
; i
> 0; --i
) {
1779 res
= fat_get_entry(old_dir
, &old_longname_offset
, &old_bh
, &old_de
);
1781 printk("vfat_rename: problem 1\n");
1784 old_de
->name
[0] = DELETED_FLAG
;
1786 fat_mark_buffer_dirty(sb
, old_bh
, 1);
1788 PRINTK3(("vfat_rename 15b\n"));
1790 if (S_ISDIR(old_inode
->i_mode
)) {
1791 if ((res
= fat_scan(old_inode
,MSDOS_DOTDOT
,&dotdot_bh
,
1792 &dotdot_de
,&dotdot_ino
,SCAN_ANY
)) < 0) goto rename_done
;
1793 if (!(dotdot_inode
= iget(old_inode
->i_sb
,dotdot_ino
))) {
1794 fat_brelse(sb
, dotdot_bh
);
1798 MSDOS_I(dotdot_inode
)->i_start
= MSDOS_I(new_dir
)->i_start
;
1799 MSDOS_I(dotdot_inode
)->i_logstart
= MSDOS_I(new_dir
)->i_logstart
;
1800 dotdot_de
->start
= CT_LE_W(MSDOS_I(new_dir
)->i_logstart
);
1801 dotdot_de
->starthi
= CT_LE_W((MSDOS_I(new_dir
)->i_logstart
) >> 16);
1802 mark_inode_dirty(dotdot_inode
);
1803 fat_mark_buffer_dirty(sb
, dotdot_bh
, 1);
1806 /* no need to mark them dirty */
1807 dotdot_inode
->i_nlink
= new_dir
->i_nlink
;
1809 fat_brelse(sb
, dotdot_bh
);
1812 if (res
> 0) res
= 0;
1815 drop_replace_inodes(old_dentry
, new_inode
);
1816 d_move(old_dentry
, new_dentry
);
1822 fat_unlock_creation();
1824 fat_brelse(sb
, old_bh
);
1826 fat_brelse(sb
, new_bh
);
1834 /* Public inode operations for the VFAT fs */
1835 struct inode_operations vfat_dir_inode_operations
= {
1836 &fat_dir_operations
, /* default directory file-ops */
1837 vfat_create
, /* create */
1838 vfat_lookup
, /* lookup */
1840 vfat_unlink
, /* unlink */
1842 vfat_mkdir
, /* mkdir */
1843 vfat_rmdir
, /* rmdir */
1845 vfat_rename
, /* rename */
1846 NULL
, /* readlink */
1847 NULL
, /* followlink */
1848 NULL
, /* readpage */
1849 NULL
, /* writepage */
1850 fat_bmap
, /* bmap */
1851 NULL
, /* truncate */
1852 NULL
/* permission */
1856 void vfat_read_inode(struct inode
*inode
)
1858 fat_read_inode(inode
, &vfat_dir_inode_operations
);
1862 int init_module(void)
1864 return init_vfat_fs();
1867 void cleanup_module(void)
1869 unregister_filesystem(&vfat_fs_type
);
1872 #endif /* ifdef MODULE */