Merge with 2.3.99-pre1.
[linux-2.6/linux-mips.git] / fs / vfat / namei.c
blob1f7c788f58cb546f526a3f1ba89b39f9f5962f41
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 if (dentry->d_time == dentry->d_parent->d_inode->i_version) {
85 return 1;
87 return 0;
90 static int simple_getbool(char *s, int *setval)
92 if (s) {
93 if (!strcmp(s,"1") || !strcmp(s,"yes") || !strcmp(s,"true")) {
94 *setval = 1;
95 } else if (!strcmp(s,"0") || !strcmp(s,"no") || !strcmp(s,"false")) {
96 *setval = 0;
97 } else {
98 return 0;
100 } else {
101 *setval = 1;
103 return 1;
106 static int parse_options(char *options, struct fat_mount_options *opts)
108 char *this_char,*value,save,*savep;
109 int ret, val;
111 opts->unicode_xlate = opts->posixfs = 0;
112 opts->numtail = 1;
113 opts->utf8 = 0;
115 if (!options) return 1;
116 save = 0;
117 savep = NULL;
118 ret = 1;
119 for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
120 if ((value = strchr(this_char,'=')) != NULL) {
121 save = *value;
122 savep = value;
123 *value++ = 0;
125 if (!strcmp(this_char,"utf8")) {
126 ret = simple_getbool(value, &val);
127 if (ret) opts->utf8 = val;
128 } else if (!strcmp(this_char,"uni_xlate")) {
129 ret = simple_getbool(value, &val);
130 if (ret) opts->unicode_xlate = val;
131 } else if (!strcmp(this_char,"posix")) {
132 ret = simple_getbool(value, &val);
133 if (ret) opts->posixfs = val;
134 } else if (!strcmp(this_char,"nonumtail")) {
135 ret = simple_getbool(value, &val);
136 if (ret) {
137 opts->numtail = !val;
140 if (this_char != options)
141 *(this_char-1) = ',';
142 if (value) {
143 *savep = save;
145 if (ret == 0) {
146 return 0;
149 if (opts->unicode_xlate) {
150 opts->utf8 = 0;
152 return 1;
155 static inline unsigned char
156 vfat_getlower(struct nls_table *t, unsigned char c)
158 return t->charset2lower[c];
161 static inline unsigned char
162 vfat_tolower(struct nls_table *t, unsigned char c)
164 unsigned char nc = t->charset2lower[c];
166 return nc ? nc : c;
169 static inline unsigned char
170 vfat_getupper(struct nls_table *t, unsigned char c)
172 return t->charset2upper[c];
175 static inline unsigned char
176 vfat_toupper(struct nls_table *t, unsigned char c)
178 unsigned char nc = t->charset2upper[c];
180 return nc ? nc : c;
183 static int
184 vfat_strnicmp(struct nls_table *t, const unsigned char *s1,
185 const unsigned char *s2, int len)
187 while(len--)
188 if (vfat_tolower(t, *s1++) != vfat_tolower(t, *s2++))
189 return 1;
191 return 0;
194 static inline unsigned char
195 vfat_uni2short(struct nls_table *t, struct nls_unicode uc)
197 unsigned char *up;
199 up = t->page_uni2charset[uc.uni2];
200 if (up)
201 return up[uc.uni1];
203 return 0;
206 static inline unsigned char
207 vfat_uni2upper_short(struct nls_table *t, struct nls_unicode uc)
209 unsigned char *up;
211 up = t->page_uni2charset[uc.uni2];
212 if (up)
213 return vfat_toupper(t, up[uc.uni1]);
215 return 0;
219 * Compute the hash for the vfat name corresponding to the dentry.
220 * Note: if the name is invalid, we leave the hash code unchanged so
221 * that the existing dentry can be used. The vfat fs routines will
222 * return ENOENT or EINVAL as appropriate.
224 static int vfat_hash(struct dentry *dentry, struct qstr *qstr)
226 const char *name;
227 int len;
229 len = qstr->len;
230 name = qstr->name;
231 while (len && name[len-1] == '.')
232 len--;
234 qstr->hash = full_name_hash(name, len);
236 return 0;
240 * Compute the hash for the vfat name corresponding to the dentry.
241 * Note: if the name is invalid, we leave the hash code unchanged so
242 * that the existing dentry can be used. The vfat fs routines will
243 * return ENOENT or EINVAL as appropriate.
245 static int vfat_hashi(struct dentry *dentry, struct qstr *qstr)
247 struct nls_table *t = MSDOS_SB(dentry->d_inode->i_sb)->nls_io;
248 const char *name;
249 int len;
250 unsigned long hash;
252 len = qstr->len;
253 name = qstr->name;
254 while (len && name[len-1] == '.')
255 len--;
257 hash = init_name_hash();
258 while (len--)
259 hash = partial_name_hash(vfat_tolower(t, *name++), hash);
260 qstr->hash = end_name_hash(hash);
262 return 0;
266 * Case insensitive compare of two vfat names.
268 static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b)
270 struct nls_table *t = MSDOS_SB(dentry->d_inode->i_sb)->nls_io;
271 int alen, blen;
273 /* A filename cannot end in '.' or we treat it like it has none */
274 alen = a->len;
275 blen = b->len;
276 while (alen && a->name[alen-1] == '.')
277 alen--;
278 while (blen && b->name[blen-1] == '.')
279 blen--;
280 if (alen == blen) {
281 if (vfat_strnicmp(t, a->name, b->name, alen) == 0)
282 return 0;
284 return 1;
288 * Case sensitive compare of two vfat names.
290 static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b)
292 int alen, blen;
294 /* A filename cannot end in '.' or we treat it like it has none */
295 alen = a->len;
296 blen = b->len;
297 while (alen && a->name[alen-1] == '.')
298 alen--;
299 while (blen && b->name[blen-1] == '.')
300 blen--;
301 if (alen == blen) {
302 if (strncmp(a->name, b->name, alen) == 0)
303 return 0;
305 return 1;
308 #ifdef DEBUG
310 static void
311 check_stack(const char *fname, int lineno)
313 int stack_level;
314 char *pg_dir;
316 stack_level = (long)(&pg_dir)-current->kernel_stack_page;
317 if (stack_level < 0)
318 printk("*-*-*-* vfat kstack overflow in %s line %d: SL=%d\n",
319 fname, lineno, stack_level);
320 else if (stack_level < 500)
321 printk("*-*-*-* vfat kstack low in %s line %d: SL=%d\n",
322 fname, lineno, stack_level);
323 #if 0
324 else
325 printk("------- vfat kstack ok in %s line %d: SL=%d\n",
326 fname, lineno, stack_level);
327 #endif
328 #if 0
329 if (*(unsigned long *) current->kernel_stack_page != STACK_MAGIC) {
330 printk("******* vfat stack corruption detected in %s at line %d\n",
331 fname, lineno);
333 #endif
336 static int debug = 0;
337 static void dump_fat(struct super_block *sb,int start)
339 printk("[");
340 while (start) {
341 printk("%d ",start);
342 start = fat_access(sb,start,-1);
343 if (!start) {
344 printk("ERROR");
345 break;
347 if (start == -1) break;
349 printk("]\n");
352 static void dump_de(struct msdos_dir_entry *de)
354 int i;
355 unsigned char *p = (unsigned char *) de;
356 printk("[");
358 for (i = 0; i < 32; i++, p++) {
359 printk("%02x ", *p);
361 printk("]\n");
364 #endif
366 /* MS-DOS "device special files" */
368 static const char *reserved3_names[] = {
369 "con ", "prn ", "nul ", "aux ", NULL
372 static const char *reserved4_names[] = {
373 "com1 ", "com2 ", "com3 ", "com4 ", "com5 ",
374 "com6 ", "com7 ", "com8 ", "com9 ",
375 "lpt1 ", "lpt2 ", "lpt3 ", "lpt4 ", "lpt5 ",
376 "lpt6 ", "lpt7 ", "lpt8 ", "lpt9 ",
377 NULL };
380 /* Characters that are undesirable in an MS-DOS file name */
382 static char bad_chars[] = "*?<>|\":/\\";
383 static char replace_chars[] = "[];,+=";
385 /* Checks the validity of a long MS-DOS filename */
386 /* Returns negative number on error, 0 for a normal
387 * return, and 1 for . or .. */
389 static int vfat_valid_longname(const char *name, int len, int xlate)
391 const char **reserved, *walk;
392 unsigned char c;
393 int i, baselen;
395 if (len && name[len-1] == ' ') return -EINVAL;
396 if (len >= 256) return -EINVAL;
397 for (i = 0; i < len; i++) {
398 c = name[i];
399 if (xlate && c == ':') continue;
400 if (strchr(bad_chars,c)) {
401 return -EINVAL;
404 if (len < 3) return 0;
406 for (walk = name; *walk != 0 && *walk != '.'; walk++);
407 baselen = walk - name;
409 if (baselen == 3) {
410 for (reserved = reserved3_names; *reserved; reserved++) {
411 if (!strnicmp(name,*reserved,baselen))
412 return -EINVAL;
414 } else if (baselen == 4) {
415 for (reserved = reserved4_names; *reserved; reserved++) {
416 if (!strnicmp(name,*reserved,baselen))
417 return -EINVAL;
420 return 0;
423 static int vfat_valid_shortname(struct nls_table *nls, struct nls_unicode *name,
424 int len)
426 struct nls_unicode *walk;
427 unsigned char c, l;
428 int space;
430 c = vfat_uni2upper_short(nls, *name);
431 if (IS_FREE(&c))
432 return -EINVAL;
434 space = 1; /* disallow names starting with a dot */
435 for (walk = name; len && walk-name < 8;) {
436 len--;
437 l = vfat_uni2short(nls, *walk++);
438 c = vfat_getupper(nls, l);
439 if (!c) return -EINVAL;
440 if (l != vfat_tolower(nls, c)) return -EINVAL;
441 if (strchr(replace_chars,c)) return -EINVAL;
442 if (c < ' '|| c==':') return -EINVAL;
443 if (c == '.') break;
444 space = c == ' ';
446 if (space) return -EINVAL;
447 if (len && c != '.') {
448 len--;
449 c = vfat_uni2upper_short(nls, *walk++);
450 if (c != '.') return -EINVAL;
452 if (c == '.') {
453 if (len >= 4) return -EINVAL;
454 while (len > 0) {
455 len--;
456 l = vfat_uni2short(nls, *walk++);
457 c = vfat_getupper(nls, l);
458 if (!c) return -EINVAL;
459 if (l != vfat_tolower(nls, c)) return -EINVAL;
460 if (strchr(replace_chars,c))
461 return -EINVAL;
462 if (c < ' ' || c == '.'|| c==':')
463 return -EINVAL;
464 space = c == ' ';
466 if (space) return -EINVAL;
469 return 0;
472 static int vfat_find_form(struct inode *dir,char *name)
474 struct msdos_dir_entry *de;
475 struct buffer_head *bh = NULL;
476 int ino,res;
478 res=fat_scan(dir,name,&bh,&de,&ino);
479 fat_brelse(dir->i_sb, bh);
480 if (res<0)
481 return -ENOENT;
482 return 0;
485 static int vfat_format_name(struct nls_table *nls, struct nls_unicode *name,
486 int len, char *res)
488 char *walk;
489 unsigned char c;
490 int space;
492 c = vfat_uni2upper_short(nls, *name);
493 if (IS_FREE(&c))
494 return -EINVAL;
496 space = 1; /* disallow names starting with a dot */
497 for (walk = res; len--; walk++) {
498 c = vfat_uni2upper_short(nls, *name++);
499 if (c == '.') break;
500 if (!c) return -EINVAL;
501 if (walk-res == 8) return -EINVAL;
502 if (strchr(replace_chars,c)) return -EINVAL;
503 if (c < ' '|| c==':') return -EINVAL;
504 space = c == ' ';
505 *walk = c;
507 if (space) return -EINVAL;
508 if (len >= 0) {
509 while (walk-res < 8) *walk++ = ' ';
510 while (len > 0 && walk-res < MSDOS_NAME) {
511 c = vfat_uni2upper_short(nls, *name++);
512 len--;
513 if (!c) return -EINVAL;
514 if (strchr(replace_chars,c))
515 return -EINVAL;
516 if (c < ' ' || c == '.'|| c==':')
517 return -EINVAL;
518 space = c == ' ';
519 *walk++ = c;
521 if (space) return -EINVAL;
522 if (len) return -EINVAL;
524 while (walk-res < MSDOS_NAME) *walk++ = ' ';
526 return 0;
529 static char skip_chars[] = ".:\"?<>| ";
531 /* Given a valid longname, create a unique shortname. Make sure the
532 * shortname does not exist
534 static int vfat_create_shortname(struct inode *dir, struct nls_table *nls,
535 struct nls_unicode *name, int len,
536 char *name_res)
538 struct nls_unicode *ip, *op, *ext_start, *end, *name_start;
539 struct nls_unicode msdos_name[13];
540 char base[9], ext[4], buf[8], *p;
541 int sz, extlen, baselen, i;
543 PRINTK2(("Entering vfat_create_shortname\n"));
544 sz = 0; /* Make compiler happy */
545 if (len <= 12) {
546 /* Do a case insensitive search if the name would be a valid
547 * shortname if is were all capitalized. However, do not
548 * allow spaces in short names because Win95 scandisk does
549 * not like that */
550 for (i = 0, op = &msdos_name[0], ip = name; ; i++, ip++, op++) {
551 if (i == len) {
552 if (vfat_format_name(nls, &msdos_name[0], len,
553 name_res) < 0)
554 break;
555 PRINTK3(("vfat_create_shortname 1\n"));
556 if (vfat_find_form(dir, name_res) < 0)
557 return 0;
558 return -EEXIST;
560 if (vfat_uni2upper_short(nls, *ip) == ' ')
561 break;
562 *op = *ip;
566 PRINTK3(("vfat_create_shortname 3\n"));
567 /* Now, we need to create a shortname from the long name */
568 ext_start = end = &name[len];
569 while (--ext_start >= name) {
570 if (vfat_uni2upper_short(nls, *ext_start) == '.') {
571 if (ext_start == end - 1) {
572 sz = len;
573 ext_start = NULL;
575 break;
578 if (ext_start == name - 1) {
579 sz = len;
580 ext_start = NULL;
581 } else if (ext_start) {
583 * Names which start with a dot could be just
584 * an extension eg. "...test". In this case Win95
585 * uses the extension as the name and sets no extension.
587 name_start = &name[0];
588 while (name_start < ext_start)
590 unsigned char c = vfat_uni2upper_short(nls, *name_start);
591 if (!c)
592 break;
593 if (!strchr(skip_chars, c))
594 break;
595 name_start++;
597 if (name_start != ext_start) {
598 sz = ext_start - name;
599 ext_start++;
600 } else {
601 sz = len;
602 ext_start=NULL;
606 for (baselen = i = 0, p = base, ip = name; i < sz && baselen < 8; i++)
608 unsigned char c = vfat_uni2upper_short(nls, *ip);
609 if (!c) {
610 *p++ = c = '_';
611 baselen++;
612 } else if (!strchr(skip_chars, c)) {
613 if (strchr(replace_chars, c))
614 *p = '_';
615 else
616 *p = c;
617 p++; baselen++;
619 ip++;
621 if (baselen == 0) {
622 return -EINVAL;
625 extlen = 0;
626 if (ext_start) {
627 for (p = ext, ip = ext_start; extlen < 3 && ip < end; ip++) {
628 unsigned char c = vfat_uni2upper_short(nls, *ip);
629 if (!c) {
630 *p++ = c = '_';
631 extlen++;
632 } else if (!strchr(skip_chars, c)) {
633 if (strchr(replace_chars, c))
634 *p = '_';
635 else
636 *p = c;
637 p++; extlen++;
641 ext[extlen] = '\0';
642 base[baselen] = '\0';
644 /* Yes, it can happen. ".\xe5" would do it. */
645 if (IS_FREE(base))
646 base[0]='_';
648 /* OK, at this point we know that base is not longer than 8 symbols,
649 * ext is not longer than 3, base is nonempty, both don't contain
650 * any bad symbols (lowercase transformed to uppercase).
653 memset(name_res, ' ', MSDOS_NAME);
654 memcpy(name_res,base,baselen);
655 memcpy(name_res+8,ext,extlen);
656 if (MSDOS_SB(dir->i_sb)->options.numtail == 0)
657 if (vfat_find_form(dir, name_res) < 0)
658 return 0;
661 * Try to find a unique extension. This used to
662 * iterate through all possibilities sequentially,
663 * but that gave extremely bad performance. Windows
664 * only tries a few cases before using random
665 * values for part of the base.
668 if (baselen>6)
669 baselen = 6;
670 name_res[baselen] = '~';
671 for (i = 1; i < 10; i++) {
672 name_res[baselen+1] = i + '0';
673 if (vfat_find_form(dir, name_res) < 0)
674 return 0;
677 i = jiffies & 0xffff;
678 sz = (jiffies >> 16) & 0x7;
679 if (baselen>2)
680 baselen = 2;
681 name_res[baselen+4] = '~';
682 name_res[baselen+5] = '1' + sz;
683 while (1) {
684 sprintf(buf, "%04X", i);
685 memcpy(&name_res[baselen], buf, 4);
686 if (vfat_find_form(dir, name_res) < 0)
687 break;
688 i -= 11;
690 return 0;
693 /* Translate a string, including coded sequences into Unicode */
694 static int
695 xlate_to_uni(const char *name, int len, char *outname, int *longlen, int *outlen,
696 int escape, int utf8, struct nls_table *nls)
698 const unsigned char *ip;
699 unsigned char nc;
700 char *op;
701 unsigned int ec;
702 int i, k, fill;
704 if (utf8) {
705 *outlen = utf8_mbstowcs((__u16 *) outname, name, PAGE_SIZE);
706 if (name[len-1] == '.')
707 *outlen-=2;
708 op = &outname[*outlen * sizeof(__u16)];
709 } else {
710 if (name[len-1] == '.')
711 len--;
712 if (nls) {
713 for (i = 0, ip = name, op = outname, *outlen = 0;
714 i < len && *outlen <= 260; *outlen += 1)
716 if (escape && (*ip == ':')) {
717 if (i > len - 5)
718 return -EINVAL;
719 ec = 0;
720 for (k = 1; k < 5; k++) {
721 nc = ip[k];
722 ec <<= 4;
723 if (nc >= '0' && nc <= '9') {
724 ec |= nc - '0';
725 continue;
727 if (nc >= 'a' && nc <= 'f') {
728 ec |= nc - ('a' - 10);
729 continue;
731 if (nc >= 'A' && nc <= 'F') {
732 ec |= nc - ('A' - 10);
733 continue;
735 return -EINVAL;
737 *op++ = ec & 0xFF;
738 *op++ = ec >> 8;
739 ip += 5;
740 i += 5;
741 } else {
742 *op++ = nls->charset2uni[*ip].uni1;
743 *op++ = nls->charset2uni[*ip].uni2;
744 ip++;
745 i++;
748 } else {
749 for (i = 0, ip = name, op = outname, *outlen = 0;
750 i < len && *outlen <= 260; i++, *outlen += 1)
752 *op++ = *ip++;
753 *op++ = 0;
757 if (*outlen > 260)
758 return -ENAMETOOLONG;
760 *longlen = *outlen;
761 if (*outlen % 13) {
762 *op++ = 0;
763 *op++ = 0;
764 *outlen += 1;
765 if (*outlen % 13) {
766 fill = 13 - (*outlen % 13);
767 for (i = 0; i < fill; i++) {
768 *op++ = 0xff;
769 *op++ = 0xff;
771 *outlen += fill;
775 return 0;
778 static int
779 vfat_fill_slots(struct inode *dir, struct msdos_dir_slot *ds, const char *name,
780 int len, int *slots, int uni_xlate)
782 struct nls_table *nls_io, *nls_disk;
783 struct nls_unicode *uname;
784 struct msdos_dir_slot *ps;
785 struct msdos_dir_entry *de;
786 unsigned long page;
787 unsigned char cksum;
788 const char *ip;
789 char *uniname, msdos_name[MSDOS_NAME];
790 int res, utf8, slot, ulen, unilen, i;
791 loff_t offset;
793 de = (struct msdos_dir_entry *) ds;
794 utf8 = MSDOS_SB(dir->i_sb)->options.utf8;
795 nls_io = MSDOS_SB(dir->i_sb)->nls_io;
796 nls_disk = MSDOS_SB(dir->i_sb)->nls_disk;
798 if (name[len-1] == '.') len--;
799 if(!(page = __get_free_page(GFP_KERNEL)))
800 return -ENOMEM;
801 uniname = (char *) page;
802 res = xlate_to_uni(name, len, uniname, &ulen, &unilen, uni_xlate,
803 utf8, nls_io);
804 if (res < 0)
805 goto out_free;
807 uname = (struct nls_unicode *) page;
808 if (vfat_valid_shortname(nls_disk, uname, ulen) >= 0) {
809 res = vfat_format_name(nls_disk, uname, ulen, de->name);
810 if (!res)
811 goto out_free;
813 res = vfat_create_shortname(dir, nls_disk, uname, ulen, msdos_name);
814 if (res)
815 goto out_free;
817 *slots = unilen / 13;
818 for (cksum = i = 0; i < 11; i++) {
819 cksum = (((cksum&1)<<7)|((cksum&0xfe)>>1)) + msdos_name[i];
821 PRINTK3(("vfat_fill_slots 3: slots=%d\n",*slots));
823 for (ps = ds, slot = *slots; slot > 0; slot--, ps++) {
824 ps->id = slot;
825 ps->attr = ATTR_EXT;
826 ps->reserved = 0;
827 ps->alias_checksum = cksum;
828 ps->start = 0;
829 offset = (slot - 1) * 26;
830 ip = &uniname[offset];
831 memcpy(ps->name0_4, ip, 10);
832 memcpy(ps->name5_10, ip+10, 12);
833 memcpy(ps->name11_12, ip+22, 4);
835 ds[0].id |= 0x40;
837 de = (struct msdos_dir_entry *) ps;
838 PRINTK3(("vfat_fill_slots 9\n"));
839 strncpy(de->name, msdos_name, MSDOS_NAME);
840 (*slots)++;
842 out_free:
843 free_page(page);
844 return res;
847 /* We can't get "." or ".." here - VFS takes care of those cases */
849 static int vfat_build_slots(struct inode *dir,const char *name,int len,
850 struct msdos_dir_slot *ds, int *slots)
852 int res, xlate;
854 xlate = MSDOS_SB(dir->i_sb)->options.unicode_xlate;
855 *slots = 1;
856 res = vfat_valid_longname(name, len, xlate);
857 if (res < 0)
858 return res;
859 return vfat_fill_slots(dir, ds, name, len, slots, xlate);
862 static int vfat_add_entry(struct inode *dir,struct qstr* qname,
863 int is_dir,struct vfat_slot_info *sinfo_out,
864 struct buffer_head **bh, struct msdos_dir_entry **de)
866 struct super_block *sb = dir->i_sb;
867 struct msdos_dir_slot *ps;
868 loff_t offset;
869 struct msdos_dir_slot *ds;
870 int slots, slot;
871 int res;
872 struct msdos_dir_entry *de1;
873 struct buffer_head *bh1;
874 int ino;
875 int len;
876 loff_t dummy;
878 ds = (struct msdos_dir_slot *)
879 kmalloc(sizeof(struct msdos_dir_slot)*MSDOS_SLOTS, GFP_KERNEL);
880 if (ds == NULL) return -ENOMEM;
882 len = qname->len;
883 while (len && qname->name[len-1] == '.')
884 len--;
885 res = fat_search_long(dir, qname->name, len,
886 (MSDOS_SB(sb)->options.name_check != 's') ||
887 !MSDOS_SB(sb)->options.posixfs,
888 &dummy, &dummy);
889 if (res > 0) /* found */
890 res = -EEXIST;
891 if (res)
892 goto cleanup;
894 res = vfat_build_slots(dir, qname->name, len, ds, &slots);
895 if (res < 0) goto cleanup;
897 offset = fat_add_entries(dir, slots, &bh1, &de1, &ino);
898 if (offset < 0) {
899 res = offset;
900 goto cleanup;
902 fat_brelse(sb, bh1);
904 /* Now create the new entry */
905 *bh = NULL;
906 for (slot = 0, ps = ds; slot < slots; slot++, ps++) {
907 if (fat_get_entry(dir,&offset,bh,de, &sinfo_out->ino) < 0) {
908 res = -EIO;
909 goto cleanup;
911 memcpy(*de, ps, sizeof(struct msdos_dir_slot));
912 fat_mark_buffer_dirty(sb, *bh, 1);
915 dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;
916 mark_inode_dirty(dir);
918 fat_date_unix2dos(dir->i_mtime,&(*de)->time,&(*de)->date);
919 (*de)->ctime_ms = 0;
920 (*de)->ctime = (*de)->time;
921 (*de)->adate = (*de)->cdate = (*de)->date;
922 (*de)->start = 0;
923 (*de)->starthi = 0;
924 (*de)->size = 0;
925 (*de)->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
926 (*de)->lcase = CASE_LOWER_BASE | CASE_LOWER_EXT;
929 fat_mark_buffer_dirty(sb, *bh, 1);
931 /* slots can't be less than 1 */
932 sinfo_out->long_slots = slots - 1;
933 sinfo_out->longname_offset = offset - sizeof(struct msdos_dir_slot) * slots;
934 res = 0;
936 cleanup:
937 kfree(ds);
938 return res;
941 static int vfat_find(struct inode *dir,struct qstr* qname,
942 struct vfat_slot_info *sinfo, struct buffer_head **last_bh,
943 struct msdos_dir_entry **last_de)
945 struct super_block *sb = dir->i_sb;
946 loff_t offset;
947 int res,len;
949 len = qname->len;
950 while (len && qname->name[len-1] == '.')
951 len--;
952 res = fat_search_long(dir, qname->name, len,
953 (MSDOS_SB(sb)->options.name_check != 's'),
954 &offset,&sinfo->longname_offset);
955 if (res>0) {
956 sinfo->long_slots = res-1;
957 if (fat_get_entry(dir,&offset,last_bh,last_de,&sinfo->ino)>=0)
958 return 0;
959 res = -EIO;
961 return res ? res : -ENOENT;
964 /* Find a hashed dentry for inode; NULL if there are none */
965 static struct dentry *find_alias(struct inode *inode)
967 struct list_head *head, *next, *tmp;
968 struct dentry *alias;
970 head = &inode->i_dentry;
971 next = inode->i_dentry.next;
972 while (next != head) {
973 tmp = next;
974 next = tmp->next;
975 alias = list_entry(tmp, struct dentry, d_alias);
976 if (!d_unhashed(alias))
977 return dget(alias);
979 return NULL;
982 struct dentry *vfat_lookup(struct inode *dir,struct dentry *dentry)
984 int res;
985 struct vfat_slot_info sinfo;
986 struct inode *inode;
987 struct dentry *alias;
988 struct buffer_head *bh = NULL;
989 struct msdos_dir_entry *de;
990 int table;
992 PRINTK2(("vfat_lookup: name=%s, len=%d\n",
993 dentry->d_name.name, dentry->d_name.len));
995 table = (MSDOS_SB(dir->i_sb)->options.name_check == 's') ? 2 : 0;
996 dentry->d_op = &vfat_dentry_ops[table];
998 inode = NULL;
999 res = vfat_find(dir,&dentry->d_name,&sinfo,&bh,&de);
1000 if (res < 0) {
1001 table++;
1002 goto error;
1004 inode = fat_build_inode(dir->i_sb, de, sinfo.ino, &res);
1005 fat_brelse(dir->i_sb, bh);
1006 if (res)
1007 return ERR_PTR(res);
1008 alias = find_alias(inode);
1009 if (alias) {
1010 if (d_invalidate(alias)==0)
1011 dput(alias);
1012 else {
1013 iput(inode);
1014 return alias;
1018 error:
1019 dentry->d_op = &vfat_dentry_ops[table];
1020 dentry->d_time = dentry->d_parent->d_inode->i_version;
1021 d_add(dentry,inode);
1022 return NULL;
1025 int vfat_create(struct inode *dir,struct dentry* dentry,int mode)
1027 struct super_block *sb = dir->i_sb;
1028 struct inode *inode = NULL;
1029 struct buffer_head *bh = NULL;
1030 struct msdos_dir_entry *de;
1031 struct vfat_slot_info sinfo;
1032 int res;
1034 res = vfat_add_entry(dir, &dentry->d_name, 0, &sinfo, &bh, &de);
1035 if (res < 0)
1036 return res;
1037 inode = fat_build_inode(sb, de, sinfo.ino, &res);
1038 fat_brelse(sb, bh);
1039 if (!inode)
1040 return res;
1041 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
1042 mark_inode_dirty(inode);
1043 inode->i_version = ++event;
1044 dir->i_version = event;
1045 dentry->d_time = dentry->d_parent->d_inode->i_version;
1046 d_instantiate(dentry,inode);
1047 return 0;
1050 static void vfat_remove_entry(struct inode *dir,struct vfat_slot_info *sinfo,
1051 struct buffer_head *bh, struct msdos_dir_entry *de)
1053 struct super_block *sb = dir->i_sb;
1054 loff_t offset;
1055 int i,ino;
1057 /* remove the shortname */
1058 dir->i_mtime = CURRENT_TIME;
1059 dir->i_atime = CURRENT_TIME;
1060 dir->i_version = ++event;
1061 mark_inode_dirty(dir);
1062 de->name[0] = DELETED_FLAG;
1063 fat_mark_buffer_dirty(sb, bh, 1);
1064 /* remove the longname */
1065 offset = sinfo->longname_offset; de = NULL;
1066 for (i = sinfo->long_slots; i > 0; --i) {
1067 if (fat_get_entry(dir, &offset, &bh, &de, &ino) < 0)
1068 continue;
1069 de->name[0] = DELETED_FLAG;
1070 de->attr = 0;
1071 fat_mark_buffer_dirty(sb, bh, 1);
1073 if (bh) fat_brelse(sb, bh);
1076 int vfat_rmdir(struct inode *dir,struct dentry* dentry)
1078 int res;
1079 struct vfat_slot_info sinfo;
1080 struct buffer_head *bh = NULL;
1081 struct msdos_dir_entry *de;
1083 if (!d_unhashed(dentry))
1084 return -EBUSY;
1086 res = fat_dir_empty(dentry->d_inode);
1087 if (res)
1088 return res;
1090 res = vfat_find(dir,&dentry->d_name,&sinfo, &bh, &de);
1091 if (res<0)
1092 return res;
1093 dentry->d_inode->i_nlink = 0;
1094 dentry->d_inode->i_mtime = CURRENT_TIME;
1095 dentry->d_inode->i_atime = CURRENT_TIME;
1096 fat_detach(dentry->d_inode);
1097 mark_inode_dirty(dentry->d_inode);
1098 /* releases bh */
1099 vfat_remove_entry(dir,&sinfo,bh,de);
1100 dir->i_nlink--;
1101 return 0;
1104 int vfat_unlink(struct inode *dir, struct dentry* dentry)
1106 int res;
1107 struct vfat_slot_info sinfo;
1108 struct buffer_head *bh = NULL;
1109 struct msdos_dir_entry *de;
1111 PRINTK1(("vfat_unlink: %s\n", dentry->d_name.name));
1112 res = vfat_find(dir,&dentry->d_name,&sinfo,&bh,&de);
1113 if (res < 0)
1114 return res;
1115 dentry->d_inode->i_nlink = 0;
1116 dentry->d_inode->i_mtime = CURRENT_TIME;
1117 dentry->d_inode->i_atime = CURRENT_TIME;
1118 fat_detach(dentry->d_inode);
1119 mark_inode_dirty(dentry->d_inode);
1120 /* releases bh */
1121 vfat_remove_entry(dir,&sinfo,bh,de);
1122 d_delete(dentry);
1124 return res;
1128 int vfat_mkdir(struct inode *dir,struct dentry* dentry,int mode)
1130 struct super_block *sb = dir->i_sb;
1131 struct inode *inode = NULL;
1132 struct vfat_slot_info sinfo;
1133 struct buffer_head *bh = NULL;
1134 struct msdos_dir_entry *de;
1135 int res;
1137 res = vfat_add_entry(dir, &dentry->d_name, 1, &sinfo, &bh, &de);
1138 if (res < 0)
1139 return res;
1140 inode = fat_build_inode(sb, de, sinfo.ino, &res);
1141 if (!inode)
1142 goto out;
1143 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
1144 mark_inode_dirty(inode);
1145 inode->i_version = ++event;
1146 dir->i_version = event;
1147 dir->i_nlink++;
1148 inode->i_nlink = 2; /* no need to mark them dirty */
1149 res = fat_new_dir(inode, dir, 1);
1150 if (res < 0)
1151 goto mkdir_failed;
1152 dentry->d_time = dentry->d_parent->d_inode->i_version;
1153 d_instantiate(dentry,inode);
1154 out:
1155 fat_brelse(sb, bh);
1156 return res;
1158 mkdir_failed:
1159 inode->i_nlink = 0;
1160 inode->i_mtime = CURRENT_TIME;
1161 inode->i_atime = CURRENT_TIME;
1162 fat_detach(inode);
1163 mark_inode_dirty(inode);
1164 /* releases bh */
1165 vfat_remove_entry(dir,&sinfo,bh,de);
1166 iput(inode);
1167 dir->i_nlink--;
1168 return res;
1171 int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
1172 struct inode *new_dir,struct dentry *new_dentry)
1174 struct super_block *sb = old_dir->i_sb;
1175 struct buffer_head *old_bh,*new_bh,*dotdot_bh;
1176 struct msdos_dir_entry *old_de,*new_de,*dotdot_de;
1177 int dotdot_ino;
1178 struct inode *old_inode, *new_inode;
1179 int res, is_dir;
1180 struct vfat_slot_info old_sinfo,sinfo;
1182 old_bh = new_bh = dotdot_bh = NULL;
1183 old_inode = old_dentry->d_inode;
1184 new_inode = new_dentry->d_inode;
1185 res = vfat_find(old_dir,&old_dentry->d_name,&old_sinfo,&old_bh,&old_de);
1186 PRINTK3(("vfat_rename 2\n"));
1187 if (res < 0) goto rename_done;
1189 is_dir = S_ISDIR(old_inode->i_mode);
1191 if (is_dir && (res = fat_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh,
1192 &dotdot_de,&dotdot_ino)) < 0)
1193 goto rename_done;
1195 if (new_dentry->d_inode) {
1196 res = vfat_find(new_dir,&new_dentry->d_name,&sinfo,&new_bh,
1197 &new_de);
1198 if (res < 0 || MSDOS_I(new_inode)->i_location != sinfo.ino) {
1199 /* WTF??? Cry and fail. */
1200 printk(KERN_WARNING "vfat_rename: fs corrupted\n");
1201 goto rename_done;
1204 if (is_dir) {
1205 res =-EBUSY;
1206 if (!d_unhashed(new_dentry))
1207 goto rename_done;
1208 res = fat_dir_empty(new_inode);
1209 if (res)
1210 goto rename_done;
1212 fat_detach(new_inode);
1213 } else {
1214 res = vfat_add_entry(new_dir,&new_dentry->d_name,is_dir,&sinfo,
1215 &new_bh,&new_de);
1216 if (res < 0) goto rename_done;
1219 new_dir->i_version = ++event;
1221 /* releases old_bh */
1222 vfat_remove_entry(old_dir,&old_sinfo,old_bh,old_de);
1223 old_bh=NULL;
1224 fat_detach(old_inode);
1225 fat_attach(old_inode, sinfo.ino);
1226 mark_inode_dirty(old_inode);
1228 old_dir->i_version = ++event;
1229 old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
1230 mark_inode_dirty(old_dir);
1231 if (new_inode) {
1232 new_inode->i_nlink--;
1233 new_inode->i_ctime=CURRENT_TIME;
1236 if (is_dir) {
1237 int start = MSDOS_I(new_dir)->i_logstart;
1238 dotdot_de->start = CT_LE_W(start);
1239 dotdot_de->starthi = CT_LE_W(start>>16);
1240 fat_mark_buffer_dirty(sb, dotdot_bh, 1);
1241 old_dir->i_nlink--;
1242 if (new_inode) {
1243 new_inode->i_nlink--;
1244 } else {
1245 new_dir->i_nlink++;
1246 mark_inode_dirty(new_dir);
1250 rename_done:
1251 fat_brelse(sb, dotdot_bh);
1252 fat_brelse(sb, old_bh);
1253 fat_brelse(sb, new_bh);
1254 return res;
1259 /* Public inode operations for the VFAT fs */
1260 struct inode_operations vfat_dir_inode_operations = {
1261 create: vfat_create,
1262 lookup: vfat_lookup,
1263 unlink: vfat_unlink,
1264 mkdir: vfat_mkdir,
1265 rmdir: vfat_rmdir,
1266 rename: vfat_rename,
1267 setattr: fat_notify_change,
1270 struct super_block *vfat_read_super(struct super_block *sb,void *data,
1271 int silent)
1273 struct super_block *res;
1275 MSDOS_SB(sb)->options.isvfat = 1;
1277 res = fat_read_super(sb, data, silent, &vfat_dir_inode_operations);
1278 if (res == NULL)
1279 return NULL;
1281 if (parse_options((char *) data, &(MSDOS_SB(sb)->options))) {
1282 MSDOS_SB(sb)->options.dotsOK = 0;
1283 if (MSDOS_SB(sb)->options.posixfs) {
1284 MSDOS_SB(sb)->options.name_check = 's';
1286 if (MSDOS_SB(sb)->options.name_check != 's') {
1287 sb->s_root->d_op = &vfat_dentry_ops[0];
1288 } else {
1289 sb->s_root->d_op = &vfat_dentry_ops[2];
1293 return res;