18 #include <linux/module.h>
20 #include <linux/ctype.h>
21 #include <linux/slab.h>
34 static int vfat_revalidate_shortname(
struct dentry *
dentry)
37 spin_lock(&dentry->
d_lock);
40 spin_unlock(&dentry->
d_lock);
44 static int vfat_revalidate(
struct dentry *dentry,
unsigned int flags)
52 return vfat_revalidate_shortname(dentry);
55 static int vfat_revalidate_ci(
struct dentry *dentry,
unsigned int flags)
57 if (flags & LOOKUP_RCU)
88 return vfat_revalidate_shortname(dentry);
92 static unsigned int __vfat_striptail_len(
unsigned int len,
const char *
name)
94 while (len && name[len - 1] ==
'.')
99 static unsigned int vfat_striptail_len(
const struct qstr *
qstr)
101 return __vfat_striptail_len(qstr->len, qstr->
name);
110 static int vfat_hash(
const struct dentry *dentry,
const struct inode *
inode,
123 static int vfat_hashi(
const struct dentry *dentry,
const struct inode *inode,
127 const unsigned char *
name;
132 len = vfat_striptail_len(qstr);
136 hash = partial_name_hash(nls_tolower(t, *name++), hash);
137 qstr->hash = end_name_hash(hash);
145 static int vfat_cmpi(
const struct dentry *parent,
const struct inode *pinode,
146 const struct dentry *dentry,
const struct inode *inode,
147 unsigned int len,
const char *
str,
const struct qstr *name)
150 unsigned int alen, blen;
153 alen = vfat_striptail_len(name);
154 blen = __vfat_striptail_len(len, str);
156 if (nls_strnicmp(t, name->
name, str, alen) == 0)
165 static int vfat_cmp(
const struct dentry *parent,
const struct inode *pinode,
166 const struct dentry *dentry,
const struct inode *inode,
167 unsigned int len,
const char *str,
const struct qstr *name)
169 unsigned int alen, blen;
172 alen = vfat_striptail_len(name);
173 blen = __vfat_striptail_len(len, str);
182 .d_revalidate = vfat_revalidate_ci,
183 .d_hash = vfat_hashi,
184 .d_compare = vfat_cmpi,
188 .d_revalidate = vfat_revalidate,
190 .d_compare = vfat_cmp,
195 static inline wchar_t vfat_bad_char(
wchar_t w)
198 || (w ==
'*') || (w ==
'?') || (w ==
'<') || (w ==
'>')
199 || (w ==
'|') || (w ==
'"') || (w ==
':') || (w ==
'/')
203 static inline wchar_t vfat_replace_char(
wchar_t w)
205 return (w ==
'[') || (w ==
']') || (w ==
';') || (w ==
',')
206 || (w ==
'+') || (w ==
'=');
209 static wchar_t vfat_skip_char(
wchar_t w)
211 return (w ==
'.') || (w ==
' ');
214 static inline int vfat_is_used_badchars(
const wchar_t *
s,
int len)
218 for (i = 0; i < len; i++)
219 if (vfat_bad_char(s[i]))
228 static int vfat_find_form(
struct inode *dir,
unsigned char *name)
263 #define INIT_SHORTNAME_INFO(x) do { \
269 static inline int to_shortname_char(
struct nls_table *nls,
275 if (vfat_skip_char(*src)) {
279 if (vfat_replace_char(*src)) {
285 len = nls->
uni2char(*src, buf, buf_size);
290 }
else if (len == 1) {
291 unsigned char prev = buf[0];
293 if (buf[0] >= 0x7F) {
298 buf[0] = nls_toupper(nls, buf[0]);
319 static int vfat_create_shortname(
struct inode *dir,
struct nls_table *nls,
320 wchar_t *uname,
int ulen,
321 unsigned char *name_res,
unsigned char *lcase)
328 int sz = 0, extlen, baselen,
i, numtail_baselen, numtail2_baselen;
337 ext_start = end = &uname[
ulen];
338 while (--ext_start >= uname) {
339 if (*ext_start == 0x002E) {
340 if (ext_start == end - 1) {
348 if (ext_start == uname - 1) {
351 }
else if (ext_start) {
357 name_start = &uname[0];
358 while (name_start < ext_start) {
359 if (!vfat_skip_char(*name_start))
363 if (name_start != ext_start) {
364 sz = ext_start - uname;
373 numtail2_baselen = 2;
374 for (baselen = i = 0, p = base, ip = uname; i < sz; i++, ip++) {
375 chl = to_shortname_char(nls, charbuf,
sizeof(charbuf),
380 if (baselen < 2 && (baselen + chl) > 2)
381 numtail2_baselen = baselen;
382 if (baselen < 6 && (baselen + chl) > 6)
383 numtail_baselen = baselen;
384 for (chi = 0; chi < chl; chi++) {
391 if ((chi < chl - 1) || (ip + 1) - uname < sz)
402 for (p = ext, ip = ext_start; extlen < 3 && ip <
end; ip++) {
403 chl = to_shortname_char(nls, charbuf,
sizeof(charbuf),
408 if ((extlen + chl) > 3) {
412 for (chi = 0; chi < chl; chi++) {
424 base[baselen] =
'\0';
436 memcpy(name_res, base, baselen);
437 memcpy(name_res + 8, ext, extlen);
439 if (is_shortname && base_info.valid && ext_info.valid) {
440 if (vfat_find_form(dir, name_res) == 0)
444 return (base_info.upper && ext_info.upper);
446 if ((base_info.upper || base_info.lower) &&
447 (ext_info.upper || ext_info.lower)) {
448 if (!base_info.upper && base_info.lower)
450 if (!ext_info.upper && ext_info.lower)
461 if (vfat_find_form(dir, name_res) < 0)
473 baselen = numtail_baselen;
476 name_res[baselen] =
'~';
477 for (i = 1; i < 10; i++) {
478 name_res[baselen + 1] = i +
'0';
479 if (vfat_find_form(dir, name_res) < 0)
486 baselen = numtail2_baselen;
489 name_res[baselen + 4] =
'~';
490 name_res[baselen + 5] =
'1' + sz;
492 snprintf(buf,
sizeof(buf),
"%04X", i & 0xffff);
493 memcpy(&name_res[baselen], buf, 4);
494 if (vfat_find_form(dir, name_res) < 0)
503 xlate_to_uni(
const unsigned char *name,
int len,
unsigned char *outname,
504 int *longlen,
int *
outlen,
int escape,
int utf8,
507 const unsigned char *
ip;
522 op = &outname[*outlen *
sizeof(
wchar_t)];
524 for (i = 0, ip = name, op = outname, *outlen = 0;
527 if (escape && (*ip ==
':')) {
531 for (k = 1; k < 5; k++) {
534 if (nc >=
'0' && nc <=
'9') {
538 if (nc >=
'a' && nc <=
'f') {
539 ec |= nc - (
'a' - 10);
542 if (nc >=
'A' && nc <=
'F') {
543 ec |= nc - (
'A' - 10);
553 charlen = nls->
char2uni(ip, len - i,
572 fill = 13 - (*outlen % 13);
573 for (i = 0; i <
fill; i++) {
584 static int vfat_build_slots(
struct inode *dir,
const unsigned char *name,
585 int len,
int is_dir,
int cluster,
607 err = xlate_to_uni(name, len, (
unsigned char *)uname, &ulen, &usize,
612 err = vfat_is_used_badchars(uname, ulen);
616 err = vfat_create_shortname(dir, sbi->
nls_disk, uname, ulen,
627 cksum = fat_checksum(msdos_name);
629 *nr_slots = usize / 13;
630 for (ps = slots, i = *nr_slots; i > 0; i--, ps++) {
636 offset = (i - 1) * 13;
637 fatwchar_to16(ps->
name0_4, uname + offset, 5);
638 fatwchar_to16(ps->
name5_10, uname + offset + 5, 6);
639 fatwchar_to16(ps->
name11_12, uname + offset + 11, 2);
654 fat_set_start(de, cluster);
661 static int vfat_add_entry(
struct inode *dir,
struct qstr *qname,
int is_dir,
669 len = vfat_striptail_len(qname);
677 err = vfat_build_slots(dir, qname->
name, len, is_dir, cluster, ts,
691 mark_inode_dirty(dir);
697 static int vfat_find(
struct inode *dir,
struct qstr *qname,
700 unsigned int len = vfat_striptail_len(qname);
710 static int vfat_d_anon_disconn(
struct dentry *dentry)
715 static struct dentry *vfat_lookup(
struct inode *dir,
struct dentry *dentry,
721 struct dentry *
alias;
726 err = vfat_find(dir, &dentry->
d_name, &sinfo);
738 err = PTR_ERR(inode);
743 if (alias && !vfat_d_anon_disconn(alias)) {
751 BUG_ON(d_unhashed(alias));
773 static int vfat_create(
struct inode *dir,
struct dentry *dentry,
umode_t mode,
785 err = vfat_add_entry(dir, &dentry->
d_name, 0, 0, &ts, &sinfo);
793 err = PTR_ERR(inode);
807 static int vfat_rmdir(
struct inode *dir,
struct dentry *dentry)
809 struct inode *inode = dentry->
d_inode;
819 err = vfat_find(dir, &dentry->
d_name, &sinfo);
837 static int vfat_unlink(
struct inode *dir,
struct dentry *dentry)
839 struct inode *inode = dentry->
d_inode;
846 err = vfat_find(dir, &dentry->
d_name, &sinfo);
862 static int vfat_mkdir(
struct inode *dir,
struct dentry *dentry,
umode_t mode)
878 err = vfat_add_entry(dir, &dentry->
d_name, 1, cluster, &ts, &sinfo);
887 err = PTR_ERR(inode);
909 static int vfat_rename(
struct inode *old_dir,
struct dentry *old_dentry,
910 struct inode *new_dir,
struct dentry *new_dentry)
912 struct buffer_head *dotdot_bh;
918 int err, is_dir, update_dotdot, corrupt = 0;
921 old_sinfo.bh = sinfo.
bh = dotdot_bh =
NULL;
922 old_inode = old_dentry->
d_inode;
923 new_inode = new_dentry->
d_inode;
925 err = vfat_find(old_dir, &old_dentry->
d_name, &old_sinfo);
930 update_dotdot = (is_dir && old_dir != new_dir);
945 new_i_pos = MSDOS_I(new_inode)->i_pos;
948 err = vfat_add_entry(new_dir, &new_dentry->
d_name, is_dir, 0,
952 new_i_pos = sinfo.
i_pos;
963 mark_inode_dirty(old_inode);
966 fat_set_start(dotdot_de, MSDOS_I(new_dir)->i_logstart);
987 mark_inode_dirty(old_dir);
998 brelse(old_sinfo.bh);
1007 if (update_dotdot) {
1008 fat_set_start(dotdot_de, MSDOS_I(old_dir)->i_logstart);
1031 "%s: Filesystem corrupted (i_pos %lld)",
1032 __func__, sinfo.
i_pos);
1038 .create = vfat_create,
1039 .lookup = vfat_lookup,
1040 .unlink = vfat_unlink,
1041 .mkdir = vfat_mkdir,
1042 .rmdir = vfat_rmdir,
1043 .rename = vfat_rename,
1050 MSDOS_SB(sb)->dir_ops = &vfat_dir_inode_operations;
1051 if (MSDOS_SB(sb)->
options.name_check !=
's')
1052 sb->
s_d_op = &vfat_ci_dentry_ops;
1054 sb->
s_d_op = &vfat_dentry_ops;
1057 static int vfat_fill_super(
struct super_block *sb,
void *
data,
int silent)
1063 int flags,
const char *dev_name,
1066 return mount_bdev(fs_type, flags, dev_name, data, vfat_fill_super);
1072 .mount = vfat_mount,
1077 static int __init init_vfat_fs(
void)
1082 static void __exit exit_vfat_fs(
void)