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