Import 2.3.13
[davej-history.git] / fs / vfat / namei.c
blob0f23487ba3d3423decf58ccc855ddbb8d0d8bf0b
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.
13 #define __NO_VERSION__
14 #include <linux/module.h>
16 #include <linux/sched.h>
17 #include <linux/msdos_fs.h>
18 #include <linux/nls.h>
19 #include <linux/kernel.h>
20 #include <linux/errno.h>
21 #include <linux/string.h>
22 #include <linux/ctype.h>
23 #include <linux/stat.h>
24 #include <linux/mm.h>
25 #include <linux/malloc.h>
27 #include "../fat/msbuffer.h"
29 #define DEBUG_LEVEL 0
30 #if (DEBUG_LEVEL >= 1)
31 # define PRINTK1(x) printk x
32 #else
33 # define PRINTK1(x)
34 #endif
35 #if (DEBUG_LEVEL >= 2)
36 # define PRINTK2(x) printk x
37 #else
38 # define PRINTK2(x)
39 #endif
40 #if (DEBUG_LEVEL >= 3)
41 # define PRINTK3(x) printk x
42 #else
43 # define PRINTK3(x)
44 #endif
46 #ifndef DEBUG
47 # define CHECK_STACK
48 #else
49 # define CHECK_STACK check_stack(__FILE__, __LINE__)
50 #endif
52 static int vfat_hashi(struct dentry *parent, struct qstr *qstr);
53 static int vfat_hash(struct dentry *parent, struct qstr *qstr);
54 static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);
55 static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b);
56 static int vfat_revalidate(struct dentry *dentry, int);
58 static struct dentry_operations vfat_dentry_ops[4] = {
60 NULL, /* d_revalidate */
61 vfat_hashi,
62 vfat_cmpi,
63 NULL /* d_delete */
66 vfat_revalidate,
67 vfat_hashi,
68 vfat_cmpi,
69 NULL /* d_delete */
72 NULL, /* d_revalidate */
73 vfat_hash,
74 vfat_cmp,
75 NULL /* d_delete */
78 vfat_revalidate,
79 vfat_hash,
80 vfat_cmp,
81 NULL /* d_delete */
85 static void vfat_put_super_callback(struct super_block *sb)
87 MOD_DEC_USE_COUNT;
90 static int vfat_revalidate(struct dentry *dentry, int flags)
92 PRINTK1(("vfat_revalidate: %s\n", dentry->d_name.name));
93 if (dentry->d_time == dentry->d_parent->d_inode->i_version) {
94 return 1;
96 return 0;
99 static int simple_getbool(char *s, int *setval)
101 if (s) {
102 if (!strcmp(s,"1") || !strcmp(s,"yes") || !strcmp(s,"true")) {
103 *setval = 1;
104 } else if (!strcmp(s,"0") || !strcmp(s,"no") || !strcmp(s,"false")) {
105 *setval = 0;
106 } else {
107 return 0;
109 } else {
110 *setval = 1;
112 return 1;
115 static int parse_options(char *options, struct fat_mount_options *opts)
117 char *this_char,*value,save,*savep;
118 int ret, val;
120 opts->unicode_xlate = opts->posixfs = 0;
121 opts->numtail = 1;
122 opts->utf8 = 0;
124 if (!options) return 1;
125 save = 0;
126 savep = NULL;
127 ret = 1;
128 for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
129 if ((value = strchr(this_char,'=')) != NULL) {
130 save = *value;
131 savep = value;
132 *value++ = 0;
134 if (!strcmp(this_char,"utf8")) {
135 ret = simple_getbool(value, &val);
136 if (ret) opts->utf8 = val;
137 } else if (!strcmp(this_char,"uni_xlate")) {
138 ret = simple_getbool(value, &val);
139 if (ret) opts->unicode_xlate = val;
140 } else if (!strcmp(this_char,"posix")) {
141 ret = simple_getbool(value, &val);
142 if (ret) opts->posixfs = val;
143 } else if (!strcmp(this_char,"nonumtail")) {
144 ret = simple_getbool(value, &val);
145 if (ret) {
146 opts->numtail = !val;
149 if (this_char != options)
150 *(this_char-1) = ',';
151 if (value) {
152 *savep = save;
154 if (ret == 0) {
155 return 0;
158 if (opts->unicode_xlate) {
159 opts->utf8 = 0;
161 return 1;
165 * Compute the hash for the vfat name corresponding to the dentry.
166 * Note: if the name is invalid, we leave the hash code unchanged so
167 * that the existing dentry can be used. The vfat fs routines will
168 * return ENOENT or EINVAL as appropriate.
170 static int vfat_hash(struct dentry *dentry, struct qstr *qstr)
172 const char *name;
173 int len;
175 len = qstr->len;
176 name = qstr->name;
177 while (len && name[len-1] == '.')
178 len--;
180 qstr->hash = full_name_hash(name, len);
182 return 0;
186 * Compute the hash for the vfat name corresponding to the dentry.
187 * Note: if the name is invalid, we leave the hash code unchanged so
188 * that the existing dentry can be used. The vfat fs routines will
189 * return ENOENT or EINVAL as appropriate.
191 static int vfat_hashi(struct dentry *dentry, struct qstr *qstr)
193 const char *name;
194 int len;
195 char c;
196 unsigned long hash;
198 len = qstr->len;
199 name = qstr->name;
200 while (len && name[len-1] == '.')
201 len--;
203 hash = init_name_hash();
204 while (len--) {
205 c = tolower(*name++);
206 hash = partial_name_hash(tolower(c), hash);
208 qstr->hash = end_name_hash(hash);
210 return 0;
214 * Case insensitive compare of two vfat names.
216 static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b)
218 int alen, blen;
220 /* A filename cannot end in '.' or we treat it like it has none */
221 alen = a->len;
222 blen = b->len;
223 while (alen && a->name[alen-1] == '.')
224 alen--;
225 while (blen && b->name[blen-1] == '.')
226 blen--;
227 if (alen == blen) {
228 if (strnicmp(a->name, b->name, alen) == 0)
229 return 0;
231 return 1;
235 * Case sensitive compare of two vfat names.
237 static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b)
239 int alen, blen;
241 /* A filename cannot end in '.' or we treat it like it has none */
242 alen = a->len;
243 blen = b->len;
244 while (alen && a->name[alen-1] == '.')
245 alen--;
246 while (blen && b->name[blen-1] == '.')
247 blen--;
248 if (alen == blen) {
249 if (strncmp(a->name, b->name, alen) == 0)
250 return 0;
252 return 1;
255 #ifdef DEBUG
257 static void
258 check_stack(const char *fname, int lineno)
260 int stack_level;
261 char *pg_dir;
263 stack_level = (long)(&pg_dir)-current->kernel_stack_page;
264 if (stack_level < 0)
265 printk("*-*-*-* vfat kstack overflow in %s line %d: SL=%d\n",
266 fname, lineno, stack_level);
267 else if (stack_level < 500)
268 printk("*-*-*-* vfat kstack low in %s line %d: SL=%d\n",
269 fname, lineno, stack_level);
270 #if 0
271 else
272 printk("------- vfat kstack ok in %s line %d: SL=%d\n",
273 fname, lineno, stack_level);
274 #endif
275 #if 0
276 if (*(unsigned long *) current->kernel_stack_page != STACK_MAGIC) {
277 printk("******* vfat stack corruption detected in %s at line %d\n",
278 fname, lineno);
280 #endif
283 static int debug = 0;
284 static void dump_fat(struct super_block *sb,int start)
286 printk("[");
287 while (start) {
288 printk("%d ",start);
289 start = fat_access(sb,start,-1);
290 if (!start) {
291 printk("ERROR");
292 break;
294 if (start == -1) break;
296 printk("]\n");
299 static void dump_de(struct msdos_dir_entry *de)
301 int i;
302 unsigned char *p = (unsigned char *) de;
303 printk("[");
305 for (i = 0; i < 32; i++, p++) {
306 printk("%02x ", *p);
308 printk("]\n");
311 #endif
313 /* MS-DOS "device special files" */
315 static const char *reserved3_names[] = {
316 "con ", "prn ", "nul ", "aux ", NULL
319 static const char *reserved4_names[] = {
320 "com1 ", "com2 ", "com3 ", "com4 ", "com5 ",
321 "com6 ", "com7 ", "com8 ", "com9 ",
322 "lpt1 ", "lpt2 ", "lpt3 ", "lpt4 ", "lpt5 ",
323 "lpt6 ", "lpt7 ", "lpt8 ", "lpt9 ",
324 NULL };
327 /* Characters that are undesirable in an MS-DOS file name */
329 static char bad_chars[] = "*?<>|\":/\\";
330 static char replace_chars[] = "[];,+=";
332 /* Checks the validity of a long MS-DOS filename */
333 /* Returns negative number on error, 0 for a normal
334 * return, and 1 for . or .. */
336 static int vfat_valid_longname(const char *name, int len, int xlate)
338 const char **reserved, *walk;
339 unsigned char c;
340 int i, baselen;
342 if (IS_FREE(name)) return -EINVAL;
344 if (len && name[len-1] == ' ') return -EINVAL;
345 if (len >= 256) return -EINVAL;
346 for (i = 0; i < len; i++) {
347 c = name[i];
348 if (xlate && c == ':') continue;
349 if (strchr(bad_chars,c)) {
350 return -EINVAL;
353 if (len < 3) return 0;
355 for (walk = name; *walk != 0 && *walk != '.'; walk++);
356 baselen = walk - name;
358 if (baselen == 3) {
359 for (reserved = reserved3_names; *reserved; reserved++) {
360 if (!strnicmp(name,*reserved,baselen))
361 return -EINVAL;
363 } else if (baselen == 4) {
364 for (reserved = reserved4_names; *reserved; reserved++) {
365 if (!strnicmp(name,*reserved,baselen))
366 return -EINVAL;
369 return 0;
372 static int vfat_valid_shortname(const char *name,int len,int utf8)
374 const char *walk;
375 unsigned char c;
376 int space;
377 int baselen;
379 space = 1; /* disallow names starting with a dot */
380 c = 0;
381 for (walk = name; len && walk-name < 8;) {
382 c = *walk++;
383 len--;
384 if (utf8 && (c & 0x80)) return -EINVAL;
385 if (strchr(replace_chars,c)) return -EINVAL;
386 if (c >= 'A' && c <= 'Z') return -EINVAL;
387 if (c < ' '|| c==':') return -EINVAL;
388 if (c == '.') break;
389 space = c == ' ';
391 if (space) return -EINVAL;
392 if (len && c != '.') {
393 c = *walk++;
394 len--;
395 if (c != '.') return -EINVAL;
397 baselen = walk - name;
398 if (c == '.') {
399 baselen--;
400 if (len >= 4) return -EINVAL;
401 while (len > 0) {
402 c = *walk++;
403 len--;
404 if (utf8 && (c & 0x80)) return -EINVAL;
405 if (strchr(replace_chars,c))
406 return -EINVAL;
407 if (c < ' ' || c == '.'|| c==':')
408 return -EINVAL;
409 if (c >= 'A' && c <= 'Z') return -EINVAL;
410 space = c == ' ';
412 if (space) return -EINVAL;
415 return 0;
418 static int vfat_find_form(struct inode *dir,char *name)
420 struct msdos_dir_entry *de;
421 struct buffer_head *bh = NULL;
422 int ino,res;
424 res=fat_scan(dir,name,&bh,&de,&ino);
425 fat_brelse(dir->i_sb, bh);
426 if (res<0)
427 return -ENOENT;
428 return 0;
431 static int vfat_format_name(const char *name,int len,char *res,int utf8)
433 char *walk;
434 unsigned char c;
435 int space;
437 space = 1; /* disallow names starting with a dot */
438 for (walk = res; len-- && (c=*name++)!='.' ; walk++) {
439 if (walk-res == 8) return -EINVAL;
440 if (utf8 && (c & 0x80)) return -EINVAL;
441 if (strchr(replace_chars,c)) return -EINVAL;
442 if (c >= 'A' && c <= 'Z') return -EINVAL;
443 if (c < ' '|| c==':') return -EINVAL;
444 space = c == ' ';
445 *walk = c >= 'a' && c <= 'z' ? c-32 : c;
447 if (space) return -EINVAL;
448 if (len >= 0) {
449 while (walk-res < 8) *walk++ = ' ';
450 while (len > 0 && walk-res < MSDOS_NAME) {
451 c = *name++;
452 len--;
453 if (utf8 && (c & 0x80)) return -EINVAL;
454 if (strchr(replace_chars,c))
455 return -EINVAL;
456 if (c < ' ' || c == '.'|| c==':')
457 return -EINVAL;
458 if (c >= 'A' && c <= 'Z') return -EINVAL;
459 space = c == ' ';
460 *walk++ = c >= 'a' && c <= 'z' ? c-32 : c;
462 if (space) return -EINVAL;
463 if (len) return -EINVAL;
465 while (walk-res < MSDOS_NAME) *walk++ = ' ';
467 return 0;
470 static char skip_chars[] = ".:\"?<>| ";
472 /* Given a valid longname, create a unique shortname. Make sure the
473 * shortname does not exist
475 static int vfat_create_shortname(struct inode *dir, const char *name,
476 int len, char *name_res, int utf8)
478 const char *ip, *ext_start, *end;
479 char *p;
480 int sz, extlen, baselen;
481 char msdos_name[13];
482 char base[9], ext[4];
483 int i;
484 char buf[8];
485 const char *name_start;
487 PRINTK2(("Entering vfat_create_shortname: name=%s, len=%d\n", name, len));
488 sz = 0; /* Make compiler happy */
489 if (len && name[len-1]==' ') return -EINVAL;
490 if (len <= 12) {
491 /* Do a case insensitive search if the name would be a valid
492 * shortname if is were all capitalized. However, do not
493 * allow spaces in short names because Win95 scandisk does
494 * not like that */
495 for (i = 0, p = msdos_name, ip = name; ; i++, p++, ip++) {
496 if (i == len) {
497 if (vfat_format_name(msdos_name,
498 len, name_res, utf8) < 0)
499 break;
500 PRINTK3(("vfat_create_shortname 1\n"));
501 if (vfat_find_form(dir, name_res) < 0)
502 return 0;
503 return -EEXIST;
506 if (*ip == ' ')
507 break;
508 if (*ip >= 'A' && *ip <= 'Z') {
509 *p = *ip + 32;
510 } else {
511 *p = *ip;
516 PRINTK3(("vfat_create_shortname 3\n"));
517 /* Now, we need to create a shortname from the long name */
518 ext_start = end = &name[len];
519 while (--ext_start >= name) {
520 if (*ext_start == '.') {
521 if (ext_start == end - 1) {
522 sz = len;
523 ext_start = NULL;
525 break;
528 if (ext_start == name - 1) {
529 sz = len;
530 ext_start = NULL;
531 } else if (ext_start) {
533 * Names which start with a dot could be just
534 * an extension eg. "...test". In this case Win95
535 * uses the extension as the name and sets no extension.
537 name_start = &name[0];
538 while (name_start < ext_start)
540 if (!strchr(skip_chars,*name_start)) break;
541 name_start++;
543 if (name_start != ext_start) {
544 sz = ext_start - name;
545 ext_start++;
546 } else {
547 sz = len;
548 ext_start=NULL;
552 for (baselen = i = 0, p = base, ip = name; i < sz && baselen < 8; i++)
554 if (utf8 && (*ip & 0x80)) {
555 *p++ = '_';
556 baselen++;
557 } else if (!strchr(skip_chars, *ip)) {
558 if (*ip >= 'a' && *ip <= 'z') {
559 *p = *ip - 32;
560 } else {
561 *p = *ip;
563 if (strchr(replace_chars, *p)) *p='_';
564 p++; baselen++;
566 ip++;
568 if (baselen == 0) {
569 return -EINVAL;
572 extlen = 0;
573 if (ext_start) {
574 for (p = ext, ip = ext_start; extlen < 3 && ip < end; ip++) {
575 if (utf8 && (*ip & 0x80)) {
576 *p++ = '_';
577 extlen++;
578 } else if (!strchr(skip_chars, *ip)) {
579 if (*ip >= 'a' && *ip <= 'z') {
580 *p = *ip - 32;
581 } else {
582 *p = *ip;
584 if (strchr(replace_chars, *p)) *p='_';
585 extlen++;
586 p++;
590 ext[extlen] = '\0';
591 base[baselen] = '\0';
593 /* Yes, it can happen. ".\xe5" would do it. */
594 if (IS_FREE(base))
595 base[0]='_';
597 /* OK, at this point we know that base is not longer than 8 symbols,
598 * ext is not longer than 3, base is nonempty, both don't contain
599 * any bad symbols (lowercase transformed to uppercase).
602 memset(name_res, ' ', MSDOS_NAME);
603 memcpy(name_res,base,baselen);
604 memcpy(name_res+8,ext,extlen);
605 if (MSDOS_SB(dir->i_sb)->options.numtail == 0)
606 if (vfat_find_form(dir, name_res) < 0)
607 return 0;
610 * Try to find a unique extension. This used to
611 * iterate through all possibilities sequentially,
612 * but that gave extremely bad performance. Windows
613 * only tries a few cases before using random
614 * values for part of the base.
617 if (baselen>6)
618 baselen = 6;
619 name_res[baselen] = '~';
620 for (i = 1; i < 10; i++) {
621 name_res[baselen+1] = i + '0';
622 if (vfat_find_form(dir, name_res) < 0)
623 return 0;
626 i = jiffies & 0xffff;
627 sz = (jiffies >> 16) & 0x7;
628 if (baselen>2)
629 baselen = 2;
630 name_res[baselen+4] = '~';
631 name_res[baselen+5] = '1' + sz;
632 while (1) {
633 sprintf(buf, "%04X", i);
634 memcpy(&name_res[baselen], buf, 4);
635 if (vfat_find_form(dir, name_res) < 0)
636 break;
637 i -= 11;
639 return 0;
642 /* Translate a string, including coded sequences into Unicode */
643 static int
644 xlate_to_uni(const char *name, int len, char *outname, int *outlen,
645 int escape, int utf8, struct nls_table *nls)
647 int i;
648 const unsigned char *ip;
649 char *op;
650 int fill;
651 unsigned char c1, c2, c3;
653 if (utf8) {
654 *outlen = utf8_mbstowcs((__u16 *) outname, name, PAGE_SIZE);
655 if (name[len-1] == '.')
656 *outlen-=2;
657 op = &outname[*outlen * sizeof(__u16)];
658 } else {
659 if (name[len-1] == '.')
660 len--;
661 op = outname;
662 if (nls) {
663 for (i = 0, ip = name, op = outname, *outlen = 0;
664 i < len && *outlen <= 260; i++, *outlen += 1)
666 if (escape && (*ip == ':')) {
667 if (i > len - 4) return -EINVAL;
668 c1 = fat_esc2uni[ip[1]];
669 c2 = fat_esc2uni[ip[2]];
670 c3 = fat_esc2uni[ip[3]];
671 if (c1 == 255 || c2 == 255 || c3 == 255)
672 return -EINVAL;
673 *op++ = (c1 << 4) + (c2 >> 2);
674 *op++ = ((c2 & 0x3) << 6) + c3;
675 ip += 4;
676 } else {
677 *op++ = nls->charset2uni[*ip].uni1;
678 *op++ = nls->charset2uni[*ip].uni2;
679 ip++;
682 } else {
683 for (i = 0, ip = name, op = outname, *outlen = 0;
684 i < len && *outlen <= 260; i++, *outlen += 1)
686 *op++ = *ip++;
687 *op++ = 0;
691 if (*outlen > 260)
692 return -ENAMETOOLONG;
694 if (*outlen % 13) {
695 *op++ = 0;
696 *op++ = 0;
697 *outlen += 1;
698 if (*outlen % 13) {
699 fill = 13 - (*outlen % 13);
700 for (i = 0; i < fill; i++) {
701 *op++ = 0xff;
702 *op++ = 0xff;
704 *outlen += fill;
708 return 0;
711 static int
712 vfat_fill_long_slots(struct msdos_dir_slot *ds, const char *name, int len,
713 char *msdos_name, int *slots,
714 int uni_xlate, int utf8, struct nls_table *nls)
716 struct msdos_dir_slot *ps;
717 struct msdos_dir_entry *de;
718 int res;
719 int slot;
720 unsigned char cksum;
721 char *uniname;
722 const char *ip;
723 unsigned long page;
724 int unilen;
725 int i;
726 loff_t offset;
728 if (name[len-1] == '.') len--;
729 if(!(page = __get_free_page(GFP_KERNEL)))
730 return -ENOMEM;
731 uniname = (char *) page;
732 res = xlate_to_uni(name, len, uniname, &unilen, uni_xlate, utf8, nls);
733 if (res < 0) {
734 free_page(page);
735 return res;
738 *slots = unilen / 13;
739 for (cksum = i = 0; i < 11; i++) {
740 cksum = (((cksum&1)<<7)|((cksum&0xfe)>>1)) + msdos_name[i];
742 PRINTK3(("vfat_fill_long_slots 3: slots=%d\n",*slots));
744 for (ps = ds, slot = *slots; slot > 0; slot--, ps++) {
745 ps->id = slot;
746 ps->attr = ATTR_EXT;
747 ps->reserved = 0;
748 ps->alias_checksum = cksum;
749 ps->start = 0;
750 offset = (slot - 1) * 26;
751 ip = &uniname[offset];
752 memcpy(ps->name0_4, ip, 10);
753 memcpy(ps->name5_10, ip+10, 12);
754 memcpy(ps->name11_12, ip+22, 4);
756 ds[0].id |= 0x40;
758 de = (struct msdos_dir_entry *) ps;
759 PRINTK3(("vfat_fill_long_slots 9\n"));
760 strncpy(de->name, msdos_name, MSDOS_NAME);
761 (*slots)++;
763 free_page(page);
764 return 0;
767 /* We can't get "." or ".." here - VFS takes care of those cases */
769 static int vfat_build_slots(struct inode *dir,const char *name,int len,
770 struct msdos_dir_slot *ds, int *slots)
772 struct msdos_dir_entry *de;
773 char msdos_name[MSDOS_NAME];
774 int res, xlate, utf8;
775 struct nls_table *nls;
777 de = (struct msdos_dir_entry *) ds;
778 xlate = MSDOS_SB(dir->i_sb)->options.unicode_xlate;
779 utf8 = MSDOS_SB(dir->i_sb)->options.utf8;
780 nls = MSDOS_SB(dir->i_sb)->nls_io;
782 *slots = 1;
783 res = vfat_valid_longname(name, len, xlate);
784 if (res < 0)
785 return res;
786 if (vfat_valid_shortname(name, len, utf8) >= 0) {
787 vfat_format_name(name, len, de->name, utf8);
788 return 0;
790 res = vfat_create_shortname(dir, name, len, msdos_name, utf8);
791 if (res < 0)
792 return res;
793 return vfat_fill_long_slots(ds, name, len, msdos_name, slots, xlate,
794 utf8, nls);
797 static int vfat_add_entry(struct inode *dir,struct qstr* qname,
798 int is_dir,struct vfat_slot_info *sinfo_out,
799 struct buffer_head **bh, struct msdos_dir_entry **de)
801 struct super_block *sb = dir->i_sb;
802 struct msdos_dir_slot *ps;
803 loff_t offset;
804 struct msdos_dir_slot *ds;
805 int slots, slot;
806 int res;
807 struct msdos_dir_entry *de1;
808 struct buffer_head *bh1;
809 int ino;
810 int len;
811 loff_t dummy;
813 ds = (struct msdos_dir_slot *)
814 kmalloc(sizeof(struct msdos_dir_slot)*MSDOS_SLOTS, GFP_KERNEL);
815 if (ds == NULL) return -ENOMEM;
817 len = qname->len;
818 while (len && qname->name[len-1] == '.')
819 len--;
820 res = fat_search_long(dir, qname->name, len,
821 (MSDOS_SB(sb)->options.name_check != 's') ||
822 !MSDOS_SB(sb)->options.posixfs,
823 &dummy, &dummy);
824 if (res > 0) /* found */
825 res = -EEXIST;
826 if (res)
827 goto cleanup;
829 res = vfat_build_slots(dir, qname->name, len, ds, &slots);
830 if (res < 0) goto cleanup;
832 offset = fat_add_entries(dir, slots, &bh1, &de1, &ino);
833 if (offset < 0) {
834 res = offset;
835 goto cleanup;
837 fat_brelse(sb, bh1);
839 /* Now create the new entry */
840 *bh = NULL;
841 for (slot = 0, ps = ds; slot < slots; slot++, ps++) {
842 if (fat_get_entry(dir,&offset,bh,de, &sinfo_out->ino) < 0) {
843 res = -EIO;
844 goto cleanup;
846 memcpy(*de, ps, sizeof(struct msdos_dir_slot));
847 fat_mark_buffer_dirty(sb, *bh, 1);
850 dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;
851 mark_inode_dirty(dir);
853 fat_date_unix2dos(dir->i_mtime,&(*de)->time,&(*de)->date);
854 (*de)->ctime_ms = 0;
855 (*de)->ctime = (*de)->time;
856 (*de)->adate = (*de)->cdate = (*de)->date;
857 (*de)->start = 0;
858 (*de)->starthi = 0;
859 (*de)->size = 0;
860 (*de)->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
861 (*de)->lcase = CASE_LOWER_BASE | CASE_LOWER_EXT;
864 fat_mark_buffer_dirty(sb, *bh, 1);
866 /* slots can't be less than 1 */
867 sinfo_out->long_slots = slots - 1;
868 sinfo_out->longname_offset = offset - sizeof(struct msdos_dir_slot) * slots;
869 res = 0;
871 cleanup:
872 kfree(ds);
873 return res;
876 static int vfat_find(struct inode *dir,struct qstr* qname,
877 struct vfat_slot_info *sinfo, struct buffer_head **last_bh,
878 struct msdos_dir_entry **last_de)
880 struct super_block *sb = dir->i_sb;
881 loff_t offset;
882 int res,len;
884 len = qname->len;
885 while (len && qname->name[len-1] == '.')
886 len--;
887 res = fat_search_long(dir, qname->name, len,
888 (MSDOS_SB(sb)->options.name_check != 's'),
889 &offset,&sinfo->longname_offset);
890 if (res>0) {
891 sinfo->long_slots = res-1;
892 if (fat_get_entry(dir,&offset,last_bh,last_de,&sinfo->ino)>=0)
893 return 0;
894 res = -EIO;
896 return res ? res : -ENOENT;
899 /* Find a hashed dentry for inode; NULL if there are none */
900 static struct dentry *find_alias(struct inode *inode)
902 struct list_head *head, *next, *tmp;
903 struct dentry *alias;
905 head = &inode->i_dentry;
906 next = inode->i_dentry.next;
907 while (next != head) {
908 tmp = next;
909 next = tmp->next;
910 alias = list_entry(tmp, struct dentry, d_alias);
911 if (!list_empty(&alias->d_hash))
912 return dget(alias);
914 return NULL;
917 struct dentry *vfat_lookup(struct inode *dir,struct dentry *dentry)
919 int res;
920 struct vfat_slot_info sinfo;
921 struct inode *inode;
922 struct dentry *alias;
923 struct buffer_head *bh = NULL;
924 struct msdos_dir_entry *de;
925 int table;
927 PRINTK2(("vfat_lookup: name=%s, len=%d\n",
928 dentry->d_name.name, dentry->d_name.len));
930 table = (MSDOS_SB(dir->i_sb)->options.name_check == 's') ? 2 : 0;
931 dentry->d_op = &vfat_dentry_ops[table];
933 inode = NULL;
934 res = vfat_find(dir,&dentry->d_name,&sinfo,&bh,&de);
935 if (res < 0) {
936 table++;
937 goto error;
939 inode = fat_build_inode(dir->i_sb, de, sinfo.ino, &res);
940 fat_brelse(dir->i_sb, bh);
941 if (res)
942 return ERR_PTR(res);
943 alias = find_alias(inode);
944 if (alias) {
945 if (d_invalidate(alias)==0)
946 dput(alias);
947 else {
948 iput(inode);
949 return alias;
953 error:
954 dentry->d_op = &vfat_dentry_ops[table];
955 dentry->d_time = dentry->d_parent->d_inode->i_version;
956 d_add(dentry,inode);
957 return NULL;
960 int vfat_create(struct inode *dir,struct dentry* dentry,int mode)
962 struct super_block *sb = dir->i_sb;
963 struct inode *inode = NULL;
964 struct buffer_head *bh = NULL;
965 struct msdos_dir_entry *de;
966 struct vfat_slot_info sinfo;
967 int res;
969 res = vfat_add_entry(dir, &dentry->d_name, 0, &sinfo, &bh, &de);
970 if (res < 0)
971 return res;
972 inode = fat_build_inode(sb, de, sinfo.ino, &res);
973 fat_brelse(sb, bh);
974 if (!inode)
975 return res;
976 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
977 mark_inode_dirty(inode);
978 inode->i_version = ++event;
979 dir->i_version = event;
980 dentry->d_time = dentry->d_parent->d_inode->i_version;
981 d_instantiate(dentry,inode);
982 return 0;
985 static void vfat_remove_entry(struct inode *dir,struct vfat_slot_info *sinfo,
986 struct buffer_head *bh, struct msdos_dir_entry *de)
988 struct super_block *sb = dir->i_sb;
989 loff_t offset;
990 int i,ino;
992 /* remove the shortname */
993 dir->i_mtime = CURRENT_TIME;
994 dir->i_atime = CURRENT_TIME;
995 dir->i_version = ++event;
996 mark_inode_dirty(dir);
997 de->name[0] = DELETED_FLAG;
998 fat_mark_buffer_dirty(sb, bh, 1);
999 /* remove the longname */
1000 offset = sinfo->longname_offset; de = NULL;
1001 for (i = sinfo->long_slots; i > 0; --i) {
1002 if (fat_get_entry(dir, &offset, &bh, &de, &ino) < 0)
1003 continue;
1004 de->name[0] = DELETED_FLAG;
1005 de->attr = 0;
1006 fat_mark_buffer_dirty(sb, bh, 1);
1008 if (bh) fat_brelse(sb, bh);
1011 int vfat_rmdir(struct inode *dir,struct dentry* dentry)
1013 int res;
1014 struct vfat_slot_info sinfo;
1015 struct buffer_head *bh = NULL;
1016 struct msdos_dir_entry *de;
1018 if (!list_empty(&dentry->d_hash))
1019 return -EBUSY;
1021 res = fat_dir_empty(dentry->d_inode);
1022 if (res)
1023 return res;
1025 res = vfat_find(dir,&dentry->d_name,&sinfo, &bh, &de);
1026 if (res<0)
1027 return res;
1028 dentry->d_inode->i_nlink = 0;
1029 dentry->d_inode->i_mtime = CURRENT_TIME;
1030 dentry->d_inode->i_atime = CURRENT_TIME;
1031 fat_detach(dentry->d_inode);
1032 mark_inode_dirty(dentry->d_inode);
1033 /* releases bh */
1034 vfat_remove_entry(dir,&sinfo,bh,de);
1035 dir->i_nlink--;
1036 return 0;
1039 int vfat_unlink(struct inode *dir, struct dentry* dentry)
1041 int res;
1042 struct vfat_slot_info sinfo;
1043 struct buffer_head *bh = NULL;
1044 struct msdos_dir_entry *de;
1046 PRINTK1(("vfat_unlink: %s\n", dentry->d_name.name));
1047 res = vfat_find(dir,&dentry->d_name,&sinfo,&bh,&de);
1048 if (res < 0)
1049 return res;
1050 dentry->d_inode->i_nlink = 0;
1051 dentry->d_inode->i_mtime = CURRENT_TIME;
1052 dentry->d_inode->i_atime = CURRENT_TIME;
1053 fat_detach(dentry->d_inode);
1054 mark_inode_dirty(dentry->d_inode);
1055 /* releases bh */
1056 vfat_remove_entry(dir,&sinfo,bh,de);
1057 d_delete(dentry);
1059 return res;
1063 int vfat_mkdir(struct inode *dir,struct dentry* dentry,int mode)
1065 struct super_block *sb = dir->i_sb;
1066 struct inode *inode = NULL;
1067 struct vfat_slot_info sinfo;
1068 struct buffer_head *bh = NULL;
1069 struct msdos_dir_entry *de;
1070 int res;
1072 res = vfat_add_entry(dir, &dentry->d_name, 1, &sinfo, &bh, &de);
1073 if (res < 0)
1074 return res;
1075 inode = fat_build_inode(sb, de, sinfo.ino, &res);
1076 if (!inode)
1077 goto out;
1078 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
1079 mark_inode_dirty(inode);
1080 inode->i_version = ++event;
1081 dir->i_version = event;
1082 dir->i_nlink++;
1083 inode->i_nlink = 2; /* no need to mark them dirty */
1084 res = fat_new_dir(inode, dir, 1);
1085 if (res < 0)
1086 goto mkdir_failed;
1087 dentry->d_time = dentry->d_parent->d_inode->i_version;
1088 d_instantiate(dentry,inode);
1089 out:
1090 fat_brelse(sb, bh);
1091 return res;
1093 mkdir_failed:
1094 inode->i_nlink = 0;
1095 inode->i_mtime = CURRENT_TIME;
1096 inode->i_atime = CURRENT_TIME;
1097 fat_detach(inode);
1098 mark_inode_dirty(inode);
1099 /* releases bh */
1100 vfat_remove_entry(dir,&sinfo,bh,de);
1101 iput(inode);
1102 dir->i_nlink--;
1103 return res;
1106 int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
1107 struct inode *new_dir,struct dentry *new_dentry)
1109 struct super_block *sb = old_dir->i_sb;
1110 struct buffer_head *old_bh,*new_bh,*dotdot_bh;
1111 struct msdos_dir_entry *old_de,*new_de,*dotdot_de;
1112 int dotdot_ino;
1113 struct inode *old_inode, *new_inode;
1114 int res, is_dir;
1115 struct vfat_slot_info old_sinfo,sinfo;
1117 old_bh = new_bh = dotdot_bh = NULL;
1118 old_inode = old_dentry->d_inode;
1119 new_inode = new_dentry->d_inode;
1120 res = vfat_find(old_dir,&old_dentry->d_name,&old_sinfo,&old_bh,&old_de);
1121 PRINTK3(("vfat_rename 2\n"));
1122 if (res < 0) goto rename_done;
1124 is_dir = S_ISDIR(old_inode->i_mode);
1126 if (is_dir && (res = fat_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh,
1127 &dotdot_de,&dotdot_ino)) < 0)
1128 goto rename_done;
1130 if (new_dentry->d_inode) {
1131 res = vfat_find(new_dir,&new_dentry->d_name,&sinfo,&new_bh,
1132 &new_de);
1133 if (res < 0 || MSDOS_I(new_inode)->i_location != sinfo.ino) {
1134 /* WTF??? Cry and fail. */
1135 printk(KERN_WARNING "vfat_rename: fs corrupted\n");
1136 goto rename_done;
1139 if (is_dir) {
1140 res = fat_dir_empty(new_inode);
1141 if (res)
1142 goto rename_done;
1144 fat_detach(new_inode);
1145 } else {
1146 res = vfat_add_entry(new_dir,&new_dentry->d_name,is_dir,&sinfo,
1147 &new_bh,&new_de);
1148 if (res < 0) goto rename_done;
1151 new_dir->i_version = ++event;
1153 /* releases old_bh */
1154 vfat_remove_entry(old_dir,&old_sinfo,old_bh,old_de);
1155 old_bh=NULL;
1156 fat_detach(old_inode);
1157 fat_attach(old_inode, sinfo.ino);
1158 mark_inode_dirty(old_inode);
1160 old_dir->i_version = ++event;
1161 old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
1162 mark_inode_dirty(old_dir);
1163 if (new_inode) {
1164 new_inode->i_nlink--;
1165 new_inode->i_ctime=CURRENT_TIME;
1168 if (is_dir) {
1169 int start = MSDOS_I(new_dir)->i_logstart;
1170 dotdot_de->start = CT_LE_W(start);
1171 dotdot_de->starthi = CT_LE_W(start>>16);
1172 fat_mark_buffer_dirty(sb, dotdot_bh, 1);
1173 old_dir->i_nlink--;
1174 if (new_inode) {
1175 new_inode->i_nlink--;
1176 } else {
1177 new_dir->i_nlink++;
1178 mark_inode_dirty(new_dir);
1182 rename_done:
1183 fat_brelse(sb, dotdot_bh);
1184 fat_brelse(sb, old_bh);
1185 fat_brelse(sb, new_bh);
1186 return res;
1191 /* Public inode operations for the VFAT fs */
1192 struct inode_operations vfat_dir_inode_operations = {
1193 &fat_dir_operations, /* default directory file-ops */
1194 vfat_create, /* create */
1195 vfat_lookup, /* lookup */
1196 NULL, /* link */
1197 vfat_unlink, /* unlink */
1198 NULL, /* symlink */
1199 vfat_mkdir, /* mkdir */
1200 vfat_rmdir, /* rmdir */
1201 NULL, /* mknod */
1202 vfat_rename, /* rename */
1203 NULL, /* readlink */
1204 NULL, /* followlink */
1205 NULL, /* get_block */
1206 NULL, /* readpage */
1207 NULL, /* writepage */
1208 NULL, /* flushpage */
1209 NULL, /* truncate */
1210 NULL, /* permission */
1211 NULL, /* smap */
1212 NULL /* revalidate */
1215 struct super_block *vfat_read_super(struct super_block *sb,void *data,
1216 int silent)
1218 struct super_block *res;
1220 MOD_INC_USE_COUNT;
1222 MSDOS_SB(sb)->options.isvfat = 1;
1224 res = fat_read_super(sb, data, silent, &vfat_dir_inode_operations);
1225 if (res == NULL) {
1226 sb->s_dev = 0;
1227 MOD_DEC_USE_COUNT;
1228 return NULL;
1231 if (!parse_options((char *) data, &(MSDOS_SB(sb)->options))) {
1232 MOD_DEC_USE_COUNT;
1233 } else {
1234 MSDOS_SB(sb)->put_super_callback=vfat_put_super_callback;
1235 MSDOS_SB(sb)->options.dotsOK = 0;
1236 if (MSDOS_SB(sb)->options.posixfs) {
1237 MSDOS_SB(sb)->options.name_check = 's';
1239 if (MSDOS_SB(sb)->options.name_check != 's') {
1240 sb->s_root->d_op = &vfat_dentry_ops[0];
1241 } else {
1242 sb->s_root->d_op = &vfat_dentry_ops[2];
1246 return res;
1249 #ifdef MODULE
1250 int init_module(void)
1252 return init_vfat_fs();
1255 void cleanup_module(void)
1257 unregister_filesystem(&vfat_fs_type);
1260 #endif /* ifdef MODULE */