Linux 2.2.0
[davej-history.git] / fs / vfat / namei.c
blobd832bd99c45b24f88673d6df58c47ffd0b6f566d
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 struct vfat_find_info {
53 const char *name;
54 int len;
55 int new_filename;
56 int found;
57 int is_long;
58 off_t offset;
59 off_t short_offset;
60 int long_slots;
61 ino_t ino;
62 int posix;
63 int anycase;
66 void vfat_read_inode(struct inode *inode);
67 static int vfat_valid_shortname(const char *,int, int, int);
68 static int vfat_format_name(const char *, int, char *, int, int);
69 static int vfat_valid_longname(const char *, int, int, int);
70 static int vfat_hashi(struct dentry *parent, struct qstr *qstr);
71 static int vfat_hash(struct dentry *parent, struct qstr *qstr);
72 static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);
73 static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b);
74 static int vfat_revalidate(struct dentry *dentry);
76 static struct dentry_operations vfat_dentry_ops[4] = {
78 NULL, /* d_revalidate */
79 vfat_hashi,
80 vfat_cmpi,
81 NULL /* d_delete */
84 vfat_revalidate,
85 vfat_hashi,
86 vfat_cmpi,
87 NULL /* d_delete */
90 NULL, /* d_revalidate */
91 vfat_hash,
92 vfat_cmp,
93 NULL /* d_delete */
96 vfat_revalidate,
97 vfat_hash,
98 vfat_cmp,
99 NULL /* d_delete */
103 void vfat_put_super(struct super_block *sb)
105 fat_put_super(sb);
106 MOD_DEC_USE_COUNT;
109 static int vfat_revalidate(struct dentry *dentry)
111 PRINTK1(("vfat_revalidate: %s\n", dentry->d_name.name));
112 if (dentry->d_time == dentry->d_parent->d_inode->i_version) {
113 return 1;
115 return 0;
118 static struct super_operations vfat_sops = {
119 vfat_read_inode,
120 fat_write_inode,
121 fat_put_inode,
122 fat_delete_inode,
123 fat_notify_change,
124 vfat_put_super,
125 NULL, /* write_super */
126 fat_statfs,
127 NULL /* remount */
130 static int simple_getbool(char *s, int *setval)
132 if (s) {
133 if (!strcmp(s,"1") || !strcmp(s,"yes") || !strcmp(s,"true")) {
134 *setval = 1;
135 } else if (!strcmp(s,"0") || !strcmp(s,"no") || !strcmp(s,"false")) {
136 *setval = 0;
137 } else {
138 return 0;
140 } else {
141 *setval = 1;
143 return 1;
146 static int parse_options(char *options, struct fat_mount_options *opts)
148 char *this_char,*value,save,*savep;
149 int ret, val;
151 opts->unicode_xlate = opts->posixfs = 0;
152 opts->numtail = 1;
153 opts->utf8 = 0;
155 if (!options) return 1;
156 save = 0;
157 savep = NULL;
158 ret = 1;
159 for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
160 if ((value = strchr(this_char,'=')) != NULL) {
161 save = *value;
162 savep = value;
163 *value++ = 0;
165 if (!strcmp(this_char,"utf8")) {
166 ret = simple_getbool(value, &val);
167 if (ret) opts->utf8 = val;
168 } else if (!strcmp(this_char,"uni_xlate")) {
169 ret = simple_getbool(value, &val);
170 if (ret) opts->unicode_xlate = val;
171 } else if (!strcmp(this_char,"posix")) {
172 ret = simple_getbool(value, &val);
173 if (ret) opts->posixfs = val;
174 } else if (!strcmp(this_char,"nonumtail")) {
175 ret = simple_getbool(value, &val);
176 if (ret) {
177 opts->numtail = !val;
180 if (this_char != options)
181 *(this_char-1) = ',';
182 if (value) {
183 *savep = save;
185 if (ret == 0) {
186 return 0;
189 if (opts->unicode_xlate) {
190 opts->utf8 = 0;
192 return 1;
196 * Compute the hash for the vfat name corresponding to the dentry.
197 * Note: if the name is invalid, we leave the hash code unchanged so
198 * that the existing dentry can be used. The vfat fs routines will
199 * return ENOENT or EINVAL as appropriate.
201 static int vfat_hash(struct dentry *dentry, struct qstr *qstr)
203 const char *name;
204 int len;
206 len = qstr->len;
207 name = qstr->name;
208 while (len && name[len-1] == '.')
209 len--;
211 qstr->hash = full_name_hash(name, len);
213 return 0;
217 * Compute the hash for the vfat name corresponding to the dentry.
218 * Note: if the name is invalid, we leave the hash code unchanged so
219 * that the existing dentry can be used. The vfat fs routines will
220 * return ENOENT or EINVAL as appropriate.
222 static int vfat_hashi(struct dentry *dentry, struct qstr *qstr)
224 const char *name;
225 int len;
226 char c;
227 unsigned long hash;
229 len = qstr->len;
230 name = qstr->name;
231 while (len && name[len-1] == '.')
232 len--;
234 hash = init_name_hash();
235 while (len--) {
236 c = tolower(*name++);
237 hash = partial_name_hash(tolower(c), hash);
239 qstr->hash = end_name_hash(hash);
241 return 0;
245 * Case insensitive compare of two vfat names.
247 static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b)
249 int alen, blen;
251 /* A filename cannot end in '.' or we treat it like it has none */
252 alen = a->len;
253 blen = b->len;
254 while (alen && a->name[alen-1] == '.')
255 alen--;
256 while (blen && b->name[blen-1] == '.')
257 blen--;
258 if (alen == blen) {
259 if (strnicmp(a->name, b->name, alen) == 0)
260 return 0;
262 return 1;
266 * Case sensitive compare of two vfat names.
268 static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b)
270 int alen, blen;
272 /* A filename cannot end in '.' or we treat it like it has none */
273 alen = a->len;
274 blen = b->len;
275 while (alen && a->name[alen-1] == '.')
276 alen--;
277 while (blen && b->name[blen-1] == '.')
278 blen--;
279 if (alen == blen) {
280 if (strncmp(a->name, b->name, alen) == 0)
281 return 0;
283 return 1;
286 struct super_block *vfat_read_super(struct super_block *sb,void *data,
287 int silent)
289 struct super_block *res;
291 MOD_INC_USE_COUNT;
293 MSDOS_SB(sb)->options.isvfat = 1;
295 sb->s_op = &vfat_sops;
296 res = fat_read_super(sb, data, silent);
297 if (res == NULL) {
298 sb->s_dev = 0;
299 MOD_DEC_USE_COUNT;
300 return NULL;
303 if (!parse_options((char *) data, &(MSDOS_SB(sb)->options))) {
304 MOD_DEC_USE_COUNT;
305 } else {
306 MSDOS_SB(sb)->options.dotsOK = 0;
307 if (MSDOS_SB(sb)->options.posixfs) {
308 MSDOS_SB(sb)->options.name_check = 's';
310 if (MSDOS_SB(sb)->options.name_check != 's') {
311 sb->s_root->d_op = &vfat_dentry_ops[0];
312 } else {
313 sb->s_root->d_op = &vfat_dentry_ops[2];
317 return res;
320 #ifdef DEBUG
322 static void
323 check_stack(const char *fname, int lineno)
325 int stack_level;
326 char *pg_dir;
328 stack_level = (long)(&pg_dir)-current->kernel_stack_page;
329 if (stack_level < 0)
330 printk("*-*-*-* vfat kstack overflow in %s line %d: SL=%d\n",
331 fname, lineno, stack_level);
332 else if (stack_level < 500)
333 printk("*-*-*-* vfat kstack low in %s line %d: SL=%d\n",
334 fname, lineno, stack_level);
335 #if 0
336 else
337 printk("------- vfat kstack ok in %s line %d: SL=%d\n",
338 fname, lineno, stack_level);
339 #endif
340 #if 0
341 if (*(unsigned long *) current->kernel_stack_page != STACK_MAGIC) {
342 printk("******* vfat stack corruption detected in %s at line %d\n",
343 fname, lineno);
345 #endif
348 static int debug = 0;
349 static void dump_fat(struct super_block *sb,int start)
351 printk("[");
352 while (start) {
353 printk("%d ",start);
354 start = fat_access(sb,start,-1);
355 if (!start) {
356 printk("ERROR");
357 break;
359 if (start == -1) break;
361 printk("]\n");
364 static void dump_de(struct msdos_dir_entry *de)
366 int i;
367 unsigned char *p = (unsigned char *) de;
368 printk("[");
370 for (i = 0; i < 32; i++, p++) {
371 printk("%02x ", *p);
373 printk("]\n");
376 #endif
378 /* MS-DOS "device special files" */
380 static const char *reserved3_names[] = {
381 "con ", "prn ", "nul ", "aux ", NULL
384 static const char *reserved4_names[] = {
385 "com1 ", "com2 ", "com3 ", "com4 ", "com5 ",
386 "com6 ", "com7 ", "com8 ", "com9 ",
387 "lpt1 ", "lpt2 ", "lpt3 ", "lpt4 ", "lpt5 ",
388 "lpt6 ", "lpt7 ", "lpt8 ", "lpt9 ",
389 NULL };
392 /* Characters that are undesirable in an MS-DOS file name */
394 static char bad_chars[] = "*?<>|\":/\\";
395 static char replace_chars[] = "[];,+=";
397 static int vfat_find(struct inode *dir,struct qstr* name,
398 int new_filename,int is_dir,
399 struct vfat_slot_info *sinfo_out);
401 /* Checks the validity of a long MS-DOS filename */
402 /* Returns negative number on error, 0 for a normal
403 * return, and 1 for . or .. */
405 static int vfat_valid_longname(const char *name, int len, int dot_dirs,
406 int xlate)
408 const char **reserved, *walk;
409 unsigned char c;
410 int i, baselen;
412 if (IS_FREE(name)) return -EINVAL;
413 if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {
414 if (!dot_dirs) return -EEXIST;
415 return 1;
418 if (len && name[len-1] == ' ') return -EINVAL;
419 if (len >= 256) return -EINVAL;
420 for (i = 0; i < len; i++) {
421 c = name[i];
422 if (xlate && c == ':') continue;
423 if (strchr(bad_chars,c)) {
424 return -EINVAL;
427 if (len < 3) return 0;
429 for (walk = name; *walk != 0 && *walk != '.'; walk++);
430 baselen = walk - name;
432 if (baselen == 3) {
433 for (reserved = reserved3_names; *reserved; reserved++) {
434 if (!strnicmp(name,*reserved,baselen))
435 return -EINVAL;
437 } else if (baselen == 4) {
438 for (reserved = reserved4_names; *reserved; reserved++) {
439 if (!strnicmp(name,*reserved,baselen))
440 return -EINVAL;
443 return 0;
446 static int vfat_valid_shortname(const char *name,int len,
447 int dot_dirs, int utf8)
449 const char *walk;
450 unsigned char c;
451 int space;
452 int baselen;
454 if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {
455 if (!dot_dirs) return -EEXIST;
456 return 1;
459 space = 1; /* disallow names starting with a dot */
460 c = 0;
461 for (walk = name; len && walk-name < 8;) {
462 c = *walk++;
463 len--;
464 if (utf8 && (c & 0x80)) return -EINVAL;
465 if (strchr(replace_chars,c)) return -EINVAL;
466 if (c >= 'A' && c <= 'Z') return -EINVAL;
467 if (c < ' '|| c==':') return -EINVAL;
468 if (c == '.') break;
469 space = c == ' ';
471 if (space) return -EINVAL;
472 if (len && c != '.') {
473 c = *walk++;
474 len--;
475 if (c != '.') return -EINVAL;
477 baselen = walk - name;
478 if (c == '.') {
479 baselen--;
480 if (len >= 4) return -EINVAL;
481 while (len > 0) {
482 c = *walk++;
483 len--;
484 if (utf8 && (c & 0x80)) return -EINVAL;
485 if (strchr(replace_chars,c))
486 return -EINVAL;
487 if (c < ' ' || c == '.'|| c==':')
488 return -EINVAL;
489 if (c >= 'A' && c <= 'Z') return -EINVAL;
490 space = c == ' ';
492 if (space) return -EINVAL;
495 return 0;
498 static int vfat_find_form(struct inode *dir,char *name)
500 struct msdos_dir_entry *de;
501 struct buffer_head *bh = NULL;
502 loff_t pos = 0;
504 while(fat_get_entry(dir, &pos, &bh, &de) >= 0) {
505 if (de->attr == ATTR_EXT)
506 continue;
507 if (memcmp(de->name,name,MSDOS_NAME))
508 continue;
509 brelse(bh);
510 return 0;
512 brelse(bh);
513 return -ENOENT;
516 static int vfat_format_name(const char *name,int len,char *res,
517 int dot_dirs,int utf8)
519 char *walk;
520 unsigned char c;
521 int space;
523 if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {
524 if (!dot_dirs) return -EEXIST;
525 memset(res+1,' ',10);
526 while (len--) *res++ = '.';
527 return 0;
530 space = 1; /* disallow names starting with a dot */
531 for (walk = res; len-- && (c=*name++)!='.' ; walk++) {
532 if (walk-res == 8) return -EINVAL;
533 if (utf8 && (c & 0x80)) return -EINVAL;
534 if (strchr(replace_chars,c)) return -EINVAL;
535 if (c >= 'A' && c <= 'Z') return -EINVAL;
536 if (c < ' '|| c==':') return -EINVAL;
537 space = c == ' ';
538 *walk = c >= 'a' && c <= 'z' ? c-32 : c;
540 if (space) return -EINVAL;
541 if (len >= 0) {
542 while (walk-res < 8) *walk++ = ' ';
543 while (len > 0 && walk-res < MSDOS_NAME) {
544 c = *name++;
545 len--;
546 if (utf8 && (c & 0x80)) return -EINVAL;
547 if (strchr(replace_chars,c))
548 return -EINVAL;
549 if (c < ' ' || c == '.'|| c==':')
550 return -EINVAL;
551 if (c >= 'A' && c <= 'Z') return -EINVAL;
552 space = c == ' ';
553 *walk++ = c >= 'a' && c <= 'z' ? c-32 : c;
555 if (space) return -EINVAL;
556 if (len) return -EINVAL;
558 while (walk-res < MSDOS_NAME) *walk++ = ' ';
560 return 0;
563 static char skip_chars[] = ".:\"?<>| ";
565 /* Given a valid longname, create a unique shortname. Make sure the
566 * shortname does not exist
568 static int vfat_create_shortname(struct inode *dir, const char *name,
569 int len, char *name_res, int utf8)
571 const char *ip, *ext_start, *end;
572 char *p;
573 int sz, extlen, baselen;
574 char msdos_name[13];
575 char base[9], ext[4];
576 int i;
577 char buf[8];
578 const char *name_start;
580 PRINTK2(("Entering vfat_create_shortname: name=%s, len=%d\n", name, len));
581 sz = 0; /* Make compiler happy */
582 if (len && name[len-1]==' ') return -EINVAL;
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, p = msdos_name, ip = name; ; i++, p++, ip++) {
589 if (i == len) {
590 if (vfat_format_name(msdos_name,
591 len, name_res, 1, utf8) < 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;
599 if (*ip == ' ')
600 break;
601 if (*ip >= 'A' && *ip <= 'Z') {
602 *p = *ip + 32;
603 } else {
604 *p = *ip;
609 PRINTK3(("vfat_create_shortname 3\n"));
610 /* Now, we need to create a shortname from the long name */
611 ext_start = end = &name[len];
612 while (--ext_start >= name) {
613 if (*ext_start == '.') {
614 if (ext_start == end - 1) {
615 sz = len;
616 ext_start = NULL;
618 break;
621 if (ext_start == name - 1) {
622 sz = len;
623 ext_start = NULL;
624 } else if (ext_start) {
626 * Names which start with a dot could be just
627 * an extension eg. "...test". In this case Win95
628 * uses the extension as the name and sets no extension.
630 name_start = &name[0];
631 while (name_start < ext_start)
633 if (!strchr(skip_chars,*name_start)) break;
634 name_start++;
636 if (name_start != ext_start) {
637 sz = ext_start - name;
638 ext_start++;
639 } else {
640 sz = len;
641 ext_start=NULL;
645 for (baselen = i = 0, p = base, ip = name; i < sz && baselen < 8; i++)
647 if (utf8 && (*ip & 0x80)) {
648 *p++ = '_';
649 baselen++;
650 } else if (!strchr(skip_chars, *ip)) {
651 if (*ip >= 'a' && *ip <= 'z') {
652 *p = *ip - 32;
653 } else {
654 *p = *ip;
656 if (strchr(replace_chars, *p)) *p='_';
657 p++; baselen++;
659 ip++;
661 if (baselen == 0) {
662 return -EINVAL;
665 extlen = 0;
666 if (ext_start) {
667 for (p = ext, ip = ext_start; extlen < 3 && ip < end; ip++) {
668 if (utf8 && (*ip & 0x80)) {
669 *p++ = '_';
670 extlen++;
671 } else if (!strchr(skip_chars, *ip)) {
672 if (*ip >= 'a' && *ip <= 'z') {
673 *p = *ip - 32;
674 } else {
675 *p = *ip;
677 if (strchr(replace_chars, *p)) *p='_';
678 extlen++;
679 p++;
683 ext[extlen] = '\0';
684 base[baselen] = '\0';
686 /* Yes, it can happen. ".\xe5" would do it. */
687 if (IS_FREE(base))
688 base[0]='_';
690 /* OK, at this point we know that base is not longer than 8 symbols,
691 * ext is not longer than 3, base is nonempty, both don't contain
692 * any bad symbols (lowercase transformed to uppercase).
695 memset(name_res, ' ', MSDOS_NAME);
696 memcpy(name_res,base,baselen);
697 memcpy(name_res+8,ext,extlen);
698 if (MSDOS_SB(dir->i_sb)->options.numtail == 0)
699 if (vfat_find_form(dir, name_res) < 0)
700 return 0;
703 * Try to find a unique extension. This used to
704 * iterate through all possibilities sequentially,
705 * but that gave extremely bad performance. Windows
706 * only tries a few cases before using random
707 * values for part of the base.
710 if (baselen>6)
711 baselen = 6;
712 name_res[baselen] = '~';
713 for (i = 1; i < 10; i++) {
714 name_res[baselen+1] = i + '0';
715 if (vfat_find_form(dir, name_res) < 0)
716 return 0;
719 i = jiffies & 0xffff;
720 sz = (jiffies >> 16) & 0x7;
721 if (baselen>2)
722 baselen = 2;
723 name_res[baselen+4] = '~';
724 name_res[baselen+5] = '1' + sz;
725 while (1) {
726 sprintf(buf, "%04X", i);
727 memcpy(&name_res[baselen], buf, 4);
728 if (vfat_find_form(dir, name_res) < 0)
729 break;
730 i -= 11;
732 return 0;
735 static loff_t vfat_find_free_slots(struct inode *dir,int slots)
737 struct super_block *sb = dir->i_sb;
738 loff_t offset, curr;
739 struct msdos_dir_entry *de;
740 struct buffer_head *bh;
741 struct inode *inode;
742 int ino;
743 int row;
744 int done;
745 int res;
746 int added;
748 PRINTK2(("vfat_find_free_slots: find %d free slots\n", slots));
749 offset = curr = 0;
750 bh = NULL;
751 row = 0;
752 ino = fat_get_entry(dir,&curr,&bh,&de);
754 for (added = 0; added < 2; added++) {
755 while (ino > -1) {
756 done = IS_FREE(de->name);
757 if (done) {
758 inode = iget(sb,ino);
759 if (inode) {
760 /* Directory slots of busy deleted files aren't available yet. */
761 done = !MSDOS_I(inode)->i_busy;
762 /* PRINTK3(("inode %d still busy\n", ino)); */
763 iput(inode);
766 if (done) {
767 row++;
768 if (row == slots) {
769 fat_brelse(sb, bh);
770 /* printk("----- Free offset at %d\n", offset); */
771 return offset;
773 } else {
774 row = 0;
775 offset = curr;
777 ino = fat_get_entry(dir,&curr,&bh,&de);
780 if ((dir->i_ino == MSDOS_ROOT_INO) &&
781 (MSDOS_SB(sb)->fat_bits != 32))
782 return -ENOSPC;
783 if ((res = fat_add_cluster(dir)) < 0) return res;
784 ino = fat_get_entry(dir,&curr,&bh,&de);
786 return -ENOSPC;
789 /* Translate a string, including coded sequences into Unicode */
790 static int
791 xlate_to_uni(const char *name, int len, char *outname, int *outlen,
792 int escape, int utf8, struct nls_table *nls)
794 int i;
795 const unsigned char *ip;
796 char *op;
797 int fill;
798 unsigned char c1, c2, c3;
800 if (utf8) {
801 *outlen = utf8_mbstowcs((__u16 *) outname, name, PAGE_SIZE);
802 if (name[len-1] == '.')
803 *outlen-=2;
804 op = &outname[*outlen * sizeof(__u16)];
805 } else {
806 if (name[len-1] == '.')
807 len--;
808 op = outname;
809 if (nls) {
810 for (i = 0, ip = name, op = outname, *outlen = 0;
811 i < len && *outlen <= 260; i++, *outlen += 1)
813 if (escape && (*ip == ':')) {
814 if (i > len - 4) return -EINVAL;
815 c1 = fat_esc2uni[ip[1]];
816 c2 = fat_esc2uni[ip[2]];
817 c3 = fat_esc2uni[ip[3]];
818 if (c1 == 255 || c2 == 255 || c3 == 255)
819 return -EINVAL;
820 *op++ = (c1 << 4) + (c2 >> 2);
821 *op++ = ((c2 & 0x3) << 6) + c3;
822 ip += 4;
823 } else {
824 *op++ = nls->charset2uni[*ip].uni1;
825 *op++ = nls->charset2uni[*ip].uni2;
826 ip++;
829 } else {
830 for (i = 0, ip = name, op = outname, *outlen = 0;
831 i < len && *outlen <= 260; i++, *outlen += 1)
833 *op++ = *ip++;
834 *op++ = 0;
838 if (*outlen > 260)
839 return -ENAMETOOLONG;
841 if (*outlen % 13) {
842 *op++ = 0;
843 *op++ = 0;
844 *outlen += 1;
845 if (*outlen % 13) {
846 fill = 13 - (*outlen % 13);
847 for (i = 0; i < fill; i++) {
848 *op++ = 0xff;
849 *op++ = 0xff;
851 *outlen += fill;
855 return 0;
858 static int
859 vfat_fill_long_slots(struct msdos_dir_slot *ds, const char *name, int len,
860 char *msdos_name, int *slots,
861 int uni_xlate, int utf8, struct nls_table *nls)
863 struct msdos_dir_slot *ps;
864 struct msdos_dir_entry *de;
865 int res;
866 int slot;
867 unsigned char cksum;
868 char *uniname;
869 const char *ip;
870 unsigned long page;
871 int unilen;
872 int i;
873 loff_t offset;
875 if (name[len-1] == '.') len--;
876 if(!(page = __get_free_page(GFP_KERNEL)))
877 return -ENOMEM;
878 uniname = (char *) page;
879 res = xlate_to_uni(name, len, uniname, &unilen, uni_xlate, utf8, nls);
880 if (res < 0) {
881 free_page(page);
882 return res;
885 *slots = unilen / 13;
886 for (cksum = i = 0; i < 11; i++) {
887 cksum = (((cksum&1)<<7)|((cksum&0xfe)>>1)) + msdos_name[i];
889 PRINTK3(("vfat_fill_long_slots 3: slots=%d\n",*slots));
891 for (ps = ds, slot = *slots; slot > 0; slot--, ps++) {
892 int end, j;
894 PRINTK3(("vfat_fill_long_slots 4\n"));
895 ps->id = slot;
896 ps->attr = ATTR_EXT;
897 ps->reserved = 0;
898 ps->alias_checksum = cksum;
899 ps->start = 0;
900 PRINTK3(("vfat_fill_long_slots 5: uniname=%s\n",uniname));
901 offset = (slot - 1) * 26;
902 ip = &uniname[offset];
903 j = offset;
904 end = 0;
905 for (i = 0; i < 10; i += 2) {
906 ps->name0_4[i] = *ip++;
907 ps->name0_4[i+1] = *ip++;
909 PRINTK3(("vfat_fill_long_slots 6\n"));
910 for (i = 0; i < 12; i += 2) {
911 ps->name5_10[i] = *ip++;
912 ps->name5_10[i+1] = *ip++;
914 PRINTK3(("vfat_fill_long_slots 7\n"));
915 for (i = 0; i < 4; i += 2) {
916 ps->name11_12[i] = *ip++;
917 ps->name11_12[i+1] = *ip++;
920 PRINTK3(("vfat_fill_long_slots 8\n"));
921 ds[0].id |= 0x40;
923 de = (struct msdos_dir_entry *) ps;
924 PRINTK3(("vfat_fill_long_slots 9\n"));
925 strncpy(de->name, msdos_name, MSDOS_NAME);
927 free_page(page);
928 return 0;
931 static int vfat_build_slots(struct inode *dir,const char *name,int len,
932 struct msdos_dir_slot *ds, int *slots, int *is_long)
934 struct msdos_dir_entry *de;
935 char msdos_name[MSDOS_NAME];
936 int res, xlate, utf8;
937 struct nls_table *nls;
939 PRINTK2(("Entering vfat_build_slots: name=%s, len=%d\n", name, len));
940 de = (struct msdos_dir_entry *) ds;
941 xlate = MSDOS_SB(dir->i_sb)->options.unicode_xlate;
942 utf8 = MSDOS_SB(dir->i_sb)->options.utf8;
943 nls = MSDOS_SB(dir->i_sb)->nls_io;
945 *slots = 1;
946 *is_long = 0;
947 if (len == 1 && name[0] == '.') {
948 strncpy(de->name, MSDOS_DOT, MSDOS_NAME);
949 } else if (len == 2 && name[0] == '.' && name[1] == '.') {
950 strncpy(de->name, MSDOS_DOT, MSDOS_NAME);
951 } else {
952 PRINTK3(("vfat_build_slots 4\n"));
953 res = vfat_valid_longname(name, len, 1, xlate);
954 if (res < 0) {
955 return res;
957 res = vfat_valid_shortname(name, len, 1, utf8);
958 if (res > -1) {
959 PRINTK3(("vfat_build_slots 5a\n"));
960 res = vfat_format_name(name, len, de->name, 1, utf8);
961 PRINTK3(("vfat_build_slots 5b\n"));
962 } else {
963 res = vfat_create_shortname(dir, name, len, msdos_name, utf8);
964 if (res < 0) {
965 return res;
968 *is_long = 1;
970 return vfat_fill_long_slots(ds, name, len, msdos_name,
971 slots, xlate, utf8, nls);
974 return 0;
977 static int vfat_readdir_cb(
978 filldir_t filldir,
979 void * buf,
980 const char * name,
981 int name_len,
982 int is_long,
983 off_t offset,
984 off_t short_offset,
985 int long_slots,
986 ino_t ino)
988 struct vfat_find_info *vf = (struct vfat_find_info *) buf;
989 const char *s1, *s2;
990 int i;
992 #ifdef DEBUG
993 if (debug) printk("cb: vf.name=%s, len=%d, name=%s, name_len=%d\n",
994 vf->name, vf->len, name, name_len);
995 #endif
997 if (vf->len != name_len) {
998 return 0;
1001 s1 = name; s2 = vf->name;
1002 for (i = 0; i < name_len; i++) {
1003 if (vf->anycase || (vf->new_filename && !vf->posix)) {
1004 if (tolower(*s1) != tolower(*s2))
1005 return 0;
1006 } else {
1007 if (*s1 != *s2)
1008 return 0;
1010 s1++; s2++;
1012 vf->found = 1;
1013 vf->is_long = is_long;
1014 vf->offset = (offset == 2) ? 0 : offset;
1015 vf->short_offset = (short_offset == 2) ? 0 : short_offset;
1016 vf->long_slots = long_slots;
1017 vf->ino = ino;
1018 return -1;
1021 static int vfat_find(struct inode *dir,struct qstr* qname,
1022 int new_filename,int is_dir,struct vfat_slot_info *sinfo_out)
1024 struct super_block *sb = dir->i_sb;
1025 struct vfat_find_info vf;
1026 struct file fil;
1027 struct buffer_head *bh;
1028 struct msdos_dir_entry *de;
1029 struct msdos_dir_slot *ps;
1030 loff_t offset;
1031 struct msdos_dir_slot *ds;
1032 int is_long;
1033 int slots, slot;
1034 int res;
1036 PRINTK2(("Entering vfat_find\n"));
1038 ds = (struct msdos_dir_slot *)
1039 kmalloc(sizeof(struct msdos_dir_slot)*MSDOS_SLOTS, GFP_KERNEL);
1040 if (ds == NULL) return -ENOMEM;
1042 fil.f_pos = 0;
1043 vf.name = qname->name;
1044 vf.len = qname->len;
1045 while (vf.len && vf.name[vf.len-1] == '.') {
1046 vf.len--;
1048 vf.new_filename = new_filename;
1049 vf.found = 0;
1050 vf.posix = MSDOS_SB(sb)->options.posixfs;
1051 vf.anycase = (MSDOS_SB(sb)->options.name_check != 's');
1052 res = fat_readdirx(dir,&fil,(void *)&vf,vfat_readdir_cb,NULL,1,1,0);
1053 PRINTK3(("vfat_find: Debug 1\n"));
1054 if (res < 0) goto cleanup;
1055 if (vf.found) {
1056 if (new_filename) {
1057 res = -EEXIST;
1058 goto cleanup;
1060 sinfo_out->longname_offset = vf.offset;
1061 sinfo_out->shortname_offset = vf.short_offset;
1062 sinfo_out->is_long = vf.is_long;
1063 sinfo_out->long_slots = vf.long_slots;
1064 sinfo_out->total_slots = vf.long_slots + 1;
1065 sinfo_out->ino = vf.ino;
1067 PRINTK3(("vfat_find: Debug 2\n"));
1068 res = 0;
1069 goto cleanup;
1072 PRINTK3(("vfat_find: Debug 3\n"));
1073 if (!new_filename) {
1074 res = -ENOENT;
1075 goto cleanup;
1078 res = vfat_build_slots(dir, qname->name, vf.len, ds,
1079 &slots, &is_long);
1080 /* Here we either have is_long and slots>=0 or slots==1 */
1081 if (res < 0) goto cleanup;
1083 de = (struct msdos_dir_entry *) ds;
1085 bh = NULL;
1087 PRINTK3(("vfat_find: create file 1\n"));
1088 if (is_long) slots++;
1089 offset = vfat_find_free_slots(dir, slots);
1090 if (offset < 0) {
1091 res = offset;
1092 goto cleanup;
1095 PRINTK3(("vfat_find: create file 2\n"));
1096 /* Now create the new entry */
1097 bh = NULL;
1098 for (slot = 0, ps = ds; slot < slots; slot++, ps++) {
1099 PRINTK3(("vfat_find: create file 3, slot=%d\n",slot));
1100 sinfo_out->ino = fat_get_entry(dir,&offset,&bh,&de);
1101 if (sinfo_out->ino < 0) {
1102 PRINTK3(("vfat_find: problem\n"));
1103 res = sinfo_out->ino;
1104 goto cleanup;
1106 memcpy(de, ps, sizeof(struct msdos_dir_slot));
1107 fat_mark_buffer_dirty(sb, bh, 1);
1110 PRINTK3(("vfat_find: create file 4\n"));
1111 dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;
1112 mark_inode_dirty(dir);
1114 PRINTK3(("vfat_find: create file 5\n"));
1116 fat_date_unix2dos(dir->i_mtime,&de->time,&de->date);
1117 de->ctime_ms = 0;
1118 de->ctime = de->time;
1119 de->adate = de->cdate = de->date;
1120 de->start = 0;
1121 de->starthi = 0;
1122 de->size = 0;
1123 de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
1124 de->lcase = CASE_LOWER_BASE | CASE_LOWER_EXT;
1127 fat_mark_buffer_dirty(sb, bh, 1);
1128 fat_brelse(sb, bh);
1130 /* slots can't be less than 1 */
1131 sinfo_out->is_long = (slots > 1);
1132 sinfo_out->long_slots = slots - 1;
1133 sinfo_out->total_slots = slots;
1134 sinfo_out->shortname_offset = offset - sizeof(struct msdos_dir_slot);
1135 sinfo_out->longname_offset = offset - sizeof(struct msdos_dir_slot) * slots;
1136 res = 0;
1138 cleanup:
1139 kfree(ds);
1140 return res;
1143 int vfat_lookup(struct inode *dir,struct dentry *dentry)
1145 int res;
1146 struct vfat_slot_info sinfo;
1147 struct inode *result;
1148 int table;
1150 PRINTK2(("vfat_lookup: name=%s, len=%d\n",
1151 dentry->d_name.name, dentry->d_name.len));
1153 table = (MSDOS_SB(dir->i_sb)->options.name_check == 's') ? 2 : 0;
1154 dentry->d_op = &vfat_dentry_ops[table];
1156 result = NULL;
1157 if ((res = vfat_find(dir,&dentry->d_name,0,0,&sinfo)) < 0) {
1158 result = NULL;
1159 table++;
1160 goto error;
1162 PRINTK3(("vfat_lookup 4.5\n"));
1163 if (!(result = iget(dir->i_sb,sinfo.ino)))
1164 return -EACCES;
1165 PRINTK3(("vfat_lookup 5\n"));
1166 if (MSDOS_I(result)->i_busy) { /* mkdir in progress */
1167 iput(result);
1168 result = NULL;
1169 table++;
1170 goto error;
1172 PRINTK3(("vfat_lookup 6\n"));
1173 error:
1174 dentry->d_op = &vfat_dentry_ops[table];
1175 dentry->d_time = dentry->d_parent->d_inode->i_version;
1176 d_add(dentry,result);
1177 return 0;
1181 static int vfat_create_entry(struct inode *dir,struct qstr* qname,
1182 int is_dir, struct inode **result)
1184 struct super_block *sb = dir->i_sb;
1185 int res,ino;
1186 loff_t offset;
1187 struct buffer_head *bh;
1188 struct msdos_dir_entry *de;
1189 struct vfat_slot_info sinfo;
1191 *result=0;
1192 PRINTK1(("vfat_create_entry: Entering\n"));
1193 res = vfat_find(dir, qname, 1, is_dir, &sinfo);
1194 if (res < 0) {
1195 return res;
1198 offset = sinfo.shortname_offset;
1200 PRINTK3(("vfat_create_entry 2\n"));
1201 bh = NULL;
1202 ino = fat_get_entry(dir, &offset, &bh, &de);
1203 if (ino < 0) {
1204 PRINTK3(("vfat_mkdir problem\n"));
1205 if (bh)
1206 fat_brelse(sb, bh);
1207 return ino;
1209 PRINTK3(("vfat_create_entry 3\n"));
1211 if ((*result = iget(dir->i_sb,ino)) != NULL)
1212 vfat_read_inode(*result);
1213 fat_brelse(sb, bh);
1214 if (!*result)
1215 return -EIO;
1216 (*result)->i_mtime = (*result)->i_atime = (*result)->i_ctime =
1217 CURRENT_TIME;
1218 mark_inode_dirty(*result);
1219 (*result)->i_version = ++event;
1220 dir->i_version = event;
1222 return 0;
1225 int vfat_create(struct inode *dir,struct dentry* dentry,int mode)
1227 int res;
1228 struct inode *result;
1230 result=NULL;
1231 fat_lock_creation();
1232 res = vfat_create_entry(dir,&dentry->d_name,0,&result);
1233 fat_unlock_creation();
1234 if (res < 0) {
1235 PRINTK3(("vfat_create: unable to get new entry\n"));
1236 } else {
1237 dentry->d_time = dentry->d_parent->d_inode->i_version;
1238 d_instantiate(dentry,result);
1240 return res;
1243 static int vfat_create_a_dotdir(struct inode *dir,struct inode *parent,
1244 struct buffer_head *bh,
1245 struct msdos_dir_entry *de,int ino,const char *name, int isdot)
1247 struct super_block *sb = dir->i_sb;
1248 struct inode *dot;
1250 PRINTK2(("vfat_create_a_dotdir: Entering\n"));
1253 * XXX all times should be set by caller upon successful completion.
1255 dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
1256 mark_inode_dirty(dir);
1257 memcpy(de->name,name,MSDOS_NAME);
1258 de->lcase = 0;
1259 de->attr = ATTR_DIR;
1260 de->start = 0;
1261 de->starthi = 0;
1262 fat_date_unix2dos(dir->i_mtime,&de->time,&de->date);
1263 de->ctime_ms = 0;
1264 de->ctime = de->time;
1265 de->adate = de->cdate = de->date;
1266 de->size = 0;
1267 fat_mark_buffer_dirty(sb, bh, 1);
1268 dot = iget(dir->i_sb,ino);
1269 if (!dot)
1270 return -EIO;
1271 vfat_read_inode(dot);
1272 dot->i_mtime = dot->i_atime = CURRENT_TIME;
1273 mark_inode_dirty(dot);
1274 if (isdot) {
1275 dot->i_size = dir->i_size;
1276 MSDOS_I(dot)->i_start = MSDOS_I(dir)->i_start;
1277 MSDOS_I(dot)->i_logstart = MSDOS_I(dir)->i_logstart;
1278 dot->i_nlink = dir->i_nlink;
1279 } else {
1280 dot->i_size = parent->i_size;
1281 MSDOS_I(dot)->i_start = MSDOS_I(parent)->i_start;
1282 MSDOS_I(dot)->i_logstart = MSDOS_I(parent)->i_logstart;
1283 dot->i_nlink = parent->i_nlink;
1286 iput(dot);
1288 PRINTK3(("vfat_create_a_dotdir 2\n"));
1289 return 0;
1292 static int vfat_create_dotdirs(struct inode *dir, struct inode *parent)
1294 struct super_block *sb = dir->i_sb;
1295 int res;
1296 struct buffer_head *bh;
1297 struct msdos_dir_entry *de;
1298 loff_t offset;
1300 PRINTK2(("vfat_create_dotdirs: Entering\n"));
1301 if ((res = fat_add_cluster(dir)) < 0) return res;
1303 PRINTK3(("vfat_create_dotdirs 2\n"));
1304 offset = 0;
1305 bh = NULL;
1306 if ((res = fat_get_entry(dir,&offset,&bh,&de)) < 0) return res;
1308 PRINTK3(("vfat_create_dotdirs 3\n"));
1309 res = vfat_create_a_dotdir(dir, parent, bh, de, res, MSDOS_DOT, 1);
1310 PRINTK3(("vfat_create_dotdirs 4\n"));
1311 if (res < 0) {
1312 fat_brelse(sb, bh);
1313 return res;
1315 PRINTK3(("vfat_create_dotdirs 5\n"));
1317 if ((res = fat_get_entry(dir,&offset,&bh,&de)) < 0) {
1318 fat_brelse(sb, bh);
1319 return res;
1321 PRINTK3(("vfat_create_dotdirs 6\n"));
1323 res = vfat_create_a_dotdir(dir, parent, bh, de, res, MSDOS_DOTDOT, 0);
1324 PRINTK3(("vfat_create_dotdirs 7\n"));
1325 fat_brelse(sb, bh);
1327 return res;
1330 /***** See if directory is empty */
1331 static int vfat_empty(struct inode *dir)
1333 struct super_block *sb = dir->i_sb;
1334 loff_t pos;
1335 struct buffer_head *bh;
1336 struct msdos_dir_entry *de;
1338 if (MSDOS_I(dir)->i_start) { /* may be zero in mkdir */
1339 pos = 0;
1340 bh = NULL;
1341 while (fat_get_entry(dir,&pos,&bh,&de) > -1) {
1342 /* Skip extended filename entries */
1343 if (de->attr == ATTR_EXT) continue;
1345 if (!IS_FREE(de->name) && strncmp(de->name,MSDOS_DOT,
1346 MSDOS_NAME) && strncmp(de->name,MSDOS_DOTDOT,
1347 MSDOS_NAME)) {
1348 fat_brelse(sb, bh);
1349 return -ENOTEMPTY;
1352 if (bh)
1353 fat_brelse(sb, bh);
1355 return 0;
1358 static void vfat_free_ino(struct inode *dir,struct buffer_head *bh,
1359 struct msdos_dir_entry *de,struct inode* victim)
1361 struct super_block *sb = dir->i_sb;
1362 victim->i_nlink = 0;
1363 victim->i_mtime = dir->i_mtime = CURRENT_TIME;
1364 victim->i_atime = dir->i_atime = CURRENT_TIME;
1365 dir->i_version = ++event;
1366 MSDOS_I(victim)->i_busy = 1;
1367 mark_inode_dirty(dir);
1368 mark_inode_dirty(victim);
1369 de->name[0] = DELETED_FLAG;
1370 fat_mark_buffer_dirty(sb, bh, 1);
1373 static int vfat_remove_entry(struct inode *dir,struct vfat_slot_info *sinfo,
1374 struct inode* victim)
1376 struct super_block *sb = dir->i_sb;
1377 loff_t offset;
1378 struct buffer_head *bh=NULL;
1379 struct msdos_dir_entry *de;
1380 int res, i;
1382 /* remove the shortname */
1383 offset = sinfo->shortname_offset;
1384 res = fat_get_entry(dir, &offset, &bh, &de);
1385 if (res < 0) return res;
1386 vfat_free_ino(dir,bh,de,victim);
1387 /* remove the longname */
1388 offset = sinfo->longname_offset;
1389 for (i = sinfo->long_slots; i > 0; --i) {
1390 if (fat_get_entry(dir, &offset, &bh, &de) < 0)
1391 continue;
1392 de->name[0] = DELETED_FLAG;
1393 de->attr = 0;
1394 fat_mark_buffer_dirty(sb, bh, 1);
1396 if (bh) fat_brelse(sb, bh);
1397 return 0;
1400 /* Drop all aliases */
1401 static void drop_aliases(struct dentry *dentry)
1403 struct list_head *head, *next, *tmp;
1404 struct dentry *alias;
1406 PRINTK1(("drop_replace_inodes: dentry=%p, inode=%p\n", dentry, inode));
1407 head = &dentry->d_inode->i_dentry;
1408 if (dentry->d_inode) {
1409 next = dentry->d_inode->i_dentry.next;
1410 while (next != head) {
1411 tmp = next;
1412 next = tmp->next;
1413 alias = list_entry(tmp, struct dentry, d_alias);
1414 if (alias == dentry)
1415 continue;
1417 d_drop(alias);
1422 static int vfat_rmdirx(struct inode *dir,struct dentry* dentry)
1424 int res;
1425 struct vfat_slot_info sinfo;
1427 PRINTK1(("vfat_rmdirx: dentry=%p\n", dentry));
1428 res = vfat_find(dir,&dentry->d_name,0,0,&sinfo);
1430 if (res >= 0 && sinfo.total_slots > 0) {
1431 if (!list_empty(&dentry->d_hash))
1432 return -EBUSY;
1433 /* Take care of aliases */
1434 if (dentry->d_inode->i_count > 1) {
1435 shrink_dcache_parent(dentry->d_parent);
1436 if (dentry->d_inode->i_count > 1)
1437 return -EBUSY;
1439 res = vfat_empty(dentry->d_inode);
1440 if (res)
1441 return res;
1443 res = vfat_remove_entry(dir,&sinfo,dentry->d_inode);
1444 if (res >= 0) {
1445 dir->i_nlink--;
1446 res = 0;
1449 return res;
1452 /***** Remove a directory */
1453 int vfat_rmdir(struct inode *dir,struct dentry* dentry)
1455 int res;
1456 PRINTK1(("vfat_rmdir: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
1458 res = -EBUSY;
1459 if (list_empty(&dentry->d_hash)) {
1460 res = vfat_rmdirx(dir, dentry);
1461 /* If that went OK all aliases are already dropped */
1463 return res;
1466 static int vfat_unlinkx(
1467 struct inode *dir,
1468 struct dentry* dentry,
1469 int nospc) /* Flag special file ? */
1471 int res;
1472 struct vfat_slot_info sinfo;
1474 PRINTK1(("vfat_unlinkx: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
1475 res = vfat_find(dir,&dentry->d_name,0,0,&sinfo);
1477 if (res >= 0 && sinfo.total_slots > 0) {
1478 if (!S_ISREG(dentry->d_inode->i_mode) && nospc) {
1479 return -EPERM;
1481 res = vfat_remove_entry(dir,&sinfo,dentry->d_inode);
1482 if (res > 0) {
1483 res = 0;
1487 return res;
1491 int vfat_mkdir(struct inode *dir,struct dentry* dentry,int mode)
1493 struct inode *inode;
1494 struct vfat_slot_info sinfo;
1495 int res;
1497 PRINTK1(("vfat_mkdir: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
1498 fat_lock_creation();
1499 if ((res = vfat_create_entry(dir,&dentry->d_name,1,&inode)) < 0) {
1500 fat_unlock_creation();
1501 return res;
1504 dir->i_nlink++;
1505 inode->i_nlink = 2; /* no need to mark them dirty */
1507 res = vfat_create_dotdirs(inode, dir);
1508 if (res < 0)
1509 goto mkdir_failed;
1510 fat_unlock_creation();
1511 dentry->d_time = dentry->d_parent->d_inode->i_version;
1512 d_instantiate(dentry,inode);
1513 return res;
1515 mkdir_failed:
1516 fat_unlock_creation();
1517 if (vfat_find(dir,&dentry->d_name,0,0,&sinfo) < 0)
1518 goto mkdir_panic;
1519 if (vfat_remove_entry(dir, &sinfo, inode) < 0)
1520 goto mkdir_panic;
1521 iput(inode);
1522 dir->i_nlink--;
1523 return res;
1525 mkdir_panic:
1526 dir->i_version = ++event;
1527 fat_fs_panic(dir->i_sb,"rmdir in mkdir failed");
1528 return res;
1531 /***** Unlink, as called for msdosfs */
1532 int vfat_unlink(struct inode *dir,struct dentry* dentry)
1534 int res;
1536 PRINTK1(("vfat_unlink: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
1537 res = vfat_unlinkx (dir,dentry,1);
1538 if (res >= 0) {
1539 drop_aliases(dentry);
1540 d_delete(dentry);
1542 return res;
1545 /***** Unlink, as called for uvfatfs */
1546 int vfat_unlink_uvfat(struct inode *dir,struct dentry *dentry)
1548 int res;
1550 res = vfat_unlinkx (dir,dentry,0);
1551 iput(dir);
1552 return res;
1555 int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
1556 struct inode *new_dir,struct dentry *new_dentry)
1558 struct super_block *sb = old_dir->i_sb;
1559 struct buffer_head *old_bh,*new_bh,*dotdot_bh;
1560 struct msdos_dir_entry *old_de,*dotdot_de;
1561 loff_t old_offset,new_offset,old_longname_offset;
1562 int old_slots,old_ino,new_ino,dotdot_ino;
1563 struct inode *old_inode, *new_inode, *dotdot_inode;
1564 struct dentry *walk;
1565 int res, is_dir, i;
1566 int locked = 0;
1567 struct vfat_slot_info sinfo;
1569 PRINTK1(("vfat_rename: Entering: old_dentry=%p, old_inode=%p, old ino=%ld, new_dentry=%p, new_inode=%p, new ino=%ld\n",
1570 old_dentry, old_dentry->d_inode, old_dentry->d_inode->i_ino,
1571 new_dentry, new_dentry->d_inode,
1572 new_dentry->d_inode ? new_dentry->d_inode->i_ino : 0));
1574 * POSIX is braindead (surprise, surprise). It requires that rename()
1575 * should return 0 and do nothing if the target has the same inode as
1576 * the source. Somebody, get a time machine, return to '89 and tell
1577 * RMS & Co *not* to do that idiocy, FAST!
1579 if (old_dentry->d_inode == new_dentry->d_inode)
1580 return 0;
1582 old_bh = new_bh = NULL;
1583 old_inode = new_inode = NULL;
1584 res = vfat_find(old_dir,&old_dentry->d_name,0,0,&sinfo);
1585 PRINTK3(("vfat_rename 2\n"));
1586 if (res < 0) goto rename_done;
1588 old_slots = sinfo.total_slots;
1589 old_longname_offset = sinfo.longname_offset;
1590 old_offset = sinfo.shortname_offset;
1591 old_ino = sinfo.ino;
1592 res = fat_get_entry(old_dir, &old_offset, &old_bh, &old_de);
1593 PRINTK3(("vfat_rename 3\n"));
1594 if (res < 0) goto rename_done;
1596 res = -ENOENT;
1597 old_inode = old_dentry->d_inode;
1598 is_dir = S_ISDIR(old_inode->i_mode);
1601 * Race: we can be hit by another rename after this check.
1602 * For the time being use fat_lock_creation(), but it's
1603 * ugly. FIXME.
1606 fat_lock_creation(); locked = 1;
1608 if (is_dir) {
1609 /* We can't use d_subdir() here. Arrgh. */
1610 for (walk=new_dentry;walk!=walk->d_parent;walk=walk->d_parent) {
1611 if (walk->d_inode != old_dentry->d_inode)
1612 continue;
1613 res = -EINVAL;
1614 goto rename_done;
1618 if (new_dentry->d_inode) {
1620 * OK, we have to remove the target. We should do it so
1621 * that nobody might go and find it negative. Actually we
1622 * should give warranties wrt preserving target over the
1623 * possible crash, but that's another story. We can't
1624 * get here with the target unhashed, so the directory entry
1625 * must exist.
1628 new_inode = new_dentry->d_inode;
1629 res = vfat_find(new_dir,&new_dentry->d_name,0,is_dir,&sinfo);
1630 if (res < 0 || new_inode->i_ino != sinfo.ino) {
1631 /* WTF??? Cry and fail. */
1632 printk(KERN_WARNING "vfat_rename: fs corrupted\n");
1633 goto rename_done;
1636 if (is_dir) {
1638 * Target is a directory. No other owners will
1639 * be tolerated.
1641 res = -EBUSY;
1642 if (d_invalidate(new_dentry) < 0)
1643 goto rename_done;
1645 * OK, let's try to get rid of other dentries.
1646 * No need to do it if i_count is 1.
1648 if (new_inode->i_count>1) {
1649 shrink_dcache_parent(new_dentry->d_parent);
1650 if (new_inode->i_count>1)
1651 goto rename_done;
1653 res = vfat_empty(new_inode);
1654 if (res)
1655 goto rename_done;
1656 } else {
1657 drop_aliases(new_dentry);
1659 res = vfat_remove_entry(new_dir,&sinfo,new_inode);
1660 if (res)
1661 goto rename_done;
1664 /* Serious lossage here. FAT uses braindead inode numbers scheme,
1665 * so we can't simply cannibalize the entry. It means that we have
1666 * no warranties that crash here will not make target disappear
1667 * after reboot. Lose, lose. Nothing to do with that until we'll
1668 * separate the functions of i_ino: it serves both as a search key
1669 * in icache and as a part of stat output. It would kill all the
1670 * 'busy' stuff on the spot. Later.
1673 if (is_dir)
1674 new_dir->i_nlink--;
1676 res = vfat_find(new_dir,&new_dentry->d_name,1,is_dir,&sinfo);
1678 if (res < 0) goto rename_done;
1680 new_offset = sinfo.shortname_offset;
1681 new_ino = sinfo.ino;
1683 /* XXX: take care of other owners */
1685 remove_inode_hash(old_inode);
1686 fat_cache_inval_inode(old_inode);
1687 old_inode->i_ino = new_ino;
1688 old_inode->i_version = ++event;
1689 insert_inode_hash(old_inode);
1690 mark_inode_dirty(old_inode);
1692 old_dir->i_version = ++event;
1693 new_dir->i_version = ++event;
1695 /* remove the old entry */
1696 for (i = old_slots; i > 0; --i) {
1697 res = fat_get_entry(old_dir, &old_longname_offset, &old_bh, &old_de);
1698 if (res < 0) {
1699 printk("vfat_rename: problem 1\n");
1700 continue;
1702 old_de->name[0] = DELETED_FLAG;
1703 old_de->attr = 0;
1704 fat_mark_buffer_dirty(sb, old_bh, 1);
1707 if (is_dir) {
1708 if ((res = fat_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh,
1709 &dotdot_de,&dotdot_ino,SCAN_ANY)) < 0) goto rename_done;
1710 if (!(dotdot_inode = iget(old_inode->i_sb,dotdot_ino))) {
1711 fat_brelse(sb, dotdot_bh);
1712 res = -EIO;
1713 goto rename_done;
1715 MSDOS_I(dotdot_inode)->i_start = MSDOS_I(new_dir)->i_start;
1716 MSDOS_I(dotdot_inode)->i_logstart = MSDOS_I(new_dir)->i_logstart;
1717 dotdot_de->start = CT_LE_W(MSDOS_I(new_dir)->i_logstart);
1718 dotdot_de->starthi = CT_LE_W((MSDOS_I(new_dir)->i_logstart) >> 16);
1719 mark_inode_dirty(dotdot_inode);
1720 fat_mark_buffer_dirty(sb, dotdot_bh, 1);
1721 old_dir->i_nlink--;
1722 new_dir->i_nlink++;
1723 /* no need to mark them dirty */
1724 dotdot_inode->i_nlink = new_dir->i_nlink;
1725 iput(dotdot_inode);
1726 fat_brelse(sb, dotdot_bh);
1729 if (res >= 0) {
1730 if (new_inode && is_dir)
1731 d_rehash(new_dentry);
1732 d_move(old_dentry, new_dentry);
1733 res = 0;
1736 rename_done:
1737 if (locked)
1738 fat_unlock_creation();
1739 if (old_bh)
1740 fat_brelse(sb, old_bh);
1741 if (new_bh)
1742 fat_brelse(sb, new_bh);
1743 return res;
1749 /* Public inode operations for the VFAT fs */
1750 struct inode_operations vfat_dir_inode_operations = {
1751 &fat_dir_operations, /* default directory file-ops */
1752 vfat_create, /* create */
1753 vfat_lookup, /* lookup */
1754 NULL, /* link */
1755 vfat_unlink, /* unlink */
1756 NULL, /* symlink */
1757 vfat_mkdir, /* mkdir */
1758 vfat_rmdir, /* rmdir */
1759 NULL, /* mknod */
1760 vfat_rename, /* rename */
1761 NULL, /* readlink */
1762 NULL, /* followlink */
1763 NULL, /* readpage */
1764 NULL, /* writepage */
1765 NULL, /* bmap */
1766 NULL, /* truncate */
1767 NULL /* permission */
1771 void vfat_read_inode(struct inode *inode)
1773 fat_read_inode(inode, &vfat_dir_inode_operations);
1776 #ifdef MODULE
1777 int init_module(void)
1779 return init_vfat_fs();
1782 void cleanup_module(void)
1784 unregister_filesystem(&vfat_fs_type);
1787 #endif /* ifdef MODULE */