File: /usr/src/linux/fs/vfat/namei.c

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