File: /usr/src/linux/fs/vfat/namei.c
1 /*
2 * linux/fs/vfat/namei.c
3 *
4 * Written 1992,1993 by Werner Almesberger
5 *
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.
11 *
12 * Short name translation 1999 by Wolfram Pienkoss <wp@bszh.de>
13 *
14 * Support Multibyte character and cleanup by
15 * OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
16 */
17
18 #define __NO_VERSION__
19 #include <linux/module.h>
20
21 #include <linux/sched.h>
22 #include <linux/msdos_fs.h>
23 #include <linux/nls.h>
24 #include <linux/kernel.h>
25 #include <linux/errno.h>
26 #include <linux/string.h>
27 #include <linux/ctype.h>
28 #include <linux/stat.h>
29 #include <linux/mm.h>
30 #include <linux/slab.h>
31
32 #include "../fat/msbuffer.h"
33
34 #define DEBUG_LEVEL 0
35 #if (DEBUG_LEVEL >= 1)
36 # define PRINTK1(x) printk x
37 #else
38 # define PRINTK1(x)
39 #endif
40 #if (DEBUG_LEVEL >= 2)
41 # define PRINTK2(x) printk x
42 #else
43 # define PRINTK2(x)
44 #endif
45 #if (DEBUG_LEVEL >= 3)
46 # define PRINTK3(x) printk x
47 #else
48 # define PRINTK3(x)
49 #endif
50
51 #ifndef DEBUG
52 # define CHECK_STACK
53 #else
54 # define CHECK_STACK check_stack(__FILE__, __LINE__)
55 #endif
56
57 static int vfat_hashi(struct dentry *parent, struct qstr *qstr);
58 static int vfat_hash(struct dentry *parent, struct qstr *qstr);
59 static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);
60 static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b);
61 static int vfat_revalidate(struct dentry *dentry, int);
62
63 static struct dentry_operations vfat_dentry_ops[4] = {
64 {
65 d_hash: vfat_hashi,
66 d_compare: vfat_cmpi,
67 },
68 {
69 d_revalidate: vfat_revalidate,
70 d_hash: vfat_hashi,
71 d_compare: vfat_cmpi,
72 },
73 {
74 d_hash: vfat_hash,
75 d_compare: vfat_cmp,
76 },
77 {
78 d_revalidate: vfat_revalidate,
79 d_hash: vfat_hash,
80 d_compare: vfat_cmp,
81 }
82 };
83
84 static int vfat_revalidate(struct dentry *dentry, int flags)
85 {
86 PRINTK1(("vfat_revalidate: %s\n", dentry->d_name.name));
87 spin_lock(&dcache_lock);
88 if (dentry->d_time == dentry->d_parent->d_inode->i_version) {
89 spin_unlock(&dcache_lock);
90 return 1;
91 }
92 spin_unlock(&dcache_lock);
93 return 0;
94 }
95
96 static int simple_getbool(char *s, int *setval)
97 {
98 if (s) {
99 if (!strcmp(s,"1") || !strcmp(s,"yes") || !strcmp(s,"true")) {
100 *setval = 1;
101 } else if (!strcmp(s,"0") || !strcmp(s,"no") || !strcmp(s,"false")) {
102 *setval = 0;
103 } else {
104 return 0;
105 }
106 } else {
107 *setval = 1;
108 }
109 return 1;
110 }
111
112 static int parse_options(char *options, struct fat_mount_options *opts)
113 {
114 char *this_char,*value,save,*savep;
115 int ret, val;
116
117 opts->unicode_xlate = opts->posixfs = 0;
118 opts->numtail = 1;
119 opts->utf8 = 0;
120
121 if (!options) return 1;
122 save = 0;
123 savep = NULL;
124 ret = 1;
125 for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
126 if ((value = strchr(this_char,'=')) != NULL) {
127 save = *value;
128 savep = value;
129 *value++ = 0;
130 }
131 if (!strcmp(this_char,"utf8")) {
132 ret = simple_getbool(value, &val);
133 if (ret) opts->utf8 = val;
134 } else if (!strcmp(this_char,"uni_xlate")) {
135 ret = simple_getbool(value, &val);
136 if (ret) opts->unicode_xlate = val;
137 } else if (!strcmp(this_char,"posix")) {
138 ret = simple_getbool(value, &val);
139 if (ret) opts->posixfs = val;
140 } else if (!strcmp(this_char,"nonumtail")) {
141 ret = simple_getbool(value, &val);
142 if (ret) {
143 opts->numtail = !val;
144 }
145 }
146 if (this_char != options)
147 *(this_char-1) = ',';
148 if (value) {
149 *savep = save;
150 }
151 if (ret == 0) {
152 return 0;
153 }
154 }
155 if (opts->unicode_xlate) {
156 opts->utf8 = 0;
157 }
158 return 1;
159 }
160 #if 0 /* not used functions */
161 static inline unsigned char
162 vfat_getlower(struct nls_table *t, unsigned char c)
163 {
164 return t->charset2lower[c];
165 }
166
167 static inline unsigned char
168 vfat_getupper(struct nls_table *t, unsigned char c)
169 {
170 return t->charset2upper[c];
171 }
172
173 static inline int
174 vfat_uni2short(struct nls_table *t, wchar_t uc, unsigned char *op, int bound)
175 {
176 int charlen;
177
178 if ( (charlen = t->uni2char(uc, op, bound)) < 0)
179 charlen = 0;
180
181 return charlen;
182 }
183
184 static int vfat_valid_shortname(struct nls_table *nls, wchar_t *name, int len)
185 {
186 wchar_t *walk;
187 unsigned char c, charbuf[NLS_MAX_CHARSET_SIZE];
188 int chl, chi;
189 int space;
190
191 if (vfat_uni2upper_short(nls, *name, charbuf, NLS_MAX_CHARSET_SIZE) == 0)
192 return -EINVAL;
193
194 if (IS_FREE(charbuf))
195 return -EINVAL;
196
197 chl = 0;
198 c = 0;
199 space = 1; /* disallow names starting with a dot */
200 for (walk = name; len && walk-name < 8;) {
201 len--;
202 chl = nls->uni2char(*walk++, charbuf, NLS_MAX_CHARSET_SIZE);
203 if (chl < 0)
204 return -EINVAL;
205
206 for (chi = 0; chi < chl; chi++) {
207 c = vfat_getupper(nls, charbuf[chi]);
208 if (!c) return -EINVAL;
209 if (charbuf[chi] != vfat_tolower(nls, c)) return -EINVAL;
210 if (strchr(replace_chars,c)) return -EINVAL;
211 if (c < ' '|| c==':') return -EINVAL;
212 if (c == '.') goto dot;
213 space = c == ' ';
214 }
215 }
216 dot:;
217 if (space) return -EINVAL;
218 if (len && c != '.') {
219 len--;
220 if (vfat_uni2upper_short(nls, *walk++, charbuf, NLS_MAX_CHARSET_SIZE) == 1) {
221 if (charbuf[0] != '.') return -EINVAL;
222 } else
223 return -EINVAL;
224 c = '.';
225 }
226 if (c == '.') {
227 if (len >= 4) return -EINVAL;
228 while (len > 0) {
229 len--;
230 chl = nls->uni2char(*walk++, charbuf, NLS_MAX_CHARSET_SIZE);
231 if (chl < 0)
232 return -EINVAL;
233 for (chi = 0; chi < chl; chi++) {
234 c = vfat_getupper(nls, charbuf[chi]);
235 if (!c) return -EINVAL;
236 if (charbuf[chi] != vfat_tolower(nls, c)) return -EINVAL;
237 if (strchr(replace_chars,c))
238 return -EINVAL;
239 if (c < ' ' || c == '.'|| c==':')
240 return -EINVAL;
241 space = c == ' ';
242 }
243 }
244 if (space) return -EINVAL;
245 }
246
247 return 0;
248 }
249
250 static int vfat_format_name(struct nls_table *nls, wchar_t *name,
251 int len, char *res)
252 {
253 char *walk;
254 unsigned char charbuf[NLS_MAX_CHARSET_SIZE];
255 int chi, chl;
256 int space;
257
258 if (vfat_uni2upper_short(nls, *name, charbuf, NLS_MAX_CHARSET_SIZE) == 0)
259 return -EINVAL;
260
261 if (IS_FREE(charbuf))
262 return -EINVAL;
263
264 space = 1; /* disallow names starting with a dot */
265 for (walk = res; len--; ) {
266 chl = vfat_uni2upper_short(nls, *name++, charbuf, NLS_MAX_CHARSET_SIZE);
267 if (chl == 0)
268 return -EINVAL;
269 for (chi = 0; chi < chl; chi++){
270 if (charbuf[chi] == '.') goto dot;
271 if (!charbuf[chi]) return -EINVAL;
272 if (walk-res == 8) return -EINVAL;
273 if (strchr(replace_chars,charbuf[chi])) return -EINVAL;
274 if (charbuf[chi] < ' '|| charbuf[chi]==':') return -EINVAL;
275 space = charbuf[chi] == ' ';
276 *walk = charbuf[chi];
277 walk++;
278 }
279 }
280 dot:;
281 if (space) return -EINVAL;
282 if (len >= 0) {
283 while (walk-res < 8) *walk++ = ' ';
284 while (len > 0 && walk-res < MSDOS_NAME) {
285 chl = vfat_uni2upper_short(nls, *name++, charbuf, NLS_MAX_CHARSET_SIZE);
286 if (len < chl)
287 chl = len;
288 len -= chl;
289 for (chi = 0; chi < chl; chi++){
290 if (!charbuf[chi]) return -EINVAL;
291 if (strchr(replace_chars,charbuf[chi]))
292 return -EINVAL;
293 if (charbuf[chi] < ' ' || charbuf[chi] == '.'|| charbuf[chi]==':')
294 return -EINVAL;
295 space = charbuf[chi] == ' ';
296 *walk++ = charbuf[chi];
297 }
298 }
299 if (space) return -EINVAL;
300 if (len) return -EINVAL;
301 }
302 while (walk-res < MSDOS_NAME) *walk++ = ' ';
303
304 return 0;
305 }
306
307 static inline int
308 vfat_uni2upper_short(struct nls_table *t, wchar_t uc, char *op, int bound)
309 {
310 int chl;
311
312 if ( (chl = t->uni2char(uc, op, bound)) < 0)
313 chl = 0;
314
315 if (chl == 1)
316 op[0] = vfat_toupper(t, op[0]);
317
318 return chl;
319 }
320 #endif
321 static inline unsigned char
322 vfat_tolower(struct nls_table *t, unsigned char c)
323 {
324 unsigned char nc = t->charset2lower[c];
325
326 return nc ? nc : c;
327 }
328
329 static inline unsigned char
330 vfat_toupper(struct nls_table *t, unsigned char c)
331 {
332 unsigned char nc = t->charset2upper[c];
333
334 return nc ? nc : c;
335 }
336
337 static int
338 vfat_strnicmp(struct nls_table *t, const unsigned char *s1,
339 const unsigned char *s2, int len)
340 {
341 while(len--)
342 if (vfat_tolower(t, *s1++) != vfat_tolower(t, *s2++))
343 return 1;
344
345 return 0;
346 }
347
348 /*
349 * Compute the hash for the vfat name corresponding to the dentry.
350 * Note: if the name is invalid, we leave the hash code unchanged so
351 * that the existing dentry can be used. The vfat fs routines will
352 * return ENOENT or EINVAL as appropriate.
353 */
354 static int vfat_hash(struct dentry *dentry, struct qstr *qstr)
355 {
356 const char *name;
357 int len;
358
359 len = qstr->len;
360 name = qstr->name;
361 while (len && name[len-1] == '.')
362 len--;
363
364 qstr->hash = full_name_hash(name, len);
365
366 return 0;
367 }
368
369 /*
370 * Compute the hash for the vfat name corresponding to the dentry.
371 * Note: if the name is invalid, we leave the hash code unchanged so
372 * that the existing dentry can be used. The vfat fs routines will
373 * return ENOENT or EINVAL as appropriate.
374 */
375 static int vfat_hashi(struct dentry *dentry, struct qstr *qstr)
376 {
377 struct nls_table *t = MSDOS_SB(dentry->d_inode->i_sb)->nls_io;
378 const char *name;
379 int len;
380 unsigned long hash;
381
382 len = qstr->len;
383 name = qstr->name;
384 while (len && name[len-1] == '.')
385 len--;
386
387 hash = init_name_hash();
388 while (len--)
389 hash = partial_name_hash(vfat_tolower(t, *name++), hash);
390 qstr->hash = end_name_hash(hash);
391
392 return 0;
393 }
394
395 /*
396 * Case insensitive compare of two vfat names.
397 */
398 static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b)
399 {
400 struct nls_table *t = MSDOS_SB(dentry->d_inode->i_sb)->nls_io;
401 int alen, blen;
402
403 /* A filename cannot end in '.' or we treat it like it has none */
404 alen = a->len;
405 blen = b->len;
406 while (alen && a->name[alen-1] == '.')
407 alen--;
408 while (blen && b->name[blen-1] == '.')
409 blen--;
410 if (alen == blen) {
411 if (vfat_strnicmp(t, a->name, b->name, alen) == 0)
412 return 0;
413 }
414 return 1;
415 }
416
417 /*
418 * Case sensitive compare of two vfat names.
419 */
420 static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b)
421 {
422 int alen, blen;
423
424 /* A filename cannot end in '.' or we treat it like it has none */
425 alen = a->len;
426 blen = b->len;
427 while (alen && a->name[alen-1] == '.')
428 alen--;
429 while (blen && b->name[blen-1] == '.')
430 blen--;
431 if (alen == blen) {
432 if (strncmp(a->name, b->name, alen) == 0)
433 return 0;
434 }
435 return 1;
436 }
437
438 #ifdef DEBUG
439
440 static void
441 check_stack(const char *fname, int lineno)
442 {
443 int stack_level;
444 char *pg_dir;
445
446 stack_level = (long)(&pg_dir)-current->kernel_stack_page;
447 if (stack_level < 0)
448 printk("*-*-*-* vfat kstack overflow in %s line %d: SL=%d\n",
449 fname, lineno, stack_level);
450 else if (stack_level < 500)
451 printk("*-*-*-* vfat kstack low in %s line %d: SL=%d\n",
452 fname, lineno, stack_level);
453 #if 0
454 else
455 printk("------- vfat kstack ok in %s line %d: SL=%d\n",
456 fname, lineno, stack_level);
457 #endif
458 #if 0
459 if (*(unsigned long *) current->kernel_stack_page != STACK_MAGIC) {
460 printk("******* vfat stack corruption detected in %s at line %d\n",
461 fname, lineno);
462 }
463 #endif
464 }
465
466 static int debug = 0;
467 static void dump_fat(struct super_block *sb,int start)
468 {
469 printk("[");
470 while (start) {
471 printk("%d ",start);
472 start = fat_access(sb,start,-1);
473 if (!start) {
474 printk("ERROR");
475 break;
476 }
477 if (start == -1) break;
478 }
479 printk("]\n");
480 }
481
482 static void dump_de(struct msdos_dir_entry *de)
483 {
484 int i;
485 unsigned char *p = (unsigned char *) de;
486 printk("[");
487
488 for (i = 0; i < 32; i++, p++) {
489 printk("%02x ", *p);
490 }
491 printk("]\n");
492 }
493
494 #endif
495
496 /* MS-DOS "device special files" */
497
498 static const char *reserved3_names[] = {
499 "con ", "prn ", "nul ", "aux ", NULL
500 };
501
502 static const char *reserved4_names[] = {
503 "com1 ", "com2 ", "com3 ", "com4 ", "com5 ",
504 "com6 ", "com7 ", "com8 ", "com9 ",
505 "lpt1 ", "lpt2 ", "lpt3 ", "lpt4 ", "lpt5 ",
506 "lpt6 ", "lpt7 ", "lpt8 ", "lpt9 ",
507 NULL };
508
509
510 /* Characters that are undesirable in an MS-DOS file name */
511
512 static wchar_t bad_chars[] = {
513 /* `*' `?' `<' `>' `|' `"' `:' `/' `\' */
514 0x002A, 0x003F, 0x003C, 0x003E, 0x007C, 0x0022, 0x003A, 0x002F, 0x005C, 0,
515 };
516 #define IS_BADCHAR(uni) (vfat_unistrchr(bad_chars, (uni)) != NULL)
517
518 static wchar_t replace_chars[] = {
519 /* `[' `]' `;' `,' `+' `=' */
520 0x005B, 0x005D, 0x003B, 0x002C, 0x002B, 0x003D, 0,
521 };
522 #define IS_REPLACECHAR(uni) (vfat_unistrchr(replace_chars, (uni)) != NULL)
523
524 static inline wchar_t *vfat_unistrchr(const wchar_t *s, const wchar_t c)
525 {
526 for(; *s != c; ++s)
527 if (*s == 0)
528 return NULL;
529 return (wchar_t *) s;
530 }
531
532 static inline int vfat_is_used_badchars(const wchar_t *s, int len)
533 {
534 int i;
535
536 for (i = 0; i < len; i++)
537 if (s[i] < 0x0020 || IS_BADCHAR(s[i]))
538 return -EINVAL;
539 return 0;
540 }
541
542 /* Checks the validity of a long MS-DOS filename */
543 /* Returns negative number on error, 0 for a normal
544 * return, and 1 for . or .. */
545
546 static int vfat_valid_longname(const char *name, int len, int xlate)
547 {
548 const char **reserved, *walk;
549 int baselen;
550
551 if (len && name[len-1] == ' ') return -EINVAL;
552 if (len >= 256) return -EINVAL;
553 if (len < 3) return 0;
554
555 for (walk = name; *walk != 0 && *walk != '.'; walk++);
556 baselen = walk - name;
557
558 if (baselen == 3) {
559 for (reserved = reserved3_names; *reserved; reserved++) {
560 if (!strnicmp(name,*reserved,baselen))
561 return -EINVAL;
562 }
563 } else if (baselen == 4) {
564 for (reserved = reserved4_names; *reserved; reserved++) {
565 if (!strnicmp(name,*reserved,baselen))
566 return -EINVAL;
567 }
568 }
569 return 0;
570 }
571
572 static int vfat_find_form(struct inode *dir,char *name)
573 {
574 struct msdos_dir_entry *de;
575 struct buffer_head *bh = NULL;
576 int ino,res;
577
578 res=fat_scan(dir,name,&bh,&de,&ino);
579 fat_brelse(dir->i_sb, bh);
580 if (res<0)
581 return -ENOENT;
582 return 0;
583 }
584
585 static wchar_t skip_chars[] = {
586 /* `.' ` ' */
587 0x002E, 0x0020, 0,
588 };
589 #define IS_SKIPCHAR(uni) \
590 ((wchar_t)(uni) == skip_chars[0] || (wchar_t)(uni) == skip_chars[1])
591
592 /* Given a valid longname, create a unique shortname. Make sure the
593 * shortname does not exist
594 * Returns negative number on error, 0 for a normal
595 * return, and 1 for valid shortname
596 */
597 static int vfat_create_shortname(struct inode *dir, struct nls_table *nls,
598 wchar_t *uname, int ulen,
599 char *name_res)
600 {
601 wchar_t *ip, *ext_start, *end, *name_start;
602 unsigned char base[9], ext[4], buf[8], *p;
603 unsigned char charbuf[NLS_MAX_CHARSET_SIZE];
604 int chl, chi;
605 int sz = 0, extlen, baselen, i, numtail_baselen, numtail2_baselen;
606 int is_uppercase, is_shortname;
607
608 /*
609 * 1) Valid characters for the 8.3 format alias are any
610 * combination of letters, uppercase alphabets, digits, any of
611 * the following special characters:
612 * $ % ' ` - @ { } ~ ! # ( ) & _ ^
613 * In this case Longfilename is not stored in disk.
614 *
615 * 2) File name is 8.3 format, but it contain the lowercase
616 * alphabet etc. In this case numtail is not added, but
617 * Longfilename is stored.
618 *
619 * 3) When the one except for the above, or the following special
620 * character are contained:
621 * . [ ] ; , + =
622 * numtail is added, and Longfilename must be stored in disk .
623 */
624 is_uppercase = 1;
625 is_shortname = 1;
626
627 /* Now, we need to create a shortname from the long name */
628 ext_start = end = &uname[ulen];
629 while (--ext_start >= uname) {
630 if (*ext_start == 0x002E) { /* is `.' */
631 if (ext_start == end - 1) {
632 sz = ulen;
633 ext_start = NULL;
634 }
635 break;
636 }
637 }
638
639 if (ext_start == uname - 1) {
640 sz = ulen;
641 ext_start = NULL;
642 } else if (ext_start) {
643 /*
644 * Names which start with a dot could be just
645 * an extension eg. "...test". In this case Win95
646 * uses the extension as the name and sets no extension.
647 */
648 name_start = &uname[0];
649 while (name_start < ext_start) {
650 if (!IS_SKIPCHAR(*name_start))
651 break;
652 name_start++;
653 }
654 if (name_start != ext_start) {
655 sz = ext_start - uname;
656 ext_start++;
657 } else {
658 sz = ulen;
659 ext_start=NULL;
660 }
661 }
662
663 numtail_baselen = 6;
664 numtail2_baselen = 2;
665 for (baselen = i = 0, p = base, ip = uname; i < sz; i++, ip++)
666 {
667 if (IS_SKIPCHAR(*ip)) {
668 is_shortname = 0;
669 continue;
670 }
671 if (IS_REPLACECHAR(*ip)) {
672 is_shortname = 0;
673 charbuf[0] = '_';
674 chl = 1;
675 } else {
676 chl = nls->uni2char(*ip, charbuf, sizeof(charbuf));
677 if (chl <= 0) {
678 is_shortname = 0;
679 charbuf[0] = '_';
680 chl = 1;
681 } else if (chl == 1) {
682 unsigned char c = charbuf[0];
683 charbuf[0] = vfat_toupper(nls, charbuf[0]);
684 if (c >= 0x7F || charbuf[0] != c)
685 is_uppercase = 0;
686 } else {
687 is_uppercase = 0;
688 }
689 }
690
691 if (baselen < 2 && (baselen + chl) > 2)
692 numtail2_baselen = baselen;
693 if (baselen < 6 && (baselen + chl) > 6)
694 numtail_baselen = baselen;
695 for (chi = 0; chi < chl; chi++){
696 *p++ = charbuf[chi];
697 baselen++;
698 if (baselen >= 8)
699 break;
700 }
701 if (baselen >= 8) {
702 if ((chi < chl - 1) || (ip + 1) - uname < sz)
703 is_shortname = 0;
704 break;
705 }
706 }
707 if (baselen == 0) {
708 return -EINVAL;
709 }
710
711 extlen = 0;
712 if (ext_start) {
713 for (p = ext, ip = ext_start; extlen < 3 && ip < end; ip++) {
714 if (IS_SKIPCHAR(*ip)) {
715 is_shortname = 0;
716 continue;
717 }
718 if (IS_REPLACECHAR(*ip)) {
719 is_shortname = 0;
720 charbuf[0] = '_';
721 chl = 1;
722 } else {
723 chl = nls->uni2char(*ip, charbuf, sizeof(charbuf));
724 if (chl <= 0) {
725 is_shortname = 0;
726 charbuf[0] = '_';
727 chl = 1;
728 } else if (chl == 1) {
729 unsigned char c = charbuf[0];
730 charbuf[0] = vfat_toupper(nls, charbuf[0]);
731 if (c >= 0x7F || charbuf[0] != c)
732 is_uppercase = 0;
733 } else {
734 is_uppercase = 0;
735 }
736 }
737
738 if ((extlen + chl) > 3) {
739 is_shortname = 0;
740 break;
741 }
742 for (chi = 0; chi < chl; chi++) {
743 *p++ = charbuf[chi];
744 extlen++;
745 }
746 if (extlen >= 3) {
747 if (ip + 1 != end)
748 is_shortname = 0;
749 break;
750 }
751 }
752 }
753 ext[extlen] = '\0';
754 base[baselen] = '\0';
755
756 /* Yes, it can happen. ".\xe5" would do it. */
757 if (base[0] == DELETED_FLAG)
758 base[0] = 0x05;
759
760 /* OK, at this point we know that base is not longer than 8 symbols,
761 * ext is not longer than 3, base is nonempty, both don't contain
762 * any bad symbols (lowercase transformed to uppercase).
763 */
764
765 memset(name_res, ' ', MSDOS_NAME);
766 memcpy(name_res,base,baselen);
767 memcpy(name_res+8,ext,extlen);
768
769 if (is_shortname) {
770 if (vfat_find_form(dir, name_res) < 0)
771 return is_uppercase;
772 else
773 return -EEXIST;
774 }
775
776 if (MSDOS_SB(dir->i_sb)->options.numtail == 0)
777 if (vfat_find_form(dir, name_res) < 0)
778 return 0;
779
780 /*
781 * Try to find a unique extension. This used to
782 * iterate through all possibilities sequentially,
783 * but that gave extremely bad performance. Windows
784 * only tries a few cases before using random
785 * values for part of the base.
786 */
787
788 if (baselen>6) {
789 baselen = numtail_baselen;
790 name_res[7] = ' ';
791 }
792 name_res[baselen] = '~';
793 for (i = 1; i < 10; i++) {
794 name_res[baselen+1] = i + '0';
795 if (vfat_find_form(dir, name_res) < 0)
796 return 0;
797 }
798
799 i = jiffies & 0xffff;
800 sz = (jiffies >> 16) & 0x7;
801 if (baselen>2) {
802 baselen = numtail2_baselen;
803 name_res[7] = ' ';
804 }
805 name_res[baselen+4] = '~';
806 name_res[baselen+5] = '1' + sz;
807 while (1) {
808 sprintf(buf, "%04X", i);
809 memcpy(&name_res[baselen], buf, 4);
810 if (vfat_find_form(dir, name_res) < 0)
811 break;
812 i -= 11;
813 }
814 return 0;
815 }
816
817 /* Translate a string, including coded sequences into Unicode */
818 static int
819 xlate_to_uni(const char *name, int len, char *outname, int *longlen, int *outlen,
820 int escape, int utf8, struct nls_table *nls)
821 {
822 const unsigned char *ip;
823 unsigned char nc;
824 char *op;
825 unsigned int ec;
826 int i, k, fill;
827 int charlen;
828
829 if (utf8) {
830 *outlen = utf8_mbstowcs((__u16 *) outname, name, PAGE_SIZE);
831 if (name[len-1] == '.')
832 *outlen-=2;
833 op = &outname[*outlen * sizeof(__u16)];
834 } else {
835 if (name[len-1] == '.')
836 len--;
837 if (nls) {
838 for (i = 0, ip = name, op = outname, *outlen = 0;
839 i < len && *outlen <= 260; *outlen += 1)
840 {
841 if (escape && (*ip == ':')) {
842 if (i > len - 5)
843 return -EINVAL;
844 ec = 0;
845 for (k = 1; k < 5; k++) {
846 nc = ip[k];
847 ec <<= 4;
848 if (nc >= '0' && nc <= '9') {
849 ec |= nc - '0';
850 continue;
851 }
852 if (nc >= 'a' && nc <= 'f') {
853 ec |= nc - ('a' - 10);
854 continue;
855 }
856 if (nc >= 'A' && nc <= 'F') {
857 ec |= nc - ('A' - 10);
858 continue;
859 }
860 return -EINVAL;
861 }
862 *op++ = ec & 0xFF;
863 *op++ = ec >> 8;
864 ip += 5;
865 i += 5;
866 } else {
867 if ((charlen = nls->char2uni(ip, len-i, (wchar_t *)op)) < 0)
868 return -EINVAL;
869
870 ip += charlen;
871 i += charlen;
872 op += 2;
873 }
874 }
875 } else {
876 for (i = 0, ip = name, op = outname, *outlen = 0;
877 i < len && *outlen <= 260; i++, *outlen += 1)
878 {
879 *op++ = *ip++;
880 *op++ = 0;
881 }
882 }
883 }
884 if (*outlen > 260)
885 return -ENAMETOOLONG;
886
887 *longlen = *outlen;
888 if (*outlen % 13) {
889 *op++ = 0;
890 *op++ = 0;
891 *outlen += 1;
892 if (*outlen % 13) {
893 fill = 13 - (*outlen % 13);
894 for (i = 0; i < fill; i++) {
895 *op++ = 0xff;
896 *op++ = 0xff;
897 }
898 *outlen += fill;
899 }
900 }
901
902 return 0;
903 }
904
905 static int
906 vfat_fill_slots(struct inode *dir, struct msdos_dir_slot *ds, const char *name,
907 int len, int *slots, int uni_xlate)
908 {
909 struct nls_table *nls_io, *nls_disk;
910 wchar_t *uname;
911 struct msdos_dir_slot *ps;
912 struct msdos_dir_entry *de;
913 unsigned long page;
914 unsigned char cksum;
915 const char *ip;
916 char *uniname, msdos_name[MSDOS_NAME];
917 int res, utf8, slot, ulen, unilen, i;
918 loff_t offset;
919
920 de = (struct msdos_dir_entry *) ds;
921 utf8 = MSDOS_SB(dir->i_sb)->options.utf8;
922 nls_io = MSDOS_SB(dir->i_sb)->nls_io;
923 nls_disk = MSDOS_SB(dir->i_sb)->nls_disk;
924
925 if (name[len-1] == '.') len--;
926 if(!(page = __get_free_page(GFP_KERNEL)))
927 return -ENOMEM;
928 uniname = (char *) page;
929
930 res = xlate_to_uni(name, len, uniname, &ulen, &unilen, uni_xlate,
931 utf8, nls_io);
932 if (res < 0)
933 goto out_free;
934
935 uname = (wchar_t *) page;
936 res = vfat_is_used_badchars(uname, ulen);
937 if (res < 0)
938 goto out_free;
939
940 res = vfat_create_shortname(dir, nls_disk, uname, ulen, msdos_name);
941 if (res < 0)
942 goto out_free;
943 else if (res == 1) {
944 strncpy(de->name, msdos_name, MSDOS_NAME);
945 res = 0;
946 goto out_free;
947 }
948
949 *slots = unilen / 13;
950 for (cksum = i = 0; i < 11; i++) {
951 cksum = (((cksum&1)<<7)|((cksum&0xfe)>>1)) + msdos_name[i];
952 }
953 PRINTK3(("vfat_fill_slots 3: slots=%d\n",*slots));
954
955 for (ps = ds, slot = *slots; slot > 0; slot--, ps++) {
956 ps->id = slot;
957 ps->attr = ATTR_EXT;
958 ps->reserved = 0;
959 ps->alias_checksum = cksum;
960 ps->start = 0;
961 offset = (slot - 1) * 26;
962 ip = &uniname[offset];
963 memcpy(ps->name0_4, ip, 10);
964 memcpy(ps->name5_10, ip+10, 12);
965 memcpy(ps->name11_12, ip+22, 4);
966 }
967 ds[0].id |= 0x40;
968
969 de = (struct msdos_dir_entry *) ps;
970 PRINTK3(("vfat_fill_slots 9\n"));
971 strncpy(de->name, msdos_name, MSDOS_NAME);
972 (*slots)++;
973
974 out_free:
975 free_page(page);
976 return res;
977 }
978
979 /* We can't get "." or ".." here - VFS takes care of those cases */
980
981 static int vfat_build_slots(struct inode *dir,const char *name,int len,
982 struct msdos_dir_slot *ds, int *slots)
983 {
984 int res, xlate;
985
986 xlate = MSDOS_SB(dir->i_sb)->options.unicode_xlate;
987 *slots = 1;
988 res = vfat_valid_longname(name, len, xlate);
989 if (res < 0)
990 return res;
991 return vfat_fill_slots(dir, ds, name, len, slots, xlate);
992 }
993
994 static int vfat_add_entry(struct inode *dir,struct qstr* qname,
995 int is_dir,struct vfat_slot_info *sinfo_out,
996 struct buffer_head **bh, struct msdos_dir_entry **de)
997 {
998 struct super_block *sb = dir->i_sb;
999 struct msdos_dir_slot *ps;
1000 loff_t offset;
1001 struct msdos_dir_slot *ds;
1002 int slots, slot;
1003 int res;
1004 struct msdos_dir_entry *de1;
1005 struct buffer_head *bh1;
1006 int ino;
1007 int len;
1008 loff_t dummy;
1009
1010 ds = (struct msdos_dir_slot *)
1011 kmalloc(sizeof(struct msdos_dir_slot)*MSDOS_SLOTS, GFP_KERNEL);
1012 if (ds == NULL) return -ENOMEM;
1013
1014 len = qname->len;
1015 while (len && qname->name[len-1] == '.')
1016 len--;
1017 res = fat_search_long(dir, qname->name, len,
1018 (MSDOS_SB(sb)->options.name_check != 's') ||
1019 !MSDOS_SB(sb)->options.posixfs,
1020 &dummy, &dummy);
1021 if (res > 0) /* found */
1022 res = -EEXIST;
1023 if (res)
1024 goto cleanup;
1025
1026 res = vfat_build_slots(dir, qname->name, len, ds, &slots);
1027 if (res < 0)
1028 goto cleanup;
1029
1030 offset = fat_add_entries(dir, slots, &bh1, &de1, &ino);
1031 if (offset < 0) {
1032 res = offset;
1033 goto cleanup;
1034 }
1035 fat_brelse(sb, bh1);
1036
1037 /* Now create the new entry */
1038 *bh = NULL;
1039 for (slot = 0, ps = ds; slot < slots; slot++, ps++) {
1040 if (fat_get_entry(dir,&offset,bh,de, &sinfo_out->ino) < 0) {
1041 res = -EIO;
1042 goto cleanup;
1043 }
1044 memcpy(*de, ps, sizeof(struct msdos_dir_slot));
1045 fat_mark_buffer_dirty(sb, *bh);
1046 }
1047
1048 dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;
1049 mark_inode_dirty(dir);
1050
1051 fat_date_unix2dos(dir->i_mtime,&(*de)->time,&(*de)->date);
1052 (*de)->ctime_ms = 0;
1053 (*de)->ctime = (*de)->time;
1054 (*de)->adate = (*de)->cdate = (*de)->date;
1055 (*de)->start = 0;
1056 (*de)->starthi = 0;
1057 (*de)->size = 0;
1058 (*de)->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
1059 (*de)->lcase = CASE_LOWER_BASE | CASE_LOWER_EXT;
1060
1061
1062 fat_mark_buffer_dirty(sb, *bh);
1063
1064 /* slots can't be less than 1 */
1065 sinfo_out->long_slots = slots - 1;
1066 sinfo_out->longname_offset = offset - sizeof(struct msdos_dir_slot) * slots;
1067 res = 0;
1068
1069 cleanup:
1070 kfree(ds);
1071 return res;
1072 }
1073
1074 static int vfat_find(struct inode *dir,struct qstr* qname,
1075 struct vfat_slot_info *sinfo, struct buffer_head **last_bh,
1076 struct msdos_dir_entry **last_de)
1077 {
1078 struct super_block *sb = dir->i_sb;
1079 loff_t offset;
1080 int res,len;
1081
1082 len = qname->len;
1083 while (len && qname->name[len-1] == '.')
1084 len--;
1085 res = fat_search_long(dir, qname->name, len,
1086 (MSDOS_SB(sb)->options.name_check != 's'),
1087 &offset,&sinfo->longname_offset);
1088 if (res>0) {
1089 sinfo->long_slots = res-1;
1090 if (fat_get_entry(dir,&offset,last_bh,last_de,&sinfo->ino)>=0)
1091 return 0;
1092 res = -EIO;
1093 }
1094 return res ? res : -ENOENT;
1095 }
1096
1097 struct dentry *vfat_lookup(struct inode *dir,struct dentry *dentry)
1098 {
1099 int res;
1100 struct vfat_slot_info sinfo;
1101 struct inode *inode;
1102 struct dentry *alias;
1103 struct buffer_head *bh = NULL;
1104 struct msdos_dir_entry *de;
1105 int table;
1106
1107 PRINTK2(("vfat_lookup: name=%s, len=%d\n",
1108 dentry->d_name.name, dentry->d_name.len));
1109
1110 table = (MSDOS_SB(dir->i_sb)->options.name_check == 's') ? 2 : 0;
1111 dentry->d_op = &vfat_dentry_ops[table];
1112
1113 inode = NULL;
1114 res = vfat_find(dir,&dentry->d_name,&sinfo,&bh,&de);
1115 if (res < 0) {
1116 table++;
1117 goto error;
1118 }
1119 inode = fat_build_inode(dir->i_sb, de, sinfo.ino, &res);
1120 fat_brelse(dir->i_sb, bh);
1121 if (res)
1122 return ERR_PTR(res);
1123 alias = d_find_alias(inode);
1124 if (alias) {
1125 if (d_invalidate(alias)==0)
1126 dput(alias);
1127 else {
1128 iput(inode);
1129 return alias;
1130 }
1131
1132 }
1133 error:
1134 dentry->d_op = &vfat_dentry_ops[table];
1135 dentry->d_time = dentry->d_parent->d_inode->i_version;
1136 d_add(dentry,inode);
1137 return NULL;
1138 }
1139
1140 int vfat_create(struct inode *dir,struct dentry* dentry,int mode)
1141 {
1142 struct super_block *sb = dir->i_sb;
1143 struct inode *inode = NULL;
1144 struct buffer_head *bh = NULL;
1145 struct msdos_dir_entry *de;
1146 struct vfat_slot_info sinfo;
1147 int res;
1148
1149 res = vfat_add_entry(dir, &dentry->d_name, 0, &sinfo, &bh, &de);
1150 if (res < 0)
1151 return res;
1152 inode = fat_build_inode(sb, de, sinfo.ino, &res);
1153 fat_brelse(sb, bh);
1154 if (!inode)
1155 return res;
1156 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
1157 mark_inode_dirty(inode);
1158 inode->i_version = ++event;
1159 dir->i_version = event;
1160 dentry->d_time = dentry->d_parent->d_inode->i_version;
1161 d_instantiate(dentry,inode);
1162 return 0;
1163 }
1164
1165 static void vfat_remove_entry(struct inode *dir,struct vfat_slot_info *sinfo,
1166 struct buffer_head *bh, struct msdos_dir_entry *de)
1167 {
1168 struct super_block *sb = dir->i_sb;
1169 loff_t offset;
1170 int i,ino;
1171
1172 /* remove the shortname */
1173 dir->i_mtime = CURRENT_TIME;
1174 dir->i_atime = CURRENT_TIME;
1175 dir->i_version = ++event;
1176 mark_inode_dirty(dir);
1177 de->name[0] = DELETED_FLAG;
1178 fat_mark_buffer_dirty(sb, bh);
1179 /* remove the longname */
1180 offset = sinfo->longname_offset; de = NULL;
1181 for (i = sinfo->long_slots; i > 0; --i) {
1182 if (fat_get_entry(dir, &offset, &bh, &de, &ino) < 0)
1183 continue;
1184 de->name[0] = DELETED_FLAG;
1185 de->attr = 0;
1186 fat_mark_buffer_dirty(sb, bh);
1187 }
1188 if (bh) fat_brelse(sb, bh);
1189 }
1190
1191 int vfat_rmdir(struct inode *dir,struct dentry* dentry)
1192 {
1193 int res;
1194 struct vfat_slot_info sinfo;
1195 struct buffer_head *bh = NULL;
1196 struct msdos_dir_entry *de;
1197
1198 res = fat_dir_empty(dentry->d_inode);
1199 if (res)
1200 return res;
1201
1202 res = vfat_find(dir,&dentry->d_name,&sinfo, &bh, &de);
1203 if (res<0)
1204 return res;
1205 dentry->d_inode->i_nlink = 0;
1206 dentry->d_inode->i_mtime = CURRENT_TIME;
1207 dentry->d_inode->i_atime = CURRENT_TIME;
1208 fat_detach(dentry->d_inode);
1209 mark_inode_dirty(dentry->d_inode);
1210 /* releases bh */
1211 vfat_remove_entry(dir,&sinfo,bh,de);
1212 dir->i_nlink--;
1213 return 0;
1214 }
1215
1216 int vfat_unlink(struct inode *dir, struct dentry* dentry)
1217 {
1218 int res;
1219 struct vfat_slot_info sinfo;
1220 struct buffer_head *bh = NULL;
1221 struct msdos_dir_entry *de;
1222
1223 PRINTK1(("vfat_unlink: %s\n", dentry->d_name.name));
1224 res = vfat_find(dir,&dentry->d_name,&sinfo,&bh,&de);
1225 if (res < 0)
1226 return res;
1227 dentry->d_inode->i_nlink = 0;
1228 dentry->d_inode->i_mtime = CURRENT_TIME;
1229 dentry->d_inode->i_atime = CURRENT_TIME;
1230 fat_detach(dentry->d_inode);
1231 mark_inode_dirty(dentry->d_inode);
1232 /* releases bh */
1233 vfat_remove_entry(dir,&sinfo,bh,de);
1234
1235 return res;
1236 }
1237
1238
1239 int vfat_mkdir(struct inode *dir,struct dentry* dentry,int mode)
1240 {
1241 struct super_block *sb = dir->i_sb;
1242 struct inode *inode = NULL;
1243 struct vfat_slot_info sinfo;
1244 struct buffer_head *bh = NULL;
1245 struct msdos_dir_entry *de;
1246 int res;
1247
1248 res = vfat_add_entry(dir, &dentry->d_name, 1, &sinfo, &bh, &de);
1249 if (res < 0)
1250 return res;
1251 inode = fat_build_inode(sb, de, sinfo.ino, &res);
1252 if (!inode)
1253 goto out;
1254 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
1255 mark_inode_dirty(inode);
1256 inode->i_version = ++event;
1257 dir->i_version = event;
1258 dir->i_nlink++;
1259 inode->i_nlink = 2; /* no need to mark them dirty */
1260 res = fat_new_dir(inode, dir, 1);
1261 if (res < 0)
1262 goto mkdir_failed;
1263 dentry->d_time = dentry->d_parent->d_inode->i_version;
1264 d_instantiate(dentry,inode);
1265 out:
1266 fat_brelse(sb, bh);
1267 return res;
1268
1269 mkdir_failed:
1270 inode->i_nlink = 0;
1271 inode->i_mtime = CURRENT_TIME;
1272 inode->i_atime = CURRENT_TIME;
1273 fat_detach(inode);
1274 mark_inode_dirty(inode);
1275 /* releases bh */
1276 vfat_remove_entry(dir,&sinfo,bh,de);
1277 iput(inode);
1278 dir->i_nlink--;
1279 return res;
1280 }
1281
1282 int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
1283 struct inode *new_dir,struct dentry *new_dentry)
1284 {
1285 struct super_block *sb = old_dir->i_sb;
1286 struct buffer_head *old_bh,*new_bh,*dotdot_bh;
1287 struct msdos_dir_entry *old_de,*new_de,*dotdot_de;
1288 int dotdot_ino;
1289 struct inode *old_inode, *new_inode;
1290 int res, is_dir;
1291 struct vfat_slot_info old_sinfo,sinfo;
1292
1293 old_bh = new_bh = dotdot_bh = NULL;
1294 old_inode = old_dentry->d_inode;
1295 new_inode = new_dentry->d_inode;
1296 res = vfat_find(old_dir,&old_dentry->d_name,&old_sinfo,&old_bh,&old_de);
1297 PRINTK3(("vfat_rename 2\n"));
1298 if (res < 0) goto rename_done;
1299
1300 is_dir = S_ISDIR(old_inode->i_mode);
1301
1302 if (is_dir && (res = fat_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh,
1303 &dotdot_de,&dotdot_ino)) < 0)
1304 goto rename_done;
1305
1306 if (new_dentry->d_inode) {
1307 res = vfat_find(new_dir,&new_dentry->d_name,&sinfo,&new_bh,
1308 &new_de);
1309 if (res < 0 || MSDOS_I(new_inode)->i_location != sinfo.ino) {
1310 /* WTF??? Cry and fail. */
1311 printk(KERN_WARNING "vfat_rename: fs corrupted\n");
1312 goto rename_done;
1313 }
1314
1315 if (is_dir) {
1316 res = fat_dir_empty(new_inode);
1317 if (res)
1318 goto rename_done;
1319 }
1320 fat_detach(new_inode);
1321 } else {
1322 res = vfat_add_entry(new_dir,&new_dentry->d_name,is_dir,&sinfo,
1323 &new_bh,&new_de);
1324 if (res < 0) goto rename_done;
1325 }
1326
1327 new_dir->i_version = ++event;
1328
1329 /* releases old_bh */
1330 vfat_remove_entry(old_dir,&old_sinfo,old_bh,old_de);
1331 old_bh=NULL;
1332 fat_detach(old_inode);
1333 fat_attach(old_inode, sinfo.ino);
1334 mark_inode_dirty(old_inode);
1335
1336 old_dir->i_version = ++event;
1337 old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
1338 mark_inode_dirty(old_dir);
1339 if (new_inode) {
1340 new_inode->i_nlink--;
1341 new_inode->i_ctime=CURRENT_TIME;
1342 }
1343
1344 if (is_dir) {
1345 int start = MSDOS_I(new_dir)->i_logstart;
1346 dotdot_de->start = CT_LE_W(start);
1347 dotdot_de->starthi = CT_LE_W(start>>16);
1348 fat_mark_buffer_dirty(sb, dotdot_bh);
1349 old_dir->i_nlink--;
1350 if (new_inode) {
1351 new_inode->i_nlink--;
1352 } else {
1353 new_dir->i_nlink++;
1354 mark_inode_dirty(new_dir);
1355 }
1356 }
1357
1358 rename_done:
1359 fat_brelse(sb, dotdot_bh);
1360 fat_brelse(sb, old_bh);
1361 fat_brelse(sb, new_bh);
1362 return res;
1363
1364 }
1365
1366
1367 /* Public inode operations for the VFAT fs */
1368 struct inode_operations vfat_dir_inode_operations = {
1369 create: vfat_create,
1370 lookup: vfat_lookup,
1371 unlink: vfat_unlink,
1372 mkdir: vfat_mkdir,
1373 rmdir: vfat_rmdir,
1374 rename: vfat_rename,
1375 setattr: fat_notify_change,
1376 };
1377
1378 struct super_block *vfat_read_super(struct super_block *sb,void *data,
1379 int silent)
1380 {
1381 struct super_block *res;
1382
1383 MSDOS_SB(sb)->options.isvfat = 1;
1384
1385 res = fat_read_super(sb, data, silent, &vfat_dir_inode_operations);
1386 if (res == NULL)
1387 return NULL;
1388
1389 if (parse_options((char *) data, &(MSDOS_SB(sb)->options))) {
1390 MSDOS_SB(sb)->options.dotsOK = 0;
1391 if (MSDOS_SB(sb)->options.posixfs) {
1392 MSDOS_SB(sb)->options.name_check = 's';
1393 }
1394 if (MSDOS_SB(sb)->options.name_check != 's') {
1395 sb->s_root->d_op = &vfat_dentry_ops[0];
1396 } else {
1397 sb->s_root->d_op = &vfat_dentry_ops[2];
1398 }
1399 }
1400
1401 return res;
1402 }
1403