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.
12 * Short name translation 1999 by Wolfram Pienkoss <wp@bsz.shk.th.schule.de>
15 #define __NO_VERSION__
16 #include <linux/module.h>
18 #include <linux/sched.h>
19 #include <linux/msdos_fs.h>
20 #include <linux/nls.h>
21 #include <linux/kernel.h>
22 #include <linux/errno.h>
23 #include <linux/string.h>
24 #include <linux/ctype.h>
25 #include <linux/stat.h>
27 #include <linux/malloc.h>
29 #include "../fat/msbuffer.h"
32 #if (DEBUG_LEVEL >= 1)
33 # define PRINTK1(x) printk x
37 #if (DEBUG_LEVEL >= 2)
38 # define PRINTK2(x) printk x
42 #if (DEBUG_LEVEL >= 3)
43 # define PRINTK3(x) printk x
51 # define CHECK_STACK check_stack(__FILE__, __LINE__)
54 static int vfat_hashi(struct dentry
*parent
, struct qstr
*qstr
);
55 static int vfat_hash(struct dentry
*parent
, struct qstr
*qstr
);
56 static int vfat_cmpi(struct dentry
*dentry
, struct qstr
*a
, struct qstr
*b
);
57 static int vfat_cmp(struct dentry
*dentry
, struct qstr
*a
, struct qstr
*b
);
58 static int vfat_revalidate(struct dentry
*dentry
, int);
60 static struct dentry_operations vfat_dentry_ops
[4] = {
66 d_revalidate
: vfat_revalidate
,
75 d_revalidate
: vfat_revalidate
,
81 static int vfat_revalidate(struct dentry
*dentry
, int flags
)
83 PRINTK1(("vfat_revalidate: %s\n", dentry
->d_name
.name
));
84 if (dentry
->d_time
== dentry
->d_parent
->d_inode
->i_version
) {
90 static int simple_getbool(char *s
, int *setval
)
93 if (!strcmp(s
,"1") || !strcmp(s
,"yes") || !strcmp(s
,"true")) {
95 } else if (!strcmp(s
,"0") || !strcmp(s
,"no") || !strcmp(s
,"false")) {
106 static int parse_options(char *options
, struct fat_mount_options
*opts
)
108 char *this_char
,*value
,save
,*savep
;
111 opts
->unicode_xlate
= opts
->posixfs
= 0;
115 if (!options
) return 1;
119 for (this_char
= strtok(options
,","); this_char
; this_char
= strtok(NULL
,",")) {
120 if ((value
= strchr(this_char
,'=')) != NULL
) {
125 if (!strcmp(this_char
,"utf8")) {
126 ret
= simple_getbool(value
, &val
);
127 if (ret
) opts
->utf8
= val
;
128 } else if (!strcmp(this_char
,"uni_xlate")) {
129 ret
= simple_getbool(value
, &val
);
130 if (ret
) opts
->unicode_xlate
= val
;
131 } else if (!strcmp(this_char
,"posix")) {
132 ret
= simple_getbool(value
, &val
);
133 if (ret
) opts
->posixfs
= val
;
134 } else if (!strcmp(this_char
,"nonumtail")) {
135 ret
= simple_getbool(value
, &val
);
137 opts
->numtail
= !val
;
140 if (this_char
!= options
)
141 *(this_char
-1) = ',';
149 if (opts
->unicode_xlate
) {
155 static inline unsigned char
156 vfat_getlower(struct nls_table
*t
, unsigned char c
)
158 return t
->charset2lower
[c
];
161 static inline unsigned char
162 vfat_tolower(struct nls_table
*t
, unsigned char c
)
164 unsigned char nc
= t
->charset2lower
[c
];
169 static inline unsigned char
170 vfat_getupper(struct nls_table
*t
, unsigned char c
)
172 return t
->charset2upper
[c
];
175 static inline unsigned char
176 vfat_toupper(struct nls_table
*t
, unsigned char c
)
178 unsigned char nc
= t
->charset2upper
[c
];
184 vfat_strnicmp(struct nls_table
*t
, const unsigned char *s1
,
185 const unsigned char *s2
, int len
)
188 if (vfat_tolower(t
, *s1
++) != vfat_tolower(t
, *s2
++))
194 static inline unsigned char
195 vfat_uni2short(struct nls_table
*t
, struct nls_unicode uc
)
199 up
= t
->page_uni2charset
[uc
.uni2
];
206 static inline unsigned char
207 vfat_uni2upper_short(struct nls_table
*t
, struct nls_unicode uc
)
211 up
= t
->page_uni2charset
[uc
.uni2
];
213 return vfat_toupper(t
, up
[uc
.uni1
]);
219 * Compute the hash for the vfat name corresponding to the dentry.
220 * Note: if the name is invalid, we leave the hash code unchanged so
221 * that the existing dentry can be used. The vfat fs routines will
222 * return ENOENT or EINVAL as appropriate.
224 static int vfat_hash(struct dentry
*dentry
, struct qstr
*qstr
)
231 while (len
&& name
[len
-1] == '.')
234 qstr
->hash
= full_name_hash(name
, len
);
240 * Compute the hash for the vfat name corresponding to the dentry.
241 * Note: if the name is invalid, we leave the hash code unchanged so
242 * that the existing dentry can be used. The vfat fs routines will
243 * return ENOENT or EINVAL as appropriate.
245 static int vfat_hashi(struct dentry
*dentry
, struct qstr
*qstr
)
247 struct nls_table
*t
= MSDOS_SB(dentry
->d_inode
->i_sb
)->nls_io
;
254 while (len
&& name
[len
-1] == '.')
257 hash
= init_name_hash();
259 hash
= partial_name_hash(vfat_tolower(t
, *name
++), hash
);
260 qstr
->hash
= end_name_hash(hash
);
266 * Case insensitive compare of two vfat names.
268 static int vfat_cmpi(struct dentry
*dentry
, struct qstr
*a
, struct qstr
*b
)
270 struct nls_table
*t
= MSDOS_SB(dentry
->d_inode
->i_sb
)->nls_io
;
273 /* A filename cannot end in '.' or we treat it like it has none */
276 while (alen
&& a
->name
[alen
-1] == '.')
278 while (blen
&& b
->name
[blen
-1] == '.')
281 if (vfat_strnicmp(t
, a
->name
, b
->name
, alen
) == 0)
288 * Case sensitive compare of two vfat names.
290 static int vfat_cmp(struct dentry
*dentry
, struct qstr
*a
, struct qstr
*b
)
294 /* A filename cannot end in '.' or we treat it like it has none */
297 while (alen
&& a
->name
[alen
-1] == '.')
299 while (blen
&& b
->name
[blen
-1] == '.')
302 if (strncmp(a
->name
, b
->name
, alen
) == 0)
311 check_stack(const char *fname
, int lineno
)
316 stack_level
= (long)(&pg_dir
)-current
->kernel_stack_page
;
318 printk("*-*-*-* vfat kstack overflow in %s line %d: SL=%d\n",
319 fname
, lineno
, stack_level
);
320 else if (stack_level
< 500)
321 printk("*-*-*-* vfat kstack low in %s line %d: SL=%d\n",
322 fname
, lineno
, stack_level
);
325 printk("------- vfat kstack ok in %s line %d: SL=%d\n",
326 fname
, lineno
, stack_level
);
329 if (*(unsigned long *) current
->kernel_stack_page
!= STACK_MAGIC
) {
330 printk("******* vfat stack corruption detected in %s at line %d\n",
336 static int debug
= 0;
337 static void dump_fat(struct super_block
*sb
,int start
)
342 start
= fat_access(sb
,start
,-1);
347 if (start
== -1) break;
352 static void dump_de(struct msdos_dir_entry
*de
)
355 unsigned char *p
= (unsigned char *) de
;
358 for (i
= 0; i
< 32; i
++, p
++) {
366 /* MS-DOS "device special files" */
368 static const char *reserved3_names
[] = {
369 "con ", "prn ", "nul ", "aux ", NULL
372 static const char *reserved4_names
[] = {
373 "com1 ", "com2 ", "com3 ", "com4 ", "com5 ",
374 "com6 ", "com7 ", "com8 ", "com9 ",
375 "lpt1 ", "lpt2 ", "lpt3 ", "lpt4 ", "lpt5 ",
376 "lpt6 ", "lpt7 ", "lpt8 ", "lpt9 ",
380 /* Characters that are undesirable in an MS-DOS file name */
382 static char bad_chars
[] = "*?<>|\":/\\";
383 static char replace_chars
[] = "[];,+=";
385 /* Checks the validity of a long MS-DOS filename */
386 /* Returns negative number on error, 0 for a normal
387 * return, and 1 for . or .. */
389 static int vfat_valid_longname(const char *name
, int len
, int xlate
)
391 const char **reserved
, *walk
;
395 if (len
&& name
[len
-1] == ' ') return -EINVAL
;
396 if (len
>= 256) return -EINVAL
;
397 for (i
= 0; i
< len
; i
++) {
399 if (xlate
&& c
== ':') continue;
400 if (strchr(bad_chars
,c
)) {
404 if (len
< 3) return 0;
406 for (walk
= name
; *walk
!= 0 && *walk
!= '.'; walk
++);
407 baselen
= walk
- name
;
410 for (reserved
= reserved3_names
; *reserved
; reserved
++) {
411 if (!strnicmp(name
,*reserved
,baselen
))
414 } else if (baselen
== 4) {
415 for (reserved
= reserved4_names
; *reserved
; reserved
++) {
416 if (!strnicmp(name
,*reserved
,baselen
))
423 static int vfat_valid_shortname(struct nls_table
*nls
, struct nls_unicode
*name
,
426 struct nls_unicode
*walk
;
430 c
= vfat_uni2upper_short(nls
, *name
);
434 space
= 1; /* disallow names starting with a dot */
435 for (walk
= name
; len
&& walk
-name
< 8;) {
437 l
= vfat_uni2short(nls
, *walk
++);
438 c
= vfat_getupper(nls
, l
);
439 if (!c
) return -EINVAL
;
440 if (l
!= vfat_tolower(nls
, c
)) return -EINVAL
;
441 if (strchr(replace_chars
,c
)) return -EINVAL
;
442 if (c
< ' '|| c
==':') return -EINVAL
;
446 if (space
) return -EINVAL
;
447 if (len
&& c
!= '.') {
449 c
= vfat_uni2upper_short(nls
, *walk
++);
450 if (c
!= '.') return -EINVAL
;
453 if (len
>= 4) return -EINVAL
;
456 l
= vfat_uni2short(nls
, *walk
++);
457 c
= vfat_getupper(nls
, l
);
458 if (!c
) return -EINVAL
;
459 if (l
!= vfat_tolower(nls
, c
)) return -EINVAL
;
460 if (strchr(replace_chars
,c
))
462 if (c
< ' ' || c
== '.'|| c
==':')
466 if (space
) return -EINVAL
;
472 static int vfat_find_form(struct inode
*dir
,char *name
)
474 struct msdos_dir_entry
*de
;
475 struct buffer_head
*bh
= NULL
;
478 res
=fat_scan(dir
,name
,&bh
,&de
,&ino
);
479 fat_brelse(dir
->i_sb
, bh
);
485 static int vfat_format_name(struct nls_table
*nls
, struct nls_unicode
*name
,
492 c
= vfat_uni2upper_short(nls
, *name
);
496 space
= 1; /* disallow names starting with a dot */
497 for (walk
= res
; len
--; walk
++) {
498 c
= vfat_uni2upper_short(nls
, *name
++);
500 if (!c
) return -EINVAL
;
501 if (walk
-res
== 8) return -EINVAL
;
502 if (strchr(replace_chars
,c
)) return -EINVAL
;
503 if (c
< ' '|| c
==':') return -EINVAL
;
507 if (space
) return -EINVAL
;
509 while (walk
-res
< 8) *walk
++ = ' ';
510 while (len
> 0 && walk
-res
< MSDOS_NAME
) {
511 c
= vfat_uni2upper_short(nls
, *name
++);
513 if (!c
) return -EINVAL
;
514 if (strchr(replace_chars
,c
))
516 if (c
< ' ' || c
== '.'|| c
==':')
521 if (space
) return -EINVAL
;
522 if (len
) return -EINVAL
;
524 while (walk
-res
< MSDOS_NAME
) *walk
++ = ' ';
529 static char skip_chars
[] = ".:\"?<>| ";
531 /* Given a valid longname, create a unique shortname. Make sure the
532 * shortname does not exist
534 static int vfat_create_shortname(struct inode
*dir
, struct nls_table
*nls
,
535 struct nls_unicode
*name
, int len
,
538 struct nls_unicode
*ip
, *op
, *ext_start
, *end
, *name_start
;
539 struct nls_unicode msdos_name
[13];
540 char base
[9], ext
[4], buf
[8], *p
;
541 int sz
, extlen
, baselen
, i
;
543 PRINTK2(("Entering vfat_create_shortname\n"));
544 sz
= 0; /* Make compiler happy */
546 /* Do a case insensitive search if the name would be a valid
547 * shortname if is were all capitalized. However, do not
548 * allow spaces in short names because Win95 scandisk does
550 for (i
= 0, op
= &msdos_name
[0], ip
= name
; ; i
++, ip
++, op
++) {
552 if (vfat_format_name(nls
, &msdos_name
[0], len
,
555 PRINTK3(("vfat_create_shortname 1\n"));
556 if (vfat_find_form(dir
, name_res
) < 0)
560 if (vfat_uni2upper_short(nls
, *ip
) == ' ')
566 PRINTK3(("vfat_create_shortname 3\n"));
567 /* Now, we need to create a shortname from the long name */
568 ext_start
= end
= &name
[len
];
569 while (--ext_start
>= name
) {
570 if (vfat_uni2upper_short(nls
, *ext_start
) == '.') {
571 if (ext_start
== end
- 1) {
578 if (ext_start
== name
- 1) {
581 } else if (ext_start
) {
583 * Names which start with a dot could be just
584 * an extension eg. "...test". In this case Win95
585 * uses the extension as the name and sets no extension.
587 name_start
= &name
[0];
588 while (name_start
< ext_start
)
590 unsigned char c
= vfat_uni2upper_short(nls
, *name_start
);
593 if (!strchr(skip_chars
, c
))
597 if (name_start
!= ext_start
) {
598 sz
= ext_start
- name
;
606 for (baselen
= i
= 0, p
= base
, ip
= name
; i
< sz
&& baselen
< 8; i
++)
608 unsigned char c
= vfat_uni2upper_short(nls
, *ip
);
612 } else if (!strchr(skip_chars
, c
)) {
613 if (strchr(replace_chars
, c
))
627 for (p
= ext
, ip
= ext_start
; extlen
< 3 && ip
< end
; ip
++) {
628 unsigned char c
= vfat_uni2upper_short(nls
, *ip
);
632 } else if (!strchr(skip_chars
, c
)) {
633 if (strchr(replace_chars
, c
))
642 base
[baselen
] = '\0';
644 /* Yes, it can happen. ".\xe5" would do it. */
648 /* OK, at this point we know that base is not longer than 8 symbols,
649 * ext is not longer than 3, base is nonempty, both don't contain
650 * any bad symbols (lowercase transformed to uppercase).
653 memset(name_res
, ' ', MSDOS_NAME
);
654 memcpy(name_res
,base
,baselen
);
655 memcpy(name_res
+8,ext
,extlen
);
656 if (MSDOS_SB(dir
->i_sb
)->options
.numtail
== 0)
657 if (vfat_find_form(dir
, name_res
) < 0)
661 * Try to find a unique extension. This used to
662 * iterate through all possibilities sequentially,
663 * but that gave extremely bad performance. Windows
664 * only tries a few cases before using random
665 * values for part of the base.
670 name_res
[baselen
] = '~';
671 for (i
= 1; i
< 10; i
++) {
672 name_res
[baselen
+1] = i
+ '0';
673 if (vfat_find_form(dir
, name_res
) < 0)
677 i
= jiffies
& 0xffff;
678 sz
= (jiffies
>> 16) & 0x7;
681 name_res
[baselen
+4] = '~';
682 name_res
[baselen
+5] = '1' + sz
;
684 sprintf(buf
, "%04X", i
);
685 memcpy(&name_res
[baselen
], buf
, 4);
686 if (vfat_find_form(dir
, name_res
) < 0)
693 /* Translate a string, including coded sequences into Unicode */
695 xlate_to_uni(const char *name
, int len
, char *outname
, int *longlen
, int *outlen
,
696 int escape
, int utf8
, struct nls_table
*nls
)
698 const unsigned char *ip
;
705 *outlen
= utf8_mbstowcs((__u16
*) outname
, name
, PAGE_SIZE
);
706 if (name
[len
-1] == '.')
708 op
= &outname
[*outlen
* sizeof(__u16
)];
710 if (name
[len
-1] == '.')
713 for (i
= 0, ip
= name
, op
= outname
, *outlen
= 0;
714 i
< len
&& *outlen
<= 260; *outlen
+= 1)
716 if (escape
&& (*ip
== ':')) {
720 for (k
= 1; k
< 5; k
++) {
723 if (nc
>= '0' && nc
<= '9') {
727 if (nc
>= 'a' && nc
<= 'f') {
728 ec
|= nc
- ('a' - 10);
731 if (nc
>= 'A' && nc
<= 'F') {
732 ec
|= nc
- ('A' - 10);
742 *op
++ = nls
->charset2uni
[*ip
].uni1
;
743 *op
++ = nls
->charset2uni
[*ip
].uni2
;
749 for (i
= 0, ip
= name
, op
= outname
, *outlen
= 0;
750 i
< len
&& *outlen
<= 260; i
++, *outlen
+= 1)
758 return -ENAMETOOLONG
;
766 fill
= 13 - (*outlen
% 13);
767 for (i
= 0; i
< fill
; i
++) {
779 vfat_fill_slots(struct inode
*dir
, struct msdos_dir_slot
*ds
, const char *name
,
780 int len
, int *slots
, int uni_xlate
)
782 struct nls_table
*nls_io
, *nls_disk
;
783 struct nls_unicode
*uname
;
784 struct msdos_dir_slot
*ps
;
785 struct msdos_dir_entry
*de
;
789 char *uniname
, msdos_name
[MSDOS_NAME
];
790 int res
, utf8
, slot
, ulen
, unilen
, i
;
793 de
= (struct msdos_dir_entry
*) ds
;
794 utf8
= MSDOS_SB(dir
->i_sb
)->options
.utf8
;
795 nls_io
= MSDOS_SB(dir
->i_sb
)->nls_io
;
796 nls_disk
= MSDOS_SB(dir
->i_sb
)->nls_disk
;
798 if (name
[len
-1] == '.') len
--;
799 if(!(page
= __get_free_page(GFP_KERNEL
)))
801 uniname
= (char *) page
;
802 res
= xlate_to_uni(name
, len
, uniname
, &ulen
, &unilen
, uni_xlate
,
807 uname
= (struct nls_unicode
*) page
;
808 if (vfat_valid_shortname(nls_disk
, uname
, ulen
) >= 0) {
809 res
= vfat_format_name(nls_disk
, uname
, ulen
, de
->name
);
813 res
= vfat_create_shortname(dir
, nls_disk
, uname
, ulen
, msdos_name
);
817 *slots
= unilen
/ 13;
818 for (cksum
= i
= 0; i
< 11; i
++) {
819 cksum
= (((cksum
&1)<<7)|((cksum
&0xfe)>>1)) + msdos_name
[i
];
821 PRINTK3(("vfat_fill_slots 3: slots=%d\n",*slots
));
823 for (ps
= ds
, slot
= *slots
; slot
> 0; slot
--, ps
++) {
827 ps
->alias_checksum
= cksum
;
829 offset
= (slot
- 1) * 26;
830 ip
= &uniname
[offset
];
831 memcpy(ps
->name0_4
, ip
, 10);
832 memcpy(ps
->name5_10
, ip
+10, 12);
833 memcpy(ps
->name11_12
, ip
+22, 4);
837 de
= (struct msdos_dir_entry
*) ps
;
838 PRINTK3(("vfat_fill_slots 9\n"));
839 strncpy(de
->name
, msdos_name
, MSDOS_NAME
);
847 /* We can't get "." or ".." here - VFS takes care of those cases */
849 static int vfat_build_slots(struct inode
*dir
,const char *name
,int len
,
850 struct msdos_dir_slot
*ds
, int *slots
)
854 xlate
= MSDOS_SB(dir
->i_sb
)->options
.unicode_xlate
;
856 res
= vfat_valid_longname(name
, len
, xlate
);
859 return vfat_fill_slots(dir
, ds
, name
, len
, slots
, xlate
);
862 static int vfat_add_entry(struct inode
*dir
,struct qstr
* qname
,
863 int is_dir
,struct vfat_slot_info
*sinfo_out
,
864 struct buffer_head
**bh
, struct msdos_dir_entry
**de
)
866 struct super_block
*sb
= dir
->i_sb
;
867 struct msdos_dir_slot
*ps
;
869 struct msdos_dir_slot
*ds
;
872 struct msdos_dir_entry
*de1
;
873 struct buffer_head
*bh1
;
878 ds
= (struct msdos_dir_slot
*)
879 kmalloc(sizeof(struct msdos_dir_slot
)*MSDOS_SLOTS
, GFP_KERNEL
);
880 if (ds
== NULL
) return -ENOMEM
;
883 while (len
&& qname
->name
[len
-1] == '.')
885 res
= fat_search_long(dir
, qname
->name
, len
,
886 (MSDOS_SB(sb
)->options
.name_check
!= 's') ||
887 !MSDOS_SB(sb
)->options
.posixfs
,
889 if (res
> 0) /* found */
894 res
= vfat_build_slots(dir
, qname
->name
, len
, ds
, &slots
);
895 if (res
< 0) goto cleanup
;
897 offset
= fat_add_entries(dir
, slots
, &bh1
, &de1
, &ino
);
904 /* Now create the new entry */
906 for (slot
= 0, ps
= ds
; slot
< slots
; slot
++, ps
++) {
907 if (fat_get_entry(dir
,&offset
,bh
,de
, &sinfo_out
->ino
) < 0) {
911 memcpy(*de
, ps
, sizeof(struct msdos_dir_slot
));
912 fat_mark_buffer_dirty(sb
, *bh
, 1);
915 dir
->i_ctime
= dir
->i_mtime
= dir
->i_atime
= CURRENT_TIME
;
916 mark_inode_dirty(dir
);
918 fat_date_unix2dos(dir
->i_mtime
,&(*de
)->time
,&(*de
)->date
);
920 (*de
)->ctime
= (*de
)->time
;
921 (*de
)->adate
= (*de
)->cdate
= (*de
)->date
;
925 (*de
)->attr
= is_dir
? ATTR_DIR
: ATTR_ARCH
;
926 (*de
)->lcase
= CASE_LOWER_BASE
| CASE_LOWER_EXT
;
929 fat_mark_buffer_dirty(sb
, *bh
, 1);
931 /* slots can't be less than 1 */
932 sinfo_out
->long_slots
= slots
- 1;
933 sinfo_out
->longname_offset
= offset
- sizeof(struct msdos_dir_slot
) * slots
;
941 static int vfat_find(struct inode
*dir
,struct qstr
* qname
,
942 struct vfat_slot_info
*sinfo
, struct buffer_head
**last_bh
,
943 struct msdos_dir_entry
**last_de
)
945 struct super_block
*sb
= dir
->i_sb
;
950 while (len
&& qname
->name
[len
-1] == '.')
952 res
= fat_search_long(dir
, qname
->name
, len
,
953 (MSDOS_SB(sb
)->options
.name_check
!= 's'),
954 &offset
,&sinfo
->longname_offset
);
956 sinfo
->long_slots
= res
-1;
957 if (fat_get_entry(dir
,&offset
,last_bh
,last_de
,&sinfo
->ino
)>=0)
961 return res
? res
: -ENOENT
;
964 /* Find a hashed dentry for inode; NULL if there are none */
965 static struct dentry
*find_alias(struct inode
*inode
)
967 struct list_head
*head
, *next
, *tmp
;
968 struct dentry
*alias
;
970 head
= &inode
->i_dentry
;
971 next
= inode
->i_dentry
.next
;
972 while (next
!= head
) {
975 alias
= list_entry(tmp
, struct dentry
, d_alias
);
976 if (!d_unhashed(alias
))
982 struct dentry
*vfat_lookup(struct inode
*dir
,struct dentry
*dentry
)
985 struct vfat_slot_info sinfo
;
987 struct dentry
*alias
;
988 struct buffer_head
*bh
= NULL
;
989 struct msdos_dir_entry
*de
;
992 PRINTK2(("vfat_lookup: name=%s, len=%d\n",
993 dentry
->d_name
.name
, dentry
->d_name
.len
));
995 table
= (MSDOS_SB(dir
->i_sb
)->options
.name_check
== 's') ? 2 : 0;
996 dentry
->d_op
= &vfat_dentry_ops
[table
];
999 res
= vfat_find(dir
,&dentry
->d_name
,&sinfo
,&bh
,&de
);
1004 inode
= fat_build_inode(dir
->i_sb
, de
, sinfo
.ino
, &res
);
1005 fat_brelse(dir
->i_sb
, bh
);
1007 return ERR_PTR(res
);
1008 alias
= find_alias(inode
);
1010 if (d_invalidate(alias
)==0)
1019 dentry
->d_op
= &vfat_dentry_ops
[table
];
1020 dentry
->d_time
= dentry
->d_parent
->d_inode
->i_version
;
1021 d_add(dentry
,inode
);
1025 int vfat_create(struct inode
*dir
,struct dentry
* dentry
,int mode
)
1027 struct super_block
*sb
= dir
->i_sb
;
1028 struct inode
*inode
= NULL
;
1029 struct buffer_head
*bh
= NULL
;
1030 struct msdos_dir_entry
*de
;
1031 struct vfat_slot_info sinfo
;
1034 res
= vfat_add_entry(dir
, &dentry
->d_name
, 0, &sinfo
, &bh
, &de
);
1037 inode
= fat_build_inode(sb
, de
, sinfo
.ino
, &res
);
1041 inode
->i_mtime
= inode
->i_atime
= inode
->i_ctime
= CURRENT_TIME
;
1042 mark_inode_dirty(inode
);
1043 inode
->i_version
= ++event
;
1044 dir
->i_version
= event
;
1045 dentry
->d_time
= dentry
->d_parent
->d_inode
->i_version
;
1046 d_instantiate(dentry
,inode
);
1050 static void vfat_remove_entry(struct inode
*dir
,struct vfat_slot_info
*sinfo
,
1051 struct buffer_head
*bh
, struct msdos_dir_entry
*de
)
1053 struct super_block
*sb
= dir
->i_sb
;
1057 /* remove the shortname */
1058 dir
->i_mtime
= CURRENT_TIME
;
1059 dir
->i_atime
= CURRENT_TIME
;
1060 dir
->i_version
= ++event
;
1061 mark_inode_dirty(dir
);
1062 de
->name
[0] = DELETED_FLAG
;
1063 fat_mark_buffer_dirty(sb
, bh
, 1);
1064 /* remove the longname */
1065 offset
= sinfo
->longname_offset
; de
= NULL
;
1066 for (i
= sinfo
->long_slots
; i
> 0; --i
) {
1067 if (fat_get_entry(dir
, &offset
, &bh
, &de
, &ino
) < 0)
1069 de
->name
[0] = DELETED_FLAG
;
1071 fat_mark_buffer_dirty(sb
, bh
, 1);
1073 if (bh
) fat_brelse(sb
, bh
);
1076 int vfat_rmdir(struct inode
*dir
,struct dentry
* dentry
)
1079 struct vfat_slot_info sinfo
;
1080 struct buffer_head
*bh
= NULL
;
1081 struct msdos_dir_entry
*de
;
1083 if (!d_unhashed(dentry
))
1086 res
= fat_dir_empty(dentry
->d_inode
);
1090 res
= vfat_find(dir
,&dentry
->d_name
,&sinfo
, &bh
, &de
);
1093 dentry
->d_inode
->i_nlink
= 0;
1094 dentry
->d_inode
->i_mtime
= CURRENT_TIME
;
1095 dentry
->d_inode
->i_atime
= CURRENT_TIME
;
1096 fat_detach(dentry
->d_inode
);
1097 mark_inode_dirty(dentry
->d_inode
);
1099 vfat_remove_entry(dir
,&sinfo
,bh
,de
);
1104 int vfat_unlink(struct inode
*dir
, struct dentry
* dentry
)
1107 struct vfat_slot_info sinfo
;
1108 struct buffer_head
*bh
= NULL
;
1109 struct msdos_dir_entry
*de
;
1111 PRINTK1(("vfat_unlink: %s\n", dentry
->d_name
.name
));
1112 res
= vfat_find(dir
,&dentry
->d_name
,&sinfo
,&bh
,&de
);
1115 dentry
->d_inode
->i_nlink
= 0;
1116 dentry
->d_inode
->i_mtime
= CURRENT_TIME
;
1117 dentry
->d_inode
->i_atime
= CURRENT_TIME
;
1118 fat_detach(dentry
->d_inode
);
1119 mark_inode_dirty(dentry
->d_inode
);
1121 vfat_remove_entry(dir
,&sinfo
,bh
,de
);
1128 int vfat_mkdir(struct inode
*dir
,struct dentry
* dentry
,int mode
)
1130 struct super_block
*sb
= dir
->i_sb
;
1131 struct inode
*inode
= NULL
;
1132 struct vfat_slot_info sinfo
;
1133 struct buffer_head
*bh
= NULL
;
1134 struct msdos_dir_entry
*de
;
1137 res
= vfat_add_entry(dir
, &dentry
->d_name
, 1, &sinfo
, &bh
, &de
);
1140 inode
= fat_build_inode(sb
, de
, sinfo
.ino
, &res
);
1143 inode
->i_mtime
= inode
->i_atime
= inode
->i_ctime
= CURRENT_TIME
;
1144 mark_inode_dirty(inode
);
1145 inode
->i_version
= ++event
;
1146 dir
->i_version
= event
;
1148 inode
->i_nlink
= 2; /* no need to mark them dirty */
1149 res
= fat_new_dir(inode
, dir
, 1);
1152 dentry
->d_time
= dentry
->d_parent
->d_inode
->i_version
;
1153 d_instantiate(dentry
,inode
);
1160 inode
->i_mtime
= CURRENT_TIME
;
1161 inode
->i_atime
= CURRENT_TIME
;
1163 mark_inode_dirty(inode
);
1165 vfat_remove_entry(dir
,&sinfo
,bh
,de
);
1171 int vfat_rename(struct inode
*old_dir
,struct dentry
*old_dentry
,
1172 struct inode
*new_dir
,struct dentry
*new_dentry
)
1174 struct super_block
*sb
= old_dir
->i_sb
;
1175 struct buffer_head
*old_bh
,*new_bh
,*dotdot_bh
;
1176 struct msdos_dir_entry
*old_de
,*new_de
,*dotdot_de
;
1178 struct inode
*old_inode
, *new_inode
;
1180 struct vfat_slot_info old_sinfo
,sinfo
;
1182 old_bh
= new_bh
= dotdot_bh
= NULL
;
1183 old_inode
= old_dentry
->d_inode
;
1184 new_inode
= new_dentry
->d_inode
;
1185 res
= vfat_find(old_dir
,&old_dentry
->d_name
,&old_sinfo
,&old_bh
,&old_de
);
1186 PRINTK3(("vfat_rename 2\n"));
1187 if (res
< 0) goto rename_done
;
1189 is_dir
= S_ISDIR(old_inode
->i_mode
);
1191 if (is_dir
&& (res
= fat_scan(old_inode
,MSDOS_DOTDOT
,&dotdot_bh
,
1192 &dotdot_de
,&dotdot_ino
)) < 0)
1195 if (new_dentry
->d_inode
) {
1196 res
= vfat_find(new_dir
,&new_dentry
->d_name
,&sinfo
,&new_bh
,
1198 if (res
< 0 || MSDOS_I(new_inode
)->i_location
!= sinfo
.ino
) {
1199 /* WTF??? Cry and fail. */
1200 printk(KERN_WARNING
"vfat_rename: fs corrupted\n");
1206 if (!d_unhashed(new_dentry
))
1208 res
= fat_dir_empty(new_inode
);
1212 fat_detach(new_inode
);
1214 res
= vfat_add_entry(new_dir
,&new_dentry
->d_name
,is_dir
,&sinfo
,
1216 if (res
< 0) goto rename_done
;
1219 new_dir
->i_version
= ++event
;
1221 /* releases old_bh */
1222 vfat_remove_entry(old_dir
,&old_sinfo
,old_bh
,old_de
);
1224 fat_detach(old_inode
);
1225 fat_attach(old_inode
, sinfo
.ino
);
1226 mark_inode_dirty(old_inode
);
1228 old_dir
->i_version
= ++event
;
1229 old_dir
->i_ctime
= old_dir
->i_mtime
= CURRENT_TIME
;
1230 mark_inode_dirty(old_dir
);
1232 new_inode
->i_nlink
--;
1233 new_inode
->i_ctime
=CURRENT_TIME
;
1237 int start
= MSDOS_I(new_dir
)->i_logstart
;
1238 dotdot_de
->start
= CT_LE_W(start
);
1239 dotdot_de
->starthi
= CT_LE_W(start
>>16);
1240 fat_mark_buffer_dirty(sb
, dotdot_bh
, 1);
1243 new_inode
->i_nlink
--;
1246 mark_inode_dirty(new_dir
);
1251 fat_brelse(sb
, dotdot_bh
);
1252 fat_brelse(sb
, old_bh
);
1253 fat_brelse(sb
, new_bh
);
1259 /* Public inode operations for the VFAT fs */
1260 struct inode_operations vfat_dir_inode_operations
= {
1261 create
: vfat_create
,
1262 lookup
: vfat_lookup
,
1263 unlink
: vfat_unlink
,
1266 rename
: vfat_rename
,
1267 setattr
: fat_notify_change
,
1270 struct super_block
*vfat_read_super(struct super_block
*sb
,void *data
,
1273 struct super_block
*res
;
1275 MSDOS_SB(sb
)->options
.isvfat
= 1;
1277 res
= fat_read_super(sb
, data
, silent
, &vfat_dir_inode_operations
);
1281 if (parse_options((char *) data
, &(MSDOS_SB(sb
)->options
))) {
1282 MSDOS_SB(sb
)->options
.dotsOK
= 0;
1283 if (MSDOS_SB(sb
)->options
.posixfs
) {
1284 MSDOS_SB(sb
)->options
.name_check
= 's';
1286 if (MSDOS_SB(sb
)->options
.name_check
!= 's') {
1287 sb
->s_root
->d_op
= &vfat_dentry_ops
[0];
1289 sb
->s_root
->d_op
= &vfat_dentry_ops
[2];