1 /*
2  *  linux/fs/vfat/namei.c
3  *
4  *  Written 1992,1993 by Werner Almesberger
5  *
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.
11  *
12  *  Short name translation 1999, 2001 by Wolfram Pienkoss <wp@bszh.de>
13  *
14  *  Support Multibyte character and cleanup by
15  *  				OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
16  */
17 
18 #include <linux/module.h>
19 
20 #include <linux/sched.h>
21 #include <linux/msdos_fs.h>
22 #include <linux/nls.h>
23 #include <linux/kernel.h>
24 #include <linux/errno.h>
25 #include <linux/string.h>
26 #include <linux/ctype.h>
27 #include <linux/stat.h>
28 #include <linux/mm.h>
29 #include <linux/slab.h>
30 
31 #define DEBUG_LEVEL 0
32 #if (DEBUG_LEVEL >= 1)
33 #  define PRINTK1(x) printk x
34 #else
35 #  define PRINTK1(x)
36 #endif
37 #if (DEBUG_LEVEL >= 2)
38 #  define PRINTK2(x) printk x
39 #else
40 #  define PRINTK2(x)
41 #endif
42 #if (DEBUG_LEVEL >= 3)
43 #  define PRINTK3(x) printk x
44 #else
45 #  define PRINTK3(x)
46 #endif
47 
48 static int vfat_hashi(struct dentry *parent, struct qstr *qstr);
49 static int vfat_hash(struct dentry *parent, struct qstr *qstr);
50 static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);
51 static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b);
52 static int vfat_revalidate(struct dentry *dentry, int);
53 
54 static struct dentry_operations vfat_dentry_ops[4] = {
55 	{
56 		d_hash:		vfat_hashi,
57 		d_compare:	vfat_cmpi,
58 	},
59 	{
60 		d_revalidate:	vfat_revalidate,
61 		d_hash:		vfat_hashi,
62 		d_compare:	vfat_cmpi,
63 	},
64 	{
65 		d_hash:		vfat_hash,
66 		d_compare:	vfat_cmp,
67 	},
68 	{
69 		d_revalidate:	vfat_revalidate,
70 		d_hash:		vfat_hash,
71 		d_compare:	vfat_cmp,
72 	}
73 };
74 
vfat_revalidate(struct dentry * dentry,int flags)75 static int vfat_revalidate(struct dentry *dentry, int flags)
76 {
77 	PRINTK1(("vfat_revalidate: %s\n", dentry->d_name.name));
78 	spin_lock(&dcache_lock);
79 	if (dentry->d_time == dentry->d_parent->d_inode->i_version) {
80 		spin_unlock(&dcache_lock);
81 		return 1;
82 	}
83 	spin_unlock(&dcache_lock);
84 	return 0;
85 }
86 
simple_getbool(char * s,int * setval)87 static int simple_getbool(char *s, int *setval)
88 {
89 	if (s) {
90 		if (!strcmp(s,"1") || !strcmp(s,"yes") || !strcmp(s,"true")) {
91 			*setval = 1;
92 		} else if (!strcmp(s,"0") || !strcmp(s,"no") || !strcmp(s,"false")) {
93 			*setval = 0;
94 		} else {
95 			return 0;
96 		}
97 	} else {
98 		*setval = 1;
99 	}
100 	return 1;
101 }
102 
parse_options(char * options,struct fat_mount_options * opts)103 static int parse_options(char *options,	struct fat_mount_options *opts)
104 {
105 	char *this_char,*value,save,*savep;
106 	int ret, val;
107 
108 	opts->unicode_xlate = opts->posixfs = 0;
109 	opts->numtail = 1;
110 	opts->utf8 = 0;
111 	opts->shortname = VFAT_SFN_DISPLAY_LOWER | VFAT_SFN_CREATE_WIN95;
112 	/* for backward compatible */
113 	if (opts->nocase) {
114 		opts->nocase = 0;
115 		opts->shortname = VFAT_SFN_DISPLAY_WIN95
116 		  		| VFAT_SFN_CREATE_WIN95;
117 	}
118 
119 	if (!options) return 1;
120 	save = 0;
121 	savep = NULL;
122 	ret = 1;
123 	for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
124 		if ((value = strchr(this_char,'=')) != NULL) {
125 			save = *value;
126 			savep = value;
127 			*value++ = 0;
128 		}
129 		if (!strcmp(this_char,"utf8")) {
130 			ret = simple_getbool(value, &val);
131 			if (ret) opts->utf8 = val;
132 		} else if (!strcmp(this_char,"uni_xlate")) {
133 			ret = simple_getbool(value, &val);
134 			if (ret) opts->unicode_xlate = val;
135 		} else if (!strcmp(this_char,"posix")) {
136 			ret = simple_getbool(value, &val);
137 			if (ret) opts->posixfs = val;
138 		} else if (!strcmp(this_char,"nonumtail")) {
139 			ret = simple_getbool(value, &val);
140 			if (ret) {
141 				opts->numtail = !val;
142 			}
143 		} else if (!strcmp(this_char, "shortname")) {
144 			if (!strcmp(value, "lower"))
145 				opts->shortname = VFAT_SFN_DISPLAY_LOWER
146 						| VFAT_SFN_CREATE_WIN95;
147 			else if (!strcmp(value, "win95"))
148 				opts->shortname = VFAT_SFN_DISPLAY_WIN95
149 						| VFAT_SFN_CREATE_WIN95;
150 			else if (!strcmp(value, "winnt"))
151 				opts->shortname = VFAT_SFN_DISPLAY_WINNT
152 						| VFAT_SFN_CREATE_WINNT;
153 			else if (!strcmp(value, "mixed"))
154 				opts->shortname = VFAT_SFN_DISPLAY_WINNT
155 						| VFAT_SFN_CREATE_WIN95;
156 			else
157 				ret = 0;
158 		}
159 		if (this_char != options)
160 			*(this_char-1) = ',';
161 		if (value) {
162 			*savep = save;
163 		}
164 		if (ret == 0) {
165 			return 0;
166 		}
167 	}
168 	if (opts->unicode_xlate) {
169 		opts->utf8 = 0;
170 	}
171 	return 1;
172 }
173 
174 static inline unsigned char
vfat_tolower(struct nls_table * t,unsigned char c)175 vfat_tolower(struct nls_table *t, unsigned char c)
176 {
177 	unsigned char nc = t->charset2lower[c];
178 
179 	return nc ? nc : c;
180 }
181 
182 static inline unsigned char
vfat_toupper(struct nls_table * t,unsigned char c)183 vfat_toupper(struct nls_table *t, unsigned char c)
184 {
185 	unsigned char nc = t->charset2upper[c];
186 
187 	return nc ? nc : c;
188 }
189 
190 static int
vfat_strnicmp(struct nls_table * t,const unsigned char * s1,const unsigned char * s2,int len)191 vfat_strnicmp(struct nls_table *t, const unsigned char *s1,
192 					const unsigned char *s2, int len)
193 {
194 	while(len--)
195 		if (vfat_tolower(t, *s1++) != vfat_tolower(t, *s2++))
196 			return 1;
197 
198 	return 0;
199 }
200 
201 /*
202  * Compute the hash for the vfat name corresponding to the dentry.
203  * Note: if the name is invalid, we leave the hash code unchanged so
204  * that the existing dentry can be used. The vfat fs routines will
205  * return ENOENT or EINVAL as appropriate.
206  */
vfat_hash(struct dentry * dentry,struct qstr * qstr)207 static int vfat_hash(struct dentry *dentry, struct qstr *qstr)
208 {
209 	const char *name;
210 	int len;
211 
212 	len = qstr->len;
213 	name = qstr->name;
214 	while (len && name[len-1] == '.')
215 		len--;
216 
217 	qstr->hash = full_name_hash(name, len);
218 
219 	return 0;
220 }
221 
222 /*
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.
227  */
vfat_hashi(struct dentry * dentry,struct qstr * qstr)228 static int vfat_hashi(struct dentry *dentry, struct qstr *qstr)
229 {
230 	struct nls_table *t = MSDOS_SB(dentry->d_inode->i_sb)->nls_io;
231 	const char *name;
232 	int len;
233 	unsigned long hash;
234 
235 	len = qstr->len;
236 	name = qstr->name;
237 	while (len && name[len-1] == '.')
238 		len--;
239 
240 	hash = init_name_hash();
241 	while (len--)
242 		hash = partial_name_hash(vfat_tolower(t, *name++), hash);
243 	qstr->hash = end_name_hash(hash);
244 
245 	return 0;
246 }
247 
248 /*
249  * Case insensitive compare of two vfat names.
250  */
vfat_cmpi(struct dentry * dentry,struct qstr * a,struct qstr * b)251 static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b)
252 {
253 	struct nls_table *t = MSDOS_SB(dentry->d_inode->i_sb)->nls_io;
254 	int alen, blen;
255 
256 	/* A filename cannot end in '.' or we treat it like it has none */
257 	alen = a->len;
258 	blen = b->len;
259 	while (alen && a->name[alen-1] == '.')
260 		alen--;
261 	while (blen && b->name[blen-1] == '.')
262 		blen--;
263 	if (alen == blen) {
264 		if (vfat_strnicmp(t, a->name, b->name, alen) == 0)
265 			return 0;
266 	}
267 	return 1;
268 }
269 
270 /*
271  * Case sensitive compare of two vfat names.
272  */
vfat_cmp(struct dentry * dentry,struct qstr * a,struct qstr * b)273 static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b)
274 {
275 	int alen, blen;
276 
277 	/* A filename cannot end in '.' or we treat it like it has none */
278 	alen = a->len;
279 	blen = b->len;
280 	while (alen && a->name[alen-1] == '.')
281 		alen--;
282 	while (blen && b->name[blen-1] == '.')
283 		blen--;
284 	if (alen == blen) {
285 		if (strncmp(a->name, b->name, alen) == 0)
286 			return 0;
287 	}
288 	return 1;
289 }
290 
291 #ifdef DEBUG
292 
dump_fat(struct super_block * sb,int start)293 static void dump_fat(struct super_block *sb,int start)
294 {
295 	printk("[");
296 	while (start) {
297 		printk("%d ",start);
298 		start = fat_access(sb,start,-1);
299 		if (!start) {
300 			printk("ERROR");
301 			break;
302 		}
303 		if (start == -1) break;
304 	}
305 	printk("]\n");
306 }
307 
dump_de(struct msdos_dir_entry * de)308 static void dump_de(struct msdos_dir_entry *de)
309 {
310 	int i;
311 	unsigned char *p = (unsigned char *) de;
312 	printk("[");
313 
314 	for (i = 0; i < 32; i++, p++) {
315 		printk("%02x ", *p);
316 	}
317 	printk("]\n");
318 }
319 
320 #endif
321 
322 /* MS-DOS "device special files" */
323 
324 static const char *reserved3_names[] = {
325 	"con     ", "prn     ", "nul     ", "aux     ", NULL
326 };
327 
328 static const char *reserved4_names[] = {
329 	"com1    ", "com2    ", "com3    ", "com4    ", "com5    ",
330 	"com6    ", "com7    ", "com8    ", "com9    ",
331 	"lpt1    ", "lpt2    ", "lpt3    ", "lpt4    ", "lpt5    ",
332 	"lpt6    ", "lpt7    ", "lpt8    ", "lpt9    ",
333 	NULL };
334 
335 
336 /* Characters that are undesirable in an MS-DOS file name */
337 
338 static wchar_t bad_chars[] = {
339 	/*  `*'     `?'     `<'    `>'      `|'     `"'     `:'     `/' */
340 	0x002A, 0x003F, 0x003C, 0x003E, 0x007C, 0x0022, 0x003A, 0x002F,
341 	/*  `\' */
342 	0x005C, 0,
343 };
344 #define IS_BADCHAR(uni)	(vfat_unistrchr(bad_chars, (uni)) != NULL)
345 
346 static wchar_t replace_chars[] = {
347 	/*  `['     `]'    `;'     `,'     `+'      `=' */
348 	0x005B, 0x005D, 0x003B, 0x002C, 0x002B, 0x003D, 0,
349 };
350 #define IS_REPLACECHAR(uni)	(vfat_unistrchr(replace_chars, (uni)) != NULL)
351 
352 static wchar_t skip_chars[] = {
353 	/*  `.'     ` ' */
354 	0x002E, 0x0020, 0,
355 };
356 #define IS_SKIPCHAR(uni) \
357 	((wchar_t)(uni) == skip_chars[0] || (wchar_t)(uni) == skip_chars[1])
358 
vfat_unistrchr(const wchar_t * s,const wchar_t c)359 static inline wchar_t *vfat_unistrchr(const wchar_t *s, const wchar_t c)
360 {
361 	for(; *s != c; ++s)
362 		if (*s == 0)
363 			return NULL;
364 	return (wchar_t *) s;
365 }
366 
vfat_is_used_badchars(const wchar_t * s,int len)367 static inline int vfat_is_used_badchars(const wchar_t *s, int len)
368 {
369 	int i;
370 
371 	for (i = 0; i < len; i++)
372 		if (s[i] < 0x0020 || IS_BADCHAR(s[i]))
373 			return -EINVAL;
374 	return 0;
375 }
376 
377 /* Checks the validity of a long MS-DOS filename */
378 /* Returns negative number on error, 0 for a normal
379  * return, and 1 for . or .. */
380 
vfat_valid_longname(const char * name,int len,int xlate)381 static int vfat_valid_longname(const char *name, int len, int xlate)
382 {
383 	const char **reserved, *walk;
384 	int baselen;
385 
386 	if (len && name[len-1] == ' ') return -EINVAL;
387 	if (len >= 256) return -EINVAL;
388  	if (len < 3) return 0;
389 
390 	for (walk = name; *walk != 0 && *walk != '.'; walk++);
391 	baselen = walk - name;
392 
393 	if (baselen == 3) {
394 		for (reserved = reserved3_names; *reserved; reserved++) {
395 			if (!strnicmp(name,*reserved,baselen))
396 				return -EINVAL;
397 		}
398 	} else if (baselen == 4) {
399 		for (reserved = reserved4_names; *reserved; reserved++) {
400 			if (!strnicmp(name,*reserved,baselen))
401 				return -EINVAL;
402 		}
403 	}
404 	return 0;
405 }
406 
vfat_find_form(struct inode * dir,char * name)407 static int vfat_find_form(struct inode *dir,char *name)
408 {
409 	struct msdos_dir_entry *de;
410 	struct buffer_head *bh = NULL;
411 	loff_t i_pos;
412 	int res;
413 
414 	res = fat_scan(dir, name, &bh, &de, &i_pos);
415 	fat_brelse(dir->i_sb, bh);
416 	if (res<0)
417 		return -ENOENT;
418 	return 0;
419 }
420 
421 /*
422  * 1) Valid characters for the 8.3 format alias are any combination of
423  * letters, uppercase alphabets, digits, any of the
424  * following special characters:
425  *     $ % ' ` - @ { } ~ ! # ( ) & _ ^
426  * In this case Longfilename is not stored in disk.
427  *
428  * WinNT's Extension:
429  * File name and extension name is contain uppercase/lowercase
430  * only. And it is expressed by CASE_LOWER_BASE and CASE_LOWER_EXT.
431  *
432  * 2) File name is 8.3 format, but it contain the uppercase and
433  * lowercase char, muliti bytes char, etc. In this case numtail is not
434  * added, but Longfilename is stored.
435  *
436  * 3) When the one except for the above, or the following special
437  * character are contained:
438  *        .   [ ] ; , + =
439  * numtail is added, and Longfilename must be stored in disk .
440  */
441 struct shortname_info {
442 	unsigned char lower:1,
443 		      upper:1,
444 		      valid:1;
445 };
446 #define INIT_SHORTNAME_INFO(x)	do {		\
447 	(x)->lower = 1;				\
448 	(x)->upper = 1;				\
449 	(x)->valid = 1;				\
450 } while (0)
451 
452 static inline unsigned char
shortname_info_to_lcase(struct shortname_info * base,struct shortname_info * ext)453 shortname_info_to_lcase(struct shortname_info *base,
454 			struct shortname_info *ext)
455 {
456 	unsigned char lcase = 0;
457 
458 	if (base->valid && ext->valid) {
459 		if (!base->upper && base->lower && (ext->lower || ext->upper))
460 			lcase |= CASE_LOWER_BASE;
461 		if (!ext->upper && ext->lower && (base->lower || base->upper))
462 			lcase |= CASE_LOWER_EXT;
463 	}
464 
465 	return lcase;
466 }
467 
to_shortname_char(struct nls_table * nls,char * buf,int buf_size,wchar_t * src,struct shortname_info * info)468 static inline int to_shortname_char(struct nls_table *nls,
469 				    char *buf, int buf_size, wchar_t *src,
470 				    struct shortname_info *info)
471 {
472 	int len;
473 
474 	if (IS_SKIPCHAR(*src)) {
475 		info->valid = 0;
476 		return 0;
477 	}
478 	if (IS_REPLACECHAR(*src)) {
479 		info->valid = 0;
480 		buf[0] = '_';
481 		return 1;
482 	}
483 
484 	len = nls->uni2char(*src, buf, buf_size);
485 	if (len <= 0) {
486 		info->valid = 0;
487 		buf[0] = '_';
488 		len = 1;
489 	} else if (len == 1) {
490 		unsigned char prev = buf[0];
491 
492 		if (buf[0] >= 0x7F) {
493 			info->lower = 0;
494 			info->upper = 0;
495 		}
496 
497 		buf[0] = vfat_toupper(nls, buf[0]);
498 		if (isalpha(buf[0])) {
499 			if (buf[0] == prev)
500 				info->lower = 0;
501 			else
502 				info->upper = 0;
503 		}
504 	} else {
505 		info->lower = 0;
506 		info->upper = 0;
507 	}
508 
509 	return len;
510 }
511 
512 /*
513  * Given a valid longname, create a unique shortname.  Make sure the
514  * shortname does not exist
515  * Returns negative number on error, 0 for a normal
516  * return, and 1 for valid shortname
517  */
vfat_create_shortname(struct inode * dir,struct nls_table * nls,wchar_t * uname,int ulen,char * name_res,unsigned char * lcase)518 static int vfat_create_shortname(struct inode *dir, struct nls_table *nls,
519 				 wchar_t *uname, int ulen,
520 				 char *name_res, unsigned char *lcase)
521 {
522 	wchar_t *ip, *ext_start, *end, *name_start;
523 	unsigned char base[9], ext[4], buf[8], *p;
524 	unsigned char charbuf[NLS_MAX_CHARSET_SIZE];
525 	int chl, chi;
526 	int sz = 0, extlen, baselen, i, numtail_baselen, numtail2_baselen;
527 	int is_shortname;
528 	struct shortname_info base_info, ext_info;
529 	unsigned short opt_shortname = MSDOS_SB(dir->i_sb)->options.shortname;
530 
531 	is_shortname = 1;
532 	INIT_SHORTNAME_INFO(&base_info);
533 	INIT_SHORTNAME_INFO(&ext_info);
534 
535 	/* Now, we need to create a shortname from the long name */
536 	ext_start = end = &uname[ulen];
537 	while (--ext_start >= uname) {
538 		if (*ext_start == 0x002E) { /* is `.' */
539 			if (ext_start == end - 1) {
540 				sz = ulen;
541 				ext_start = NULL;
542 			}
543 			break;
544 		}
545 	}
546 
547 	if (ext_start == uname - 1) {
548 		sz = ulen;
549 		ext_start = NULL;
550 	} else if (ext_start) {
551 		/*
552 		 * Names which start with a dot could be just
553 		 * an extension eg. "...test".  In this case Win95
554 		 * uses the extension as the name and sets no extension.
555 		 */
556 		name_start = &uname[0];
557 		while (name_start < ext_start) {
558 			if (!IS_SKIPCHAR(*name_start))
559 				break;
560 			name_start++;
561 		}
562 		if (name_start != ext_start) {
563 			sz = ext_start - uname;
564 			ext_start++;
565 		} else {
566 			sz = ulen;
567 			ext_start=NULL;
568 		}
569 	}
570 
571 	numtail_baselen = 6;
572 	numtail2_baselen = 2;
573 	for (baselen = i = 0, p = base, ip = uname; i < sz; i++, ip++) {
574 		chl = to_shortname_char(nls, charbuf, sizeof(charbuf),
575 					ip, &base_info);
576 		if (chl == 0)
577 			continue;
578 
579 		if (baselen < 2 && (baselen + chl) > 2)
580 			numtail2_baselen = baselen;
581 		if (baselen < 6 && (baselen + chl) > 6)
582 			numtail_baselen = baselen;
583 		for (chi = 0; chi < chl; chi++){
584 			*p++ = charbuf[chi];
585 			baselen++;
586 			if (baselen >= 8)
587 				break;
588 		}
589 		if (baselen >= 8) {
590 			if ((chi < chl - 1) || (ip + 1) - uname < sz)
591 				is_shortname = 0;
592 			break;
593 		}
594 	}
595 	if (baselen == 0) {
596 		return -EINVAL;
597 	}
598 
599 	extlen = 0;
600 	if (ext_start) {
601 		for (p = ext, ip = ext_start; extlen < 3 && ip < end; ip++) {
602 			chl = to_shortname_char(nls, charbuf, sizeof(charbuf),
603 						ip, &ext_info);
604 			if (chl == 0)
605 				continue;
606 
607 			if ((extlen + chl) > 3) {
608 				is_shortname = 0;
609 				break;
610 			}
611 			for (chi = 0; chi < chl; chi++) {
612 				*p++ = charbuf[chi];
613 				extlen++;
614 			}
615 			if (extlen >= 3) {
616 				if (ip + 1 != end)
617 					is_shortname = 0;
618 				break;
619 			}
620 		}
621 	}
622 	ext[extlen] = '\0';
623 	base[baselen] = '\0';
624 
625 	/* Yes, it can happen. ".\xe5" would do it. */
626 	if (base[0] == DELETED_FLAG)
627 		base[0] = 0x05;
628 
629 	/* OK, at this point we know that base is not longer than 8 symbols,
630 	 * ext is not longer than 3, base is nonempty, both don't contain
631 	 * any bad symbols (lowercase transformed to uppercase).
632 	 */
633 
634 	memset(name_res, ' ', MSDOS_NAME);
635 	memcpy(name_res, base, baselen);
636 	memcpy(name_res + 8, ext, extlen);
637 	*lcase = 0;
638 	if (is_shortname && base_info.valid && ext_info.valid) {
639 		if (vfat_find_form(dir, name_res) == 0)
640 			return -EEXIST;
641 
642 		if (opt_shortname & VFAT_SFN_CREATE_WIN95) {
643 			return (base_info.upper && ext_info.upper);
644 		} else if (opt_shortname & VFAT_SFN_CREATE_WINNT) {
645 			if ((base_info.upper || base_info.lower)
646 			    && (ext_info.upper || ext_info.lower)) {
647 				*lcase = shortname_info_to_lcase(&base_info,
648 								 &ext_info);
649 				return 1;
650 			}
651 			return 0;
652 		} else {
653 			BUG();
654 		}
655 	}
656 
657 	if (MSDOS_SB(dir->i_sb)->options.numtail == 0)
658 		if (vfat_find_form(dir, name_res) < 0)
659 			return 0;
660 
661 	/*
662 	 * Try to find a unique extension.  This used to
663 	 * iterate through all possibilities sequentially,
664 	 * but that gave extremely bad performance.  Windows
665 	 * only tries a few cases before using random
666 	 * values for part of the base.
667 	 */
668 
669 	if (baselen>6) {
670 		baselen = numtail_baselen;
671 		name_res[7] = ' ';
672 	}
673 	name_res[baselen] = '~';
674 	for (i = 1; i < 10; i++) {
675 		name_res[baselen+1] = i + '0';
676 		if (vfat_find_form(dir, name_res) < 0)
677 			return 0;
678 	}
679 
680 	i = jiffies & 0xffff;
681 	sz = (jiffies >> 16) & 0x7;
682 	if (baselen>2) {
683 		baselen = numtail2_baselen;
684 		name_res[7] = ' ';
685 	}
686 	name_res[baselen+4] = '~';
687 	name_res[baselen+5] = '1' + sz;
688 	while (1) {
689 		sprintf(buf, "%04X", i);
690 		memcpy(&name_res[baselen], buf, 4);
691 		if (vfat_find_form(dir, name_res) < 0)
692 			break;
693 		i -= 11;
694 	}
695 	return 0;
696 }
697 
698 /* Translate a string, including coded sequences into Unicode */
699 static int
xlate_to_uni(const char * name,int len,char * outname,int * longlen,int * outlen,int escape,int utf8,struct nls_table * nls)700 xlate_to_uni(const char *name, int len, char *outname, int *longlen, int *outlen,
701 	     int escape, int utf8, struct nls_table *nls)
702 {
703 	const unsigned char *ip;
704 	unsigned char nc;
705 	char *op;
706 	unsigned int ec;
707 	int i, k, fill;
708 	int charlen;
709 
710 	if (utf8) {
711 		*outlen = utf8_mbstowcs((__u16 *) outname, name, PAGE_SIZE);
712 		if (name[len-1] == '.')
713 			*outlen-=2;
714 		op = &outname[*outlen * sizeof(__u16)];
715 	} else {
716 		if (name[len-1] == '.')
717 			len--;
718 		if (nls) {
719 			for (i = 0, ip = name, op = outname, *outlen = 0;
720 			     i < len && *outlen <= 260; *outlen += 1)
721 			{
722 				if (escape && (*ip == ':')) {
723 					if (i > len - 5)
724 						return -EINVAL;
725 					ec = 0;
726 					for (k = 1; k < 5; k++) {
727 						nc = ip[k];
728 						ec <<= 4;
729 						if (nc >= '0' && nc <= '9') {
730 							ec |= nc - '0';
731 							continue;
732 						}
733 						if (nc >= 'a' && nc <= 'f') {
734 							ec |= nc - ('a' - 10);
735 							continue;
736 						}
737 						if (nc >= 'A' && nc <= 'F') {
738 							ec |= nc - ('A' - 10);
739 							continue;
740 						}
741 						return -EINVAL;
742 					}
743 					*op++ = ec & 0xFF;
744 					*op++ = ec >> 8;
745 					ip += 5;
746 					i += 5;
747 				} else {
748 					if ((charlen = nls->char2uni(ip, len-i, (wchar_t *)op)) < 0)
749 						return -EINVAL;
750 					ip += charlen;
751 					i += charlen;
752 					op += 2;
753 				}
754 			}
755 		} else {
756 			for (i = 0, ip = name, op = outname, *outlen = 0;
757 			     i < len && *outlen <= 260; i++, *outlen += 1)
758 			{
759 				*op++ = *ip++;
760 				*op++ = 0;
761 			}
762 		}
763 	}
764 	if (*outlen > 260)
765 		return -ENAMETOOLONG;
766 
767 	*longlen = *outlen;
768 	if (*outlen % 13) {
769 		*op++ = 0;
770 		*op++ = 0;
771 		*outlen += 1;
772 		if (*outlen % 13) {
773 			fill = 13 - (*outlen % 13);
774 			for (i = 0; i < fill; i++) {
775 				*op++ = 0xff;
776 				*op++ = 0xff;
777 			}
778 			*outlen += fill;
779 		}
780 	}
781 
782 	return 0;
783 }
784 
785 static int
vfat_fill_slots(struct inode * dir,struct msdos_dir_slot * ds,const char * name,int len,int * slots,int is_dir,int uni_xlate)786 vfat_fill_slots(struct inode *dir, struct msdos_dir_slot *ds, const char *name,
787 		int len, int *slots, int is_dir, int uni_xlate)
788 {
789 	struct nls_table *nls_io, *nls_disk;
790 	wchar_t *uname;
791 	struct msdos_dir_slot *ps;
792 	struct msdos_dir_entry *de;
793 	unsigned long page;
794 	unsigned char cksum, lcase;
795 	char *uniname, msdos_name[MSDOS_NAME];
796 	int res, utf8, slot, ulen, unilen, i;
797 	loff_t offset;
798 
799 	*slots = 0;
800 	utf8 = MSDOS_SB(dir->i_sb)->options.utf8;
801 	nls_io = MSDOS_SB(dir->i_sb)->nls_io;
802 	nls_disk = MSDOS_SB(dir->i_sb)->nls_disk;
803 
804 	if (name[len-1] == '.')
805 		len--;
806 	if(!(page = __get_free_page(GFP_KERNEL)))
807 		return -ENOMEM;
808 
809 	uniname = (char *) page;
810 	res = xlate_to_uni(name, len, uniname, &ulen, &unilen, uni_xlate,
811 			   utf8, nls_io);
812 	if (res < 0)
813 		goto out_free;
814 
815 	uname = (wchar_t *) page;
816 	res = vfat_is_used_badchars(uname, ulen);
817 	if (res < 0)
818 		goto out_free;
819 
820 	res = vfat_create_shortname(dir, nls_disk, uname, ulen,
821 				    msdos_name, &lcase);
822 	if (res < 0)
823 		goto out_free;
824 	else if (res == 1) {
825 		de = (struct msdos_dir_entry *)ds;
826 		res = 0;
827 		goto shortname;
828 	}
829 
830 	/* build the entry of long file name */
831 	*slots = unilen / 13;
832 	for (cksum = i = 0; i < 11; i++) {
833 		cksum = (((cksum&1)<<7)|((cksum&0xfe)>>1)) + msdos_name[i];
834 	}
835 	PRINTK3(("vfat_fill_slots 3: slots=%d\n",*slots));
836 
837 	for (ps = ds, slot = *slots; slot > 0; slot--, ps++) {
838 		ps->id = slot;
839 		ps->attr = ATTR_EXT;
840 		ps->reserved = 0;
841 		ps->alias_checksum = cksum;
842 		ps->start = 0;
843 		offset = (slot - 1) * 13;
844 		fatwchar_to16(ps->name0_4, uname + offset, 5);
845 		fatwchar_to16(ps->name5_10, uname + offset + 5, 6);
846 		fatwchar_to16(ps->name11_12, uname + offset + 11, 2);
847 	}
848 	ds[0].id |= 0x40;
849 	de = (struct msdos_dir_entry *) ps;
850 
851 shortname:
852 	PRINTK3(("vfat_fill_slots 9\n"));
853 	/* build the entry of 8.3 alias name */
854 	(*slots)++;
855 	strncpy(de->name, msdos_name, MSDOS_NAME);
856 	de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
857 	de->lcase = lcase;
858 	de->adate = de->cdate = de->date = 0;
859 	de->ctime_ms = de->ctime = de->time = 0;
860 	de->start = 0;
861 	de->starthi = 0;
862 	de->size = 0;
863 
864 out_free:
865 	free_page(page);
866 	return res;
867 }
868 
869 /* We can't get "." or ".." here - VFS takes care of those cases */
870 
vfat_build_slots(struct inode * dir,const char * name,int len,struct msdos_dir_slot * ds,int * slots,int is_dir)871 static int vfat_build_slots(struct inode *dir, const char *name, int len,
872 			    struct msdos_dir_slot *ds, int *slots, int is_dir)
873 {
874 	int res, xlate;
875 
876 	xlate = MSDOS_SB(dir->i_sb)->options.unicode_xlate;
877 	res = vfat_valid_longname(name, len, xlate);
878 	if (res < 0)
879 		return res;
880 
881 	return vfat_fill_slots(dir, ds, name, len, slots, is_dir, xlate);
882 }
883 
vfat_add_entry(struct inode * dir,struct qstr * qname,int is_dir,struct vfat_slot_info * sinfo_out,struct buffer_head ** bh,struct msdos_dir_entry ** de)884 static int vfat_add_entry(struct inode *dir,struct qstr* qname,
885 			  int is_dir, struct vfat_slot_info *sinfo_out,
886 			  struct buffer_head **bh, struct msdos_dir_entry **de)
887 {
888 	struct super_block *sb = dir->i_sb;
889 	struct msdos_dir_slot *dir_slots;
890 	loff_t offset;
891 	int slots, slot;
892 	int res, len;
893 	struct msdos_dir_entry *dummy_de;
894 	struct buffer_head *dummy_bh;
895 	loff_t dummy_i_pos;
896 	loff_t dummy;
897 
898 	dir_slots = (struct msdos_dir_slot *)
899 	       kmalloc(sizeof(struct msdos_dir_slot) * MSDOS_SLOTS, GFP_KERNEL);
900 	if (dir_slots == NULL)
901 		return -ENOMEM;
902 
903 	len = qname->len;
904 	while (len && qname->name[len-1] == '.')
905 		len--;
906 	res = fat_search_long(dir, qname->name, len,
907 			      (MSDOS_SB(sb)->options.name_check != 's')
908 			      || !MSDOS_SB(sb)->options.posixfs,
909 			      &dummy, &dummy);
910 	if (res > 0) /* found */
911 		res = -EEXIST;
912 	if (res)
913 		goto cleanup;
914 
915 	res = vfat_build_slots(dir, qname->name, len,
916 			       dir_slots, &slots, is_dir);
917 	if (res < 0)
918 		goto cleanup;
919 
920 	/* build the empty directory entry of number of slots */
921 	offset = fat_add_entries(dir, slots, &dummy_bh, &dummy_de, &dummy_i_pos);
922 	if (offset < 0) {
923 		res = offset;
924 		goto cleanup;
925 	}
926 	fat_brelse(sb, dummy_bh);
927 
928 	/* Now create the new entry */
929 	*bh = NULL;
930 	for (slot = 0; slot < slots; slot++) {
931 		if (fat_get_entry(dir, &offset, bh, de, &sinfo_out->i_pos) < 0) {
932 			res = -EIO;
933 			goto cleanup;
934 		}
935 		memcpy(*de, dir_slots + slot, sizeof(struct msdos_dir_slot));
936 		fat_mark_buffer_dirty(sb, *bh);
937 	}
938 
939 	res = 0;
940 	/* update timestamp */
941 	dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;
942 	mark_inode_dirty(dir);
943 
944 	fat_date_unix2dos(dir->i_mtime, &(*de)->time, &(*de)->date);
945 	(*de)->ctime = (*de)->time;
946 	(*de)->adate = (*de)->cdate = (*de)->date;
947 
948 	fat_mark_buffer_dirty(sb, *bh);
949 
950 	/* slots can't be less than 1 */
951 	sinfo_out->long_slots = slots - 1;
952 	sinfo_out->longname_offset =
953 		offset - sizeof(struct msdos_dir_slot) * slots;
954 
955 cleanup:
956 	kfree(dir_slots);
957 	return res;
958 }
959 
vfat_find(struct inode * dir,struct qstr * qname,struct vfat_slot_info * sinfo,struct buffer_head ** last_bh,struct msdos_dir_entry ** last_de)960 static int vfat_find(struct inode *dir,struct qstr* qname,
961 	struct vfat_slot_info *sinfo, struct buffer_head **last_bh,
962 	struct msdos_dir_entry **last_de)
963 {
964 	struct super_block *sb = dir->i_sb;
965 	loff_t offset;
966 	int res,len;
967 
968 	len = qname->len;
969 	while (len && qname->name[len-1] == '.')
970 		len--;
971 	res = fat_search_long(dir, qname->name, len,
972 			(MSDOS_SB(sb)->options.name_check != 's'),
973 			&offset,&sinfo->longname_offset);
974 	if (res>0) {
975 		sinfo->long_slots = res-1;
976 		if (fat_get_entry(dir,&offset,last_bh,last_de,&sinfo->i_pos)>=0)
977 			return 0;
978 		res = -EIO;
979 	}
980 	return res ? res : -ENOENT;
981 }
982 
vfat_lookup(struct inode * dir,struct dentry * dentry)983 struct dentry *vfat_lookup(struct inode *dir,struct dentry *dentry)
984 {
985 	int res;
986 	struct vfat_slot_info sinfo;
987 	struct inode *inode;
988 	struct dentry *alias;
989 	struct buffer_head *bh = NULL;
990 	struct msdos_dir_entry *de;
991 	int table;
992 
993 	PRINTK2(("vfat_lookup: name=%s, len=%d\n",
994 		 dentry->d_name.name, dentry->d_name.len));
995 
996 	table = (MSDOS_SB(dir->i_sb)->options.name_check == 's') ? 2 : 0;
997 	dentry->d_op = &vfat_dentry_ops[table];
998 
999 	inode = NULL;
1000 	res = vfat_find(dir,&dentry->d_name,&sinfo,&bh,&de);
1001 	if (res < 0) {
1002 		table++;
1003 		goto error;
1004 	}
1005 	inode = fat_build_inode(dir->i_sb, de, sinfo.i_pos, &res);
1006 	fat_brelse(dir->i_sb, bh);
1007 	if (res)
1008 		return ERR_PTR(res);
1009 	alias = d_find_alias(inode);
1010 	if (alias) {
1011 		if (d_invalidate(alias)==0)
1012 			dput(alias);
1013 		else {
1014 			iput(inode);
1015 			return alias;
1016 		}
1017 
1018 	}
1019 error:
1020 	dentry->d_op = &vfat_dentry_ops[table];
1021 	dentry->d_time = dentry->d_parent->d_inode->i_version;
1022 	d_add(dentry,inode);
1023 	return NULL;
1024 }
1025 
vfat_create(struct inode * dir,struct dentry * dentry,int mode)1026 int vfat_create(struct inode *dir,struct dentry* dentry,int mode)
1027 {
1028 	struct super_block *sb = dir->i_sb;
1029 	struct inode *inode = NULL;
1030 	struct buffer_head *bh = NULL;
1031 	struct msdos_dir_entry *de;
1032 	struct vfat_slot_info sinfo;
1033 	int res;
1034 
1035 	res = vfat_add_entry(dir, &dentry->d_name, 0, &sinfo, &bh, &de);
1036 	if (res < 0)
1037 		return res;
1038 	inode = fat_build_inode(sb, de, sinfo.i_pos, &res);
1039 	fat_brelse(sb, bh);
1040 	if (!inode)
1041 		return res;
1042 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
1043 	mark_inode_dirty(inode);
1044 	inode->i_version = ++event;
1045 	dir->i_version = event;
1046 	dentry->d_time = dentry->d_parent->d_inode->i_version;
1047 	d_instantiate(dentry,inode);
1048 	return 0;
1049 }
1050 
vfat_remove_entry(struct inode * dir,struct vfat_slot_info * sinfo,struct buffer_head * bh,struct msdos_dir_entry * de)1051 static void vfat_remove_entry(struct inode *dir,struct vfat_slot_info *sinfo,
1052      struct buffer_head *bh, struct msdos_dir_entry *de)
1053 {
1054 	struct super_block *sb = dir->i_sb;
1055 	loff_t offset, i_pos;
1056 	int i;
1057 
1058 	/* remove the shortname */
1059 	dir->i_mtime = CURRENT_TIME;
1060 	dir->i_atime = CURRENT_TIME;
1061 	dir->i_version = ++event;
1062 	mark_inode_dirty(dir);
1063 	de->name[0] = DELETED_FLAG;
1064 	fat_mark_buffer_dirty(sb, bh);
1065 	/* remove the longname */
1066 	offset = sinfo->longname_offset; de = NULL;
1067 	for (i = sinfo->long_slots; i > 0; --i) {
1068 		if (fat_get_entry(dir, &offset, &bh, &de, &i_pos) < 0)
1069 			continue;
1070 		de->name[0] = DELETED_FLAG;
1071 		de->attr = 0;
1072 		fat_mark_buffer_dirty(sb, bh);
1073 	}
1074 	if (bh) fat_brelse(sb, bh);
1075 }
1076 
vfat_rmdir(struct inode * dir,struct dentry * dentry)1077 int vfat_rmdir(struct inode *dir,struct dentry* dentry)
1078 {
1079 	int res;
1080 	struct vfat_slot_info sinfo;
1081 	struct buffer_head *bh = NULL;
1082 	struct msdos_dir_entry *de;
1083 
1084 	res = fat_dir_empty(dentry->d_inode);
1085 	if (res)
1086 		return res;
1087 
1088 	res = vfat_find(dir,&dentry->d_name,&sinfo, &bh, &de);
1089 	if (res<0)
1090 		return res;
1091 	dentry->d_inode->i_nlink = 0;
1092 	dentry->d_inode->i_mtime = CURRENT_TIME;
1093 	dentry->d_inode->i_atime = CURRENT_TIME;
1094 	fat_detach(dentry->d_inode);
1095 	mark_inode_dirty(dentry->d_inode);
1096 	/* releases bh */
1097 	vfat_remove_entry(dir,&sinfo,bh,de);
1098 	dir->i_nlink--;
1099 	return 0;
1100 }
1101 
vfat_unlink(struct inode * dir,struct dentry * dentry)1102 int vfat_unlink(struct inode *dir, struct dentry* dentry)
1103 {
1104 	int res;
1105 	struct vfat_slot_info sinfo;
1106 	struct buffer_head *bh = NULL;
1107 	struct msdos_dir_entry *de;
1108 
1109 	PRINTK1(("vfat_unlink: %s\n", dentry->d_name.name));
1110 	res = vfat_find(dir,&dentry->d_name,&sinfo,&bh,&de);
1111 	if (res < 0)
1112 		return res;
1113 	dentry->d_inode->i_nlink = 0;
1114 	dentry->d_inode->i_mtime = CURRENT_TIME;
1115 	dentry->d_inode->i_atime = CURRENT_TIME;
1116 	fat_detach(dentry->d_inode);
1117 	mark_inode_dirty(dentry->d_inode);
1118 	/* releases bh */
1119 	vfat_remove_entry(dir,&sinfo,bh,de);
1120 
1121 	return res;
1122 }
1123 
1124 
vfat_mkdir(struct inode * dir,struct dentry * dentry,int mode)1125 int vfat_mkdir(struct inode *dir,struct dentry* dentry,int mode)
1126 {
1127 	struct super_block *sb = dir->i_sb;
1128 	struct inode *inode = NULL;
1129 	struct vfat_slot_info sinfo;
1130 	struct buffer_head *bh = NULL;
1131 	struct msdos_dir_entry *de;
1132 	int res;
1133 
1134 	res = vfat_add_entry(dir, &dentry->d_name, 1, &sinfo, &bh, &de);
1135 	if (res < 0)
1136 		return res;
1137 	inode = fat_build_inode(sb, de, sinfo.i_pos, &res);
1138 	if (!inode)
1139 		goto out;
1140 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
1141 	mark_inode_dirty(inode);
1142 	inode->i_version = ++event;
1143 	dir->i_version = event;
1144 	dir->i_nlink++;
1145 	inode->i_nlink = 2; /* no need to mark them dirty */
1146 	res = fat_new_dir(inode, dir, 1);
1147 	if (res < 0)
1148 		goto mkdir_failed;
1149 	dentry->d_time = dentry->d_parent->d_inode->i_version;
1150 	d_instantiate(dentry,inode);
1151 out:
1152 	fat_brelse(sb, bh);
1153 	return res;
1154 
1155 mkdir_failed:
1156 	inode->i_nlink = 0;
1157 	inode->i_mtime = CURRENT_TIME;
1158 	inode->i_atime = CURRENT_TIME;
1159 	fat_detach(inode);
1160 	mark_inode_dirty(inode);
1161 	/* releases bh */
1162 	vfat_remove_entry(dir,&sinfo,bh,de);
1163 	iput(inode);
1164 	dir->i_nlink--;
1165 	return res;
1166 }
1167 
vfat_rename(struct inode * old_dir,struct dentry * old_dentry,struct inode * new_dir,struct dentry * new_dentry)1168 int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
1169 		struct inode *new_dir,struct dentry *new_dentry)
1170 {
1171 	struct super_block *sb = old_dir->i_sb;
1172 	struct buffer_head *old_bh,*new_bh,*dotdot_bh;
1173 	struct msdos_dir_entry *old_de,*new_de,*dotdot_de;
1174 	loff_t dotdot_i_pos;
1175 	struct inode *old_inode, *new_inode;
1176 	int res, is_dir;
1177 	struct vfat_slot_info old_sinfo,sinfo;
1178 
1179 	old_bh = new_bh = dotdot_bh = NULL;
1180 	old_inode = old_dentry->d_inode;
1181 	new_inode = new_dentry->d_inode;
1182 	res = vfat_find(old_dir,&old_dentry->d_name,&old_sinfo,&old_bh,&old_de);
1183 	PRINTK3(("vfat_rename 2\n"));
1184 	if (res < 0) goto rename_done;
1185 
1186 	is_dir = S_ISDIR(old_inode->i_mode);
1187 
1188 	if (is_dir && (res = fat_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh,
1189 				&dotdot_de,&dotdot_i_pos)) < 0)
1190 		goto rename_done;
1191 
1192 	if (new_dentry->d_inode) {
1193 		res = vfat_find(new_dir,&new_dentry->d_name,&sinfo,&new_bh,
1194 				&new_de);
1195 		if (res < 0 || MSDOS_I(new_inode)->i_pos != sinfo.i_pos) {
1196 			/* WTF??? Cry and fail. */
1197 			printk(KERN_WARNING "vfat_rename: fs corrupted\n");
1198 			goto rename_done;
1199 		}
1200 
1201 		if (is_dir) {
1202 			res = fat_dir_empty(new_inode);
1203 			if (res)
1204 				goto rename_done;
1205 		}
1206 		fat_detach(new_inode);
1207 	} else {
1208 		res = vfat_add_entry(new_dir,&new_dentry->d_name,is_dir,&sinfo,
1209 					&new_bh,&new_de);
1210 		if (res < 0) goto rename_done;
1211 	}
1212 
1213 	new_dir->i_version = ++event;
1214 
1215 	/* releases old_bh */
1216 	vfat_remove_entry(old_dir,&old_sinfo,old_bh,old_de);
1217 	old_bh=NULL;
1218 	fat_detach(old_inode);
1219 	fat_attach(old_inode, sinfo.i_pos);
1220 	mark_inode_dirty(old_inode);
1221 
1222 	old_dir->i_version = ++event;
1223 	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
1224 	mark_inode_dirty(old_dir);
1225 	if (new_inode) {
1226 		new_inode->i_nlink--;
1227 		new_inode->i_ctime=CURRENT_TIME;
1228 	}
1229 
1230 	if (is_dir) {
1231 		int start = MSDOS_I(new_dir)->i_logstart;
1232 		dotdot_de->start = CT_LE_W(start);
1233 		dotdot_de->starthi = CT_LE_W(start>>16);
1234 		fat_mark_buffer_dirty(sb, dotdot_bh);
1235 		old_dir->i_nlink--;
1236 		if (new_inode) {
1237 			new_inode->i_nlink--;
1238 		} else {
1239 			new_dir->i_nlink++;
1240 			mark_inode_dirty(new_dir);
1241 		}
1242 	}
1243 
1244 rename_done:
1245 	fat_brelse(sb, dotdot_bh);
1246 	fat_brelse(sb, old_bh);
1247 	fat_brelse(sb, new_bh);
1248 	return res;
1249 
1250 }
1251 
1252 
1253 /* Public inode operations for the VFAT fs */
1254 struct inode_operations vfat_dir_inode_operations = {
1255 	create:		vfat_create,
1256 	lookup:		vfat_lookup,
1257 	unlink:		vfat_unlink,
1258 	mkdir:		vfat_mkdir,
1259 	rmdir:		vfat_rmdir,
1260 	rename:		vfat_rename,
1261 	setattr:	fat_notify_change,
1262 };
1263 
vfat_read_super(struct super_block * sb,void * data,int silent)1264 struct super_block *vfat_read_super(struct super_block *sb,void *data,
1265 				    int silent)
1266 {
1267 	struct super_block *res;
1268 
1269 	MSDOS_SB(sb)->options.isvfat = 1;
1270 
1271 	res = fat_read_super(sb, data, silent, &vfat_dir_inode_operations);
1272 	if (res == NULL)
1273 		return NULL;
1274 
1275 	if (parse_options((char *) data, &(MSDOS_SB(sb)->options))) {
1276 		MSDOS_SB(sb)->options.dotsOK = 0;
1277 		if (MSDOS_SB(sb)->options.posixfs) {
1278 			MSDOS_SB(sb)->options.name_check = 's';
1279 		}
1280 		if (MSDOS_SB(sb)->options.name_check != 's') {
1281 			sb->s_root->d_op = &vfat_dentry_ops[0];
1282 		} else {
1283 			sb->s_root->d_op = &vfat_dentry_ops[2];
1284 		}
1285 	}
1286 
1287 	return res;
1288 }
1289