Import 2.1.116pre2
[davej-history.git] / fs / vfat / namei.c
blobbe37113d54728acafbbfd4eb020c044fcdb8ca56
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 static int strnicmp(const char *s1, const char *s2, int len)
105 int n = 0;
106 while (*s1 && *s2 && (tolower(*s1) == tolower(*s2))) {
107 s1++; s2++; n++;
108 if (n == len) return 0;
110 if (*s1 == 0 && *s2 == 0) return 0;
111 if (*s1 && *s2) {
112 if (*s1 > *s2) return 1;
113 return -1;
115 if (*s1) return 1;
116 return -1;
119 void vfat_put_super(struct super_block *sb)
121 fat_put_super(sb);
122 MOD_DEC_USE_COUNT;
125 static int vfat_revalidate(struct dentry *dentry)
127 PRINTK1(("vfat_revalidate: %s\n", dentry->d_name.name));
128 if (dentry->d_time == dentry->d_parent->d_inode->i_version) {
129 return 1;
131 return 0;
134 static struct super_operations vfat_sops = {
135 vfat_read_inode,
136 fat_write_inode,
137 fat_put_inode,
138 fat_delete_inode,
139 fat_notify_change,
140 vfat_put_super,
141 NULL, /* write_super */
142 fat_statfs,
143 NULL /* remount */
146 static int simple_getbool(char *s, int *setval)
148 if (s) {
149 if (!strcmp(s,"1") || !strcmp(s,"yes") || !strcmp(s,"true")) {
150 *setval = 1;
151 } else if (!strcmp(s,"0") || !strcmp(s,"no") || !strcmp(s,"false")) {
152 *setval = 0;
153 } else {
154 return 0;
156 } else {
157 *setval = 1;
159 return 1;
162 static int parse_options(char *options, struct fat_mount_options *opts)
164 char *this_char,*value,save,*savep;
165 int ret, val;
167 opts->unicode_xlate = opts->posixfs = 0;
168 opts->numtail = 1;
169 opts->utf8 = 0;
171 if (!options) return 1;
172 save = 0;
173 savep = NULL;
174 ret = 1;
175 for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
176 if ((value = strchr(this_char,'=')) != NULL) {
177 save = *value;
178 savep = value;
179 *value++ = 0;
181 if (!strcmp(this_char,"utf8")) {
182 ret = simple_getbool(value, &val);
183 if (ret) opts->utf8 = val;
184 } else if (!strcmp(this_char,"uni_xlate")) {
185 ret = simple_getbool(value, &val);
186 if (ret) opts->unicode_xlate = val;
187 } else if (!strcmp(this_char,"posix")) {
188 ret = simple_getbool(value, &val);
189 if (ret) opts->posixfs = val;
190 } else if (!strcmp(this_char,"nonumtail")) {
191 ret = simple_getbool(value, &val);
192 if (ret) {
193 opts->numtail = !val;
196 if (this_char != options)
197 *(this_char-1) = ',';
198 if (value) {
199 *savep = save;
201 if (ret == 0) {
202 return 0;
205 if (opts->unicode_xlate) {
206 opts->utf8 = 0;
208 return 1;
212 * Compute the hash for the vfat name corresponding to the dentry.
213 * Note: if the name is invalid, we leave the hash code unchanged so
214 * that the existing dentry can be used. The vfat fs routines will
215 * return ENOENT or EINVAL as appropriate.
217 static int vfat_hash(struct dentry *dentry, struct qstr *qstr)
219 const char *name;
220 int len;
222 len = qstr->len;
223 name = qstr->name;
224 while (len && name[len-1] == '.')
225 len--;
227 qstr->hash = full_name_hash(name, len);
229 return 0;
233 * Compute the hash for the vfat name corresponding to the dentry.
234 * Note: if the name is invalid, we leave the hash code unchanged so
235 * that the existing dentry can be used. The vfat fs routines will
236 * return ENOENT or EINVAL as appropriate.
238 static int vfat_hashi(struct dentry *dentry, struct qstr *qstr)
240 const char *name;
241 int len;
242 char c;
243 unsigned long hash;
245 len = qstr->len;
246 name = qstr->name;
247 while (len && name[len-1] == '.')
248 len--;
250 hash = init_name_hash();
251 while (len--) {
252 c = tolower(*name++);
253 hash = partial_name_hash(tolower(c), hash);
255 qstr->hash = end_name_hash(hash);
257 return 0;
261 * Case insensitive compare of two vfat names.
263 static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b)
265 int alen, blen;
267 /* A filename cannot end in '.' or we treat it like it has none */
268 alen = a->len;
269 blen = b->len;
270 while (alen && a->name[alen-1] == '.')
271 alen--;
272 while (blen && b->name[blen-1] == '.')
273 blen--;
274 if (alen == blen) {
275 if (strnicmp(a->name, b->name, alen) == 0)
276 return 0;
278 return 1;
282 * Case sensitive compare of two vfat names.
284 static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b)
286 int alen, blen;
288 /* A filename cannot end in '.' or we treat it like it has none */
289 alen = a->len;
290 blen = b->len;
291 while (alen && a->name[alen-1] == '.')
292 alen--;
293 while (blen && b->name[blen-1] == '.')
294 blen--;
295 if (alen == blen) {
296 if (strncmp(a->name, b->name, alen) == 0)
297 return 0;
299 return 1;
302 struct super_block *vfat_read_super(struct super_block *sb,void *data,
303 int silent)
305 struct super_block *res;
307 MOD_INC_USE_COUNT;
309 MSDOS_SB(sb)->options.isvfat = 1;
311 sb->s_op = &vfat_sops;
312 res = fat_read_super(sb, data, silent);
313 if (res == NULL) {
314 sb->s_dev = 0;
315 MOD_DEC_USE_COUNT;
316 return NULL;
319 if (!parse_options((char *) data, &(MSDOS_SB(sb)->options))) {
320 MOD_DEC_USE_COUNT;
321 } else {
322 MSDOS_SB(sb)->options.dotsOK = 0;
323 if (MSDOS_SB(sb)->options.posixfs) {
324 MSDOS_SB(sb)->options.name_check = 's';
326 if (MSDOS_SB(sb)->options.name_check != 's') {
327 sb->s_root->d_op = &vfat_dentry_ops[0];
328 } else {
329 sb->s_root->d_op = &vfat_dentry_ops[2];
333 return res;
336 #ifdef DEBUG
338 static void
339 check_stack(const char *fname, int lineno)
341 int stack_level;
342 char *pg_dir;
344 stack_level = (long)(&pg_dir)-current->kernel_stack_page;
345 if (stack_level < 0)
346 printk("*-*-*-* vfat kstack overflow in %s line %d: SL=%d\n",
347 fname, lineno, stack_level);
348 else if (stack_level < 500)
349 printk("*-*-*-* vfat kstack low in %s line %d: SL=%d\n",
350 fname, lineno, stack_level);
351 #if 0
352 else
353 printk("------- vfat kstack ok in %s line %d: SL=%d\n",
354 fname, lineno, stack_level);
355 #endif
356 #if 0
357 if (*(unsigned long *) current->kernel_stack_page != STACK_MAGIC) {
358 printk("******* vfat stack corruption detected in %s at line %d\n",
359 fname, lineno);
361 #endif
364 static int debug = 0;
365 static void dump_fat(struct super_block *sb,int start)
367 printk("[");
368 while (start) {
369 printk("%d ",start);
370 start = fat_access(sb,start,-1);
371 if (!start) {
372 printk("ERROR");
373 break;
375 if (start == -1) break;
377 printk("]\n");
380 static void dump_de(struct msdos_dir_entry *de)
382 int i;
383 unsigned char *p = (unsigned char *) de;
384 printk("[");
386 for (i = 0; i < 32; i++, p++) {
387 printk("%02x ", *p);
389 printk("]\n");
392 #endif
394 /* MS-DOS "device special files" */
396 static const char *reserved3_names[] = {
397 "con ", "prn ", "nul ", "aux ", NULL
400 static const char *reserved4_names[] = {
401 "com1 ", "com2 ", "com3 ", "com4 ", "com5 ",
402 "com6 ", "com7 ", "com8 ", "com9 ",
403 "lpt1 ", "lpt2 ", "lpt3 ", "lpt4 ", "lpt5 ",
404 "lpt6 ", "lpt7 ", "lpt8 ", "lpt9 ",
405 NULL };
408 /* Characters that are undesirable in an MS-DOS file name */
410 static char bad_chars[] = "*?<>|\":/\\";
411 static char replace_chars[] = "[];,+=";
413 static int vfat_find(struct inode *dir,struct qstr* name,
414 int find_long,int new_filename,int is_dir,
415 struct vfat_slot_info *sinfo_out);
417 /* Checks the validity of a long MS-DOS filename */
418 /* Returns negative number on error, 0 for a normal
419 * return, and 1 for . or .. */
421 static int vfat_valid_longname(const char *name, int len, int dot_dirs,
422 int xlate)
424 const char **reserved, *walk;
425 unsigned char c;
426 int i, baselen;
428 if (IS_FREE(name)) return -EINVAL;
429 if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {
430 if (!dot_dirs) return -EEXIST;
431 return 1;
434 if (len && name[len-1] == ' ') return -EINVAL;
435 if (len >= 256) return -EINVAL;
436 for (i = 0; i < len; i++) {
437 c = name[i];
438 if (xlate && c == ':') continue;
439 if (strchr(bad_chars,c)) {
440 return -EINVAL;
443 if (len < 3) return 0;
445 for (walk = name; *walk != 0 && *walk != '.'; walk++);
446 baselen = walk - name;
448 if (baselen == 3) {
449 for (reserved = reserved3_names; *reserved; reserved++) {
450 if (!strnicmp(name,*reserved,baselen))
451 return -EINVAL;
453 } else if (baselen == 4) {
454 for (reserved = reserved4_names; *reserved; reserved++) {
455 if (!strnicmp(name,*reserved,baselen))
456 return -EINVAL;
459 return 0;
462 static int vfat_valid_shortname(const char *name,int len,
463 int dot_dirs, int utf8)
465 const char *walk, **reserved;
466 unsigned char c;
467 int space;
468 int baselen;
470 if (IS_FREE(name)) return -EINVAL;
471 if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {
472 if (!dot_dirs) return -EEXIST;
473 return 1;
476 space = 1; /* disallow names starting with a dot */
477 c = 0;
478 for (walk = name; len && walk-name < 8;) {
479 c = *walk++;
480 len--;
481 if (utf8 && (c & 0x80)) return -EINVAL;
482 if (strchr(bad_chars,c)) return -EINVAL;
483 if (strchr(replace_chars,c)) return -EINVAL;
484 if (c >= 'A' && c <= 'Z') return -EINVAL;
485 if (c < ' ' || c == ':' || c == '\\') return -EINVAL;
486 if ((walk == name) && (c == 0xE5)) c = 0x05;
487 if (c == '.') break;
488 space = c == ' ';
490 if (space) return -EINVAL;
491 if (len && c != '.') {
492 c = *walk++;
493 len--;
494 if (c != '.') return -EINVAL;
496 while (c != '.' && len--) c = *walk++;
497 baselen = walk - name;
498 if (c == '.') {
499 baselen--;
500 if (len >= 4) return -EINVAL;
501 while (len > 0 && walk-name < (MSDOS_NAME+1)) {
502 c = *walk++;
503 len--;
504 if (utf8 && (c & 0x80)) return -EINVAL;
505 if (strchr(bad_chars,c)) return -EINVAL;
506 if (strchr(replace_chars,c))
507 return -EINVAL;
508 if (c < ' ' || c == ':' || c == '\\' || c == '.')
509 return -EINVAL;
510 if (c >= 'A' && c <= 'Z') return -EINVAL;
511 space = c == ' ';
513 if (space) return -EINVAL;
514 if (len) return -EINVAL;
516 if (baselen == 3) {
517 for (reserved = reserved3_names; *reserved; reserved++)
518 if (!strnicmp(name,*reserved,baselen)) return -EINVAL;
519 } else if (baselen == 4) {
520 for (reserved = reserved4_names; *reserved; reserved++)
521 if (!strnicmp(name,*reserved,baselen)) return -EINVAL;
524 return 0;
527 /* Takes a short filename and converts it to a formatted MS-DOS filename.
528 * If the short filename is not a valid MS-DOS filename, an error is
529 * returned. The formatted short filename is returned in 'res'.
532 static int vfat_format_name(const char *name,int len,char *res,
533 int dot_dirs,int utf8)
535 char *walk;
536 const char **reserved;
537 unsigned char c;
538 int space;
540 if (IS_FREE(name)) return -EINVAL;
541 if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {
542 if (!dot_dirs) return -EEXIST;
543 memset(res+1,' ',10);
544 while (len--) *res++ = '.';
545 return 0;
548 space = 1; /* disallow names starting with a dot */
549 c = 0;
550 for (walk = res; len && walk-res < 8; walk++) {
551 c = *name++;
552 len--;
553 if (utf8 && (c & 0x80)) return -EINVAL;
554 if (strchr(bad_chars,c)) return -EINVAL;
555 if (strchr(replace_chars,c)) return -EINVAL;
556 if (c >= 'A' && c <= 'Z') return -EINVAL;
557 if (c < ' ' || c == ':' || c == '\\') return -EINVAL;
558 if (c == '.') break;
559 space = c == ' ';
560 *walk = c >= 'a' && c <= 'z' ? c-32 : c;
562 if (space) return -EINVAL;
563 if (len && c != '.') {
564 c = *name++;
565 len--;
566 if (c != '.') return -EINVAL;
568 while (c != '.' && len--) c = *name++;
569 if (c == '.') {
570 while (walk-res < 8) *walk++ = ' ';
571 while (len > 0 && walk-res < MSDOS_NAME) {
572 c = *name++;
573 len--;
574 if (utf8 && (c & 0x80)) return -EINVAL;
575 if (strchr(bad_chars,c)) return -EINVAL;
576 if (strchr(replace_chars,c))
577 return -EINVAL;
578 if (c < ' ' || c == ':' || c == '\\' || c == '.')
579 return -EINVAL;
580 if (c >= 'A' && c <= 'Z') return -EINVAL;
581 space = c == ' ';
582 *walk++ = c >= 'a' && c <= 'z' ? c-32 : c;
584 if (space) return -EINVAL;
585 if (len) return -EINVAL;
587 while (walk-res < MSDOS_NAME) *walk++ = ' ';
588 for (reserved = reserved3_names; *reserved; reserved++)
589 if (!strnicmp(res,*reserved,8)) return -EINVAL;
590 for (reserved = reserved4_names; *reserved; reserved++)
591 if (!strnicmp(res,*reserved,8)) return -EINVAL;
593 return 0;
596 static char skip_chars[] = ".:\"?<>| ";
598 /* Given a valid longname, create a unique shortname. Make sure the
599 * shortname does not exist
601 static int vfat_create_shortname(struct inode *dir, const char *name,
602 int len, char *name_res, int utf8)
604 const char *ip, *ext_start, *end;
605 char *p;
606 int sz, extlen, baselen, totlen;
607 char msdos_name[13];
608 char base[9], ext[4];
609 int i;
610 int res;
611 int spaces;
612 char buf[8];
613 struct vfat_slot_info sinfo;
614 const char *name_start;
615 struct qstr qname;
617 PRINTK2(("Entering vfat_create_shortname: name=%s, len=%d\n", name, len));
618 sz = 0; /* Make compiler happy */
619 if (len && name[len-1]==' ') return -EINVAL;
620 if (len <= 12) {
621 /* Do a case insensitive search if the name would be a valid
622 * shortname if is were all capitalized. However, do not
623 * allow spaces in short names because Win95 scandisk does
624 * not like that */
625 res = 0;
626 for (i = 0, p = msdos_name, ip = name; i < len; i++, p++, ip++)
628 if (*ip == ' ') {
629 res = -1;
630 break;
632 if (*ip >= 'A' && *ip <= 'Z') {
633 *p = *ip + 32;
634 } else {
635 *p = *ip;
638 if (res == 0) {
639 res = vfat_format_name(msdos_name, len, name_res, 1, utf8);
641 if (res > -1) {
642 PRINTK3(("vfat_create_shortname 1\n"));
643 qname.name=msdos_name;
644 qname.len=len;
645 res = vfat_find(dir, &qname, 0, 0, 0, &sinfo);
646 PRINTK3(("vfat_create_shortname 2\n"));
647 if (res > -1) return -EEXIST;
648 return 0;
652 PRINTK3(("vfat_create_shortname 3\n"));
653 /* Now, we need to create a shortname from the long name */
654 ext_start = end = &name[len];
655 while (--ext_start >= name) {
656 if (*ext_start == '.') {
657 if (ext_start == end - 1) {
658 sz = len;
659 ext_start = NULL;
661 break;
664 if (ext_start == name - 1) {
665 sz = len;
666 ext_start = NULL;
667 } else if (ext_start) {
669 * Names which start with a dot could be just
670 * an extension eg. "...test". In this case Win95
671 * uses the extension as the name and sets no extension.
673 name_start = &name[0];
674 while (name_start < ext_start)
676 if (!strchr(skip_chars,*name_start)) break;
677 name_start++;
679 if (name_start != ext_start) {
680 sz = ext_start - name;
681 ext_start++;
682 } else {
683 sz = len;
684 ext_start=NULL;
688 for (baselen = i = 0, p = base, ip = name; i < sz && baselen < 8; i++)
690 if (utf8 && (*ip & 0x80)) {
691 *p++ = '_';
692 baselen++;
693 } else if (!strchr(skip_chars, *ip)) {
694 if (*ip >= 'A' && *ip <= 'Z') {
695 *p = *ip + 32;
696 } else {
697 *p = *ip;
699 if (strchr(replace_chars, *p)) *p='_';
700 p++; baselen++;
702 ip++;
704 if (baselen == 0) {
705 return -EINVAL;
708 spaces = 8 - baselen;
710 if (ext_start) {
711 extlen = 0;
712 for (p = ext, ip = ext_start; extlen < 3 && ip < end; ip++) {
713 if (utf8 && (*ip & 0x80)) {
714 *p++ = '_';
715 extlen++;
716 } else if (!strchr(skip_chars, *ip)) {
717 if (*ip >= 'A' && *ip <= 'Z') {
718 *p = *ip + 32;
719 } else {
720 *p = *ip;
722 if (strchr(replace_chars, *p)) *p='_';
723 extlen++;
724 p++;
727 } else {
728 extlen = 0;
730 ext[extlen] = '\0';
731 base[baselen] = '\0';
733 strcpy(msdos_name, base);
734 msdos_name[baselen] = '.';
735 strcpy(&msdos_name[baselen+1], ext);
737 totlen = baselen + extlen + (extlen > 0);
738 res = 0;
739 if (MSDOS_SB(dir->i_sb)->options.numtail == 0) {
740 qname.name=msdos_name;
741 qname.len=totlen;
742 res = vfat_find(dir, &qname, 0, 0, 0, &sinfo);
745 if (res > -1) {
747 * Try to find a unique extension. This used to
748 * iterate through all possibilities sequentially,
749 * but that gave extremely bad performance. Windows
750 * only tries a few cases before using random
751 * values for part of the base.
754 if (2 > spaces) {
755 baselen = baselen - (2 - spaces);
756 spaces = 2;
758 msdos_name[baselen] = '~';
759 msdos_name[baselen+2] = '.';
760 strcpy(&msdos_name[baselen+3], ext);
761 totlen = baselen + 2 + extlen + (extlen > 0);
762 qname.name=msdos_name;
763 qname.len=totlen;
764 for (i = 1; res > -1 && i < 10; i++) {
765 strncpy(msdos_name, base, baselen);
766 msdos_name[baselen+1] = i + '0';
767 res = vfat_find(dir, &qname, 0, 0, 0, &sinfo);
770 if (res > -1) {
771 i = jiffies & 0xffff;
772 sz = (jiffies >> 16) & 0x7;
773 if (6 > spaces) {
774 baselen = baselen - (6 - spaces);
775 spaces = 6;
777 msdos_name[baselen+4] = '~';
778 msdos_name[baselen+5] = '1' + sz;
779 msdos_name[baselen+6] = '.';
780 strcpy(&msdos_name[baselen+7], ext);
781 totlen = baselen + 6 + extlen + (extlen > 0);
782 qname.name=msdos_name;
783 qname.len=totlen;
784 while (res > -1) {
785 sprintf(buf, "%04x", i);
786 memcpy(&msdos_name[baselen], buf, 4);
787 msdos_name[12] = 0;
788 res = vfat_find(dir, &qname, 0, 0, 0, &sinfo);
789 i -= 11;
793 res = vfat_format_name(msdos_name, totlen, name_res, 1, utf8);
794 return res;
797 static loff_t vfat_find_free_slots(struct inode *dir,int slots)
799 struct super_block *sb = dir->i_sb;
800 loff_t offset, curr;
801 struct msdos_dir_entry *de;
802 struct buffer_head *bh;
803 struct inode *inode;
804 int ino;
805 int row;
806 int done;
807 int res;
808 int added;
810 PRINTK2(("vfat_find_free_slots: find %d free slots\n", slots));
811 offset = curr = 0;
812 bh = NULL;
813 row = 0;
814 ino = fat_get_entry(dir,&curr,&bh,&de);
816 for (added = 0; added < 2; added++) {
817 while (ino > -1) {
818 done = IS_FREE(de->name);
819 if (done) {
820 inode = iget(sb,ino);
821 if (inode) {
822 /* Directory slots of busy deleted files aren't available yet. */
823 done = !MSDOS_I(inode)->i_busy;
824 /* PRINTK3(("inode %d still busy\n", ino)); */
825 iput(inode);
828 if (done) {
829 row++;
830 if (row == slots) {
831 fat_brelse(sb, bh);
832 /* printk("----- Free offset at %d\n", offset); */
833 return offset;
835 } else {
836 row = 0;
837 offset = curr;
839 ino = fat_get_entry(dir,&curr,&bh,&de);
842 if ((dir->i_ino == MSDOS_ROOT_INO) &&
843 (MSDOS_SB(sb)->fat_bits != 32))
844 return -ENOSPC;
845 if ((res = fat_add_cluster(dir)) < 0) return res;
846 ino = fat_get_entry(dir,&curr,&bh,&de);
848 return -ENOSPC;
851 /* Translate a string, including coded sequences into Unicode */
852 static int
853 xlate_to_uni(const char *name, int len, char *outname, int *outlen,
854 int escape, int utf8, struct nls_table *nls)
856 int i;
857 const unsigned char *ip;
858 char *op;
859 int fill;
860 unsigned char c1, c2, c3;
862 if (utf8) {
863 *outlen = utf8_mbstowcs((__u16 *) outname, name, PAGE_SIZE);
864 if (name[len-1] == '.')
865 *outlen-=2;
866 op = &outname[*outlen * sizeof(__u16)];
867 } else {
868 if (name[len-1] == '.')
869 len--;
870 op = outname;
871 if (nls) {
872 for (i = 0, ip = name, op = outname, *outlen = 0;
873 i < len && *outlen <= 260; i++, *outlen += 1)
875 if (escape && (*ip == ':')) {
876 if (i > len - 4) return -EINVAL;
877 c1 = fat_esc2uni[ip[1]];
878 c2 = fat_esc2uni[ip[2]];
879 c3 = fat_esc2uni[ip[3]];
880 if (c1 == 255 || c2 == 255 || c3 == 255)
881 return -EINVAL;
882 *op++ = (c1 << 4) + (c2 >> 2);
883 *op++ = ((c2 & 0x3) << 6) + c3;
884 ip += 4;
885 } else {
886 *op++ = nls->charset2uni[*ip].uni1;
887 *op++ = nls->charset2uni[*ip].uni2;
888 ip++;
891 } else {
892 for (i = 0, ip = name, op = outname, *outlen = 0;
893 i < len && *outlen <= 260; i++, *outlen += 1)
895 *op++ = *ip++;
896 *op++ = 0;
900 if (*outlen > 260)
901 return -ENAMETOOLONG;
903 if (*outlen % 13) {
904 *op++ = 0;
905 *op++ = 0;
906 *outlen += 1;
907 if (*outlen % 13) {
908 fill = 13 - (*outlen % 13);
909 for (i = 0; i < fill; i++) {
910 *op++ = 0xff;
911 *op++ = 0xff;
913 *outlen += fill;
917 return 0;
920 static int
921 vfat_fill_long_slots(struct msdos_dir_slot *ds, const char *name, int len,
922 char *msdos_name, int *slots,
923 int uni_xlate, int utf8, struct nls_table *nls)
925 struct msdos_dir_slot *ps;
926 struct msdos_dir_entry *de;
927 int res;
928 int slot;
929 unsigned char cksum;
930 char *uniname;
931 const char *ip;
932 unsigned long page;
933 int unilen;
934 int i;
935 loff_t offset;
937 if (name[len-1] == '.') len--;
938 if(!(page = __get_free_page(GFP_KERNEL)))
939 return -ENOMEM;
940 uniname = (char *) page;
941 res = xlate_to_uni(name, len, uniname, &unilen, uni_xlate, utf8, nls);
942 if (res < 0) {
943 free_page(page);
944 return res;
947 *slots = unilen / 13;
948 for (cksum = i = 0; i < 11; i++) {
949 cksum = (((cksum&1)<<7)|((cksum&0xfe)>>1)) + msdos_name[i];
951 PRINTK3(("vfat_fill_long_slots 3: slots=%d\n",*slots));
953 for (ps = ds, slot = *slots; slot > 0; slot--, ps++) {
954 int end, j;
956 PRINTK3(("vfat_fill_long_slots 4\n"));
957 ps->id = slot;
958 ps->attr = ATTR_EXT;
959 ps->reserved = 0;
960 ps->alias_checksum = cksum;
961 ps->start = 0;
962 PRINTK3(("vfat_fill_long_slots 5: uniname=%s\n",uniname));
963 offset = (slot - 1) * 26;
964 ip = &uniname[offset];
965 j = offset;
966 end = 0;
967 for (i = 0; i < 10; i += 2) {
968 ps->name0_4[i] = *ip++;
969 ps->name0_4[i+1] = *ip++;
971 PRINTK3(("vfat_fill_long_slots 6\n"));
972 for (i = 0; i < 12; i += 2) {
973 ps->name5_10[i] = *ip++;
974 ps->name5_10[i+1] = *ip++;
976 PRINTK3(("vfat_fill_long_slots 7\n"));
977 for (i = 0; i < 4; i += 2) {
978 ps->name11_12[i] = *ip++;
979 ps->name11_12[i+1] = *ip++;
982 PRINTK3(("vfat_fill_long_slots 8\n"));
983 ds[0].id |= 0x40;
985 de = (struct msdos_dir_entry *) ps;
986 PRINTK3(("vfat_fill_long_slots 9\n"));
987 strncpy(de->name, msdos_name, MSDOS_NAME);
989 free_page(page);
990 return 0;
993 static int vfat_build_slots(struct inode *dir,const char *name,int len,
994 struct msdos_dir_slot *ds, int *slots, int *is_long)
996 struct msdos_dir_entry *de;
997 char msdos_name[MSDOS_NAME];
998 int res, xlate, utf8;
999 struct nls_table *nls;
1001 PRINTK2(("Entering vfat_build_slots: name=%s, len=%d\n", name, len));
1002 de = (struct msdos_dir_entry *) ds;
1003 xlate = MSDOS_SB(dir->i_sb)->options.unicode_xlate;
1004 utf8 = MSDOS_SB(dir->i_sb)->options.utf8;
1005 nls = MSDOS_SB(dir->i_sb)->nls_io;
1007 *slots = 1;
1008 *is_long = 0;
1009 if (len == 1 && name[0] == '.') {
1010 strncpy(de->name, MSDOS_DOT, MSDOS_NAME);
1011 } else if (len == 2 && name[0] == '.' && name[1] == '.') {
1012 strncpy(de->name, MSDOS_DOT, MSDOS_NAME);
1013 } else {
1014 PRINTK3(("vfat_build_slots 4\n"));
1015 res = vfat_valid_shortname(name, len, 1, utf8);
1016 if (res > -1) {
1017 PRINTK3(("vfat_build_slots 5a\n"));
1018 res = vfat_format_name(name, len, de->name, 1, utf8);
1019 PRINTK3(("vfat_build_slots 5b\n"));
1020 } else {
1021 res = vfat_create_shortname(dir, name, len, msdos_name, utf8);
1022 if (res < 0) {
1023 return res;
1026 res = vfat_valid_longname(name, len, 1, xlate);
1027 if (res < 0) {
1028 return res;
1031 *is_long = 1;
1033 return vfat_fill_long_slots(ds, name, len, msdos_name,
1034 slots, xlate, utf8, nls);
1037 return 0;
1040 static int vfat_readdir_cb(
1041 filldir_t filldir,
1042 void * buf,
1043 const char * name,
1044 int name_len,
1045 int is_long,
1046 off_t offset,
1047 off_t short_offset,
1048 int long_slots,
1049 ino_t ino)
1051 struct vfat_find_info *vf = (struct vfat_find_info *) buf;
1052 const char *s1, *s2;
1053 int i;
1055 #ifdef DEBUG
1056 if (debug) printk("cb: vf.name=%s, len=%d, name=%s, name_len=%d\n",
1057 vf->name, vf->len, name, name_len);
1058 #endif
1060 if (vf->len != name_len) {
1061 return 0;
1064 s1 = name; s2 = vf->name;
1065 for (i = 0; i < name_len; i++) {
1066 if (vf->anycase || (vf->new_filename && !vf->posix)) {
1067 if (tolower(*s1) != tolower(*s2))
1068 return 0;
1069 } else {
1070 if (*s1 != *s2)
1071 return 0;
1073 s1++; s2++;
1075 vf->found = 1;
1076 vf->is_long = is_long;
1077 vf->offset = (offset == 2) ? 0 : offset;
1078 vf->short_offset = (short_offset == 2) ? 0 : short_offset;
1079 vf->long_slots = long_slots;
1080 vf->ino = ino;
1081 return -1;
1084 static int vfat_find(struct inode *dir,struct qstr* qname,
1085 int find_long, int new_filename,int is_dir,struct vfat_slot_info *sinfo_out)
1087 struct super_block *sb = dir->i_sb;
1088 struct vfat_find_info vf;
1089 struct file fil;
1090 struct buffer_head *bh;
1091 struct msdos_dir_entry *de;
1092 struct msdos_dir_slot *ps;
1093 loff_t offset;
1094 struct msdos_dir_slot *ds;
1095 int is_long;
1096 int slots, slot;
1097 int res;
1099 PRINTK2(("Entering vfat_find\n"));
1101 ds = (struct msdos_dir_slot *)
1102 kmalloc(sizeof(struct msdos_dir_slot)*MSDOS_SLOTS, GFP_KERNEL);
1103 if (ds == NULL) return -ENOMEM;
1105 fil.f_pos = 0;
1106 vf.name = qname->name;
1107 vf.len = qname->len;
1108 while (vf.len && vf.name[vf.len-1] == '.') {
1109 vf.len--;
1111 vf.new_filename = new_filename;
1112 vf.found = 0;
1113 vf.posix = MSDOS_SB(sb)->options.posixfs;
1114 vf.anycase = (MSDOS_SB(sb)->options.name_check != 's');
1115 res = fat_readdirx(dir,&fil,(void *)&vf,vfat_readdir_cb,NULL,1,find_long,0);
1116 PRINTK3(("vfat_find: Debug 1\n"));
1117 if (res < 0) goto cleanup;
1118 if (vf.found) {
1119 if (new_filename) {
1120 res = -EEXIST;
1121 goto cleanup;
1123 sinfo_out->longname_offset = vf.offset;
1124 sinfo_out->shortname_offset = vf.short_offset;
1125 sinfo_out->is_long = vf.is_long;
1126 sinfo_out->long_slots = vf.long_slots;
1127 sinfo_out->total_slots = vf.long_slots + 1;
1128 sinfo_out->ino = vf.ino;
1130 PRINTK3(("vfat_find: Debug 2\n"));
1131 res = 0;
1132 goto cleanup;
1135 PRINTK3(("vfat_find: Debug 3\n"));
1136 if (!vf.found && !new_filename) {
1137 res = -ENOENT;
1138 goto cleanup;
1141 res = vfat_build_slots(dir, qname->name, vf.len, ds,
1142 &slots, &is_long);
1143 if (res < 0) goto cleanup;
1145 de = (struct msdos_dir_entry *) ds;
1147 bh = NULL;
1148 if (new_filename) {
1149 PRINTK3(("vfat_find: create file 1\n"));
1150 if (is_long) slots++;
1151 offset = vfat_find_free_slots(dir, slots);
1152 if (offset < 0) {
1153 res = offset;
1154 goto cleanup;
1157 PRINTK3(("vfat_find: create file 2\n"));
1158 /* Now create the new entry */
1159 bh = NULL;
1160 for (slot = 0, ps = ds; slot < slots; slot++, ps++) {
1161 PRINTK3(("vfat_find: create file 3, slot=%d\n",slot));
1162 sinfo_out->ino = fat_get_entry(dir,&offset,&bh,&de);
1163 if (sinfo_out->ino < 0) {
1164 PRINTK3(("vfat_find: problem\n"));
1165 res = sinfo_out->ino;
1166 goto cleanup;
1168 memcpy(de, ps, sizeof(struct msdos_dir_slot));
1169 fat_mark_buffer_dirty(sb, bh, 1);
1172 PRINTK3(("vfat_find: create file 4\n"));
1173 dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;
1174 mark_inode_dirty(dir);
1176 PRINTK3(("vfat_find: create file 5\n"));
1178 fat_date_unix2dos(dir->i_mtime,&de->time,&de->date);
1179 de->ctime_ms = 0;
1180 de->ctime = de->time;
1181 de->adate = de->cdate = de->date;
1182 de->start = 0;
1183 de->starthi = 0;
1184 de->size = 0;
1185 de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
1186 de->lcase = CASE_LOWER_BASE | CASE_LOWER_EXT;
1189 fat_mark_buffer_dirty(sb, bh, 1);
1190 fat_brelse(sb, bh);
1192 sinfo_out->is_long = (slots > 1) ? 1 : 0;
1193 if (sinfo_out->is_long) {
1194 sinfo_out->long_slots = slots - 1;
1195 } else {
1196 sinfo_out->long_slots = 0;
1198 sinfo_out->total_slots = slots;
1199 sinfo_out->shortname_offset = offset - sizeof(struct msdos_dir_slot);
1200 sinfo_out->longname_offset = offset - sizeof(struct msdos_dir_slot) * slots;
1201 res = 0;
1202 } else {
1203 res = -ENOENT;
1206 cleanup:
1207 kfree(ds);
1208 return res;
1211 int vfat_lookup(struct inode *dir,struct dentry *dentry)
1213 int res;
1214 struct vfat_slot_info sinfo;
1215 struct inode *result;
1216 int table;
1218 PRINTK2(("vfat_lookup: name=%s, len=%d\n",
1219 dentry->d_name.name, dentry->d_name.len));
1221 table = (MSDOS_SB(dir->i_sb)->options.name_check == 's') ? 2 : 0;
1222 dentry->d_op = &vfat_dentry_ops[table];
1224 result = NULL;
1225 if ((res = vfat_find(dir,&dentry->d_name,1,0,0,&sinfo)) < 0) {
1226 result = NULL;
1227 table++;
1228 goto error;
1230 PRINTK3(("vfat_lookup 4.5\n"));
1231 if (!(result = iget(dir->i_sb,sinfo.ino)))
1232 return -EACCES;
1233 PRINTK3(("vfat_lookup 5\n"));
1234 if (MSDOS_I(result)->i_busy) { /* mkdir in progress */
1235 iput(result);
1236 result = NULL;
1237 table++;
1238 goto error;
1240 PRINTK3(("vfat_lookup 6\n"));
1241 error:
1242 dentry->d_op = &vfat_dentry_ops[table];
1243 dentry->d_time = dentry->d_parent->d_inode->i_version;
1244 d_add(dentry,result);
1245 return 0;
1249 static int vfat_create_entry(struct inode *dir,struct qstr* qname,
1250 int is_dir, struct inode **result)
1252 struct super_block *sb = dir->i_sb;
1253 int res,ino;
1254 loff_t offset;
1255 struct buffer_head *bh;
1256 struct msdos_dir_entry *de;
1257 struct vfat_slot_info sinfo;
1259 *result=0;
1260 PRINTK1(("vfat_create_entry: Entering\n"));
1261 res = vfat_find(dir, qname, 1, 1, is_dir, &sinfo);
1262 if (res < 0) {
1263 return res;
1266 offset = sinfo.shortname_offset;
1268 PRINTK3(("vfat_create_entry 2\n"));
1269 bh = NULL;
1270 ino = fat_get_entry(dir, &offset, &bh, &de);
1271 if (ino < 0) {
1272 PRINTK3(("vfat_mkdir problem\n"));
1273 if (bh)
1274 fat_brelse(sb, bh);
1275 return ino;
1277 PRINTK3(("vfat_create_entry 3\n"));
1279 if ((*result = iget(dir->i_sb,ino)) != NULL)
1280 vfat_read_inode(*result);
1281 fat_brelse(sb, bh);
1282 if (!*result)
1283 return -EIO;
1284 (*result)->i_mtime = (*result)->i_atime = (*result)->i_ctime =
1285 CURRENT_TIME;
1286 mark_inode_dirty(*result);
1287 (*result)->i_version = ++event;
1288 dir->i_version = event;
1290 return 0;
1293 int vfat_create(struct inode *dir,struct dentry* dentry,int mode)
1295 int res;
1296 struct inode *result;
1298 result=NULL;
1299 fat_lock_creation();
1300 res = vfat_create_entry(dir,&dentry->d_name,0,&result);
1301 fat_unlock_creation();
1302 if (res < 0) {
1303 PRINTK3(("vfat_create: unable to get new entry\n"));
1304 } else {
1305 dentry->d_time = dentry->d_parent->d_inode->i_version;
1306 d_instantiate(dentry,result);
1308 return res;
1311 static int vfat_create_a_dotdir(struct inode *dir,struct inode *parent,
1312 struct buffer_head *bh,
1313 struct msdos_dir_entry *de,int ino,const char *name, int isdot)
1315 struct super_block *sb = dir->i_sb;
1316 struct inode *dot;
1318 PRINTK2(("vfat_create_a_dotdir: Entering\n"));
1321 * XXX all times should be set by caller upon successful completion.
1323 dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
1324 mark_inode_dirty(dir);
1325 memcpy(de->name,name,MSDOS_NAME);
1326 de->lcase = 0;
1327 de->attr = ATTR_DIR;
1328 de->start = 0;
1329 de->starthi = 0;
1330 fat_date_unix2dos(dir->i_mtime,&de->time,&de->date);
1331 de->ctime_ms = 0;
1332 de->ctime = de->time;
1333 de->adate = de->cdate = de->date;
1334 de->size = 0;
1335 fat_mark_buffer_dirty(sb, bh, 1);
1336 dot = iget(dir->i_sb,ino);
1337 if (!dot)
1338 return -EIO;
1339 vfat_read_inode(dot);
1340 dot->i_mtime = dot->i_atime = CURRENT_TIME;
1341 mark_inode_dirty(dot);
1342 if (isdot) {
1343 dot->i_size = dir->i_size;
1344 MSDOS_I(dot)->i_start = MSDOS_I(dir)->i_start;
1345 MSDOS_I(dot)->i_logstart = MSDOS_I(dir)->i_logstart;
1346 dot->i_nlink = dir->i_nlink;
1347 } else {
1348 dot->i_size = parent->i_size;
1349 MSDOS_I(dot)->i_start = MSDOS_I(parent)->i_start;
1350 MSDOS_I(dot)->i_logstart = MSDOS_I(parent)->i_logstart;
1351 dot->i_nlink = parent->i_nlink;
1354 iput(dot);
1356 PRINTK3(("vfat_create_a_dotdir 2\n"));
1357 return 0;
1360 static int vfat_create_dotdirs(struct inode *dir, struct inode *parent)
1362 struct super_block *sb = dir->i_sb;
1363 int res;
1364 struct buffer_head *bh;
1365 struct msdos_dir_entry *de;
1366 loff_t offset;
1368 PRINTK2(("vfat_create_dotdirs: Entering\n"));
1369 if ((res = fat_add_cluster(dir)) < 0) return res;
1371 PRINTK3(("vfat_create_dotdirs 2\n"));
1372 offset = 0;
1373 bh = NULL;
1374 if ((res = fat_get_entry(dir,&offset,&bh,&de)) < 0) return res;
1376 PRINTK3(("vfat_create_dotdirs 3\n"));
1377 res = vfat_create_a_dotdir(dir, parent, bh, de, res, MSDOS_DOT, 1);
1378 PRINTK3(("vfat_create_dotdirs 4\n"));
1379 if (res < 0) {
1380 fat_brelse(sb, bh);
1381 return res;
1383 PRINTK3(("vfat_create_dotdirs 5\n"));
1385 if ((res = fat_get_entry(dir,&offset,&bh,&de)) < 0) {
1386 fat_brelse(sb, bh);
1387 return res;
1389 PRINTK3(("vfat_create_dotdirs 6\n"));
1391 res = vfat_create_a_dotdir(dir, parent, bh, de, res, MSDOS_DOTDOT, 0);
1392 PRINTK3(("vfat_create_dotdirs 7\n"));
1393 fat_brelse(sb, bh);
1395 return res;
1398 /***** See if directory is empty */
1399 static int vfat_empty(struct inode *dir)
1401 struct super_block *sb = dir->i_sb;
1402 loff_t pos;
1403 struct buffer_head *bh;
1404 struct msdos_dir_entry *de;
1406 if (dir->i_count > 1) {
1407 return -EBUSY;
1409 if (MSDOS_I(dir)->i_start) { /* may be zero in mkdir */
1410 pos = 0;
1411 bh = NULL;
1412 while (fat_get_entry(dir,&pos,&bh,&de) > -1) {
1413 /* Skip extended filename entries */
1414 if (de->attr == ATTR_EXT) continue;
1416 if (!IS_FREE(de->name) && strncmp(de->name,MSDOS_DOT,
1417 MSDOS_NAME) && strncmp(de->name,MSDOS_DOTDOT,
1418 MSDOS_NAME)) {
1419 fat_brelse(sb, bh);
1420 return -ENOTEMPTY;
1423 if (bh)
1424 fat_brelse(sb, bh);
1426 return 0;
1429 static int vfat_rmdir_free_ino(struct inode *dir,struct buffer_head *bh,
1430 struct msdos_dir_entry *de,struct dentry* dentry)
1432 struct super_block *sb = dir->i_sb;
1433 int res;
1435 if (!S_ISDIR(dentry->d_inode->i_mode)) {
1436 return -ENOTDIR;
1438 if (dir->i_dev != dentry->d_inode->i_dev || dir == dentry->d_inode) {
1439 return -EBUSY;
1442 res = vfat_empty(dentry->d_inode);
1443 if (res) {
1444 return res;
1446 dentry->d_inode->i_nlink = 0;
1447 dentry->d_inode->i_mtime = dir->i_mtime = CURRENT_TIME;
1448 dentry->d_inode->i_atime = dir->i_atime = CURRENT_TIME;
1449 dir->i_nlink--;
1450 mark_inode_dirty(dir);
1451 mark_inode_dirty(dentry->d_inode);
1452 de->name[0] = DELETED_FLAG;
1453 fat_mark_buffer_dirty(sb, bh, 1);
1455 return 0;
1458 static int vfat_unlink_free_ino(struct inode *dir,struct buffer_head *bh,
1459 struct msdos_dir_entry *de,struct dentry* dentry,int nospc)
1461 struct super_block *sb = dir->i_sb;
1462 if ((!S_ISREG(dentry->d_inode->i_mode) && nospc) ||
1463 IS_IMMUTABLE(dentry->d_inode)) {
1464 return -EPERM;
1466 dentry->d_inode->i_nlink = 0;
1467 dentry->d_inode->i_mtime = dir->i_mtime = CURRENT_TIME;
1468 dentry->d_inode->i_atime = dir->i_atime = CURRENT_TIME;
1469 dir->i_version = ++event;
1470 MSDOS_I(dentry->d_inode)->i_busy = 1;
1471 mark_inode_dirty(dir);
1472 mark_inode_dirty(dentry->d_inode);
1473 de->name[0] = DELETED_FLAG;
1474 fat_mark_buffer_dirty(sb, bh, 1);
1476 return 0;
1479 static int vfat_remove_entry(struct inode *dir,struct vfat_slot_info *sinfo,
1480 struct buffer_head **bh,struct dentry* dentry,
1481 int is_dir,int nospc)
1483 struct super_block *sb = dir->i_sb;
1484 loff_t offset;
1485 struct msdos_dir_entry *de;
1486 int res, i;
1488 /* remove the shortname */
1489 offset = sinfo->shortname_offset;
1490 res = fat_get_entry(dir, &offset, bh, &de);
1491 if (res < 0) return res;
1492 if (is_dir) {
1493 res = vfat_rmdir_free_ino(dir,*bh,de,dentry);
1494 } else {
1495 res = vfat_unlink_free_ino(dir,*bh,de,dentry,nospc);
1497 if (res < 0) return res;
1499 /* remove the longname */
1500 offset = sinfo->longname_offset;
1501 for (i = sinfo->long_slots; i > 0; --i) {
1502 res = fat_get_entry(dir, &offset, bh, &de);
1503 if (res < 0) {
1504 continue;
1506 de->name[0] = DELETED_FLAG;
1507 de->attr = 0;
1508 fat_mark_buffer_dirty(sb, *bh, 1);
1510 return 0;
1513 /* Replace inodes in alias dentries and drop all but the initial dentry */
1514 static void drop_replace_inodes(struct dentry *dentry, struct inode *inode)
1516 struct list_head *head, *next, *tmp;
1517 struct dentry *alias;
1519 PRINTK1(("drop_replace_inodes: dentry=%p, inode=%p\n", dentry, inode));
1520 head = &dentry->d_inode->i_dentry;
1521 if (dentry->d_inode) {
1522 next = dentry->d_inode->i_dentry.next;
1523 while (next != head) {
1524 tmp = next;
1525 next = tmp->next;
1526 alias = list_entry(tmp, struct dentry, d_alias);
1527 if (inode) {
1528 list_del(&alias->d_alias);
1529 iput(alias->d_inode);
1530 d_instantiate(alias, inode);
1531 /* dentry is already accounted for */
1532 if (alias != dentry) {
1533 inode->i_count++;
1536 if (alias != dentry) {
1537 d_drop(alias);
1543 static int vfat_rmdirx(struct inode *dir,struct dentry* dentry)
1545 struct super_block *sb = dir->i_sb;
1546 int res;
1547 struct buffer_head *bh;
1548 struct vfat_slot_info sinfo;
1550 PRINTK1(("vfat_rmdirx: dentry=%p\n", dentry));
1551 res = vfat_find(dir,&dentry->d_name,1,0,0,&sinfo);
1553 if (res >= 0 && sinfo.total_slots > 0) {
1554 bh = NULL;
1555 res = vfat_remove_entry(dir,&sinfo,&bh,dentry,1,0);
1556 if (res > 0) {
1557 res = 0;
1559 dir->i_version = ++event;
1560 if (bh) fat_brelse(sb, bh);
1562 return res;
1565 /***** Remove a directory */
1566 int vfat_rmdir(struct inode *dir,struct dentry* dentry)
1568 int res;
1569 PRINTK1(("vfat_rmdir: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
1570 res = vfat_rmdirx(dir, dentry);
1571 if (res >= 0) {
1572 drop_replace_inodes(dentry, NULL);
1573 d_delete(dentry);
1575 return res;
1578 static int vfat_unlinkx(
1579 struct inode *dir,
1580 struct dentry* dentry,
1581 int nospc) /* Flag special file ? */
1583 struct super_block *sb = dir->i_sb;
1584 int res;
1585 struct buffer_head *bh;
1586 struct vfat_slot_info sinfo;
1588 PRINTK1(("vfat_unlinkx: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
1589 bh = NULL;
1590 res = vfat_find(dir,&dentry->d_name,1,0,0,&sinfo);
1592 if (res >= 0 && sinfo.total_slots > 0) {
1593 res = vfat_remove_entry(dir,&sinfo,&bh,dentry,0,nospc);
1594 if (res > 0) {
1595 res = 0;
1599 if (bh) fat_brelse(sb, bh);
1600 return res;
1604 int vfat_mkdir(struct inode *dir,struct dentry* dentry,int mode)
1606 struct inode *inode;
1607 int res;
1609 PRINTK1(("vfat_mkdir: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
1610 fat_lock_creation();
1611 if ((res = vfat_create_entry(dir,&dentry->d_name,1,&inode)) < 0) {
1612 fat_unlock_creation();
1613 return res;
1616 dir->i_nlink++;
1617 inode->i_nlink = 2; /* no need to mark them dirty */
1618 MSDOS_I(inode)->i_busy = 1; /* prevent lookups */
1620 res = vfat_create_dotdirs(inode, dir);
1621 fat_unlock_creation();
1622 MSDOS_I(inode)->i_busy = 0;
1623 dentry->d_time = dentry->d_parent->d_inode->i_version;
1624 d_instantiate(dentry,inode);
1625 if (res < 0) {
1626 if (vfat_rmdir(dir,dentry) < 0)
1627 fat_fs_panic(dir->i_sb,"rmdir in mkdir failed");
1629 return res;
1632 /***** Unlink, as called for msdosfs */
1633 int vfat_unlink(struct inode *dir,struct dentry* dentry)
1635 int res;
1637 PRINTK1(("vfat_unlink: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
1638 res = vfat_unlinkx (dir,dentry,1);
1639 if (res >= 0) {
1640 drop_replace_inodes(dentry, NULL);
1641 d_delete(dentry);
1643 return res;
1646 /***** Unlink, as called for uvfatfs */
1647 int vfat_unlink_uvfat(struct inode *dir,struct dentry *dentry)
1649 int res;
1651 res = vfat_unlinkx (dir,dentry,0);
1652 iput(dir);
1653 return res;
1656 int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
1657 struct inode *new_dir,struct dentry *new_dentry)
1659 struct super_block *sb = old_dir->i_sb;
1660 struct buffer_head *old_bh,*new_bh,*dotdot_bh;
1661 struct msdos_dir_entry *old_de,*new_de,*dotdot_de;
1662 loff_t old_offset,new_offset,old_longname_offset;
1663 int old_slots,old_ino,new_ino,dotdot_ino;
1664 struct inode *old_inode, *new_inode, *dotdot_inode;
1665 struct dentry *walk;
1666 int res, is_dir, i;
1667 int locked = 0;
1668 struct vfat_slot_info sinfo;
1669 int put_new_inode = 0;
1671 PRINTK1(("vfat_rename: Entering: old_dentry=%p, old_inode=%p, old ino=%ld, new_dentry=%p, new_inode=%p, new ino=%ld\n",
1672 old_dentry, old_dentry->d_inode, old_dentry->d_inode->i_ino,
1673 new_dentry, new_dentry->d_inode,
1674 new_dentry->d_inode ? new_dentry->d_inode->i_ino : 0));
1675 if (old_dir == new_dir &&
1676 old_dentry->d_name.len == new_dentry->d_name.len &&
1677 strncmp(old_dentry->d_name.name, new_dentry->d_name.name,
1678 old_dentry->d_name.len) == 0)
1679 return 0;
1681 old_bh = new_bh = NULL;
1682 old_inode = new_inode = NULL;
1683 res = vfat_find(old_dir,&old_dentry->d_name,1,0,0,&sinfo);
1684 PRINTK3(("vfat_rename 2\n"));
1685 if (res < 0) goto rename_done;
1687 old_slots = sinfo.total_slots;
1688 old_longname_offset = sinfo.longname_offset;
1689 old_offset = sinfo.shortname_offset;
1690 old_ino = sinfo.ino;
1691 res = fat_get_entry(old_dir, &old_offset, &old_bh, &old_de);
1692 PRINTK3(("vfat_rename 3\n"));
1693 if (res < 0) goto rename_done;
1695 res = -ENOENT;
1696 old_inode = old_dentry->d_inode;
1697 is_dir = S_ISDIR(old_inode->i_mode);
1698 if (is_dir) {
1699 if ((old_dir->i_dev != new_dir->i_dev) ||
1700 (old_ino == new_dir->i_ino)) {
1701 res = -EINVAL;
1702 goto rename_done;
1704 walk = new_dentry;
1705 /* prevent moving directory below itself */
1706 for (;;) {
1707 if (walk == old_dentry) return -EINVAL;
1708 if (walk == walk->d_parent) break;
1709 walk = walk->d_parent;
1713 res = vfat_find(new_dir,&new_dentry->d_name,1,0,is_dir,&sinfo);
1715 PRINTK3(("vfat_rename 4\n"));
1716 if (res > -1) {
1717 int new_is_dir;
1719 PRINTK3(("vfat_rename 5\n"));
1720 /* Filename currently exists. Need to delete it */
1721 new_offset = sinfo.shortname_offset;
1722 res = fat_get_entry(new_dir, &new_offset, &new_bh, &new_de);
1723 PRINTK3(("vfat_rename 6\n"));
1724 if (res < 0) goto rename_done;
1726 if (!(new_inode = iget(new_dir->i_sb,res)))
1727 goto rename_done;
1728 new_is_dir = S_ISDIR(new_inode->i_mode);
1729 iput(new_inode);
1730 if (new_is_dir) {
1731 PRINTK3(("vfat_rename 7\n"));
1732 res = vfat_rmdirx(new_dir,new_dentry);
1733 PRINTK3(("vfat_rename 8\n"));
1734 if (res < 0) goto rename_done;
1735 } else {
1736 /* Is this the same file, different case? */
1737 if (new_inode != old_inode) {
1738 PRINTK3(("vfat_rename 9\n"));
1739 res = vfat_unlink(new_dir,new_dentry);
1740 PRINTK3(("vfat_rename 10\n"));
1741 if (res < 0) goto rename_done;
1746 PRINTK3(("vfat_rename 11\n"));
1747 fat_lock_creation(); locked = 1;
1748 res = vfat_find(new_dir,&new_dentry->d_name,1,1,is_dir,&sinfo);
1750 PRINTK3(("vfat_rename 12\n"));
1751 if (res < 0) goto rename_done;
1753 new_offset = sinfo.shortname_offset;
1754 new_ino = sinfo.ino;
1755 PRINTK3(("vfat_rename 13: new_ino=%d\n", new_ino));
1757 if (!(new_inode = iget(new_dir->i_sb,new_ino))) goto rename_done;
1758 put_new_inode = 1;
1760 new_inode->i_mode = old_inode->i_mode;
1761 new_inode->i_size = old_inode->i_size;
1762 new_inode->i_blocks = old_inode->i_blocks;
1763 new_inode->i_mtime = old_inode->i_mtime;
1764 new_inode->i_atime = old_inode->i_atime;
1765 new_inode->i_ctime = old_inode->i_ctime;
1766 new_inode->i_nlink = old_inode->i_nlink;
1767 new_inode->i_op = old_inode->i_op;
1768 MSDOS_I(new_inode)->i_ctime_ms = MSDOS_I(old_inode)->i_ctime_ms;
1770 MSDOS_I(new_inode)->i_start = MSDOS_I(old_inode)->i_start;
1771 MSDOS_I(new_inode)->i_logstart = MSDOS_I(old_inode)->i_logstart;
1772 MSDOS_I(new_inode)->i_attrs = MSDOS_I(old_inode)->i_attrs;
1774 old_inode->i_nlink = 0;
1776 fat_cache_inval_inode(old_inode);
1777 mark_inode_dirty(new_inode);
1779 old_dir->i_version = ++event;
1780 new_dir->i_version = ++event;
1782 PRINTK3(("vfat_rename 14: old_slots=%d\n",old_slots));
1784 /* remove the old entry */
1785 for (i = old_slots; i > 0; --i) {
1786 res = fat_get_entry(old_dir, &old_longname_offset, &old_bh, &old_de);
1787 if (res < 0) {
1788 printk("vfat_rename: problem 1\n");
1789 continue;
1791 old_de->name[0] = DELETED_FLAG;
1792 old_de->attr = 0;
1793 fat_mark_buffer_dirty(sb, old_bh, 1);
1795 PRINTK3(("vfat_rename 15b\n"));
1797 if (S_ISDIR(old_inode->i_mode)) {
1798 if ((res = fat_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh,
1799 &dotdot_de,&dotdot_ino,SCAN_ANY)) < 0) goto rename_done;
1800 if (!(dotdot_inode = iget(old_inode->i_sb,dotdot_ino))) {
1801 fat_brelse(sb, dotdot_bh);
1802 res = -EIO;
1803 goto rename_done;
1805 MSDOS_I(dotdot_inode)->i_start = MSDOS_I(new_dir)->i_start;
1806 MSDOS_I(dotdot_inode)->i_logstart = MSDOS_I(new_dir)->i_logstart;
1807 dotdot_de->start = CT_LE_W(MSDOS_I(new_dir)->i_logstart);
1808 dotdot_de->starthi = CT_LE_W((MSDOS_I(new_dir)->i_logstart) >> 16);
1809 mark_inode_dirty(dotdot_inode);
1810 fat_mark_buffer_dirty(sb, dotdot_bh, 1);
1811 old_dir->i_nlink--;
1812 new_dir->i_nlink++;
1813 /* no need to mark them dirty */
1814 dotdot_inode->i_nlink = new_dir->i_nlink;
1815 iput(dotdot_inode);
1816 fat_brelse(sb, dotdot_bh);
1819 if (res > 0) res = 0;
1821 if (res == 0) {
1822 drop_replace_inodes(old_dentry, new_inode);
1823 d_move(old_dentry, new_dentry);
1824 put_new_inode = 0;
1827 rename_done:
1828 if (locked)
1829 fat_unlock_creation();
1830 if (old_bh)
1831 fat_brelse(sb, old_bh);
1832 if (new_bh)
1833 fat_brelse(sb, new_bh);
1834 if (put_new_inode)
1835 iput(new_inode);
1836 return res;
1841 /* Public inode operations for the VFAT fs */
1842 struct inode_operations vfat_dir_inode_operations = {
1843 &fat_dir_operations, /* default directory file-ops */
1844 vfat_create, /* create */
1845 vfat_lookup, /* lookup */
1846 NULL, /* link */
1847 vfat_unlink, /* unlink */
1848 NULL, /* symlink */
1849 vfat_mkdir, /* mkdir */
1850 vfat_rmdir, /* rmdir */
1851 NULL, /* mknod */
1852 vfat_rename, /* rename */
1853 NULL, /* readlink */
1854 NULL, /* followlink */
1855 NULL, /* readpage */
1856 NULL, /* writepage */
1857 fat_bmap, /* bmap */
1858 NULL, /* truncate */
1859 NULL /* permission */
1863 void vfat_read_inode(struct inode *inode)
1865 fat_read_inode(inode, &vfat_dir_inode_operations);
1868 #ifdef MODULE
1869 int init_module(void)
1871 return init_vfat_fs();
1874 void cleanup_module(void)
1876 unregister_filesystem(&vfat_fs_type);
1879 #endif /* ifdef MODULE */