Import 2.1.81
[davej-history.git] / fs / vfat / namei.c
blob97d2d2f629a9720c67e7035ab357c5f26a7e076f
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 #include <linux/config.h>
14 #define __NO_VERSION__
15 #include <linux/module.h>
17 #include <linux/sched.h>
18 #include <linux/msdos_fs.h>
19 #include <linux/nls.h>
20 #include <linux/kernel.h>
21 #include <linux/errno.h>
22 #include <linux/string.h>
23 #include <linux/ctype.h>
24 #include <linux/stat.h>
25 #include <linux/mm.h>
26 #include <linux/malloc.h>
28 #include "../fat/msbuffer.h"
30 #define DEBUG_LEVEL 0
31 #if (DEBUG_LEVEL >= 1)
32 # define PRINTK1(x) printk x
33 #else
34 # define PRINTK1(x)
35 #endif
36 #if (DEBUG_LEVEL >= 2)
37 # define PRINTK2(x) printk x
38 #else
39 # define PRINTK2(x)
40 #endif
41 #if (DEBUG_LEVEL >= 3)
42 # define PRINTK3(x) printk x
43 #else
44 # define PRINTK3(x)
45 #endif
47 #ifndef DEBUG
48 # define CHECK_STACK
49 #else
50 # define CHECK_STACK check_stack(__FILE__, __LINE__)
51 #endif
53 struct vfat_find_info {
54 const char *name;
55 int len;
56 int new_filename;
57 int found;
58 int is_long;
59 off_t offset;
60 off_t short_offset;
61 int long_slots;
62 ino_t ino;
63 int posix;
64 int anycase;
67 void vfat_read_inode(struct inode *inode);
68 static int vfat_valid_shortname(const char *,int, int, int);
69 static int vfat_format_name(const char *, int, char *, int, int);
70 static int vfat_valid_longname(const char *, int, int, int);
71 static int vfat_hashi(struct dentry *parent, struct qstr *qstr);
72 static int vfat_hash(struct dentry *parent, struct qstr *qstr);
73 static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);
74 static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b);
75 static int vfat_revalidate(struct dentry *dentry);
77 static struct dentry_operations vfat_dentry_ops[4] = {
79 NULL, /* d_revalidate */
80 vfat_hashi,
81 vfat_cmpi,
82 NULL /* d_delete */
85 vfat_revalidate,
86 vfat_hashi,
87 vfat_cmpi,
88 NULL /* d_delete */
91 NULL, /* d_revalidate */
92 vfat_hash,
93 vfat_cmp,
94 NULL /* d_delete */
97 vfat_revalidate,
98 vfat_hash,
99 vfat_cmp,
100 NULL /* d_delete */
104 static int strnicmp(const char *s1, const char *s2, int len)
106 int n = 0;
107 while (*s1 && *s2 && (tolower(*s1) == tolower(*s2))) {
108 s1++; s2++; n++;
109 if (n == len) return 0;
111 if (*s1 == 0 && *s2 == 0) return 0;
112 if (*s1 && *s2) {
113 if (*s1 > *s2) return 1;
114 return -1;
116 if (*s1) return 1;
117 return -1;
120 void vfat_put_super(struct super_block *sb)
122 fat_put_super(sb);
123 MOD_DEC_USE_COUNT;
126 static int vfat_revalidate(struct dentry *dentry)
128 PRINTK1(("vfat_revalidate: %s\n", dentry->d_name.name));
129 if (dentry->d_time == dentry->d_parent->d_inode->i_version) {
130 return 1;
132 return 0;
135 static struct super_operations vfat_sops = {
136 vfat_read_inode,
137 fat_write_inode,
138 fat_put_inode,
139 fat_delete_inode,
140 fat_notify_change,
141 vfat_put_super,
142 NULL, /* write_super */
143 fat_statfs,
144 NULL /* remount */
147 static int simple_getbool(char *s, int *setval)
149 if (s) {
150 if (!strcmp(s,"1") || !strcmp(s,"yes") || !strcmp(s,"true")) {
151 *setval = 1;
152 } else if (!strcmp(s,"0") || !strcmp(s,"no") || !strcmp(s,"false")) {
153 *setval = 0;
154 } else {
155 return 0;
157 } else {
158 *setval = 1;
160 return 1;
163 static int parse_options(char *options, struct fat_mount_options *opts)
165 char *this_char,*value,save,*savep;
166 int ret, val;
168 opts->unicode_xlate = opts->posixfs = 0;
169 opts->numtail = 1;
170 opts->utf8 = 0;
172 if (!options) return 1;
173 save = 0;
174 savep = NULL;
175 ret = 1;
176 for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
177 if ((value = strchr(this_char,'=')) != NULL) {
178 save = *value;
179 savep = value;
180 *value++ = 0;
182 if (!strcmp(this_char,"utf8")) {
183 ret = simple_getbool(value, &val);
184 if (ret) opts->utf8 = val;
185 } else if (!strcmp(this_char,"uni_xlate")) {
186 ret = simple_getbool(value, &val);
187 if (ret) opts->unicode_xlate = val;
188 } else if (!strcmp(this_char,"posix")) {
189 ret = simple_getbool(value, &val);
190 if (ret) opts->posixfs = val;
191 } else if (!strcmp(this_char,"nonumtail")) {
192 ret = simple_getbool(value, &val);
193 if (ret) {
194 opts->numtail = !val;
197 if (this_char != options)
198 *(this_char-1) = ',';
199 if (value) {
200 *savep = save;
202 if (ret == 0) {
203 return 0;
206 if (opts->unicode_xlate) {
207 opts->utf8 = 0;
209 return 1;
213 * Compute the hash for the vfat name corresponding to the dentry.
214 * Note: if the name is invalid, we leave the hash code unchanged so
215 * that the existing dentry can be used. The vfat fs routines will
216 * return ENOENT or EINVAL as appropriate.
218 static int vfat_hash(struct dentry *dentry, struct qstr *qstr)
220 const char *name;
221 int len;
223 len = qstr->len;
224 name = qstr->name;
225 while (len && name[len-1] == '.')
226 len--;
228 qstr->hash = full_name_hash(name, len);
230 return 0;
234 * Compute the hash for the vfat name corresponding to the dentry.
235 * Note: if the name is invalid, we leave the hash code unchanged so
236 * that the existing dentry can be used. The vfat fs routines will
237 * return ENOENT or EINVAL as appropriate.
239 static int vfat_hashi(struct dentry *dentry, struct qstr *qstr)
241 const char *name;
242 int len;
243 char c;
244 unsigned long hash;
246 len = qstr->len;
247 name = qstr->name;
248 while (len && name[len-1] == '.')
249 len--;
251 hash = init_name_hash();
252 while (len--) {
253 c = tolower(*name++);
254 hash = partial_name_hash(tolower(c), hash);
256 qstr->hash = end_name_hash(hash);
258 return 0;
262 * Case insensitive compare of two vfat names.
264 static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b)
266 int alen, blen;
268 /* A filename cannot end in '.' or we treat it like it has none */
269 alen = a->len;
270 blen = b->len;
271 while (alen && a->name[alen-1] == '.')
272 alen--;
273 while (blen && b->name[blen-1] == '.')
274 blen--;
275 if (alen == blen) {
276 if (strnicmp(a->name, b->name, alen) == 0)
277 return 0;
279 return 1;
283 * Case sensitive compare of two vfat names.
285 static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b)
287 int alen, blen;
289 /* A filename cannot end in '.' or we treat it like it has none */
290 alen = a->len;
291 blen = b->len;
292 while (alen && a->name[alen-1] == '.')
293 alen--;
294 while (blen && b->name[blen-1] == '.')
295 blen--;
296 if (alen == blen) {
297 if (strncmp(a->name, b->name, alen) == 0)
298 return 0;
300 return 1;
303 struct super_block *vfat_read_super(struct super_block *sb,void *data,
304 int silent)
306 struct super_block *res;
308 MOD_INC_USE_COUNT;
310 MSDOS_SB(sb)->options.isvfat = 1;
312 sb->s_op = &vfat_sops;
313 res = fat_read_super(sb, data, silent);
314 if (res == NULL) {
315 sb->s_dev = 0;
316 MOD_DEC_USE_COUNT;
317 return NULL;
320 if (!parse_options((char *) data, &(MSDOS_SB(sb)->options))) {
321 MOD_DEC_USE_COUNT;
322 } else {
323 MSDOS_SB(sb)->options.dotsOK = 0;
324 if (MSDOS_SB(sb)->options.posixfs) {
325 MSDOS_SB(sb)->options.name_check = 's';
327 if (MSDOS_SB(sb)->options.name_check != 's') {
328 sb->s_root->d_op = &vfat_dentry_ops[0];
329 } else {
330 sb->s_root->d_op = &vfat_dentry_ops[2];
334 return res;
337 #ifdef DEBUG
339 static void
340 check_stack(const char *fname, int lineno)
342 int stack_level;
343 char *pg_dir;
345 stack_level = (long)(&pg_dir)-current->kernel_stack_page;
346 if (stack_level < 0)
347 printk("*-*-*-* vfat kstack overflow in %s line %d: SL=%d\n",
348 fname, lineno, stack_level);
349 else if (stack_level < 500)
350 printk("*-*-*-* vfat kstack low in %s line %d: SL=%d\n",
351 fname, lineno, stack_level);
352 #if 0
353 else
354 printk("------- vfat kstack ok in %s line %d: SL=%d\n",
355 fname, lineno, stack_level);
356 #endif
357 #if 0
358 if (*(unsigned long *) current->kernel_stack_page != STACK_MAGIC) {
359 printk("******* vfat stack corruption detected in %s at line %d\n",
360 fname, lineno);
362 #endif
365 static int debug = 0;
366 static void dump_fat(struct super_block *sb,int start)
368 printk("[");
369 while (start) {
370 printk("%d ",start);
371 start = fat_access(sb,start,-1);
372 if (!start) {
373 printk("ERROR");
374 break;
376 if (start == -1) break;
378 printk("]\n");
381 static void dump_de(struct msdos_dir_entry *de)
383 int i;
384 unsigned char *p = (unsigned char *) de;
385 printk("[");
387 for (i = 0; i < 32; i++, p++) {
388 printk("%02x ", *p);
390 printk("]\n");
393 #endif
395 /* MS-DOS "device special files" */
397 static const char *reserved3_names[] = {
398 "con ", "prn ", "nul ", "aux ", NULL
401 static const char *reserved4_names[] = {
402 "com1 ", "com2 ", "com3 ", "com4 ", "com5 ",
403 "com6 ", "com7 ", "com8 ", "com9 ",
404 "lpt1 ", "lpt2 ", "lpt3 ", "lpt4 ", "lpt5 ",
405 "lpt6 ", "lpt7 ", "lpt8 ", "lpt9 ",
406 NULL };
409 /* Characters that are undesirable in an MS-DOS file name */
411 static char bad_chars[] = "*?<>|\":/\\";
412 static char replace_chars[] = "[];,+=";
414 static int vfat_find(struct inode *dir,struct qstr* name,
415 int find_long,int new_filename,int is_dir,
416 struct vfat_slot_info *sinfo_out);
418 /* Checks the validity of a long MS-DOS filename */
419 /* Returns negative number on error, 0 for a normal
420 * return, and 1 for . or .. */
422 static int vfat_valid_longname(const char *name, int len, int dot_dirs,
423 int xlate)
425 const char **reserved, *walk;
426 unsigned char c;
427 int i, baselen;
429 if (IS_FREE(name)) return -EINVAL;
430 if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {
431 if (!dot_dirs) return -EEXIST;
432 return 1;
435 if (len && name[len-1] == ' ') return -EINVAL;
436 if (len >= 256) return -EINVAL;
437 for (i = 0; i < len; i++) {
438 c = name[i];
439 if (xlate && c == ':') continue;
440 if (strchr(bad_chars,c)) {
441 return -EINVAL;
444 if (len < 3) return 0;
446 for (walk = name; *walk != 0 && *walk != '.'; walk++);
447 baselen = walk - name;
449 if (baselen == 3) {
450 for (reserved = reserved3_names; *reserved; reserved++) {
451 if (!strnicmp(name,*reserved,baselen))
452 return -EINVAL;
454 } else if (baselen == 4) {
455 for (reserved = reserved4_names; *reserved; reserved++) {
456 if (!strnicmp(name,*reserved,baselen))
457 return -EINVAL;
460 return 0;
463 static int vfat_valid_shortname(const char *name,int len,
464 int dot_dirs, int utf8)
466 const char *walk, **reserved;
467 unsigned char c;
468 int space;
469 int baselen;
471 if (IS_FREE(name)) return -EINVAL;
472 if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {
473 if (!dot_dirs) return -EEXIST;
474 return 1;
477 space = 1; /* disallow names starting with a dot */
478 c = 0;
479 for (walk = name; len && walk-name < 8;) {
480 c = *walk++;
481 len--;
482 if (utf8 && (c & 0x80)) return -EINVAL;
483 if (strchr(bad_chars,c)) return -EINVAL;
484 if (strchr(replace_chars,c)) return -EINVAL;
485 if (c >= 'A' && c <= 'Z') return -EINVAL;
486 if (c < ' ' || c == ':' || c == '\\') return -EINVAL;
487 if ((walk == name) && (c == 0xE5)) c = 0x05;
488 if (c == '.') break;
489 space = c == ' ';
491 if (space) return -EINVAL;
492 if (len && c != '.') {
493 c = *walk++;
494 len--;
495 if (c != '.') return -EINVAL;
497 while (c != '.' && len--) c = *walk++;
498 baselen = walk - name;
499 if (c == '.') {
500 baselen--;
501 if (len >= 4) return -EINVAL;
502 while (len > 0 && walk-name < (MSDOS_NAME+1)) {
503 c = *walk++;
504 len--;
505 if (utf8 && (c & 0x80)) return -EINVAL;
506 if (strchr(bad_chars,c)) return -EINVAL;
507 if (strchr(replace_chars,c))
508 return -EINVAL;
509 if (c < ' ' || c == ':' || c == '\\' || c == '.')
510 return -EINVAL;
511 if (c >= 'A' && c <= 'Z') return -EINVAL;
512 space = c == ' ';
514 if (space) return -EINVAL;
515 if (len) return -EINVAL;
517 if (baselen == 3) {
518 for (reserved = reserved3_names; *reserved; reserved++)
519 if (!strnicmp(name,*reserved,baselen)) return -EINVAL;
520 } else if (baselen == 4) {
521 for (reserved = reserved4_names; *reserved; reserved++)
522 if (!strnicmp(name,*reserved,baselen)) return -EINVAL;
525 return 0;
528 /* Takes a short filename and converts it to a formatted MS-DOS filename.
529 * If the short filename is not a valid MS-DOS filename, an error is
530 * returned. The formatted short filename is returned in 'res'.
533 static int vfat_format_name(const char *name,int len,char *res,
534 int dot_dirs,int utf8)
536 char *walk;
537 const char **reserved;
538 unsigned char c;
539 int space;
541 if (IS_FREE(name)) return -EINVAL;
542 if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {
543 if (!dot_dirs) return -EEXIST;
544 memset(res+1,' ',10);
545 while (len--) *res++ = '.';
546 return 0;
549 space = 1; /* disallow names starting with a dot */
550 c = 0;
551 for (walk = res; len && walk-res < 8; walk++) {
552 c = *name++;
553 len--;
554 if (utf8 && (c & 0x80)) return -EINVAL;
555 if (strchr(bad_chars,c)) return -EINVAL;
556 if (strchr(replace_chars,c)) return -EINVAL;
557 if (c >= 'A' && c <= 'Z') return -EINVAL;
558 if (c < ' ' || c == ':' || c == '\\') return -EINVAL;
559 if (c == '.') break;
560 space = c == ' ';
561 *walk = c >= 'a' && c <= 'z' ? c-32 : c;
563 if (space) return -EINVAL;
564 if (len && c != '.') {
565 c = *name++;
566 len--;
567 if (c != '.') return -EINVAL;
569 while (c != '.' && len--) c = *name++;
570 if (c == '.') {
571 while (walk-res < 8) *walk++ = ' ';
572 while (len > 0 && walk-res < MSDOS_NAME) {
573 c = *name++;
574 len--;
575 if (utf8 && (c & 0x80)) return -EINVAL;
576 if (strchr(bad_chars,c)) return -EINVAL;
577 if (strchr(replace_chars,c))
578 return -EINVAL;
579 if (c < ' ' || c == ':' || c == '\\' || c == '.')
580 return -EINVAL;
581 if (c >= 'A' && c <= 'Z') return -EINVAL;
582 space = c == ' ';
583 *walk++ = c >= 'a' && c <= 'z' ? c-32 : c;
585 if (space) return -EINVAL;
586 if (len) return -EINVAL;
588 while (walk-res < MSDOS_NAME) *walk++ = ' ';
589 for (reserved = reserved3_names; *reserved; reserved++)
590 if (!strnicmp(res,*reserved,8)) return -EINVAL;
591 for (reserved = reserved4_names; *reserved; reserved++)
592 if (!strnicmp(res,*reserved,8)) return -EINVAL;
594 return 0;
597 static char skip_chars[] = ".:\"?<>| ";
599 /* Given a valid longname, create a unique shortname. Make sure the
600 * shortname does not exist
602 static int vfat_create_shortname(struct inode *dir, const char *name,
603 int len, char *name_res, int utf8)
605 const char *ip, *ext_start, *end;
606 char *p;
607 int sz, extlen, baselen, totlen;
608 char msdos_name[13];
609 char base[9], ext[4];
610 int i;
611 int res;
612 int spaces;
613 char buf[8];
614 struct vfat_slot_info sinfo;
615 const char *name_start;
616 struct qstr qname;
618 PRINTK2(("Entering vfat_create_shortname: name=%s, len=%d\n", name, len));
619 sz = 0; /* Make compiler happy */
620 if (len && name[len-1]==' ') return -EINVAL;
621 if (len <= 12) {
622 /* Do a case insensitive search if the name would be a valid
623 * shortname if is were all capitalized. However, do not
624 * allow spaces in short names because Win95 scandisk does
625 * not like that */
626 res = 0;
627 for (i = 0, p = msdos_name, ip = name; i < len; i++, p++, ip++)
629 if (*ip == ' ') {
630 res = -1;
631 break;
633 if (*ip >= 'A' && *ip <= 'Z') {
634 *p = *ip + 32;
635 } else {
636 *p = *ip;
639 if (res == 0) {
640 res = vfat_format_name(msdos_name, len, name_res, 1, utf8);
642 if (res > -1) {
643 PRINTK3(("vfat_create_shortname 1\n"));
644 qname.name=msdos_name;
645 qname.len=len;
646 res = vfat_find(dir, &qname, 0, 0, 0, &sinfo);
647 PRINTK3(("vfat_create_shortname 2\n"));
648 if (res > -1) return -EEXIST;
649 return 0;
653 PRINTK3(("vfat_create_shortname 3\n"));
654 /* Now, we need to create a shortname from the long name */
655 ext_start = end = &name[len];
656 while (--ext_start >= name) {
657 if (*ext_start == '.') {
658 if (ext_start == end - 1) {
659 sz = len;
660 ext_start = NULL;
662 break;
665 if (ext_start == name - 1) {
666 sz = len;
667 ext_start = NULL;
668 } else if (ext_start) {
670 * Names which start with a dot could be just
671 * an extension eg. "...test". In this case Win95
672 * uses the extension as the name and sets no extension.
674 name_start = &name[0];
675 while (name_start < ext_start)
677 if (!strchr(skip_chars,*name_start)) break;
678 name_start++;
680 if (name_start != ext_start) {
681 sz = ext_start - name;
682 ext_start++;
683 } else {
684 sz = len;
685 ext_start=NULL;
689 for (baselen = i = 0, p = base, ip = name; i < sz && baselen < 8; i++)
691 if (utf8 && (*ip & 0x80)) {
692 *p++ = '_';
693 baselen++;
694 } else if (!strchr(skip_chars, *ip)) {
695 if (*ip >= 'A' && *ip <= 'Z') {
696 *p = *ip + 32;
697 } else {
698 *p = *ip;
700 if (strchr(replace_chars, *p)) *p='_';
701 p++; baselen++;
703 ip++;
705 if (baselen == 0) {
706 return -EINVAL;
709 spaces = 8 - baselen;
711 if (ext_start) {
712 extlen = 0;
713 for (p = ext, ip = ext_start; extlen < 3 && ip < end; ip++) {
714 if (utf8 && (*ip & 0x80)) {
715 *p++ = '_';
716 extlen++;
717 } else if (!strchr(skip_chars, *ip)) {
718 if (*ip >= 'A' && *ip <= 'Z') {
719 *p = *ip + 32;
720 } else {
721 *p = *ip;
723 if (strchr(replace_chars, *p)) *p='_';
724 extlen++;
725 p++;
728 } else {
729 extlen = 0;
731 ext[extlen] = '\0';
732 base[baselen] = '\0';
734 strcpy(msdos_name, base);
735 msdos_name[baselen] = '.';
736 strcpy(&msdos_name[baselen+1], ext);
738 totlen = baselen + extlen + (extlen > 0);
739 res = 0;
740 if (MSDOS_SB(dir->i_sb)->options.numtail == 0) {
741 qname.name=msdos_name;
742 qname.len=totlen;
743 res = vfat_find(dir, &qname, 0, 0, 0, &sinfo);
746 if (res > -1) {
748 * Try to find a unique extension. This used to
749 * iterate through all possibilities sequentially,
750 * but that gave extremely bad performance. Windows
751 * only tries a few cases before using random
752 * values for part of the base.
755 if (2 > spaces) {
756 baselen = baselen - (2 - spaces);
757 spaces = 2;
759 msdos_name[baselen] = '~';
760 msdos_name[baselen+2] = '.';
761 strcpy(&msdos_name[baselen+3], ext);
762 totlen = baselen + 2 + extlen + (extlen > 0);
763 qname.name=msdos_name;
764 qname.len=totlen;
765 for (i = 1; res > -1 && i < 10; i++) {
766 strncpy(msdos_name, base, baselen);
767 msdos_name[baselen+1] = i + '0';
768 res = vfat_find(dir, &qname, 0, 0, 0, &sinfo);
771 if (res > -1) {
772 i = jiffies & 0xffff;
773 sz = (jiffies >> 16) & 0x7;
774 if (6 > spaces) {
775 baselen = baselen - (6 - spaces);
776 spaces = 6;
778 msdos_name[baselen+4] = '~';
779 msdos_name[baselen+5] = '1' + sz;
780 msdos_name[baselen+6] = '.';
781 strcpy(&msdos_name[baselen+7], ext);
782 totlen = baselen + 6 + extlen + (extlen > 0);
783 qname.name=msdos_name;
784 qname.len=totlen;
785 while (res > -1) {
786 sprintf(buf, "%04x", i);
787 memcpy(&msdos_name[baselen], buf, 4);
788 msdos_name[12] = 0;
789 res = vfat_find(dir, &qname, 0, 0, 0, &sinfo);
790 i -= 11;
794 res = vfat_format_name(msdos_name, totlen, name_res, 1, utf8);
795 return res;
798 static loff_t vfat_find_free_slots(struct inode *dir,int slots)
800 struct super_block *sb = dir->i_sb;
801 loff_t offset, curr;
802 struct msdos_dir_entry *de;
803 struct buffer_head *bh;
804 struct inode *inode;
805 int ino;
806 int row;
807 int done;
808 int res;
809 int added;
811 PRINTK2(("vfat_find_free_slots: find %d free slots\n", slots));
812 offset = curr = 0;
813 bh = NULL;
814 row = 0;
815 ino = fat_get_entry(dir,&curr,&bh,&de);
817 for (added = 0; added < 2; added++) {
818 while (ino > -1) {
819 done = IS_FREE(de->name);
820 if (done) {
821 inode = iget(sb,ino);
822 if (inode) {
823 /* Directory slots of busy deleted files aren't available yet. */
824 done = !MSDOS_I(inode)->i_busy;
825 /* PRINTK3(("inode %d still busy\n", ino)); */
826 iput(inode);
829 if (done) {
830 row++;
831 if (row == slots) {
832 fat_brelse(sb, bh);
833 /* printk("----- Free offset at %d\n", offset); */
834 return offset;
836 } else {
837 row = 0;
838 offset = curr;
840 ino = fat_get_entry(dir,&curr,&bh,&de);
843 if ((dir->i_ino == MSDOS_ROOT_INO) &&
844 (MSDOS_SB(sb)->fat_bits != 32))
845 return -ENOSPC;
846 if ((res = fat_add_cluster(dir)) < 0) return res;
847 ino = fat_get_entry(dir,&curr,&bh,&de);
849 return -ENOSPC;
852 /* Translate a string, including coded sequences into Unicode */
853 static int
854 xlate_to_uni(const char *name, int len, char *outname, int *outlen,
855 int escape, int utf8, struct nls_table *nls)
857 int i;
858 const unsigned char *ip;
859 char *op;
860 int fill;
861 unsigned char c1, c2, c3;
863 if (utf8) {
864 *outlen = utf8_mbstowcs((__u16 *) outname, name, PAGE_SIZE);
865 if (name[len-1] == '.')
866 *outlen-=2;
867 op = &outname[*outlen * sizeof(__u16)];
868 } else {
869 if (name[len-1] == '.')
870 len--;
871 op = outname;
872 if (nls) {
873 for (i = 0, ip = name, op = outname, *outlen = 0;
874 i < len && *outlen <= 260; i++, *outlen += 1)
876 if (escape && (*ip == ':')) {
877 if (i > len - 4) return -EINVAL;
878 c1 = fat_esc2uni[ip[1]];
879 c2 = fat_esc2uni[ip[2]];
880 c3 = fat_esc2uni[ip[3]];
881 if (c1 == 255 || c2 == 255 || c3 == 255)
882 return -EINVAL;
883 *op++ = (c1 << 4) + (c2 >> 2);
884 *op++ = ((c2 & 0x3) << 6) + c3;
885 ip += 4;
886 } else {
887 *op++ = nls->charset2uni[*ip].uni1;
888 *op++ = nls->charset2uni[*ip].uni2;
889 ip++;
892 } else {
893 for (i = 0, ip = name, op = outname, *outlen = 0;
894 i < len && *outlen <= 260; i++, *outlen += 1)
896 *op++ = *ip++;
897 *op++ = 0;
901 if (*outlen > 260)
902 return -ENAMETOOLONG;
904 if (*outlen % 13) {
905 *op++ = 0;
906 *op++ = 0;
907 *outlen += 1;
908 if (*outlen % 13) {
909 fill = 13 - (*outlen % 13);
910 for (i = 0; i < fill; i++) {
911 *op++ = 0xff;
912 *op++ = 0xff;
914 *outlen += fill;
918 return 0;
921 static int
922 vfat_fill_long_slots(struct msdos_dir_slot *ds, const char *name, int len,
923 char *msdos_name, int *slots,
924 int uni_xlate, int utf8, struct nls_table *nls)
926 struct msdos_dir_slot *ps;
927 struct msdos_dir_entry *de;
928 int res;
929 int slot;
930 unsigned char cksum;
931 char *uniname;
932 const char *ip;
933 unsigned long page;
934 int unilen;
935 int i;
936 loff_t offset;
938 if (name[len-1] == '.') len--;
939 if(!(page = __get_free_page(GFP_KERNEL)))
940 return -ENOMEM;
941 uniname = (char *) page;
942 res = xlate_to_uni(name, len, uniname, &unilen, uni_xlate, utf8, nls);
943 if (res < 0) {
944 free_page(page);
945 return res;
948 *slots = unilen / 13;
949 for (cksum = i = 0; i < 11; i++) {
950 cksum = (((cksum&1)<<7)|((cksum&0xfe)>>1)) + msdos_name[i];
952 PRINTK3(("vfat_fill_long_slots 3: slots=%d\n",*slots));
954 for (ps = ds, slot = *slots; slot > 0; slot--, ps++) {
955 int end, j;
957 PRINTK3(("vfat_fill_long_slots 4\n"));
958 ps->id = slot;
959 ps->attr = ATTR_EXT;
960 ps->reserved = 0;
961 ps->alias_checksum = cksum;
962 ps->start = 0;
963 PRINTK3(("vfat_fill_long_slots 5: uniname=%s\n",uniname));
964 offset = (slot - 1) * 26;
965 ip = &uniname[offset];
966 j = offset;
967 end = 0;
968 for (i = 0; i < 10; i += 2) {
969 ps->name0_4[i] = *ip++;
970 ps->name0_4[i+1] = *ip++;
972 PRINTK3(("vfat_fill_long_slots 6\n"));
973 for (i = 0; i < 12; i += 2) {
974 ps->name5_10[i] = *ip++;
975 ps->name5_10[i+1] = *ip++;
977 PRINTK3(("vfat_fill_long_slots 7\n"));
978 for (i = 0; i < 4; i += 2) {
979 ps->name11_12[i] = *ip++;
980 ps->name11_12[i+1] = *ip++;
983 PRINTK3(("vfat_fill_long_slots 8\n"));
984 ds[0].id |= 0x40;
986 de = (struct msdos_dir_entry *) ps;
987 PRINTK3(("vfat_fill_long_slots 9\n"));
988 strncpy(de->name, msdos_name, MSDOS_NAME);
990 free_page(page);
991 return 0;
994 static int vfat_build_slots(struct inode *dir,const char *name,int len,
995 struct msdos_dir_slot *ds, int *slots, int *is_long)
997 struct msdos_dir_entry *de;
998 char msdos_name[MSDOS_NAME];
999 int res, xlate, utf8;
1000 struct nls_table *nls;
1002 PRINTK2(("Entering vfat_build_slots: name=%s, len=%d\n", name, len));
1003 de = (struct msdos_dir_entry *) ds;
1004 xlate = MSDOS_SB(dir->i_sb)->options.unicode_xlate;
1005 utf8 = MSDOS_SB(dir->i_sb)->options.utf8;
1006 nls = MSDOS_SB(dir->i_sb)->nls_io;
1008 *slots = 1;
1009 *is_long = 0;
1010 if (len == 1 && name[0] == '.') {
1011 strncpy(de->name, MSDOS_DOT, MSDOS_NAME);
1012 } else if (len == 2 && name[0] == '.' && name[1] == '.') {
1013 strncpy(de->name, MSDOS_DOT, MSDOS_NAME);
1014 } else {
1015 PRINTK3(("vfat_build_slots 4\n"));
1016 res = vfat_valid_shortname(name, len, 1, utf8);
1017 if (res > -1) {
1018 PRINTK3(("vfat_build_slots 5a\n"));
1019 res = vfat_format_name(name, len, de->name, 1, utf8);
1020 PRINTK3(("vfat_build_slots 5b\n"));
1021 } else {
1022 res = vfat_create_shortname(dir, name, len, msdos_name, utf8);
1023 if (res < 0) {
1024 return res;
1027 res = vfat_valid_longname(name, len, 1, xlate);
1028 if (res < 0) {
1029 return res;
1032 *is_long = 1;
1034 return vfat_fill_long_slots(ds, name, len, msdos_name,
1035 slots, xlate, utf8, nls);
1038 return 0;
1041 static int vfat_readdir_cb(
1042 filldir_t filldir,
1043 void * buf,
1044 const char * name,
1045 int name_len,
1046 int is_long,
1047 off_t offset,
1048 off_t short_offset,
1049 int long_slots,
1050 ino_t ino)
1052 struct vfat_find_info *vf = (struct vfat_find_info *) buf;
1053 const char *s1, *s2;
1054 int i;
1056 #ifdef DEBUG
1057 if (debug) printk("cb: vf.name=%s, len=%d, name=%s, name_len=%d\n",
1058 vf->name, vf->len, name, name_len);
1059 #endif
1061 if (vf->len != name_len) {
1062 return 0;
1065 s1 = name; s2 = vf->name;
1066 for (i = 0; i < name_len; i++) {
1067 if (vf->anycase || (vf->new_filename && !vf->posix)) {
1068 if (tolower(*s1) != tolower(*s2))
1069 return 0;
1070 } else {
1071 if (*s1 != *s2)
1072 return 0;
1074 s1++; s2++;
1076 vf->found = 1;
1077 vf->is_long = is_long;
1078 vf->offset = (offset == 2) ? 0 : offset;
1079 vf->short_offset = (short_offset == 2) ? 0 : short_offset;
1080 vf->long_slots = long_slots;
1081 vf->ino = ino;
1082 return -1;
1085 static int vfat_find(struct inode *dir,struct qstr* qname,
1086 int find_long, int new_filename,int is_dir,struct vfat_slot_info *sinfo_out)
1088 struct super_block *sb = dir->i_sb;
1089 struct vfat_find_info vf;
1090 struct file fil;
1091 struct buffer_head *bh;
1092 struct msdos_dir_entry *de;
1093 struct msdos_dir_slot *ps;
1094 loff_t offset;
1095 struct msdos_dir_slot *ds;
1096 int is_long;
1097 int slots, slot;
1098 int res;
1100 PRINTK2(("Entering vfat_find\n"));
1102 ds = (struct msdos_dir_slot *)
1103 kmalloc(sizeof(struct msdos_dir_slot)*MSDOS_SLOTS, GFP_KERNEL);
1104 if (ds == NULL) return -ENOMEM;
1106 fil.f_pos = 0;
1107 vf.name = qname->name;
1108 vf.len = qname->len;
1109 vf.new_filename = new_filename;
1110 vf.found = 0;
1111 vf.posix = MSDOS_SB(sb)->options.posixfs;
1112 vf.anycase = (MSDOS_SB(sb)->options.name_check != 's');
1113 res = fat_readdirx(dir,&fil,(void *)&vf,vfat_readdir_cb,NULL,1,find_long,0);
1114 PRINTK3(("vfat_find: Debug 1\n"));
1115 if (res < 0) goto cleanup;
1116 if (vf.found) {
1117 if (new_filename) {
1118 res = -EEXIST;
1119 goto cleanup;
1121 sinfo_out->longname_offset = vf.offset;
1122 sinfo_out->shortname_offset = vf.short_offset;
1123 sinfo_out->is_long = vf.is_long;
1124 sinfo_out->long_slots = vf.long_slots;
1125 sinfo_out->total_slots = vf.long_slots + 1;
1126 sinfo_out->ino = vf.ino;
1128 PRINTK3(("vfat_find: Debug 2\n"));
1129 res = 0;
1130 goto cleanup;
1133 PRINTK3(("vfat_find: Debug 3\n"));
1134 if (!vf.found && !new_filename) {
1135 res = -ENOENT;
1136 goto cleanup;
1139 res = vfat_build_slots(dir, qname->name, qname->len, ds,
1140 &slots, &is_long);
1141 if (res < 0) goto cleanup;
1143 de = (struct msdos_dir_entry *) ds;
1145 bh = NULL;
1146 if (new_filename) {
1147 PRINTK3(("vfat_find: create file 1\n"));
1148 if (is_long) slots++;
1149 offset = vfat_find_free_slots(dir, slots);
1150 if (offset < 0) {
1151 res = offset;
1152 goto cleanup;
1155 PRINTK3(("vfat_find: create file 2\n"));
1156 /* Now create the new entry */
1157 bh = NULL;
1158 for (slot = 0, ps = ds; slot < slots; slot++, ps++) {
1159 PRINTK3(("vfat_find: create file 3, slot=%d\n",slot));
1160 sinfo_out->ino = fat_get_entry(dir,&offset,&bh,&de);
1161 if (sinfo_out->ino < 0) {
1162 PRINTK3(("vfat_find: problem\n"));
1163 res = sinfo_out->ino;
1164 goto cleanup;
1166 memcpy(de, ps, sizeof(struct msdos_dir_slot));
1167 fat_mark_buffer_dirty(sb, bh, 1);
1170 PRINTK3(("vfat_find: create file 4\n"));
1171 dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;
1172 mark_inode_dirty(dir);
1174 PRINTK3(("vfat_find: create file 5\n"));
1176 fat_date_unix2dos(dir->i_mtime,&de->time,&de->date);
1177 de->ctime_ms = 0;
1178 de->ctime = de->time;
1179 de->adate = de->cdate = de->date;
1180 de->start = 0;
1181 de->starthi = 0;
1182 de->size = 0;
1183 de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
1184 de->lcase = CASE_LOWER_BASE | CASE_LOWER_EXT;
1187 fat_mark_buffer_dirty(sb, bh, 1);
1188 fat_brelse(sb, bh);
1190 sinfo_out->is_long = (slots > 1) ? 1 : 0;
1191 if (sinfo_out->is_long) {
1192 sinfo_out->long_slots = slots - 1;
1193 } else {
1194 sinfo_out->long_slots = 0;
1196 sinfo_out->total_slots = slots;
1197 sinfo_out->shortname_offset = offset - sizeof(struct msdos_dir_slot);
1198 sinfo_out->longname_offset = offset - sizeof(struct msdos_dir_slot) * slots;
1199 res = 0;
1200 } else {
1201 res = -ENOENT;
1204 cleanup:
1205 kfree(ds);
1206 return res;
1209 int vfat_lookup(struct inode *dir,struct dentry *dentry)
1211 int res;
1212 struct vfat_slot_info sinfo;
1213 struct inode *result;
1214 int table;
1216 PRINTK2(("vfat_lookup: name=%s, len=%d\n",
1217 dentry->d_name.name, dentry->d_name.len));
1219 table = (MSDOS_SB(dir->i_sb)->options.name_check == 's') ? 2 : 0;
1220 dentry->d_op = &vfat_dentry_ops[table];
1222 result = NULL;
1223 if ((res = vfat_find(dir,&dentry->d_name,1,0,0,&sinfo)) < 0) {
1224 result = NULL;
1225 table++;
1226 goto error;
1228 PRINTK3(("vfat_lookup 4.5\n"));
1229 if (!(result = iget(dir->i_sb,sinfo.ino)))
1230 return -EACCES;
1231 PRINTK3(("vfat_lookup 5\n"));
1232 if (MSDOS_I(result)->i_busy) { /* mkdir in progress */
1233 iput(result);
1234 result = NULL;
1235 table++;
1236 goto error;
1238 PRINTK3(("vfat_lookup 6\n"));
1239 error:
1240 dentry->d_op = &vfat_dentry_ops[table];
1241 dentry->d_time = dentry->d_parent->d_inode->i_version;
1242 d_add(dentry,result);
1243 return 0;
1247 static int vfat_create_entry(struct inode *dir,struct qstr* qname,
1248 int is_dir, struct inode **result)
1250 struct super_block *sb = dir->i_sb;
1251 int res,ino;
1252 loff_t offset;
1253 struct buffer_head *bh;
1254 struct msdos_dir_entry *de;
1255 struct vfat_slot_info sinfo;
1257 *result=0;
1258 PRINTK1(("vfat_create_entry: Entering\n"));
1259 res = vfat_find(dir, qname, 1, 1, is_dir, &sinfo);
1260 if (res < 0) {
1261 return res;
1264 offset = sinfo.shortname_offset;
1266 PRINTK3(("vfat_create_entry 2\n"));
1267 bh = NULL;
1268 ino = fat_get_entry(dir, &offset, &bh, &de);
1269 if (ino < 0) {
1270 PRINTK3(("vfat_mkdir problem\n"));
1271 if (bh)
1272 fat_brelse(sb, bh);
1273 return ino;
1275 PRINTK3(("vfat_create_entry 3\n"));
1277 if ((*result = iget(dir->i_sb,ino)) != NULL)
1278 vfat_read_inode(*result);
1279 fat_brelse(sb, bh);
1280 if (!*result)
1281 return -EIO;
1282 (*result)->i_mtime = (*result)->i_atime = (*result)->i_ctime =
1283 CURRENT_TIME;
1284 mark_inode_dirty(*result);
1285 (*result)->i_version = ++event;
1286 dir->i_version = event;
1288 return 0;
1291 int vfat_create(struct inode *dir,struct dentry* dentry,int mode)
1293 int res;
1294 struct inode *result;
1296 result=NULL;
1297 fat_lock_creation();
1298 res = vfat_create_entry(dir,&dentry->d_name,0,&result);
1299 fat_unlock_creation();
1300 if (res < 0) {
1301 PRINTK3(("vfat_create: unable to get new entry\n"));
1302 } else {
1303 dentry->d_time = dentry->d_parent->d_inode->i_version;
1304 d_instantiate(dentry,result);
1306 return res;
1309 static int vfat_create_a_dotdir(struct inode *dir,struct inode *parent,
1310 struct buffer_head *bh,
1311 struct msdos_dir_entry *de,int ino,const char *name, int isdot)
1313 struct super_block *sb = dir->i_sb;
1314 struct inode *dot;
1316 PRINTK2(("vfat_create_a_dotdir: Entering\n"));
1319 * XXX all times should be set by caller upon successful completion.
1321 dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
1322 mark_inode_dirty(dir);
1323 memcpy(de->name,name,MSDOS_NAME);
1324 de->lcase = 0;
1325 de->attr = ATTR_DIR;
1326 de->start = 0;
1327 de->starthi = 0;
1328 fat_date_unix2dos(dir->i_mtime,&de->time,&de->date);
1329 de->ctime_ms = 0;
1330 de->ctime = de->time;
1331 de->adate = de->cdate = de->date;
1332 de->size = 0;
1333 fat_mark_buffer_dirty(sb, bh, 1);
1334 dot = iget(dir->i_sb,ino);
1335 if (!dot)
1336 return -EIO;
1337 vfat_read_inode(dot);
1338 dot->i_mtime = dot->i_atime = CURRENT_TIME;
1339 mark_inode_dirty(dot);
1340 if (isdot) {
1341 dot->i_size = dir->i_size;
1342 MSDOS_I(dot)->i_start = MSDOS_I(dir)->i_start;
1343 MSDOS_I(dot)->i_logstart = MSDOS_I(dir)->i_logstart;
1344 dot->i_nlink = dir->i_nlink;
1345 } else {
1346 dot->i_size = parent->i_size;
1347 MSDOS_I(dot)->i_start = MSDOS_I(parent)->i_start;
1348 MSDOS_I(dot)->i_logstart = MSDOS_I(parent)->i_logstart;
1349 dot->i_nlink = parent->i_nlink;
1352 iput(dot);
1354 PRINTK3(("vfat_create_a_dotdir 2\n"));
1355 return 0;
1358 static int vfat_create_dotdirs(struct inode *dir, struct inode *parent)
1360 struct super_block *sb = dir->i_sb;
1361 int res;
1362 struct buffer_head *bh;
1363 struct msdos_dir_entry *de;
1364 loff_t offset;
1366 PRINTK2(("vfat_create_dotdirs: Entering\n"));
1367 if ((res = fat_add_cluster(dir)) < 0) return res;
1369 PRINTK3(("vfat_create_dotdirs 2\n"));
1370 offset = 0;
1371 bh = NULL;
1372 if ((res = fat_get_entry(dir,&offset,&bh,&de)) < 0) return res;
1374 PRINTK3(("vfat_create_dotdirs 3\n"));
1375 res = vfat_create_a_dotdir(dir, parent, bh, de, res, MSDOS_DOT, 1);
1376 PRINTK3(("vfat_create_dotdirs 4\n"));
1377 if (res < 0) {
1378 fat_brelse(sb, bh);
1379 return res;
1381 PRINTK3(("vfat_create_dotdirs 5\n"));
1383 if ((res = fat_get_entry(dir,&offset,&bh,&de)) < 0) {
1384 fat_brelse(sb, bh);
1385 return res;
1387 PRINTK3(("vfat_create_dotdirs 6\n"));
1389 res = vfat_create_a_dotdir(dir, parent, bh, de, res, MSDOS_DOTDOT, 0);
1390 PRINTK3(("vfat_create_dotdirs 7\n"));
1391 fat_brelse(sb, bh);
1393 return res;
1396 /***** See if directory is empty */
1397 static int vfat_empty(struct inode *dir)
1399 struct super_block *sb = dir->i_sb;
1400 loff_t pos;
1401 struct buffer_head *bh;
1402 struct msdos_dir_entry *de;
1404 if (dir->i_count > 1) {
1405 return -EBUSY;
1407 if (MSDOS_I(dir)->i_start) { /* may be zero in mkdir */
1408 pos = 0;
1409 bh = NULL;
1410 while (fat_get_entry(dir,&pos,&bh,&de) > -1) {
1411 /* Skip extended filename entries */
1412 if (de->attr == ATTR_EXT) continue;
1414 if (!IS_FREE(de->name) && strncmp(de->name,MSDOS_DOT,
1415 MSDOS_NAME) && strncmp(de->name,MSDOS_DOTDOT,
1416 MSDOS_NAME)) {
1417 fat_brelse(sb, bh);
1418 return -ENOTEMPTY;
1421 if (bh)
1422 fat_brelse(sb, bh);
1424 return 0;
1427 static int vfat_rmdir_free_ino(struct inode *dir,struct buffer_head *bh,
1428 struct msdos_dir_entry *de,struct dentry* dentry)
1430 struct super_block *sb = dir->i_sb;
1431 int res;
1433 if (!S_ISDIR(dentry->d_inode->i_mode)) {
1434 return -ENOTDIR;
1436 if (dir->i_dev != dentry->d_inode->i_dev || dir == dentry->d_inode) {
1437 return -EBUSY;
1440 res = vfat_empty(dentry->d_inode);
1441 if (res) {
1442 return res;
1444 dentry->d_inode->i_nlink = 0;
1445 dentry->d_inode->i_mtime = dir->i_mtime = CURRENT_TIME;
1446 dentry->d_inode->i_atime = dir->i_atime = CURRENT_TIME;
1447 dir->i_nlink--;
1448 mark_inode_dirty(dir);
1449 mark_inode_dirty(dentry->d_inode);
1450 de->name[0] = DELETED_FLAG;
1451 fat_mark_buffer_dirty(sb, bh, 1);
1453 return 0;
1456 static int vfat_unlink_free_ino(struct inode *dir,struct buffer_head *bh,
1457 struct msdos_dir_entry *de,struct dentry* dentry,int nospc)
1459 struct super_block *sb = dir->i_sb;
1460 if ((!S_ISREG(dentry->d_inode->i_mode) && nospc) ||
1461 IS_IMMUTABLE(dentry->d_inode)) {
1462 return -EPERM;
1464 dentry->d_inode->i_nlink = 0;
1465 dentry->d_inode->i_mtime = dir->i_mtime = CURRENT_TIME;
1466 dentry->d_inode->i_atime = dir->i_atime = CURRENT_TIME;
1467 dir->i_version = ++event;
1468 MSDOS_I(dentry->d_inode)->i_busy = 1;
1469 mark_inode_dirty(dir);
1470 mark_inode_dirty(dentry->d_inode);
1471 de->name[0] = DELETED_FLAG;
1472 fat_mark_buffer_dirty(sb, bh, 1);
1474 return 0;
1477 static int vfat_remove_entry(struct inode *dir,struct vfat_slot_info *sinfo,
1478 struct buffer_head **bh,struct dentry* dentry,
1479 int is_dir,int nospc)
1481 struct super_block *sb = dir->i_sb;
1482 loff_t offset;
1483 struct msdos_dir_entry *de;
1484 int res, i;
1486 /* remove the shortname */
1487 offset = sinfo->shortname_offset;
1488 res = fat_get_entry(dir, &offset, bh, &de);
1489 if (res < 0) return res;
1490 if (is_dir) {
1491 res = vfat_rmdir_free_ino(dir,*bh,de,dentry);
1492 } else {
1493 res = vfat_unlink_free_ino(dir,*bh,de,dentry,nospc);
1495 if (res < 0) return res;
1497 /* remove the longname */
1498 offset = sinfo->longname_offset;
1499 for (i = sinfo->long_slots; i > 0; --i) {
1500 res = fat_get_entry(dir, &offset, bh, &de);
1501 if (res < 0) {
1502 continue;
1504 de->name[0] = DELETED_FLAG;
1505 de->attr = 0;
1506 fat_mark_buffer_dirty(sb, *bh, 1);
1508 return 0;
1511 /* Replace inodes in alias dentries and drop all but the initial dentry */
1512 static void drop_replace_inodes(struct dentry *dentry, struct inode *inode)
1514 struct list_head *head, *next, *tmp;
1515 struct dentry *alias;
1517 PRINTK1(("drop_replace_inodes: dentry=%p, inode=%p\n", dentry, inode));
1518 head = &dentry->d_inode->i_dentry;
1519 if (dentry->d_inode) {
1520 next = dentry->d_inode->i_dentry.next;
1521 while (next != head) {
1522 tmp = next;
1523 next = tmp->next;
1524 alias = list_entry(tmp, struct dentry, d_alias);
1525 if (inode) {
1526 list_del(&alias->d_alias);
1527 iput(alias->d_inode);
1528 d_instantiate(alias, inode);
1529 /* dentry is already accounted for */
1530 if (alias != dentry) {
1531 inode->i_count++;
1534 if (alias != dentry) {
1535 d_drop(alias);
1541 static int vfat_rmdirx(struct inode *dir,struct dentry* dentry)
1543 struct super_block *sb = dir->i_sb;
1544 int res;
1545 struct buffer_head *bh;
1546 struct vfat_slot_info sinfo;
1548 PRINTK1(("vfat_rmdirx: dentry=%p\n", dentry));
1549 res = vfat_find(dir,&dentry->d_name,1,0,0,&sinfo);
1551 if (res >= 0 && sinfo.total_slots > 0) {
1552 bh = NULL;
1553 res = vfat_remove_entry(dir,&sinfo,&bh,dentry,1,0);
1554 if (res > 0) {
1555 res = 0;
1557 dir->i_version = ++event;
1558 if (bh) fat_brelse(sb, bh);
1560 return res;
1563 /***** Remove a directory */
1564 int vfat_rmdir(struct inode *dir,struct dentry* dentry)
1566 int res;
1567 PRINTK1(("vfat_rmdir: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
1568 res = vfat_rmdirx(dir, dentry);
1569 if (res >= 0) {
1570 drop_replace_inodes(dentry, NULL);
1571 d_delete(dentry);
1573 return res;
1576 static int vfat_unlinkx(
1577 struct inode *dir,
1578 struct dentry* dentry,
1579 int nospc) /* Flag special file ? */
1581 struct super_block *sb = dir->i_sb;
1582 int res;
1583 struct buffer_head *bh;
1584 struct vfat_slot_info sinfo;
1586 PRINTK1(("vfat_unlinkx: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
1587 bh = NULL;
1588 res = vfat_find(dir,&dentry->d_name,1,0,0,&sinfo);
1590 if (res >= 0 && sinfo.total_slots > 0) {
1591 res = vfat_remove_entry(dir,&sinfo,&bh,dentry,0,nospc);
1592 if (res > 0) {
1593 res = 0;
1597 if (bh) fat_brelse(sb, bh);
1598 return res;
1602 int vfat_mkdir(struct inode *dir,struct dentry* dentry,int mode)
1604 struct inode *inode;
1605 int res;
1607 PRINTK1(("vfat_mkdir: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
1608 fat_lock_creation();
1609 if ((res = vfat_create_entry(dir,&dentry->d_name,1,&inode)) < 0) {
1610 fat_unlock_creation();
1611 return res;
1614 dir->i_nlink++;
1615 inode->i_nlink = 2; /* no need to mark them dirty */
1616 MSDOS_I(inode)->i_busy = 1; /* prevent lookups */
1618 res = vfat_create_dotdirs(inode, dir);
1619 fat_unlock_creation();
1620 MSDOS_I(inode)->i_busy = 0;
1621 dentry->d_time = dentry->d_parent->d_inode->i_version;
1622 d_instantiate(dentry,inode);
1623 if (res < 0) {
1624 if (vfat_rmdir(dir,dentry) < 0)
1625 fat_fs_panic(dir->i_sb,"rmdir in mkdir failed");
1627 return res;
1630 /***** Unlink, as called for msdosfs */
1631 int vfat_unlink(struct inode *dir,struct dentry* dentry)
1633 int res;
1635 PRINTK1(("vfat_unlink: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
1636 res = vfat_unlinkx (dir,dentry,1);
1637 if (res >= 0) {
1638 drop_replace_inodes(dentry, NULL);
1639 d_delete(dentry);
1641 return res;
1644 /***** Unlink, as called for uvfatfs */
1645 int vfat_unlink_uvfat(struct inode *dir,struct dentry *dentry)
1647 int res;
1649 res = vfat_unlinkx (dir,dentry,0);
1650 iput(dir);
1651 return res;
1654 int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
1655 struct inode *new_dir,struct dentry *new_dentry)
1657 struct super_block *sb = old_dir->i_sb;
1658 struct buffer_head *old_bh,*new_bh,*dotdot_bh;
1659 struct msdos_dir_entry *old_de,*new_de,*dotdot_de;
1660 loff_t old_offset,new_offset,old_longname_offset;
1661 int old_slots,old_ino,new_ino,dotdot_ino;
1662 struct inode *old_inode, *new_inode, *dotdot_inode;
1663 struct dentry *walk;
1664 int res, is_dir, i;
1665 int locked = 0;
1666 struct vfat_slot_info sinfo;
1667 int put_new_inode = 0;
1669 PRINTK1(("vfat_rename: Entering: old_dentry=%p, old_inode=%p, old ino=%ld, new_dentry=%p, new_inode=%p, new ino=%ld\n",
1670 old_dentry, old_dentry->d_inode, old_dentry->d_inode->i_ino,
1671 new_dentry, new_dentry->d_inode,
1672 new_dentry->d_inode ? new_dentry->d_inode->i_ino : 0));
1673 if (old_dir == new_dir &&
1674 old_dentry->d_name.len == new_dentry->d_name.len &&
1675 strncmp(old_dentry->d_name.name, new_dentry->d_name.name,
1676 old_dentry->d_name.len) == 0)
1677 return 0;
1679 old_bh = new_bh = NULL;
1680 old_inode = new_inode = NULL;
1681 res = vfat_find(old_dir,&old_dentry->d_name,1,0,0,&sinfo);
1682 PRINTK3(("vfat_rename 2\n"));
1683 if (res < 0) goto rename_done;
1685 old_slots = sinfo.total_slots;
1686 old_longname_offset = sinfo.longname_offset;
1687 old_offset = sinfo.shortname_offset;
1688 old_ino = sinfo.ino;
1689 res = fat_get_entry(old_dir, &old_offset, &old_bh, &old_de);
1690 PRINTK3(("vfat_rename 3\n"));
1691 if (res < 0) goto rename_done;
1693 res = -ENOENT;
1694 old_inode = old_dentry->d_inode;
1695 is_dir = S_ISDIR(old_inode->i_mode);
1696 if (is_dir) {
1697 if ((old_dir->i_dev != new_dir->i_dev) ||
1698 (old_ino == new_dir->i_ino)) {
1699 res = -EINVAL;
1700 goto rename_done;
1702 walk = new_dentry;
1703 /* prevent moving directory below itself */
1704 for (;;) {
1705 if (walk == old_dentry) return -EINVAL;
1706 if (walk == walk->d_parent) break;
1707 walk = walk->d_parent;
1711 res = vfat_find(new_dir,&new_dentry->d_name,1,0,is_dir,&sinfo);
1713 PRINTK3(("vfat_rename 4\n"));
1714 if (res > -1) {
1715 int new_is_dir;
1717 PRINTK3(("vfat_rename 5\n"));
1718 /* Filename currently exists. Need to delete it */
1719 new_offset = sinfo.shortname_offset;
1720 res = fat_get_entry(new_dir, &new_offset, &new_bh, &new_de);
1721 PRINTK3(("vfat_rename 6\n"));
1722 if (res < 0) goto rename_done;
1724 if (!(new_inode = iget(new_dir->i_sb,res)))
1725 goto rename_done;
1726 new_is_dir = S_ISDIR(new_inode->i_mode);
1727 iput(new_inode);
1728 if (new_is_dir) {
1729 PRINTK3(("vfat_rename 7\n"));
1730 res = vfat_rmdirx(new_dir,new_dentry);
1731 PRINTK3(("vfat_rename 8\n"));
1732 if (res < 0) goto rename_done;
1733 } else {
1734 /* Is this the same file, different case? */
1735 if (new_inode != old_inode) {
1736 PRINTK3(("vfat_rename 9\n"));
1737 res = vfat_unlink(new_dir,new_dentry);
1738 PRINTK3(("vfat_rename 10\n"));
1739 if (res < 0) goto rename_done;
1744 PRINTK3(("vfat_rename 11\n"));
1745 fat_lock_creation(); locked = 1;
1746 res = vfat_find(new_dir,&new_dentry->d_name,1,1,is_dir,&sinfo);
1748 PRINTK3(("vfat_rename 12\n"));
1749 if (res < 0) goto rename_done;
1751 new_offset = sinfo.shortname_offset;
1752 new_ino = sinfo.ino;
1753 PRINTK3(("vfat_rename 13: new_ino=%d\n", new_ino));
1755 if (!(new_inode = iget(new_dir->i_sb,new_ino))) goto rename_done;
1756 put_new_inode = 1;
1758 new_inode->i_mode = old_inode->i_mode;
1759 new_inode->i_size = old_inode->i_size;
1760 new_inode->i_blocks = old_inode->i_blocks;
1761 new_inode->i_mtime = old_inode->i_mtime;
1762 new_inode->i_atime = old_inode->i_atime;
1763 new_inode->i_ctime = old_inode->i_ctime;
1764 MSDOS_I(new_inode)->i_ctime_ms = MSDOS_I(old_inode)->i_ctime_ms;
1766 MSDOS_I(new_inode)->i_start = MSDOS_I(old_inode)->i_start;
1767 MSDOS_I(new_inode)->i_logstart = MSDOS_I(old_inode)->i_logstart;
1768 MSDOS_I(new_inode)->i_attrs = MSDOS_I(old_inode)->i_attrs;
1770 mark_inode_dirty(new_inode);
1772 old_dir->i_version = ++event;
1773 new_dir->i_version = ++event;
1775 PRINTK3(("vfat_rename 14: old_slots=%d\n",old_slots));
1777 /* remove the old entry */
1778 for (i = old_slots; i > 0; --i) {
1779 res = fat_get_entry(old_dir, &old_longname_offset, &old_bh, &old_de);
1780 if (res < 0) {
1781 printk("vfat_rename: problem 1\n");
1782 continue;
1784 old_de->name[0] = DELETED_FLAG;
1785 old_de->attr = 0;
1786 fat_mark_buffer_dirty(sb, old_bh, 1);
1788 PRINTK3(("vfat_rename 15b\n"));
1790 if (S_ISDIR(old_inode->i_mode)) {
1791 if ((res = fat_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh,
1792 &dotdot_de,&dotdot_ino,SCAN_ANY)) < 0) goto rename_done;
1793 if (!(dotdot_inode = iget(old_inode->i_sb,dotdot_ino))) {
1794 fat_brelse(sb, dotdot_bh);
1795 res = -EIO;
1796 goto rename_done;
1798 MSDOS_I(dotdot_inode)->i_start = MSDOS_I(new_dir)->i_start;
1799 MSDOS_I(dotdot_inode)->i_logstart = MSDOS_I(new_dir)->i_logstart;
1800 dotdot_de->start = CT_LE_W(MSDOS_I(new_dir)->i_logstart);
1801 dotdot_de->starthi = CT_LE_W((MSDOS_I(new_dir)->i_logstart) >> 16);
1802 mark_inode_dirty(dotdot_inode);
1803 fat_mark_buffer_dirty(sb, dotdot_bh, 1);
1804 old_dir->i_nlink--;
1805 new_dir->i_nlink++;
1806 /* no need to mark them dirty */
1807 dotdot_inode->i_nlink = new_dir->i_nlink;
1808 iput(dotdot_inode);
1809 fat_brelse(sb, dotdot_bh);
1812 if (res > 0) res = 0;
1814 if (res == 0) {
1815 drop_replace_inodes(old_dentry, new_inode);
1816 d_move(old_dentry, new_dentry);
1817 put_new_inode = 0;
1820 rename_done:
1821 if (locked)
1822 fat_unlock_creation();
1823 if (old_bh)
1824 fat_brelse(sb, old_bh);
1825 if (new_bh)
1826 fat_brelse(sb, new_bh);
1827 if (put_new_inode)
1828 iput(new_inode);
1829 return res;
1834 /* Public inode operations for the VFAT fs */
1835 struct inode_operations vfat_dir_inode_operations = {
1836 &fat_dir_operations, /* default directory file-ops */
1837 vfat_create, /* create */
1838 vfat_lookup, /* lookup */
1839 NULL, /* link */
1840 vfat_unlink, /* unlink */
1841 NULL, /* symlink */
1842 vfat_mkdir, /* mkdir */
1843 vfat_rmdir, /* rmdir */
1844 NULL, /* mknod */
1845 vfat_rename, /* rename */
1846 NULL, /* readlink */
1847 NULL, /* followlink */
1848 NULL, /* readpage */
1849 NULL, /* writepage */
1850 fat_bmap, /* bmap */
1851 NULL, /* truncate */
1852 NULL /* permission */
1856 void vfat_read_inode(struct inode *inode)
1858 fat_read_inode(inode, &vfat_dir_inode_operations);
1861 #ifdef MODULE
1862 int init_module(void)
1864 return init_vfat_fs();
1867 void cleanup_module(void)
1869 unregister_filesystem(&vfat_fs_type);
1872 #endif /* ifdef MODULE */