import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / 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, 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
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
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
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
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
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
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  */
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  */
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  */
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  */
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
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
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
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
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
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
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
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
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  */
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
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
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
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
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
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
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
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
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
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
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
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  
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
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 }