Merge with Linux 2.4.0-test5-pre6.
[linux-2.6/linux-mips.git] / fs / vfat / namei.c
blob3895b0774778ec49a9537ff3eb1538989d583b4e
1 /*
2 * linux/fs/vfat/namei.c
4 * Written 1992,1993 by Werner Almesberger
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.
12 * Short name translation 1999 by Wolfram Pienkoss <wp@bsz.shk.th.schule.de>
15 #define __NO_VERSION__
16 #include <linux/module.h>
18 #include <linux/sched.h>
19 #include <linux/msdos_fs.h>
20 #include <linux/nls.h>
21 #include <linux/kernel.h>
22 #include <linux/errno.h>
23 #include <linux/string.h>
24 #include <linux/ctype.h>
25 #include <linux/stat.h>
26 #include <linux/mm.h>
27 #include <linux/malloc.h>
29 #include "../fat/msbuffer.h"
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
48 #ifndef DEBUG
49 # define CHECK_STACK
50 #else
51 # define CHECK_STACK check_stack(__FILE__, __LINE__)
52 #endif
54 static int vfat_hashi(struct dentry *parent, struct qstr *qstr);
55 static int vfat_hash(struct dentry *parent, struct qstr *qstr);
56 static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);
57 static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b);
58 static int vfat_revalidate(struct dentry *dentry, int);
60 static struct dentry_operations vfat_dentry_ops[4] = {
62 d_hash: vfat_hashi,
63 d_compare: vfat_cmpi,
66 d_revalidate: vfat_revalidate,
67 d_hash: vfat_hashi,
68 d_compare: vfat_cmpi,
71 d_hash: vfat_hash,
72 d_compare: vfat_cmp,
75 d_revalidate: vfat_revalidate,
76 d_hash: vfat_hash,
77 d_compare: vfat_cmp,
81 static int vfat_revalidate(struct dentry *dentry, int flags)
83 PRINTK1(("vfat_revalidate: %s\n", dentry->d_name.name));
84 spin_lock(&dcache_lock);
85 if (dentry->d_time == dentry->d_parent->d_inode->i_version) {
86 spin_unlock(&dcache_lock);
87 return 1;
89 spin_unlock(&dcache_lock);
90 return 0;
93 static int simple_getbool(char *s, int *setval)
95 if (s) {
96 if (!strcmp(s,"1") || !strcmp(s,"yes") || !strcmp(s,"true")) {
97 *setval = 1;
98 } else if (!strcmp(s,"0") || !strcmp(s,"no") || !strcmp(s,"false")) {
99 *setval = 0;
100 } else {
101 return 0;
103 } else {
104 *setval = 1;
106 return 1;
109 static int parse_options(char *options, struct fat_mount_options *opts)
111 char *this_char,*value,save,*savep;
112 int ret, val;
114 opts->unicode_xlate = opts->posixfs = 0;
115 opts->numtail = 1;
116 opts->utf8 = 0;
118 if (!options) return 1;
119 save = 0;
120 savep = NULL;
121 ret = 1;
122 for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
123 if ((value = strchr(this_char,'=')) != NULL) {
124 save = *value;
125 savep = value;
126 *value++ = 0;
128 if (!strcmp(this_char,"utf8")) {
129 ret = simple_getbool(value, &val);
130 if (ret) opts->utf8 = val;
131 } else if (!strcmp(this_char,"uni_xlate")) {
132 ret = simple_getbool(value, &val);
133 if (ret) opts->unicode_xlate = val;
134 } else if (!strcmp(this_char,"posix")) {
135 ret = simple_getbool(value, &val);
136 if (ret) opts->posixfs = val;
137 } else if (!strcmp(this_char,"nonumtail")) {
138 ret = simple_getbool(value, &val);
139 if (ret) {
140 opts->numtail = !val;
143 if (this_char != options)
144 *(this_char-1) = ',';
145 if (value) {
146 *savep = save;
148 if (ret == 0) {
149 return 0;
152 if (opts->unicode_xlate) {
153 opts->utf8 = 0;
155 return 1;
158 static inline unsigned char
159 vfat_getlower(struct nls_table *t, unsigned char c)
161 return t->charset2lower[c];
164 static inline unsigned char
165 vfat_tolower(struct nls_table *t, unsigned char c)
167 unsigned char nc = t->charset2lower[c];
169 return nc ? nc : c;
172 static inline unsigned char
173 vfat_getupper(struct nls_table *t, unsigned char c)
175 return t->charset2upper[c];
178 static inline unsigned char
179 vfat_toupper(struct nls_table *t, unsigned char c)
181 unsigned char nc = t->charset2upper[c];
183 return nc ? nc : c;
186 static int
187 vfat_strnicmp(struct nls_table *t, const unsigned char *s1,
188 const unsigned char *s2, int len)
190 while(len--)
191 if (vfat_tolower(t, *s1++) != vfat_tolower(t, *s2++))
192 return 1;
194 return 0;
197 static inline int
198 vfat_uni2short(struct nls_table *t, wchar_t uc, unsigned char *op, int bound)
200 int charlen;
202 if ( (charlen = t->uni2char(uc, op, bound)) < 0)
203 charlen = 0;
205 return charlen;
208 static inline int
209 vfat_uni2upper_short(struct nls_table *t, wchar_t uc, char *op, int bound)
211 int chi, chl;
213 if ( (chl = t->uni2char(uc, op, bound)) < 0)
214 chl = 0;
216 for (chi = 0; chi < chl; chi++)
217 op[chi] = vfat_toupper(t, op[chi]);
219 return chl;
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.
228 static int vfat_hash(struct dentry *dentry, struct qstr *qstr)
230 const char *name;
231 int len;
233 len = qstr->len;
234 name = qstr->name;
235 while (len && name[len-1] == '.')
236 len--;
238 qstr->hash = full_name_hash(name, len);
240 return 0;
244 * Compute the hash for the vfat name corresponding to the dentry.
245 * Note: if the name is invalid, we leave the hash code unchanged so
246 * that the existing dentry can be used. The vfat fs routines will
247 * return ENOENT or EINVAL as appropriate.
249 static int vfat_hashi(struct dentry *dentry, struct qstr *qstr)
251 struct nls_table *t = MSDOS_SB(dentry->d_inode->i_sb)->nls_io;
252 const char *name;
253 int len;
254 unsigned long hash;
256 len = qstr->len;
257 name = qstr->name;
258 while (len && name[len-1] == '.')
259 len--;
261 hash = init_name_hash();
262 while (len--)
263 hash = partial_name_hash(vfat_tolower(t, *name++), hash);
264 qstr->hash = end_name_hash(hash);
266 return 0;
270 * Case insensitive compare of two vfat names.
272 static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b)
274 struct nls_table *t = MSDOS_SB(dentry->d_inode->i_sb)->nls_io;
275 int alen, blen;
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 (vfat_strnicmp(t, a->name, b->name, alen) == 0)
286 return 0;
288 return 1;
292 * Case sensitive compare of two vfat names.
294 static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b)
296 int alen, blen;
298 /* A filename cannot end in '.' or we treat it like it has none */
299 alen = a->len;
300 blen = b->len;
301 while (alen && a->name[alen-1] == '.')
302 alen--;
303 while (blen && b->name[blen-1] == '.')
304 blen--;
305 if (alen == blen) {
306 if (strncmp(a->name, b->name, alen) == 0)
307 return 0;
309 return 1;
312 #ifdef DEBUG
314 static void
315 check_stack(const char *fname, int lineno)
317 int stack_level;
318 char *pg_dir;
320 stack_level = (long)(&pg_dir)-current->kernel_stack_page;
321 if (stack_level < 0)
322 printk("*-*-*-* vfat kstack overflow in %s line %d: SL=%d\n",
323 fname, lineno, stack_level);
324 else if (stack_level < 500)
325 printk("*-*-*-* vfat kstack low in %s line %d: SL=%d\n",
326 fname, lineno, stack_level);
327 #if 0
328 else
329 printk("------- vfat kstack ok in %s line %d: SL=%d\n",
330 fname, lineno, stack_level);
331 #endif
332 #if 0
333 if (*(unsigned long *) current->kernel_stack_page != STACK_MAGIC) {
334 printk("******* vfat stack corruption detected in %s at line %d\n",
335 fname, lineno);
337 #endif
340 static int debug = 0;
341 static void dump_fat(struct super_block *sb,int start)
343 printk("[");
344 while (start) {
345 printk("%d ",start);
346 start = fat_access(sb,start,-1);
347 if (!start) {
348 printk("ERROR");
349 break;
351 if (start == -1) break;
353 printk("]\n");
356 static void dump_de(struct msdos_dir_entry *de)
358 int i;
359 unsigned char *p = (unsigned char *) de;
360 printk("[");
362 for (i = 0; i < 32; i++, p++) {
363 printk("%02x ", *p);
365 printk("]\n");
368 #endif
370 /* MS-DOS "device special files" */
372 static const char *reserved3_names[] = {
373 "con ", "prn ", "nul ", "aux ", NULL
376 static const char *reserved4_names[] = {
377 "com1 ", "com2 ", "com3 ", "com4 ", "com5 ",
378 "com6 ", "com7 ", "com8 ", "com9 ",
379 "lpt1 ", "lpt2 ", "lpt3 ", "lpt4 ", "lpt5 ",
380 "lpt6 ", "lpt7 ", "lpt8 ", "lpt9 ",
381 NULL };
384 /* Characters that are undesirable in an MS-DOS file name */
386 static char bad_chars[] = "*?<>|\":/\\";
387 static char replace_chars[] = "[];,+=";
389 /* Checks the validity of a long MS-DOS filename */
390 /* Returns negative number on error, 0 for a normal
391 * return, and 1 for . or .. */
393 static int vfat_valid_longname(const char *name, int len, int xlate)
395 const char **reserved, *walk;
396 unsigned char c;
397 int i, baselen;
399 if (len && name[len-1] == ' ') return -EINVAL;
400 if (len >= 256) return -EINVAL;
401 for (i = 0; i < len; i++) {
402 c = name[i];
403 if (xlate && c == ':') continue;
404 if (strchr(bad_chars,c)) {
405 return -EINVAL;
408 if (len < 3) return 0;
410 for (walk = name; *walk != 0 && *walk != '.'; walk++);
411 baselen = walk - name;
413 if (baselen == 3) {
414 for (reserved = reserved3_names; *reserved; reserved++) {
415 if (!strnicmp(name,*reserved,baselen))
416 return -EINVAL;
418 } else if (baselen == 4) {
419 for (reserved = reserved4_names; *reserved; reserved++) {
420 if (!strnicmp(name,*reserved,baselen))
421 return -EINVAL;
424 return 0;
427 static int vfat_valid_shortname(struct nls_table *nls, wchar_t *name, int len)
429 wchar_t *walk;
430 unsigned char c, charbuf[NLS_MAX_CHARSET_SIZE];
431 int chl, chi;
432 int space;
434 if (vfat_uni2upper_short(nls, *name, charbuf, NLS_MAX_CHARSET_SIZE) == 0)
435 return -EINVAL;
437 if (IS_FREE(charbuf))
438 return -EINVAL;
440 chl = 0;
441 c = 0;
442 space = 1; /* disallow names starting with a dot */
443 for (walk = name; len && walk-name < 8;) {
444 len--;
445 if ( (chl = nls->uni2char(*walk, charbuf, NLS_MAX_CHARSET_SIZE)) < 0) {
446 walk++;
447 return -EINVAL;
450 for (chi = 0; chi < chl; chi++) {
451 c = vfat_getupper(nls, charbuf[chi]);
452 if (!c) return -EINVAL;
453 if (charbuf[chi] != vfat_tolower(nls, c)) return -EINVAL;
454 if (strchr(replace_chars,c)) return -EINVAL;
455 if (c < ' '|| c==':') return -EINVAL;
456 if (c == '.') goto dot;
457 space = c == ' ';
460 dot:;
461 if (space) return -EINVAL;
462 if (len && c != '.') {
463 len--;
464 if (vfat_uni2upper_short(nls, *walk++, charbuf, NLS_MAX_CHARSET_SIZE) == 1) {
465 if (charbuf[0] != '.') return -EINVAL;
466 } else
467 return -EINVAL;
468 c = '.';
470 if (c == '.') {
471 if (len >= 4) return -EINVAL;
472 while (len > 0) {
473 len--;
474 chl = vfat_uni2short(nls, *walk++, charbuf, NLS_MAX_CHARSET_SIZE);
475 if (chl < 0)
476 return -EINVAL;
477 for (chi = 0; chi < chl; chi++) {
478 c = vfat_getupper(nls, charbuf[chi]);
479 if (!c) return -EINVAL;
480 if (charbuf[chi] != vfat_tolower(nls, c)) return -EINVAL;
481 if (strchr(replace_chars,c))
482 return -EINVAL;
483 if (c < ' ' || c == '.'|| c==':')
484 return -EINVAL;
485 space = c == ' ';
488 if (space) return -EINVAL;
491 return 0;
494 static int vfat_find_form(struct inode *dir,char *name)
496 struct msdos_dir_entry *de;
497 struct buffer_head *bh = NULL;
498 int ino,res;
500 res=fat_scan(dir,name,&bh,&de,&ino);
501 fat_brelse(dir->i_sb, bh);
502 if (res<0)
503 return -ENOENT;
504 return 0;
507 static int vfat_format_name(struct nls_table *nls, wchar_t *name,
508 int len, char *res)
510 char *walk;
511 unsigned char charbuf[NLS_MAX_CHARSET_SIZE];
512 int chi, chl;
513 int space;
515 if (vfat_uni2upper_short(nls, *name, charbuf, NLS_MAX_CHARSET_SIZE) == 0)
516 return -EINVAL;
518 if (IS_FREE(charbuf))
519 return -EINVAL;
521 space = 1; /* disallow names starting with a dot */
522 for (walk = res; len--; ) {
523 chl = vfat_uni2upper_short(nls, *name++, charbuf, NLS_MAX_CHARSET_SIZE);
524 if (chl == 0)
525 return -EINVAL;
526 for (chi = 0; chi < chl; chi++){
527 if (charbuf[chi] == '.') goto dot;
528 if (!charbuf[chi]) return -EINVAL;
529 if (walk-res == 8) return -EINVAL;
530 if (strchr(replace_chars,charbuf[chi])) return -EINVAL;
531 if (charbuf[chi] < ' '|| charbuf[chi]==':') return -EINVAL;
532 space = charbuf[chi] == ' ';
533 *walk = charbuf[chi];
534 walk++;
537 dot:;
538 if (space) return -EINVAL;
539 if (len >= 0) {
540 while (walk-res < 8) *walk++ = ' ';
541 while (len > 0 && walk-res < MSDOS_NAME) {
542 chl = vfat_uni2upper_short(nls, *name++, charbuf, NLS_MAX_CHARSET_SIZE);
543 if (len < chl)
544 chl = len;
545 len -= chl;
546 for (chi = 0; chi < chl; chi++){
547 if (!charbuf[chi]) return -EINVAL;
548 if (strchr(replace_chars,charbuf[chi]))
549 return -EINVAL;
550 if (charbuf[chi] < ' ' || charbuf[chi] == '.'|| charbuf[chi]==':')
551 return -EINVAL;
552 space = charbuf[chi] == ' ';
553 *walk++ = charbuf[chi];
556 if (space) return -EINVAL;
557 if (len) return -EINVAL;
559 while (walk-res < MSDOS_NAME) *walk++ = ' ';
561 return 0;
564 static char skip_chars[] = ".:\"?<>| ";
566 /* Given a valid longname, create a unique shortname. Make sure the
567 * shortname does not exist
569 static int vfat_create_shortname(struct inode *dir, struct nls_table *nls,
570 wchar_t *name, int len,
571 char *name_res)
573 wchar_t *ip, *op, *ext_start, *end, *name_start;
574 wchar_t msdos_name[13];
575 char base[9], ext[4], buf[8], *p;
576 unsigned char charbuf[NLS_MAX_CHARSET_SIZE];
577 int chl, chi;
578 int sz, extlen, baselen, i;
580 PRINTK2(("Entering vfat_create_shortname\n"));
581 chl = 0;
582 sz = 0; /* Make compiler happy */
583 if (len <= 12) {
584 /* Do a case insensitive search if the name would be a valid
585 * shortname if is were all capitalized. However, do not
586 * allow spaces in short names because Win95 scandisk does
587 * not like that */
588 for (i = 0, op = &msdos_name[0], ip = name; ; i++, ip++, op++) {
589 if (i == len) {
590 if (vfat_format_name(nls, &msdos_name[0], len,
591 name_res) < 0)
592 break;
593 PRINTK3(("vfat_create_shortname 1\n"));
594 if (vfat_find_form(dir, name_res) < 0)
595 return 0;
596 return -EEXIST;
598 chl = vfat_uni2upper_short(nls, *ip, charbuf, NLS_MAX_CHARSET_SIZE);
599 for (chi = 0; chi < chl; chi++){
600 if (charbuf[chi] == ' ')
601 break;
603 if (chi < chl)
604 break;
606 *op = *ip;
610 PRINTK3(("vfat_create_shortname 3\n"));
611 /* Now, we need to create a shortname from the long name */
612 ext_start = end = &name[len];
613 while (--ext_start >= name) {
614 chl = vfat_uni2upper_short(nls, *ext_start, charbuf, NLS_MAX_CHARSET_SIZE);
615 for (chi = 0; chi < chl; chi++) {
616 if (charbuf[chi] == '.') {
617 if (ext_start == end - 1) {
618 sz = len;
619 ext_start = NULL;
621 break;
624 if (charbuf[chi] == '.')
625 break;
627 if (ext_start == name - 1) {
628 sz = len;
629 ext_start = NULL;
630 } else if (ext_start) {
632 * Names which start with a dot could be just
633 * an extension eg. "...test". In this case Win95
634 * uses the extension as the name and sets no extension.
636 name_start = &name[0];
637 while (name_start < ext_start)
639 chl = vfat_uni2upper_short(nls, *name_start, charbuf, NLS_MAX_CHARSET_SIZE);
640 if (chl == 0)
641 break;
642 for (chi = 0; chi < chl; chi++)
643 if (!strchr(skip_chars, charbuf[chi]))
644 break;
645 name_start++;
647 if (name_start != ext_start) {
648 sz = ext_start - name;
649 ext_start++;
650 } else {
651 sz = len;
652 ext_start=NULL;
656 for (baselen = i = 0, p = base, ip = name; i < sz && baselen < 8; i++, ip++)
658 chl = vfat_uni2upper_short(nls, *ip, charbuf, NLS_MAX_CHARSET_SIZE);
659 if (chl == 0){
660 *p++ = '_';
661 baselen++;
662 continue;
665 for (chi = 0; chi < chl; chi++){
666 if (!strchr(skip_chars, charbuf[chi])){
667 if (strchr(replace_chars, charbuf[chi]))
668 *p = '_';
669 else
670 *p = charbuf[chi];
671 p++; baselen++;
675 if (baselen == 0) {
676 return -EINVAL;
679 extlen = 0;
680 if (ext_start) {
681 for (p = ext, ip = ext_start; extlen < 3 && ip < end; ip++) {
682 chl = vfat_uni2upper_short(nls, *ip, charbuf, NLS_MAX_CHARSET_SIZE);
683 if (chl == 0) {
684 *p++ = '_';
685 extlen++;
686 continue;
689 for (chi = 0; chi < chl; chi++) {
690 if (!strchr(skip_chars, charbuf[chi])) {
691 if (strchr(replace_chars, charbuf[chi]))
692 *p = '_';
693 else
694 *p = charbuf[chi];
695 p++; extlen++;
700 ext[extlen] = '\0';
701 base[baselen] = '\0';
703 /* Yes, it can happen. ".\xe5" would do it. */
704 if (IS_FREE(base))
705 base[0]='_';
707 /* OK, at this point we know that base is not longer than 8 symbols,
708 * ext is not longer than 3, base is nonempty, both don't contain
709 * any bad symbols (lowercase transformed to uppercase).
712 memset(name_res, ' ', MSDOS_NAME);
713 memcpy(name_res,base,baselen);
714 memcpy(name_res+8,ext,extlen);
715 if (MSDOS_SB(dir->i_sb)->options.numtail == 0)
716 if (vfat_find_form(dir, name_res) < 0)
717 return 0;
720 * Try to find a unique extension. This used to
721 * iterate through all possibilities sequentially,
722 * but that gave extremely bad performance. Windows
723 * only tries a few cases before using random
724 * values for part of the base.
727 if (baselen>6)
728 baselen = 6;
729 name_res[baselen] = '~';
730 for (i = 1; i < 10; i++) {
731 name_res[baselen+1] = i + '0';
732 if (vfat_find_form(dir, name_res) < 0)
733 return 0;
736 i = jiffies & 0xffff;
737 sz = (jiffies >> 16) & 0x7;
738 if (baselen>2)
739 baselen = 2;
740 name_res[baselen+4] = '~';
741 name_res[baselen+5] = '1' + sz;
742 while (1) {
743 sprintf(buf, "%04X", i);
744 memcpy(&name_res[baselen], buf, 4);
745 if (vfat_find_form(dir, name_res) < 0)
746 break;
747 i -= 11;
749 return 0;
752 /* Translate a string, including coded sequences into Unicode */
753 static int
754 xlate_to_uni(const char *name, int len, char *outname, int *longlen, int *outlen,
755 int escape, int utf8, struct nls_table *nls)
757 const unsigned char *ip;
758 unsigned char nc;
759 char *op;
760 unsigned int ec;
761 int i, k, fill;
762 int charlen;
764 if (utf8) {
765 *outlen = utf8_mbstowcs((__u16 *) outname, name, PAGE_SIZE);
766 if (name[len-1] == '.')
767 *outlen-=2;
768 op = &outname[*outlen * sizeof(__u16)];
769 } else {
770 if (name[len-1] == '.')
771 len--;
772 if (nls) {
773 for (i = 0, ip = name, op = outname, *outlen = 0;
774 i < len && *outlen <= 260; *outlen += 1)
776 if (escape && (*ip == ':')) {
777 if (i > len - 5)
778 return -EINVAL;
779 ec = 0;
780 for (k = 1; k < 5; k++) {
781 nc = ip[k];
782 ec <<= 4;
783 if (nc >= '0' && nc <= '9') {
784 ec |= nc - '0';
785 continue;
787 if (nc >= 'a' && nc <= 'f') {
788 ec |= nc - ('a' - 10);
789 continue;
791 if (nc >= 'A' && nc <= 'F') {
792 ec |= nc - ('A' - 10);
793 continue;
795 return -EINVAL;
797 *op++ = ec & 0xFF;
798 *op++ = ec >> 8;
799 ip += 5;
800 i += 5;
801 } else {
802 if ((charlen = nls->char2uni(ip, len-i, (wchar_t *)op)) < 0)
803 return -EINVAL;
805 ip += charlen;
806 i += charlen;
807 op += 2;
810 } else {
811 for (i = 0, ip = name, op = outname, *outlen = 0;
812 i < len && *outlen <= 260; i++, *outlen += 1)
814 *op++ = *ip++;
815 *op++ = 0;
819 if (*outlen > 260)
820 return -ENAMETOOLONG;
822 *longlen = *outlen;
823 if (*outlen % 13) {
824 *op++ = 0;
825 *op++ = 0;
826 *outlen += 1;
827 if (*outlen % 13) {
828 fill = 13 - (*outlen % 13);
829 for (i = 0; i < fill; i++) {
830 *op++ = 0xff;
831 *op++ = 0xff;
833 *outlen += fill;
837 return 0;
840 static int
841 vfat_fill_slots(struct inode *dir, struct msdos_dir_slot *ds, const char *name,
842 int len, int *slots, int uni_xlate)
844 struct nls_table *nls_io, *nls_disk;
845 wchar_t *uname;
846 struct msdos_dir_slot *ps;
847 struct msdos_dir_entry *de;
848 unsigned long page;
849 unsigned char cksum;
850 const char *ip;
851 char *uniname, msdos_name[MSDOS_NAME];
852 int res, utf8, slot, ulen, unilen, i;
853 loff_t offset;
855 de = (struct msdos_dir_entry *) ds;
856 utf8 = MSDOS_SB(dir->i_sb)->options.utf8;
857 nls_io = MSDOS_SB(dir->i_sb)->nls_io;
858 nls_disk = MSDOS_SB(dir->i_sb)->nls_disk;
860 if (name[len-1] == '.') len--;
861 if(!(page = __get_free_page(GFP_KERNEL)))
862 return -ENOMEM;
863 uniname = (char *) page;
865 res = xlate_to_uni(name, len, uniname, &ulen, &unilen, uni_xlate,
866 utf8, nls_io);
867 if (res < 0)
868 goto out_free;
870 uname = (wchar_t *) page;
871 if (vfat_valid_shortname(nls_disk, uname, ulen) >= 0) {
872 res = vfat_format_name(nls_disk, uname, ulen, de->name);
873 if (!res)
874 goto out_free;
877 res = vfat_create_shortname(dir, nls_disk, uname, ulen, msdos_name);
878 if (res)
879 goto out_free;
881 *slots = unilen / 13;
882 for (cksum = i = 0; i < 11; i++) {
883 cksum = (((cksum&1)<<7)|((cksum&0xfe)>>1)) + msdos_name[i];
885 PRINTK3(("vfat_fill_slots 3: slots=%d\n",*slots));
887 for (ps = ds, slot = *slots; slot > 0; slot--, ps++) {
888 ps->id = slot;
889 ps->attr = ATTR_EXT;
890 ps->reserved = 0;
891 ps->alias_checksum = cksum;
892 ps->start = 0;
893 offset = (slot - 1) * 26;
894 ip = &uniname[offset];
895 memcpy(ps->name0_4, ip, 10);
896 memcpy(ps->name5_10, ip+10, 12);
897 memcpy(ps->name11_12, ip+22, 4);
899 ds[0].id |= 0x40;
901 de = (struct msdos_dir_entry *) ps;
902 PRINTK3(("vfat_fill_slots 9\n"));
903 strncpy(de->name, msdos_name, MSDOS_NAME);
904 (*slots)++;
906 out_free:
907 free_page(page);
908 return res;
911 /* We can't get "." or ".." here - VFS takes care of those cases */
913 static int vfat_build_slots(struct inode *dir,const char *name,int len,
914 struct msdos_dir_slot *ds, int *slots)
916 int res, xlate;
918 xlate = MSDOS_SB(dir->i_sb)->options.unicode_xlate;
919 *slots = 1;
920 res = vfat_valid_longname(name, len, xlate);
921 if (res < 0)
922 return res;
923 return vfat_fill_slots(dir, ds, name, len, slots, xlate);
926 static int vfat_add_entry(struct inode *dir,struct qstr* qname,
927 int is_dir,struct vfat_slot_info *sinfo_out,
928 struct buffer_head **bh, struct msdos_dir_entry **de)
930 struct super_block *sb = dir->i_sb;
931 struct msdos_dir_slot *ps;
932 loff_t offset;
933 struct msdos_dir_slot *ds;
934 int slots, slot;
935 int res;
936 struct msdos_dir_entry *de1;
937 struct buffer_head *bh1;
938 int ino;
939 int len;
940 loff_t dummy;
942 ds = (struct msdos_dir_slot *)
943 kmalloc(sizeof(struct msdos_dir_slot)*MSDOS_SLOTS, GFP_KERNEL);
944 if (ds == NULL) return -ENOMEM;
946 len = qname->len;
947 while (len && qname->name[len-1] == '.')
948 len--;
949 res = fat_search_long(dir, qname->name, len,
950 (MSDOS_SB(sb)->options.name_check != 's') ||
951 !MSDOS_SB(sb)->options.posixfs,
952 &dummy, &dummy);
953 if (res > 0) /* found */
954 res = -EEXIST;
955 if (res)
956 goto cleanup;
958 res = vfat_build_slots(dir, qname->name, len, ds, &slots);
959 if (res < 0) goto cleanup;
961 offset = fat_add_entries(dir, slots, &bh1, &de1, &ino);
962 if (offset < 0) {
963 res = offset;
964 goto cleanup;
966 fat_brelse(sb, bh1);
968 /* Now create the new entry */
969 *bh = NULL;
970 for (slot = 0, ps = ds; slot < slots; slot++, ps++) {
971 if (fat_get_entry(dir,&offset,bh,de, &sinfo_out->ino) < 0) {
972 res = -EIO;
973 goto cleanup;
975 memcpy(*de, ps, sizeof(struct msdos_dir_slot));
976 fat_mark_buffer_dirty(sb, *bh, 1);
979 dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;
980 mark_inode_dirty(dir);
982 fat_date_unix2dos(dir->i_mtime,&(*de)->time,&(*de)->date);
983 (*de)->ctime_ms = 0;
984 (*de)->ctime = (*de)->time;
985 (*de)->adate = (*de)->cdate = (*de)->date;
986 (*de)->start = 0;
987 (*de)->starthi = 0;
988 (*de)->size = 0;
989 (*de)->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
990 (*de)->lcase = CASE_LOWER_BASE | CASE_LOWER_EXT;
993 fat_mark_buffer_dirty(sb, *bh, 1);
995 /* slots can't be less than 1 */
996 sinfo_out->long_slots = slots - 1;
997 sinfo_out->longname_offset = offset - sizeof(struct msdos_dir_slot) * slots;
998 res = 0;
1000 cleanup:
1001 kfree(ds);
1002 return res;
1005 static int vfat_find(struct inode *dir,struct qstr* qname,
1006 struct vfat_slot_info *sinfo, struct buffer_head **last_bh,
1007 struct msdos_dir_entry **last_de)
1009 struct super_block *sb = dir->i_sb;
1010 loff_t offset;
1011 int res,len;
1013 len = qname->len;
1014 while (len && qname->name[len-1] == '.')
1015 len--;
1016 res = fat_search_long(dir, qname->name, len,
1017 (MSDOS_SB(sb)->options.name_check != 's'),
1018 &offset,&sinfo->longname_offset);
1019 if (res>0) {
1020 sinfo->long_slots = res-1;
1021 if (fat_get_entry(dir,&offset,last_bh,last_de,&sinfo->ino)>=0)
1022 return 0;
1023 res = -EIO;
1025 return res ? res : -ENOENT;
1028 struct dentry *vfat_lookup(struct inode *dir,struct dentry *dentry)
1030 int res;
1031 struct vfat_slot_info sinfo;
1032 struct inode *inode;
1033 struct dentry *alias;
1034 struct buffer_head *bh = NULL;
1035 struct msdos_dir_entry *de;
1036 int table;
1038 PRINTK2(("vfat_lookup: name=%s, len=%d\n",
1039 dentry->d_name.name, dentry->d_name.len));
1041 table = (MSDOS_SB(dir->i_sb)->options.name_check == 's') ? 2 : 0;
1042 dentry->d_op = &vfat_dentry_ops[table];
1044 inode = NULL;
1045 res = vfat_find(dir,&dentry->d_name,&sinfo,&bh,&de);
1046 if (res < 0) {
1047 table++;
1048 goto error;
1050 inode = fat_build_inode(dir->i_sb, de, sinfo.ino, &res);
1051 fat_brelse(dir->i_sb, bh);
1052 if (res)
1053 return ERR_PTR(res);
1054 alias = d_find_alias(inode);
1055 if (alias) {
1056 if (d_invalidate(alias)==0)
1057 dput(alias);
1058 else {
1059 iput(inode);
1060 return alias;
1064 error:
1065 dentry->d_op = &vfat_dentry_ops[table];
1066 dentry->d_time = dentry->d_parent->d_inode->i_version;
1067 d_add(dentry,inode);
1068 return NULL;
1071 int vfat_create(struct inode *dir,struct dentry* dentry,int mode)
1073 struct super_block *sb = dir->i_sb;
1074 struct inode *inode = NULL;
1075 struct buffer_head *bh = NULL;
1076 struct msdos_dir_entry *de;
1077 struct vfat_slot_info sinfo;
1078 int res;
1080 res = vfat_add_entry(dir, &dentry->d_name, 0, &sinfo, &bh, &de);
1081 if (res < 0)
1082 return res;
1083 inode = fat_build_inode(sb, de, sinfo.ino, &res);
1084 fat_brelse(sb, bh);
1085 if (!inode)
1086 return res;
1087 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
1088 mark_inode_dirty(inode);
1089 inode->i_version = ++event;
1090 dir->i_version = event;
1091 dentry->d_time = dentry->d_parent->d_inode->i_version;
1092 d_instantiate(dentry,inode);
1093 return 0;
1096 static void vfat_remove_entry(struct inode *dir,struct vfat_slot_info *sinfo,
1097 struct buffer_head *bh, struct msdos_dir_entry *de)
1099 struct super_block *sb = dir->i_sb;
1100 loff_t offset;
1101 int i,ino;
1103 /* remove the shortname */
1104 dir->i_mtime = CURRENT_TIME;
1105 dir->i_atime = CURRENT_TIME;
1106 dir->i_version = ++event;
1107 mark_inode_dirty(dir);
1108 de->name[0] = DELETED_FLAG;
1109 fat_mark_buffer_dirty(sb, bh, 1);
1110 /* remove the longname */
1111 offset = sinfo->longname_offset; de = NULL;
1112 for (i = sinfo->long_slots; i > 0; --i) {
1113 if (fat_get_entry(dir, &offset, &bh, &de, &ino) < 0)
1114 continue;
1115 de->name[0] = DELETED_FLAG;
1116 de->attr = 0;
1117 fat_mark_buffer_dirty(sb, bh, 1);
1119 if (bh) fat_brelse(sb, bh);
1122 int vfat_rmdir(struct inode *dir,struct dentry* dentry)
1124 int res;
1125 struct vfat_slot_info sinfo;
1126 struct buffer_head *bh = NULL;
1127 struct msdos_dir_entry *de;
1129 res = fat_dir_empty(dentry->d_inode);
1130 if (res)
1131 return res;
1133 res = vfat_find(dir,&dentry->d_name,&sinfo, &bh, &de);
1134 if (res<0)
1135 return res;
1136 dentry->d_inode->i_nlink = 0;
1137 dentry->d_inode->i_mtime = CURRENT_TIME;
1138 dentry->d_inode->i_atime = CURRENT_TIME;
1139 fat_detach(dentry->d_inode);
1140 mark_inode_dirty(dentry->d_inode);
1141 /* releases bh */
1142 vfat_remove_entry(dir,&sinfo,bh,de);
1143 dir->i_nlink--;
1144 return 0;
1147 int vfat_unlink(struct inode *dir, struct dentry* dentry)
1149 int res;
1150 struct vfat_slot_info sinfo;
1151 struct buffer_head *bh = NULL;
1152 struct msdos_dir_entry *de;
1154 PRINTK1(("vfat_unlink: %s\n", dentry->d_name.name));
1155 res = vfat_find(dir,&dentry->d_name,&sinfo,&bh,&de);
1156 if (res < 0)
1157 return res;
1158 dentry->d_inode->i_nlink = 0;
1159 dentry->d_inode->i_mtime = CURRENT_TIME;
1160 dentry->d_inode->i_atime = CURRENT_TIME;
1161 fat_detach(dentry->d_inode);
1162 mark_inode_dirty(dentry->d_inode);
1163 /* releases bh */
1164 vfat_remove_entry(dir,&sinfo,bh,de);
1166 return res;
1170 int vfat_mkdir(struct inode *dir,struct dentry* dentry,int mode)
1172 struct super_block *sb = dir->i_sb;
1173 struct inode *inode = NULL;
1174 struct vfat_slot_info sinfo;
1175 struct buffer_head *bh = NULL;
1176 struct msdos_dir_entry *de;
1177 int res;
1179 res = vfat_add_entry(dir, &dentry->d_name, 1, &sinfo, &bh, &de);
1180 if (res < 0)
1181 return res;
1182 inode = fat_build_inode(sb, de, sinfo.ino, &res);
1183 if (!inode)
1184 goto out;
1185 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
1186 mark_inode_dirty(inode);
1187 inode->i_version = ++event;
1188 dir->i_version = event;
1189 dir->i_nlink++;
1190 inode->i_nlink = 2; /* no need to mark them dirty */
1191 res = fat_new_dir(inode, dir, 1);
1192 if (res < 0)
1193 goto mkdir_failed;
1194 dentry->d_time = dentry->d_parent->d_inode->i_version;
1195 d_instantiate(dentry,inode);
1196 out:
1197 fat_brelse(sb, bh);
1198 return res;
1200 mkdir_failed:
1201 inode->i_nlink = 0;
1202 inode->i_mtime = CURRENT_TIME;
1203 inode->i_atime = CURRENT_TIME;
1204 fat_detach(inode);
1205 mark_inode_dirty(inode);
1206 /* releases bh */
1207 vfat_remove_entry(dir,&sinfo,bh,de);
1208 iput(inode);
1209 dir->i_nlink--;
1210 return res;
1213 int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
1214 struct inode *new_dir,struct dentry *new_dentry)
1216 struct super_block *sb = old_dir->i_sb;
1217 struct buffer_head *old_bh,*new_bh,*dotdot_bh;
1218 struct msdos_dir_entry *old_de,*new_de,*dotdot_de;
1219 int dotdot_ino;
1220 struct inode *old_inode, *new_inode;
1221 int res, is_dir;
1222 struct vfat_slot_info old_sinfo,sinfo;
1224 old_bh = new_bh = dotdot_bh = NULL;
1225 old_inode = old_dentry->d_inode;
1226 new_inode = new_dentry->d_inode;
1227 res = vfat_find(old_dir,&old_dentry->d_name,&old_sinfo,&old_bh,&old_de);
1228 PRINTK3(("vfat_rename 2\n"));
1229 if (res < 0) goto rename_done;
1231 is_dir = S_ISDIR(old_inode->i_mode);
1233 if (is_dir && (res = fat_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh,
1234 &dotdot_de,&dotdot_ino)) < 0)
1235 goto rename_done;
1237 if (new_dentry->d_inode) {
1238 res = vfat_find(new_dir,&new_dentry->d_name,&sinfo,&new_bh,
1239 &new_de);
1240 if (res < 0 || MSDOS_I(new_inode)->i_location != sinfo.ino) {
1241 /* WTF??? Cry and fail. */
1242 printk(KERN_WARNING "vfat_rename: fs corrupted\n");
1243 goto rename_done;
1246 if (is_dir) {
1247 res = fat_dir_empty(new_inode);
1248 if (res)
1249 goto rename_done;
1251 fat_detach(new_inode);
1252 } else {
1253 res = vfat_add_entry(new_dir,&new_dentry->d_name,is_dir,&sinfo,
1254 &new_bh,&new_de);
1255 if (res < 0) goto rename_done;
1258 new_dir->i_version = ++event;
1260 /* releases old_bh */
1261 vfat_remove_entry(old_dir,&old_sinfo,old_bh,old_de);
1262 old_bh=NULL;
1263 fat_detach(old_inode);
1264 fat_attach(old_inode, sinfo.ino);
1265 mark_inode_dirty(old_inode);
1267 old_dir->i_version = ++event;
1268 old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
1269 mark_inode_dirty(old_dir);
1270 if (new_inode) {
1271 new_inode->i_nlink--;
1272 new_inode->i_ctime=CURRENT_TIME;
1275 if (is_dir) {
1276 int start = MSDOS_I(new_dir)->i_logstart;
1277 dotdot_de->start = CT_LE_W(start);
1278 dotdot_de->starthi = CT_LE_W(start>>16);
1279 fat_mark_buffer_dirty(sb, dotdot_bh, 1);
1280 old_dir->i_nlink--;
1281 if (new_inode) {
1282 new_inode->i_nlink--;
1283 } else {
1284 new_dir->i_nlink++;
1285 mark_inode_dirty(new_dir);
1289 rename_done:
1290 fat_brelse(sb, dotdot_bh);
1291 fat_brelse(sb, old_bh);
1292 fat_brelse(sb, new_bh);
1293 return res;
1298 /* Public inode operations for the VFAT fs */
1299 struct inode_operations vfat_dir_inode_operations = {
1300 create: vfat_create,
1301 lookup: vfat_lookup,
1302 unlink: vfat_unlink,
1303 mkdir: vfat_mkdir,
1304 rmdir: vfat_rmdir,
1305 rename: vfat_rename,
1306 setattr: fat_notify_change,
1309 struct super_block *vfat_read_super(struct super_block *sb,void *data,
1310 int silent)
1312 struct super_block *res;
1314 MSDOS_SB(sb)->options.isvfat = 1;
1316 res = fat_read_super(sb, data, silent, &vfat_dir_inode_operations);
1317 if (res == NULL)
1318 return NULL;
1320 if (parse_options((char *) data, &(MSDOS_SB(sb)->options))) {
1321 MSDOS_SB(sb)->options.dotsOK = 0;
1322 if (MSDOS_SB(sb)->options.posixfs) {
1323 MSDOS_SB(sb)->options.name_check = 's';
1325 if (MSDOS_SB(sb)->options.name_check != 's') {
1326 sb->s_root->d_op = &vfat_dentry_ops[0];
1327 } else {
1328 sb->s_root->d_op = &vfat_dentry_ops[2];
1332 return res;