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
;
460 if (space
) return -EINVAL
;
461 if (len
&& c
!= '.') {
463 if (vfat_uni2upper_short(nls
, *walk
++, charbuf
, NLS_MAX_CHARSET_SIZE
) == 1) {
464 if (charbuf
[0] != '.') return -EINVAL
;
469 if (len
>= 4) return -EINVAL
;
472 chl
= vfat_uni2short(nls
, *walk
++, charbuf
, NLS_MAX_CHARSET_SIZE
);
475 for (chi
= 0; chi
< chl
; chi
++) {
476 c
= vfat_getupper(nls
, charbuf
[chi
]);
477 if (!c
) return -EINVAL
;
478 if (charbuf
[chi
] != vfat_tolower(nls
, c
)) return -EINVAL
;
479 if (strchr(replace_chars
,c
))
481 if (c
< ' ' || c
== '.'|| c
==':')
486 if (space
) return -EINVAL
;
492 static int vfat_find_form(struct inode
*dir
,char *name
)
494 struct msdos_dir_entry
*de
;
495 struct buffer_head
*bh
= NULL
;
498 res
=fat_scan(dir
,name
,&bh
,&de
,&ino
);
499 fat_brelse(dir
->i_sb
, bh
);
505 static int vfat_format_name(struct nls_table
*nls
, wchar_t *name
,
509 unsigned char charbuf
[NLS_MAX_CHARSET_SIZE
];
513 if (vfat_uni2upper_short(nls
, *name
, charbuf
, NLS_MAX_CHARSET_SIZE
) == 0)
516 if (IS_FREE(charbuf
))
519 space
= 1; /* disallow names starting with a dot */
520 for (walk
= res
; len
--; ) {
521 chl
= vfat_uni2upper_short(nls
, *name
++, charbuf
, NLS_MAX_CHARSET_SIZE
);
524 for (chi
= 0; chi
< chl
; chi
++){
525 if (charbuf
[chi
] == '.') break;
526 if (!charbuf
[chi
]) return -EINVAL
;
527 if (walk
-res
== 8) return -EINVAL
;
528 if (strchr(replace_chars
,charbuf
[chi
])) return -EINVAL
;
529 if (charbuf
[chi
] < ' '|| charbuf
[chi
]==':') return -EINVAL
;
530 space
= charbuf
[chi
] == ' ';
531 *walk
= charbuf
[chi
];
535 if (space
) return -EINVAL
;
537 while (walk
-res
< 8) *walk
++ = ' ';
538 while (len
> 0 && walk
-res
< MSDOS_NAME
) {
539 chl
= vfat_uni2upper_short(nls
, *name
++, charbuf
, NLS_MAX_CHARSET_SIZE
);
543 for (chi
= 0; chi
< chl
; chi
++){
544 if (!charbuf
[chi
]) return -EINVAL
;
545 if (strchr(replace_chars
,charbuf
[chi
]))
547 if (charbuf
[chi
] < ' ' || charbuf
[chi
] == '.'|| charbuf
[chi
]==':')
549 space
= charbuf
[chi
] == ' ';
550 *walk
++ = charbuf
[chi
];
553 if (space
) return -EINVAL
;
554 if (len
) return -EINVAL
;
556 while (walk
-res
< MSDOS_NAME
) *walk
++ = ' ';
561 static char skip_chars
[] = ".:\"?<>| ";
563 /* Given a valid longname, create a unique shortname. Make sure the
564 * shortname does not exist
566 static int vfat_create_shortname(struct inode
*dir
, struct nls_table
*nls
,
567 wchar_t *name
, int len
,
570 wchar_t *ip
, *op
, *ext_start
, *end
, *name_start
;
571 wchar_t msdos_name
[13];
572 char base
[9], ext
[4], buf
[8], *p
;
573 unsigned char charbuf
[NLS_MAX_CHARSET_SIZE
];
575 int sz
, extlen
, baselen
, i
;
577 PRINTK2(("Entering vfat_create_shortname\n"));
579 sz
= 0; /* Make compiler happy */
581 /* Do a case insensitive search if the name would be a valid
582 * shortname if is were all capitalized. However, do not
583 * allow spaces in short names because Win95 scandisk does
585 for (i
= 0, op
= &msdos_name
[0], ip
= name
; ; i
++, ip
++, op
++) {
587 if (vfat_format_name(nls
, &msdos_name
[0], len
,
590 PRINTK3(("vfat_create_shortname 1\n"));
591 if (vfat_find_form(dir
, name_res
) < 0)
595 chl
= vfat_uni2upper_short(nls
, *ip
, charbuf
, NLS_MAX_CHARSET_SIZE
);
596 for (chi
= 0; chi
< chl
; chi
++){
597 if (charbuf
[chi
] == ' ')
607 PRINTK3(("vfat_create_shortname 3\n"));
608 /* Now, we need to create a shortname from the long name */
609 ext_start
= end
= &name
[len
];
610 while (--ext_start
>= name
) {
611 chl
= vfat_uni2upper_short(nls
, *ext_start
, charbuf
, NLS_MAX_CHARSET_SIZE
);
612 for (chi
= 0; chi
< chl
; chi
++) {
613 if (charbuf
[chi
] == '.') {
614 if (ext_start
== end
- 1) {
621 if (charbuf
[chi
] == '.')
624 if (ext_start
== name
- 1) {
627 } else if (ext_start
) {
629 * Names which start with a dot could be just
630 * an extension eg. "...test". In this case Win95
631 * uses the extension as the name and sets no extension.
633 name_start
= &name
[0];
634 while (name_start
< ext_start
)
636 chl
= vfat_uni2upper_short(nls
, *name_start
, charbuf
, NLS_MAX_CHARSET_SIZE
);
639 for (chi
= 0; chi
< chl
; chi
++)
640 if (!strchr(skip_chars
, charbuf
[chi
]))
644 if (name_start
!= ext_start
) {
645 sz
= ext_start
- name
;
653 for (baselen
= i
= 0, p
= base
, ip
= name
; i
< sz
&& baselen
< 8; i
++, ip
++)
655 chl
= vfat_uni2upper_short(nls
, *ip
, charbuf
, NLS_MAX_CHARSET_SIZE
);
662 for (chi
= 0; chi
< chl
; chi
++){
663 if (!strchr(skip_chars
, charbuf
[chi
])){
664 if (strchr(replace_chars
, charbuf
[chi
]))
678 for (p
= ext
, ip
= ext_start
; extlen
< 3 && ip
< end
; ip
++) {
679 chl
= vfat_uni2upper_short(nls
, *ip
, charbuf
, NLS_MAX_CHARSET_SIZE
);
686 for (chi
= 0; chi
< chl
; chi
++) {
687 if (!strchr(skip_chars
, charbuf
[chi
])) {
688 if (strchr(replace_chars
, charbuf
[chi
]))
698 base
[baselen
] = '\0';
700 /* Yes, it can happen. ".\xe5" would do it. */
704 /* OK, at this point we know that base is not longer than 8 symbols,
705 * ext is not longer than 3, base is nonempty, both don't contain
706 * any bad symbols (lowercase transformed to uppercase).
709 memset(name_res
, ' ', MSDOS_NAME
);
710 memcpy(name_res
,base
,baselen
);
711 memcpy(name_res
+8,ext
,extlen
);
712 if (MSDOS_SB(dir
->i_sb
)->options
.numtail
== 0)
713 if (vfat_find_form(dir
, name_res
) < 0)
717 * Try to find a unique extension. This used to
718 * iterate through all possibilities sequentially,
719 * but that gave extremely bad performance. Windows
720 * only tries a few cases before using random
721 * values for part of the base.
726 name_res
[baselen
] = '~';
727 for (i
= 1; i
< 10; i
++) {
728 name_res
[baselen
+1] = i
+ '0';
729 if (vfat_find_form(dir
, name_res
) < 0)
733 i
= jiffies
& 0xffff;
734 sz
= (jiffies
>> 16) & 0x7;
737 name_res
[baselen
+4] = '~';
738 name_res
[baselen
+5] = '1' + sz
;
740 sprintf(buf
, "%04X", i
);
741 memcpy(&name_res
[baselen
], buf
, 4);
742 if (vfat_find_form(dir
, name_res
) < 0)
749 /* Translate a string, including coded sequences into Unicode */
751 xlate_to_uni(const char *name
, int len
, char *outname
, int *longlen
, int *outlen
,
752 int escape
, int utf8
, struct nls_table
*nls
)
754 const unsigned char *ip
;
762 *outlen
= utf8_mbstowcs((__u16
*) outname
, name
, PAGE_SIZE
);
763 if (name
[len
-1] == '.')
765 op
= &outname
[*outlen
* sizeof(__u16
)];
767 if (name
[len
-1] == '.')
770 for (i
= 0, ip
= name
, op
= outname
, *outlen
= 0;
771 i
< len
&& *outlen
<= 260; *outlen
+= 1)
773 if (escape
&& (*ip
== ':')) {
777 for (k
= 1; k
< 5; k
++) {
780 if (nc
>= '0' && nc
<= '9') {
784 if (nc
>= 'a' && nc
<= 'f') {
785 ec
|= nc
- ('a' - 10);
788 if (nc
>= 'A' && nc
<= 'F') {
789 ec
|= nc
- ('A' - 10);
799 if ((charlen
= nls
->char2uni(ip
, len
-i
, (wchar_t *)op
)) < 0)
808 for (i
= 0, ip
= name
, op
= outname
, *outlen
= 0;
809 i
< len
&& *outlen
<= 260; i
++, *outlen
+= 1)
817 return -ENAMETOOLONG
;
825 fill
= 13 - (*outlen
% 13);
826 for (i
= 0; i
< fill
; i
++) {
838 vfat_fill_slots(struct inode
*dir
, struct msdos_dir_slot
*ds
, const char *name
,
839 int len
, int *slots
, int uni_xlate
)
841 struct nls_table
*nls_io
, *nls_disk
;
843 struct msdos_dir_slot
*ps
;
844 struct msdos_dir_entry
*de
;
848 char *uniname
, msdos_name
[MSDOS_NAME
];
849 int res
, utf8
, slot
, ulen
, unilen
, i
;
852 de
= (struct msdos_dir_entry
*) ds
;
853 utf8
= MSDOS_SB(dir
->i_sb
)->options
.utf8
;
854 nls_io
= MSDOS_SB(dir
->i_sb
)->nls_io
;
855 nls_disk
= MSDOS_SB(dir
->i_sb
)->nls_disk
;
857 if (name
[len
-1] == '.') len
--;
858 if(!(page
= __get_free_page(GFP_KERNEL
)))
860 uniname
= (char *) page
;
862 res
= xlate_to_uni(name
, len
, uniname
, &ulen
, &unilen
, uni_xlate
,
867 uname
= (wchar_t *) page
;
868 if (vfat_valid_shortname(nls_disk
, uname
, ulen
) >= 0) {
869 res
= vfat_format_name(nls_disk
, uname
, ulen
, de
->name
);
874 res
= vfat_create_shortname(dir
, nls_disk
, uname
, ulen
, msdos_name
);
878 *slots
= unilen
/ 13;
879 for (cksum
= i
= 0; i
< 11; i
++) {
880 cksum
= (((cksum
&1)<<7)|((cksum
&0xfe)>>1)) + msdos_name
[i
];
882 PRINTK3(("vfat_fill_slots 3: slots=%d\n",*slots
));
884 for (ps
= ds
, slot
= *slots
; slot
> 0; slot
--, ps
++) {
888 ps
->alias_checksum
= cksum
;
890 offset
= (slot
- 1) * 26;
891 ip
= &uniname
[offset
];
892 memcpy(ps
->name0_4
, ip
, 10);
893 memcpy(ps
->name5_10
, ip
+10, 12);
894 memcpy(ps
->name11_12
, ip
+22, 4);
898 de
= (struct msdos_dir_entry
*) ps
;
899 PRINTK3(("vfat_fill_slots 9\n"));
900 strncpy(de
->name
, msdos_name
, MSDOS_NAME
);
908 /* We can't get "." or ".." here - VFS takes care of those cases */
910 static int vfat_build_slots(struct inode
*dir
,const char *name
,int len
,
911 struct msdos_dir_slot
*ds
, int *slots
)
915 xlate
= MSDOS_SB(dir
->i_sb
)->options
.unicode_xlate
;
917 res
= vfat_valid_longname(name
, len
, xlate
);
920 return vfat_fill_slots(dir
, ds
, name
, len
, slots
, xlate
);
923 static int vfat_add_entry(struct inode
*dir
,struct qstr
* qname
,
924 int is_dir
,struct vfat_slot_info
*sinfo_out
,
925 struct buffer_head
**bh
, struct msdos_dir_entry
**de
)
927 struct super_block
*sb
= dir
->i_sb
;
928 struct msdos_dir_slot
*ps
;
930 struct msdos_dir_slot
*ds
;
933 struct msdos_dir_entry
*de1
;
934 struct buffer_head
*bh1
;
939 ds
= (struct msdos_dir_slot
*)
940 kmalloc(sizeof(struct msdos_dir_slot
)*MSDOS_SLOTS
, GFP_KERNEL
);
941 if (ds
== NULL
) return -ENOMEM
;
944 while (len
&& qname
->name
[len
-1] == '.')
946 res
= fat_search_long(dir
, qname
->name
, len
,
947 (MSDOS_SB(sb
)->options
.name_check
!= 's') ||
948 !MSDOS_SB(sb
)->options
.posixfs
,
950 if (res
> 0) /* found */
955 res
= vfat_build_slots(dir
, qname
->name
, len
, ds
, &slots
);
956 if (res
< 0) goto cleanup
;
958 offset
= fat_add_entries(dir
, slots
, &bh1
, &de1
, &ino
);
965 /* Now create the new entry */
967 for (slot
= 0, ps
= ds
; slot
< slots
; slot
++, ps
++) {
968 if (fat_get_entry(dir
,&offset
,bh
,de
, &sinfo_out
->ino
) < 0) {
972 memcpy(*de
, ps
, sizeof(struct msdos_dir_slot
));
973 fat_mark_buffer_dirty(sb
, *bh
, 1);
976 dir
->i_ctime
= dir
->i_mtime
= dir
->i_atime
= CURRENT_TIME
;
977 mark_inode_dirty(dir
);
979 fat_date_unix2dos(dir
->i_mtime
,&(*de
)->time
,&(*de
)->date
);
981 (*de
)->ctime
= (*de
)->time
;
982 (*de
)->adate
= (*de
)->cdate
= (*de
)->date
;
986 (*de
)->attr
= is_dir
? ATTR_DIR
: ATTR_ARCH
;
987 (*de
)->lcase
= CASE_LOWER_BASE
| CASE_LOWER_EXT
;
990 fat_mark_buffer_dirty(sb
, *bh
, 1);
992 /* slots can't be less than 1 */
993 sinfo_out
->long_slots
= slots
- 1;
994 sinfo_out
->longname_offset
= offset
- sizeof(struct msdos_dir_slot
) * slots
;
1002 static int vfat_find(struct inode
*dir
,struct qstr
* qname
,
1003 struct vfat_slot_info
*sinfo
, struct buffer_head
**last_bh
,
1004 struct msdos_dir_entry
**last_de
)
1006 struct super_block
*sb
= dir
->i_sb
;
1011 while (len
&& qname
->name
[len
-1] == '.')
1013 res
= fat_search_long(dir
, qname
->name
, len
,
1014 (MSDOS_SB(sb
)->options
.name_check
!= 's'),
1015 &offset
,&sinfo
->longname_offset
);
1017 sinfo
->long_slots
= res
-1;
1018 if (fat_get_entry(dir
,&offset
,last_bh
,last_de
,&sinfo
->ino
)>=0)
1022 return res
? res
: -ENOENT
;
1025 struct dentry
*vfat_lookup(struct inode
*dir
,struct dentry
*dentry
)
1028 struct vfat_slot_info sinfo
;
1029 struct inode
*inode
;
1030 struct dentry
*alias
;
1031 struct buffer_head
*bh
= NULL
;
1032 struct msdos_dir_entry
*de
;
1035 PRINTK2(("vfat_lookup: name=%s, len=%d\n",
1036 dentry
->d_name
.name
, dentry
->d_name
.len
));
1038 table
= (MSDOS_SB(dir
->i_sb
)->options
.name_check
== 's') ? 2 : 0;
1039 dentry
->d_op
= &vfat_dentry_ops
[table
];
1042 res
= vfat_find(dir
,&dentry
->d_name
,&sinfo
,&bh
,&de
);
1047 inode
= fat_build_inode(dir
->i_sb
, de
, sinfo
.ino
, &res
);
1048 fat_brelse(dir
->i_sb
, bh
);
1050 return ERR_PTR(res
);
1051 alias
= d_find_alias(inode
);
1053 if (d_invalidate(alias
)==0)
1062 dentry
->d_op
= &vfat_dentry_ops
[table
];
1063 dentry
->d_time
= dentry
->d_parent
->d_inode
->i_version
;
1064 d_add(dentry
,inode
);
1068 int vfat_create(struct inode
*dir
,struct dentry
* dentry
,int mode
)
1070 struct super_block
*sb
= dir
->i_sb
;
1071 struct inode
*inode
= NULL
;
1072 struct buffer_head
*bh
= NULL
;
1073 struct msdos_dir_entry
*de
;
1074 struct vfat_slot_info sinfo
;
1077 res
= vfat_add_entry(dir
, &dentry
->d_name
, 0, &sinfo
, &bh
, &de
);
1080 inode
= fat_build_inode(sb
, de
, sinfo
.ino
, &res
);
1084 inode
->i_mtime
= inode
->i_atime
= inode
->i_ctime
= CURRENT_TIME
;
1085 mark_inode_dirty(inode
);
1086 inode
->i_version
= ++event
;
1087 dir
->i_version
= event
;
1088 dentry
->d_time
= dentry
->d_parent
->d_inode
->i_version
;
1089 d_instantiate(dentry
,inode
);
1093 static void vfat_remove_entry(struct inode
*dir
,struct vfat_slot_info
*sinfo
,
1094 struct buffer_head
*bh
, struct msdos_dir_entry
*de
)
1096 struct super_block
*sb
= dir
->i_sb
;
1100 /* remove the shortname */
1101 dir
->i_mtime
= CURRENT_TIME
;
1102 dir
->i_atime
= CURRENT_TIME
;
1103 dir
->i_version
= ++event
;
1104 mark_inode_dirty(dir
);
1105 de
->name
[0] = DELETED_FLAG
;
1106 fat_mark_buffer_dirty(sb
, bh
, 1);
1107 /* remove the longname */
1108 offset
= sinfo
->longname_offset
; de
= NULL
;
1109 for (i
= sinfo
->long_slots
; i
> 0; --i
) {
1110 if (fat_get_entry(dir
, &offset
, &bh
, &de
, &ino
) < 0)
1112 de
->name
[0] = DELETED_FLAG
;
1114 fat_mark_buffer_dirty(sb
, bh
, 1);
1116 if (bh
) fat_brelse(sb
, bh
);
1119 int vfat_rmdir(struct inode
*dir
,struct dentry
* dentry
)
1122 struct vfat_slot_info sinfo
;
1123 struct buffer_head
*bh
= NULL
;
1124 struct msdos_dir_entry
*de
;
1126 res
= fat_dir_empty(dentry
->d_inode
);
1130 res
= vfat_find(dir
,&dentry
->d_name
,&sinfo
, &bh
, &de
);
1133 dentry
->d_inode
->i_nlink
= 0;
1134 dentry
->d_inode
->i_mtime
= CURRENT_TIME
;
1135 dentry
->d_inode
->i_atime
= CURRENT_TIME
;
1136 fat_detach(dentry
->d_inode
);
1137 mark_inode_dirty(dentry
->d_inode
);
1139 vfat_remove_entry(dir
,&sinfo
,bh
,de
);
1144 int vfat_unlink(struct inode
*dir
, struct dentry
* dentry
)
1147 struct vfat_slot_info sinfo
;
1148 struct buffer_head
*bh
= NULL
;
1149 struct msdos_dir_entry
*de
;
1151 PRINTK1(("vfat_unlink: %s\n", dentry
->d_name
.name
));
1152 res
= vfat_find(dir
,&dentry
->d_name
,&sinfo
,&bh
,&de
);
1155 dentry
->d_inode
->i_nlink
= 0;
1156 dentry
->d_inode
->i_mtime
= CURRENT_TIME
;
1157 dentry
->d_inode
->i_atime
= CURRENT_TIME
;
1158 fat_detach(dentry
->d_inode
);
1159 mark_inode_dirty(dentry
->d_inode
);
1161 vfat_remove_entry(dir
,&sinfo
,bh
,de
);
1167 int vfat_mkdir(struct inode
*dir
,struct dentry
* dentry
,int mode
)
1169 struct super_block
*sb
= dir
->i_sb
;
1170 struct inode
*inode
= NULL
;
1171 struct vfat_slot_info sinfo
;
1172 struct buffer_head
*bh
= NULL
;
1173 struct msdos_dir_entry
*de
;
1176 res
= vfat_add_entry(dir
, &dentry
->d_name
, 1, &sinfo
, &bh
, &de
);
1179 inode
= fat_build_inode(sb
, de
, sinfo
.ino
, &res
);
1182 inode
->i_mtime
= inode
->i_atime
= inode
->i_ctime
= CURRENT_TIME
;
1183 mark_inode_dirty(inode
);
1184 inode
->i_version
= ++event
;
1185 dir
->i_version
= event
;
1187 inode
->i_nlink
= 2; /* no need to mark them dirty */
1188 res
= fat_new_dir(inode
, dir
, 1);
1191 dentry
->d_time
= dentry
->d_parent
->d_inode
->i_version
;
1192 d_instantiate(dentry
,inode
);
1199 inode
->i_mtime
= CURRENT_TIME
;
1200 inode
->i_atime
= CURRENT_TIME
;
1202 mark_inode_dirty(inode
);
1204 vfat_remove_entry(dir
,&sinfo
,bh
,de
);
1210 int vfat_rename(struct inode
*old_dir
,struct dentry
*old_dentry
,
1211 struct inode
*new_dir
,struct dentry
*new_dentry
)
1213 struct super_block
*sb
= old_dir
->i_sb
;
1214 struct buffer_head
*old_bh
,*new_bh
,*dotdot_bh
;
1215 struct msdos_dir_entry
*old_de
,*new_de
,*dotdot_de
;
1217 struct inode
*old_inode
, *new_inode
;
1219 struct vfat_slot_info old_sinfo
,sinfo
;
1221 old_bh
= new_bh
= dotdot_bh
= NULL
;
1222 old_inode
= old_dentry
->d_inode
;
1223 new_inode
= new_dentry
->d_inode
;
1224 res
= vfat_find(old_dir
,&old_dentry
->d_name
,&old_sinfo
,&old_bh
,&old_de
);
1225 PRINTK3(("vfat_rename 2\n"));
1226 if (res
< 0) goto rename_done
;
1228 is_dir
= S_ISDIR(old_inode
->i_mode
);
1230 if (is_dir
&& (res
= fat_scan(old_inode
,MSDOS_DOTDOT
,&dotdot_bh
,
1231 &dotdot_de
,&dotdot_ino
)) < 0)
1234 if (new_dentry
->d_inode
) {
1235 res
= vfat_find(new_dir
,&new_dentry
->d_name
,&sinfo
,&new_bh
,
1237 if (res
< 0 || MSDOS_I(new_inode
)->i_location
!= sinfo
.ino
) {
1238 /* WTF??? Cry and fail. */
1239 printk(KERN_WARNING
"vfat_rename: fs corrupted\n");
1244 res
= fat_dir_empty(new_inode
);
1248 fat_detach(new_inode
);
1250 res
= vfat_add_entry(new_dir
,&new_dentry
->d_name
,is_dir
,&sinfo
,
1252 if (res
< 0) goto rename_done
;
1255 new_dir
->i_version
= ++event
;
1257 /* releases old_bh */
1258 vfat_remove_entry(old_dir
,&old_sinfo
,old_bh
,old_de
);
1260 fat_detach(old_inode
);
1261 fat_attach(old_inode
, sinfo
.ino
);
1262 mark_inode_dirty(old_inode
);
1264 old_dir
->i_version
= ++event
;
1265 old_dir
->i_ctime
= old_dir
->i_mtime
= CURRENT_TIME
;
1266 mark_inode_dirty(old_dir
);
1268 new_inode
->i_nlink
--;
1269 new_inode
->i_ctime
=CURRENT_TIME
;
1273 int start
= MSDOS_I(new_dir
)->i_logstart
;
1274 dotdot_de
->start
= CT_LE_W(start
);
1275 dotdot_de
->starthi
= CT_LE_W(start
>>16);
1276 fat_mark_buffer_dirty(sb
, dotdot_bh
, 1);
1279 new_inode
->i_nlink
--;
1282 mark_inode_dirty(new_dir
);
1287 fat_brelse(sb
, dotdot_bh
);
1288 fat_brelse(sb
, old_bh
);
1289 fat_brelse(sb
, new_bh
);
1295 /* Public inode operations for the VFAT fs */
1296 struct inode_operations vfat_dir_inode_operations
= {
1297 create
: vfat_create
,
1298 lookup
: vfat_lookup
,
1299 unlink
: vfat_unlink
,
1302 rename
: vfat_rename
,
1303 setattr
: fat_notify_change
,
1306 struct super_block
*vfat_read_super(struct super_block
*sb
,void *data
,
1309 struct super_block
*res
;
1311 MSDOS_SB(sb
)->options
.isvfat
= 1;
1313 res
= fat_read_super(sb
, data
, silent
, &vfat_dir_inode_operations
);
1317 if (parse_options((char *) data
, &(MSDOS_SB(sb
)->options
))) {
1318 MSDOS_SB(sb
)->options
.dotsOK
= 0;
1319 if (MSDOS_SB(sb
)->options
.posixfs
) {
1320 MSDOS_SB(sb
)->options
.name_check
= 's';
1322 if (MSDOS_SB(sb
)->options
.name_check
!= 's') {
1323 sb
->s_root
->d_op
= &vfat_dentry_ops
[0];
1325 sb
->s_root
->d_op
= &vfat_dentry_ops
[2];