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 spin_lock(&dcache_lock
);
85 if (dentry
->d_time
== dentry
->d_parent
->d_inode
->i_version
) {
86 spin_unlock(&dcache_lock
);
89 spin_unlock(&dcache_lock
);
93 static int simple_getbool(char *s
, int *setval
)
96 if (!strcmp(s
,"1") || !strcmp(s
,"yes") || !strcmp(s
,"true")) {
98 } else if (!strcmp(s
,"0") || !strcmp(s
,"no") || !strcmp(s
,"false")) {
109 static int parse_options(char *options
, struct fat_mount_options
*opts
)
111 char *this_char
,*value
,save
,*savep
;
114 opts
->unicode_xlate
= opts
->posixfs
= 0;
118 if (!options
) return 1;
122 for (this_char
= strtok(options
,","); this_char
; this_char
= strtok(NULL
,",")) {
123 if ((value
= strchr(this_char
,'=')) != NULL
) {
128 if (!strcmp(this_char
,"utf8")) {
129 ret
= simple_getbool(value
, &val
);
130 if (ret
) opts
->utf8
= val
;
131 } else if (!strcmp(this_char
,"uni_xlate")) {
132 ret
= simple_getbool(value
, &val
);
133 if (ret
) opts
->unicode_xlate
= val
;
134 } else if (!strcmp(this_char
,"posix")) {
135 ret
= simple_getbool(value
, &val
);
136 if (ret
) opts
->posixfs
= val
;
137 } else if (!strcmp(this_char
,"nonumtail")) {
138 ret
= simple_getbool(value
, &val
);
140 opts
->numtail
= !val
;
143 if (this_char
!= options
)
144 *(this_char
-1) = ',';
152 if (opts
->unicode_xlate
) {
158 static inline unsigned char
159 vfat_getlower(struct nls_table
*t
, unsigned char c
)
161 return t
->charset2lower
[c
];
164 static inline unsigned char
165 vfat_tolower(struct nls_table
*t
, unsigned char c
)
167 unsigned char nc
= t
->charset2lower
[c
];
172 static inline unsigned char
173 vfat_getupper(struct nls_table
*t
, unsigned char c
)
175 return t
->charset2upper
[c
];
178 static inline unsigned char
179 vfat_toupper(struct nls_table
*t
, unsigned char c
)
181 unsigned char nc
= t
->charset2upper
[c
];
187 vfat_strnicmp(struct nls_table
*t
, const unsigned char *s1
,
188 const unsigned char *s2
, int len
)
191 if (vfat_tolower(t
, *s1
++) != vfat_tolower(t
, *s2
++))
198 vfat_uni2short(struct nls_table
*t
, wchar_t uc
, unsigned char *op
, int bound
)
202 if ( (charlen
= t
->uni2char(uc
, op
, bound
)) < 0)
209 vfat_uni2upper_short(struct nls_table
*t
, wchar_t uc
, char *op
, int bound
)
213 if ( (chl
= t
->uni2char(uc
, op
, bound
)) < 0)
216 for (chi
= 0; chi
< chl
; chi
++)
217 op
[chi
] = vfat_toupper(t
, op
[chi
]);
223 * Compute the hash for the vfat name corresponding to the dentry.
224 * Note: if the name is invalid, we leave the hash code unchanged so
225 * that the existing dentry can be used. The vfat fs routines will
226 * return ENOENT or EINVAL as appropriate.
228 static int vfat_hash(struct dentry
*dentry
, struct qstr
*qstr
)
235 while (len
&& name
[len
-1] == '.')
238 qstr
->hash
= full_name_hash(name
, len
);
244 * Compute the hash for the vfat name corresponding to the dentry.
245 * Note: if the name is invalid, we leave the hash code unchanged so
246 * that the existing dentry can be used. The vfat fs routines will
247 * return ENOENT or EINVAL as appropriate.
249 static int vfat_hashi(struct dentry
*dentry
, struct qstr
*qstr
)
251 struct nls_table
*t
= MSDOS_SB(dentry
->d_inode
->i_sb
)->nls_io
;
258 while (len
&& name
[len
-1] == '.')
261 hash
= init_name_hash();
263 hash
= partial_name_hash(vfat_tolower(t
, *name
++), hash
);
264 qstr
->hash
= end_name_hash(hash
);
270 * Case insensitive compare of two vfat names.
272 static int vfat_cmpi(struct dentry
*dentry
, struct qstr
*a
, struct qstr
*b
)
274 struct nls_table
*t
= MSDOS_SB(dentry
->d_inode
->i_sb
)->nls_io
;
277 /* A filename cannot end in '.' or we treat it like it has none */
280 while (alen
&& a
->name
[alen
-1] == '.')
282 while (blen
&& b
->name
[blen
-1] == '.')
285 if (vfat_strnicmp(t
, a
->name
, b
->name
, alen
) == 0)
292 * Case sensitive compare of two vfat names.
294 static int vfat_cmp(struct dentry
*dentry
, struct qstr
*a
, struct qstr
*b
)
298 /* A filename cannot end in '.' or we treat it like it has none */
301 while (alen
&& a
->name
[alen
-1] == '.')
303 while (blen
&& b
->name
[blen
-1] == '.')
306 if (strncmp(a
->name
, b
->name
, alen
) == 0)
315 check_stack(const char *fname
, int lineno
)
320 stack_level
= (long)(&pg_dir
)-current
->kernel_stack_page
;
322 printk("*-*-*-* vfat kstack overflow in %s line %d: SL=%d\n",
323 fname
, lineno
, stack_level
);
324 else if (stack_level
< 500)
325 printk("*-*-*-* vfat kstack low in %s line %d: SL=%d\n",
326 fname
, lineno
, stack_level
);
329 printk("------- vfat kstack ok in %s line %d: SL=%d\n",
330 fname
, lineno
, stack_level
);
333 if (*(unsigned long *) current
->kernel_stack_page
!= STACK_MAGIC
) {
334 printk("******* vfat stack corruption detected in %s at line %d\n",
340 static int debug
= 0;
341 static void dump_fat(struct super_block
*sb
,int start
)
346 start
= fat_access(sb
,start
,-1);
351 if (start
== -1) break;
356 static void dump_de(struct msdos_dir_entry
*de
)
359 unsigned char *p
= (unsigned char *) de
;
362 for (i
= 0; i
< 32; i
++, p
++) {
370 /* MS-DOS "device special files" */
372 static const char *reserved3_names
[] = {
373 "con ", "prn ", "nul ", "aux ", NULL
376 static const char *reserved4_names
[] = {
377 "com1 ", "com2 ", "com3 ", "com4 ", "com5 ",
378 "com6 ", "com7 ", "com8 ", "com9 ",
379 "lpt1 ", "lpt2 ", "lpt3 ", "lpt4 ", "lpt5 ",
380 "lpt6 ", "lpt7 ", "lpt8 ", "lpt9 ",
384 /* Characters that are undesirable in an MS-DOS file name */
386 static char bad_chars
[] = "*?<>|\":/\\";
387 static char replace_chars
[] = "[];,+=";
389 /* Checks the validity of a long MS-DOS filename */
390 /* Returns negative number on error, 0 for a normal
391 * return, and 1 for . or .. */
393 static int vfat_valid_longname(const char *name
, int len
, int xlate
)
395 const char **reserved
, *walk
;
399 if (len
&& name
[len
-1] == ' ') return -EINVAL
;
400 if (len
>= 256) return -EINVAL
;
401 for (i
= 0; i
< len
; i
++) {
403 if (xlate
&& c
== ':') continue;
404 if (strchr(bad_chars
,c
)) {
408 if (len
< 3) return 0;
410 for (walk
= name
; *walk
!= 0 && *walk
!= '.'; walk
++);
411 baselen
= walk
- name
;
414 for (reserved
= reserved3_names
; *reserved
; reserved
++) {
415 if (!strnicmp(name
,*reserved
,baselen
))
418 } else if (baselen
== 4) {
419 for (reserved
= reserved4_names
; *reserved
; reserved
++) {
420 if (!strnicmp(name
,*reserved
,baselen
))
427 static int vfat_valid_shortname(struct nls_table
*nls
, wchar_t *name
, int len
)
430 unsigned char c
, charbuf
[NLS_MAX_CHARSET_SIZE
];
434 if (vfat_uni2upper_short(nls
, *name
, charbuf
, NLS_MAX_CHARSET_SIZE
) == 0)
437 if (IS_FREE(charbuf
))
442 space
= 1; /* disallow names starting with a dot */
443 for (walk
= name
; len
&& walk
-name
< 8;) {
445 if ( (chl
= nls
->uni2char(*walk
, charbuf
, NLS_MAX_CHARSET_SIZE
)) < 0) {
450 for (chi
= 0; chi
< chl
; chi
++) {
451 c
= vfat_getupper(nls
, charbuf
[chi
]);
452 if (!c
) return -EINVAL
;
453 if (charbuf
[chi
] != vfat_tolower(nls
, c
)) return -EINVAL
;
454 if (strchr(replace_chars
,c
)) return -EINVAL
;
455 if (c
< ' '|| c
==':') return -EINVAL
;
456 if (c
== '.') goto dot
;
461 if (space
) return -EINVAL
;
462 if (len
&& c
!= '.') {
464 if (vfat_uni2upper_short(nls
, *walk
++, charbuf
, NLS_MAX_CHARSET_SIZE
) == 1) {
465 if (charbuf
[0] != '.') return -EINVAL
;
471 if (len
>= 4) return -EINVAL
;
474 chl
= vfat_uni2short(nls
, *walk
++, charbuf
, NLS_MAX_CHARSET_SIZE
);
477 for (chi
= 0; chi
< chl
; chi
++) {
478 c
= vfat_getupper(nls
, charbuf
[chi
]);
479 if (!c
) return -EINVAL
;
480 if (charbuf
[chi
] != vfat_tolower(nls
, c
)) return -EINVAL
;
481 if (strchr(replace_chars
,c
))
483 if (c
< ' ' || c
== '.'|| c
==':')
488 if (space
) return -EINVAL
;
494 static int vfat_find_form(struct inode
*dir
,char *name
)
496 struct msdos_dir_entry
*de
;
497 struct buffer_head
*bh
= NULL
;
500 res
=fat_scan(dir
,name
,&bh
,&de
,&ino
);
501 fat_brelse(dir
->i_sb
, bh
);
507 static int vfat_format_name(struct nls_table
*nls
, wchar_t *name
,
511 unsigned char charbuf
[NLS_MAX_CHARSET_SIZE
];
515 if (vfat_uni2upper_short(nls
, *name
, charbuf
, NLS_MAX_CHARSET_SIZE
) == 0)
518 if (IS_FREE(charbuf
))
521 space
= 1; /* disallow names starting with a dot */
522 for (walk
= res
; len
--; ) {
523 chl
= vfat_uni2upper_short(nls
, *name
++, charbuf
, NLS_MAX_CHARSET_SIZE
);
526 for (chi
= 0; chi
< chl
; chi
++){
527 if (charbuf
[chi
] == '.') goto dot
;
528 if (!charbuf
[chi
]) return -EINVAL
;
529 if (walk
-res
== 8) return -EINVAL
;
530 if (strchr(replace_chars
,charbuf
[chi
])) return -EINVAL
;
531 if (charbuf
[chi
] < ' '|| charbuf
[chi
]==':') return -EINVAL
;
532 space
= charbuf
[chi
] == ' ';
533 *walk
= charbuf
[chi
];
538 if (space
) return -EINVAL
;
540 while (walk
-res
< 8) *walk
++ = ' ';
541 while (len
> 0 && walk
-res
< MSDOS_NAME
) {
542 chl
= vfat_uni2upper_short(nls
, *name
++, charbuf
, NLS_MAX_CHARSET_SIZE
);
546 for (chi
= 0; chi
< chl
; chi
++){
547 if (!charbuf
[chi
]) return -EINVAL
;
548 if (strchr(replace_chars
,charbuf
[chi
]))
550 if (charbuf
[chi
] < ' ' || charbuf
[chi
] == '.'|| charbuf
[chi
]==':')
552 space
= charbuf
[chi
] == ' ';
553 *walk
++ = charbuf
[chi
];
556 if (space
) return -EINVAL
;
557 if (len
) return -EINVAL
;
559 while (walk
-res
< MSDOS_NAME
) *walk
++ = ' ';
564 static char skip_chars
[] = ".:\"?<>| ";
566 /* Given a valid longname, create a unique shortname. Make sure the
567 * shortname does not exist
569 static int vfat_create_shortname(struct inode
*dir
, struct nls_table
*nls
,
570 wchar_t *name
, int len
,
573 wchar_t *ip
, *op
, *ext_start
, *end
, *name_start
;
574 wchar_t msdos_name
[13];
575 char base
[9], ext
[4], buf
[8], *p
;
576 unsigned char charbuf
[NLS_MAX_CHARSET_SIZE
];
578 int sz
, extlen
, baselen
, i
;
580 PRINTK2(("Entering vfat_create_shortname\n"));
582 sz
= 0; /* Make compiler happy */
584 /* Do a case insensitive search if the name would be a valid
585 * shortname if is were all capitalized. However, do not
586 * allow spaces in short names because Win95 scandisk does
588 for (i
= 0, op
= &msdos_name
[0], ip
= name
; ; i
++, ip
++, op
++) {
590 if (vfat_format_name(nls
, &msdos_name
[0], len
,
593 PRINTK3(("vfat_create_shortname 1\n"));
594 if (vfat_find_form(dir
, name_res
) < 0)
598 chl
= vfat_uni2upper_short(nls
, *ip
, charbuf
, NLS_MAX_CHARSET_SIZE
);
599 for (chi
= 0; chi
< chl
; chi
++){
600 if (charbuf
[chi
] == ' ')
610 PRINTK3(("vfat_create_shortname 3\n"));
611 /* Now, we need to create a shortname from the long name */
612 ext_start
= end
= &name
[len
];
613 while (--ext_start
>= name
) {
614 chl
= vfat_uni2upper_short(nls
, *ext_start
, charbuf
, NLS_MAX_CHARSET_SIZE
);
615 for (chi
= 0; chi
< chl
; chi
++) {
616 if (charbuf
[chi
] == '.') {
617 if (ext_start
== end
- 1) {
624 if (charbuf
[chi
] == '.')
627 if (ext_start
== name
- 1) {
630 } else if (ext_start
) {
632 * Names which start with a dot could be just
633 * an extension eg. "...test". In this case Win95
634 * uses the extension as the name and sets no extension.
636 name_start
= &name
[0];
637 while (name_start
< ext_start
)
639 chl
= vfat_uni2upper_short(nls
, *name_start
, charbuf
, NLS_MAX_CHARSET_SIZE
);
642 for (chi
= 0; chi
< chl
; chi
++)
643 if (!strchr(skip_chars
, charbuf
[chi
]))
647 if (name_start
!= ext_start
) {
648 sz
= ext_start
- name
;
656 for (baselen
= i
= 0, p
= base
, ip
= name
; i
< sz
&& baselen
< 8; i
++, ip
++)
658 chl
= vfat_uni2upper_short(nls
, *ip
, charbuf
, NLS_MAX_CHARSET_SIZE
);
665 for (chi
= 0; chi
< chl
; chi
++){
666 if (!strchr(skip_chars
, charbuf
[chi
])){
667 if (strchr(replace_chars
, charbuf
[chi
]))
681 for (p
= ext
, ip
= ext_start
; extlen
< 3 && ip
< end
; ip
++) {
682 chl
= vfat_uni2upper_short(nls
, *ip
, charbuf
, NLS_MAX_CHARSET_SIZE
);
689 for (chi
= 0; chi
< chl
; chi
++) {
690 if (!strchr(skip_chars
, charbuf
[chi
])) {
691 if (strchr(replace_chars
, charbuf
[chi
]))
701 base
[baselen
] = '\0';
703 /* Yes, it can happen. ".\xe5" would do it. */
707 /* OK, at this point we know that base is not longer than 8 symbols,
708 * ext is not longer than 3, base is nonempty, both don't contain
709 * any bad symbols (lowercase transformed to uppercase).
712 memset(name_res
, ' ', MSDOS_NAME
);
713 memcpy(name_res
,base
,baselen
);
714 memcpy(name_res
+8,ext
,extlen
);
715 if (MSDOS_SB(dir
->i_sb
)->options
.numtail
== 0)
716 if (vfat_find_form(dir
, name_res
) < 0)
720 * Try to find a unique extension. This used to
721 * iterate through all possibilities sequentially,
722 * but that gave extremely bad performance. Windows
723 * only tries a few cases before using random
724 * values for part of the base.
729 name_res
[baselen
] = '~';
730 for (i
= 1; i
< 10; i
++) {
731 name_res
[baselen
+1] = i
+ '0';
732 if (vfat_find_form(dir
, name_res
) < 0)
736 i
= jiffies
& 0xffff;
737 sz
= (jiffies
>> 16) & 0x7;
740 name_res
[baselen
+4] = '~';
741 name_res
[baselen
+5] = '1' + sz
;
743 sprintf(buf
, "%04X", i
);
744 memcpy(&name_res
[baselen
], buf
, 4);
745 if (vfat_find_form(dir
, name_res
) < 0)
752 /* Translate a string, including coded sequences into Unicode */
754 xlate_to_uni(const char *name
, int len
, char *outname
, int *longlen
, int *outlen
,
755 int escape
, int utf8
, struct nls_table
*nls
)
757 const unsigned char *ip
;
765 *outlen
= utf8_mbstowcs((__u16
*) outname
, name
, PAGE_SIZE
);
766 if (name
[len
-1] == '.')
768 op
= &outname
[*outlen
* sizeof(__u16
)];
770 if (name
[len
-1] == '.')
773 for (i
= 0, ip
= name
, op
= outname
, *outlen
= 0;
774 i
< len
&& *outlen
<= 260; *outlen
+= 1)
776 if (escape
&& (*ip
== ':')) {
780 for (k
= 1; k
< 5; k
++) {
783 if (nc
>= '0' && nc
<= '9') {
787 if (nc
>= 'a' && nc
<= 'f') {
788 ec
|= nc
- ('a' - 10);
791 if (nc
>= 'A' && nc
<= 'F') {
792 ec
|= nc
- ('A' - 10);
802 if ((charlen
= nls
->char2uni(ip
, len
-i
, (wchar_t *)op
)) < 0)
811 for (i
= 0, ip
= name
, op
= outname
, *outlen
= 0;
812 i
< len
&& *outlen
<= 260; i
++, *outlen
+= 1)
820 return -ENAMETOOLONG
;
828 fill
= 13 - (*outlen
% 13);
829 for (i
= 0; i
< fill
; i
++) {
841 vfat_fill_slots(struct inode
*dir
, struct msdos_dir_slot
*ds
, const char *name
,
842 int len
, int *slots
, int uni_xlate
)
844 struct nls_table
*nls_io
, *nls_disk
;
846 struct msdos_dir_slot
*ps
;
847 struct msdos_dir_entry
*de
;
851 char *uniname
, msdos_name
[MSDOS_NAME
];
852 int res
, utf8
, slot
, ulen
, unilen
, i
;
855 de
= (struct msdos_dir_entry
*) ds
;
856 utf8
= MSDOS_SB(dir
->i_sb
)->options
.utf8
;
857 nls_io
= MSDOS_SB(dir
->i_sb
)->nls_io
;
858 nls_disk
= MSDOS_SB(dir
->i_sb
)->nls_disk
;
860 if (name
[len
-1] == '.') len
--;
861 if(!(page
= __get_free_page(GFP_KERNEL
)))
863 uniname
= (char *) page
;
865 res
= xlate_to_uni(name
, len
, uniname
, &ulen
, &unilen
, uni_xlate
,
870 uname
= (wchar_t *) page
;
871 if (vfat_valid_shortname(nls_disk
, uname
, ulen
) >= 0) {
872 res
= vfat_format_name(nls_disk
, uname
, ulen
, de
->name
);
877 res
= vfat_create_shortname(dir
, nls_disk
, uname
, ulen
, msdos_name
);
881 *slots
= unilen
/ 13;
882 for (cksum
= i
= 0; i
< 11; i
++) {
883 cksum
= (((cksum
&1)<<7)|((cksum
&0xfe)>>1)) + msdos_name
[i
];
885 PRINTK3(("vfat_fill_slots 3: slots=%d\n",*slots
));
887 for (ps
= ds
, slot
= *slots
; slot
> 0; slot
--, ps
++) {
891 ps
->alias_checksum
= cksum
;
893 offset
= (slot
- 1) * 26;
894 ip
= &uniname
[offset
];
895 memcpy(ps
->name0_4
, ip
, 10);
896 memcpy(ps
->name5_10
, ip
+10, 12);
897 memcpy(ps
->name11_12
, ip
+22, 4);
901 de
= (struct msdos_dir_entry
*) ps
;
902 PRINTK3(("vfat_fill_slots 9\n"));
903 strncpy(de
->name
, msdos_name
, MSDOS_NAME
);
911 /* We can't get "." or ".." here - VFS takes care of those cases */
913 static int vfat_build_slots(struct inode
*dir
,const char *name
,int len
,
914 struct msdos_dir_slot
*ds
, int *slots
)
918 xlate
= MSDOS_SB(dir
->i_sb
)->options
.unicode_xlate
;
920 res
= vfat_valid_longname(name
, len
, xlate
);
923 return vfat_fill_slots(dir
, ds
, name
, len
, slots
, xlate
);
926 static int vfat_add_entry(struct inode
*dir
,struct qstr
* qname
,
927 int is_dir
,struct vfat_slot_info
*sinfo_out
,
928 struct buffer_head
**bh
, struct msdos_dir_entry
**de
)
930 struct super_block
*sb
= dir
->i_sb
;
931 struct msdos_dir_slot
*ps
;
933 struct msdos_dir_slot
*ds
;
936 struct msdos_dir_entry
*de1
;
937 struct buffer_head
*bh1
;
942 ds
= (struct msdos_dir_slot
*)
943 kmalloc(sizeof(struct msdos_dir_slot
)*MSDOS_SLOTS
, GFP_KERNEL
);
944 if (ds
== NULL
) return -ENOMEM
;
947 while (len
&& qname
->name
[len
-1] == '.')
949 res
= fat_search_long(dir
, qname
->name
, len
,
950 (MSDOS_SB(sb
)->options
.name_check
!= 's') ||
951 !MSDOS_SB(sb
)->options
.posixfs
,
953 if (res
> 0) /* found */
958 res
= vfat_build_slots(dir
, qname
->name
, len
, ds
, &slots
);
959 if (res
< 0) goto cleanup
;
961 offset
= fat_add_entries(dir
, slots
, &bh1
, &de1
, &ino
);
968 /* Now create the new entry */
970 for (slot
= 0, ps
= ds
; slot
< slots
; slot
++, ps
++) {
971 if (fat_get_entry(dir
,&offset
,bh
,de
, &sinfo_out
->ino
) < 0) {
975 memcpy(*de
, ps
, sizeof(struct msdos_dir_slot
));
976 fat_mark_buffer_dirty(sb
, *bh
, 1);
979 dir
->i_ctime
= dir
->i_mtime
= dir
->i_atime
= CURRENT_TIME
;
980 mark_inode_dirty(dir
);
982 fat_date_unix2dos(dir
->i_mtime
,&(*de
)->time
,&(*de
)->date
);
984 (*de
)->ctime
= (*de
)->time
;
985 (*de
)->adate
= (*de
)->cdate
= (*de
)->date
;
989 (*de
)->attr
= is_dir
? ATTR_DIR
: ATTR_ARCH
;
990 (*de
)->lcase
= CASE_LOWER_BASE
| CASE_LOWER_EXT
;
993 fat_mark_buffer_dirty(sb
, *bh
, 1);
995 /* slots can't be less than 1 */
996 sinfo_out
->long_slots
= slots
- 1;
997 sinfo_out
->longname_offset
= offset
- sizeof(struct msdos_dir_slot
) * slots
;
1005 static int vfat_find(struct inode
*dir
,struct qstr
* qname
,
1006 struct vfat_slot_info
*sinfo
, struct buffer_head
**last_bh
,
1007 struct msdos_dir_entry
**last_de
)
1009 struct super_block
*sb
= dir
->i_sb
;
1014 while (len
&& qname
->name
[len
-1] == '.')
1016 res
= fat_search_long(dir
, qname
->name
, len
,
1017 (MSDOS_SB(sb
)->options
.name_check
!= 's'),
1018 &offset
,&sinfo
->longname_offset
);
1020 sinfo
->long_slots
= res
-1;
1021 if (fat_get_entry(dir
,&offset
,last_bh
,last_de
,&sinfo
->ino
)>=0)
1025 return res
? res
: -ENOENT
;
1028 struct dentry
*vfat_lookup(struct inode
*dir
,struct dentry
*dentry
)
1031 struct vfat_slot_info sinfo
;
1032 struct inode
*inode
;
1033 struct dentry
*alias
;
1034 struct buffer_head
*bh
= NULL
;
1035 struct msdos_dir_entry
*de
;
1038 PRINTK2(("vfat_lookup: name=%s, len=%d\n",
1039 dentry
->d_name
.name
, dentry
->d_name
.len
));
1041 table
= (MSDOS_SB(dir
->i_sb
)->options
.name_check
== 's') ? 2 : 0;
1042 dentry
->d_op
= &vfat_dentry_ops
[table
];
1045 res
= vfat_find(dir
,&dentry
->d_name
,&sinfo
,&bh
,&de
);
1050 inode
= fat_build_inode(dir
->i_sb
, de
, sinfo
.ino
, &res
);
1051 fat_brelse(dir
->i_sb
, bh
);
1053 return ERR_PTR(res
);
1054 alias
= d_find_alias(inode
);
1056 if (d_invalidate(alias
)==0)
1065 dentry
->d_op
= &vfat_dentry_ops
[table
];
1066 dentry
->d_time
= dentry
->d_parent
->d_inode
->i_version
;
1067 d_add(dentry
,inode
);
1071 int vfat_create(struct inode
*dir
,struct dentry
* dentry
,int mode
)
1073 struct super_block
*sb
= dir
->i_sb
;
1074 struct inode
*inode
= NULL
;
1075 struct buffer_head
*bh
= NULL
;
1076 struct msdos_dir_entry
*de
;
1077 struct vfat_slot_info sinfo
;
1080 res
= vfat_add_entry(dir
, &dentry
->d_name
, 0, &sinfo
, &bh
, &de
);
1083 inode
= fat_build_inode(sb
, de
, sinfo
.ino
, &res
);
1087 inode
->i_mtime
= inode
->i_atime
= inode
->i_ctime
= CURRENT_TIME
;
1088 mark_inode_dirty(inode
);
1089 inode
->i_version
= ++event
;
1090 dir
->i_version
= event
;
1091 dentry
->d_time
= dentry
->d_parent
->d_inode
->i_version
;
1092 d_instantiate(dentry
,inode
);
1096 static void vfat_remove_entry(struct inode
*dir
,struct vfat_slot_info
*sinfo
,
1097 struct buffer_head
*bh
, struct msdos_dir_entry
*de
)
1099 struct super_block
*sb
= dir
->i_sb
;
1103 /* remove the shortname */
1104 dir
->i_mtime
= CURRENT_TIME
;
1105 dir
->i_atime
= CURRENT_TIME
;
1106 dir
->i_version
= ++event
;
1107 mark_inode_dirty(dir
);
1108 de
->name
[0] = DELETED_FLAG
;
1109 fat_mark_buffer_dirty(sb
, bh
, 1);
1110 /* remove the longname */
1111 offset
= sinfo
->longname_offset
; de
= NULL
;
1112 for (i
= sinfo
->long_slots
; i
> 0; --i
) {
1113 if (fat_get_entry(dir
, &offset
, &bh
, &de
, &ino
) < 0)
1115 de
->name
[0] = DELETED_FLAG
;
1117 fat_mark_buffer_dirty(sb
, bh
, 1);
1119 if (bh
) fat_brelse(sb
, bh
);
1122 int vfat_rmdir(struct inode
*dir
,struct dentry
* dentry
)
1125 struct vfat_slot_info sinfo
;
1126 struct buffer_head
*bh
= NULL
;
1127 struct msdos_dir_entry
*de
;
1129 res
= fat_dir_empty(dentry
->d_inode
);
1133 res
= vfat_find(dir
,&dentry
->d_name
,&sinfo
, &bh
, &de
);
1136 dentry
->d_inode
->i_nlink
= 0;
1137 dentry
->d_inode
->i_mtime
= CURRENT_TIME
;
1138 dentry
->d_inode
->i_atime
= CURRENT_TIME
;
1139 fat_detach(dentry
->d_inode
);
1140 mark_inode_dirty(dentry
->d_inode
);
1142 vfat_remove_entry(dir
,&sinfo
,bh
,de
);
1147 int vfat_unlink(struct inode
*dir
, struct dentry
* dentry
)
1150 struct vfat_slot_info sinfo
;
1151 struct buffer_head
*bh
= NULL
;
1152 struct msdos_dir_entry
*de
;
1154 PRINTK1(("vfat_unlink: %s\n", dentry
->d_name
.name
));
1155 res
= vfat_find(dir
,&dentry
->d_name
,&sinfo
,&bh
,&de
);
1158 dentry
->d_inode
->i_nlink
= 0;
1159 dentry
->d_inode
->i_mtime
= CURRENT_TIME
;
1160 dentry
->d_inode
->i_atime
= CURRENT_TIME
;
1161 fat_detach(dentry
->d_inode
);
1162 mark_inode_dirty(dentry
->d_inode
);
1164 vfat_remove_entry(dir
,&sinfo
,bh
,de
);
1170 int vfat_mkdir(struct inode
*dir
,struct dentry
* dentry
,int mode
)
1172 struct super_block
*sb
= dir
->i_sb
;
1173 struct inode
*inode
= NULL
;
1174 struct vfat_slot_info sinfo
;
1175 struct buffer_head
*bh
= NULL
;
1176 struct msdos_dir_entry
*de
;
1179 res
= vfat_add_entry(dir
, &dentry
->d_name
, 1, &sinfo
, &bh
, &de
);
1182 inode
= fat_build_inode(sb
, de
, sinfo
.ino
, &res
);
1185 inode
->i_mtime
= inode
->i_atime
= inode
->i_ctime
= CURRENT_TIME
;
1186 mark_inode_dirty(inode
);
1187 inode
->i_version
= ++event
;
1188 dir
->i_version
= event
;
1190 inode
->i_nlink
= 2; /* no need to mark them dirty */
1191 res
= fat_new_dir(inode
, dir
, 1);
1194 dentry
->d_time
= dentry
->d_parent
->d_inode
->i_version
;
1195 d_instantiate(dentry
,inode
);
1202 inode
->i_mtime
= CURRENT_TIME
;
1203 inode
->i_atime
= CURRENT_TIME
;
1205 mark_inode_dirty(inode
);
1207 vfat_remove_entry(dir
,&sinfo
,bh
,de
);
1213 int vfat_rename(struct inode
*old_dir
,struct dentry
*old_dentry
,
1214 struct inode
*new_dir
,struct dentry
*new_dentry
)
1216 struct super_block
*sb
= old_dir
->i_sb
;
1217 struct buffer_head
*old_bh
,*new_bh
,*dotdot_bh
;
1218 struct msdos_dir_entry
*old_de
,*new_de
,*dotdot_de
;
1220 struct inode
*old_inode
, *new_inode
;
1222 struct vfat_slot_info old_sinfo
,sinfo
;
1224 old_bh
= new_bh
= dotdot_bh
= NULL
;
1225 old_inode
= old_dentry
->d_inode
;
1226 new_inode
= new_dentry
->d_inode
;
1227 res
= vfat_find(old_dir
,&old_dentry
->d_name
,&old_sinfo
,&old_bh
,&old_de
);
1228 PRINTK3(("vfat_rename 2\n"));
1229 if (res
< 0) goto rename_done
;
1231 is_dir
= S_ISDIR(old_inode
->i_mode
);
1233 if (is_dir
&& (res
= fat_scan(old_inode
,MSDOS_DOTDOT
,&dotdot_bh
,
1234 &dotdot_de
,&dotdot_ino
)) < 0)
1237 if (new_dentry
->d_inode
) {
1238 res
= vfat_find(new_dir
,&new_dentry
->d_name
,&sinfo
,&new_bh
,
1240 if (res
< 0 || MSDOS_I(new_inode
)->i_location
!= sinfo
.ino
) {
1241 /* WTF??? Cry and fail. */
1242 printk(KERN_WARNING
"vfat_rename: fs corrupted\n");
1247 res
= fat_dir_empty(new_inode
);
1251 fat_detach(new_inode
);
1253 res
= vfat_add_entry(new_dir
,&new_dentry
->d_name
,is_dir
,&sinfo
,
1255 if (res
< 0) goto rename_done
;
1258 new_dir
->i_version
= ++event
;
1260 /* releases old_bh */
1261 vfat_remove_entry(old_dir
,&old_sinfo
,old_bh
,old_de
);
1263 fat_detach(old_inode
);
1264 fat_attach(old_inode
, sinfo
.ino
);
1265 mark_inode_dirty(old_inode
);
1267 old_dir
->i_version
= ++event
;
1268 old_dir
->i_ctime
= old_dir
->i_mtime
= CURRENT_TIME
;
1269 mark_inode_dirty(old_dir
);
1271 new_inode
->i_nlink
--;
1272 new_inode
->i_ctime
=CURRENT_TIME
;
1276 int start
= MSDOS_I(new_dir
)->i_logstart
;
1277 dotdot_de
->start
= CT_LE_W(start
);
1278 dotdot_de
->starthi
= CT_LE_W(start
>>16);
1279 fat_mark_buffer_dirty(sb
, dotdot_bh
, 1);
1282 new_inode
->i_nlink
--;
1285 mark_inode_dirty(new_dir
);
1290 fat_brelse(sb
, dotdot_bh
);
1291 fat_brelse(sb
, old_bh
);
1292 fat_brelse(sb
, new_bh
);
1298 /* Public inode operations for the VFAT fs */
1299 struct inode_operations vfat_dir_inode_operations
= {
1300 create
: vfat_create
,
1301 lookup
: vfat_lookup
,
1302 unlink
: vfat_unlink
,
1305 rename
: vfat_rename
,
1306 setattr
: fat_notify_change
,
1309 struct super_block
*vfat_read_super(struct super_block
*sb
,void *data
,
1312 struct super_block
*res
;
1314 MSDOS_SB(sb
)->options
.isvfat
= 1;
1316 res
= fat_read_super(sb
, data
, silent
, &vfat_dir_inode_operations
);
1320 if (parse_options((char *) data
, &(MSDOS_SB(sb
)->options
))) {
1321 MSDOS_SB(sb
)->options
.dotsOK
= 0;
1322 if (MSDOS_SB(sb
)->options
.posixfs
) {
1323 MSDOS_SB(sb
)->options
.name_check
= 's';
1325 if (MSDOS_SB(sb
)->options
.name_check
!= 's') {
1326 sb
->s_root
->d_op
= &vfat_dentry_ops
[0];
1328 sb
->s_root
->d_op
= &vfat_dentry_ops
[2];