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, 2001 by Wolfram Pienkoss <wp@bszh.de> 13 * 14 * Support Multibyte characters and cleanup by 15 * OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> 16 */ 17 18#include <linux/module.h> 19 20#include <linux/jiffies.h> 21#include <linux/msdos_fs.h> 22#include <linux/ctype.h> 23#include <linux/slab.h> 24#include <linux/smp_lock.h> 25#include <linux/buffer_head.h> 26#include <linux/namei.h> 27 28static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd) 29{ 30 int ret = 1; 31 32 if (!dentry->d_inode && 33 nd && !(nd->flags & LOOKUP_CONTINUE) && (nd->flags & LOOKUP_CREATE)) 34 /* 35 * negative dentry is dropped, in order to make sure 36 * to use the name which a user desires if this is 37 * create path. 38 */ 39 ret = 0; 40 else { 41 spin_lock(&dentry->d_lock); 42 if (dentry->d_time != dentry->d_parent->d_inode->i_version) 43 ret = 0; 44 spin_unlock(&dentry->d_lock); 45 } 46 return ret; 47} 48 49/* returns the length of a struct qstr, ignoring trailing dots */ 50static unsigned int vfat_striptail_len(struct qstr *qstr) 51{ 52 unsigned int len = qstr->len; 53 54 while (len && qstr->name[len - 1] == '.') 55 len--; 56 return len; 57} 58 59/* 60 * Compute the hash for the vfat name corresponding to the dentry. 61 * Note: if the name is invalid, we leave the hash code unchanged so 62 * that the existing dentry can be used. The vfat fs routines will 63 * return ENOENT or EINVAL as appropriate. 64 */ 65static int vfat_hash(struct dentry *dentry, struct qstr *qstr) 66{ 67 qstr->hash = full_name_hash(qstr->name, vfat_striptail_len(qstr)); 68 return 0; 69} 70 71/* 72 * Compute the hash for the vfat name corresponding to the dentry. 73 * Note: if the name is invalid, we leave the hash code unchanged so 74 * that the existing dentry can be used. The vfat fs routines will 75 * return ENOENT or EINVAL as appropriate. 76 */ 77static int vfat_hashi(struct dentry *dentry, struct qstr *qstr) 78{ 79 struct nls_table *t = MSDOS_SB(dentry->d_inode->i_sb)->nls_io; 80 const unsigned char *name; 81 unsigned int len; 82 unsigned long hash; 83 84 name = qstr->name; 85 len = vfat_striptail_len(qstr); 86 87 hash = init_name_hash(); 88 while (len--) 89 hash = partial_name_hash(nls_tolower(t, *name++), hash); 90 qstr->hash = end_name_hash(hash); 91 92 return 0; 93} 94 95/* 96 * Case insensitive compare of two vfat names. 97 */ 98static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b) 99{ 100 struct nls_table *t = MSDOS_SB(dentry->d_inode->i_sb)->nls_io; 101 unsigned int alen, blen; 102 103 /* A filename cannot end in '.' or we treat it like it has none */ 104 alen = vfat_striptail_len(a); 105 blen = vfat_striptail_len(b); 106 if (alen == blen) { 107 if (nls_strnicmp(t, a->name, b->name, alen) == 0) 108 return 0; 109 } 110 return 1; 111} 112 113/* 114 * Case sensitive compare of two vfat names. 115 */ 116static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b) 117{ 118 unsigned int alen, blen; 119 120 /* A filename cannot end in '.' or we treat it like it has none */ 121 alen = vfat_striptail_len(a); 122 blen = vfat_striptail_len(b); 123 if (alen == blen) { 124 if (strncmp(a->name, b->name, alen) == 0) 125 return 0; 126 } 127 return 1; 128} 129 130static struct dentry_operations vfat_dentry_ops[4] = { 131 { 132 .d_hash = vfat_hashi, 133 .d_compare = vfat_cmpi, 134 }, 135 { 136 .d_revalidate = vfat_revalidate, 137 .d_hash = vfat_hashi, 138 .d_compare = vfat_cmpi, 139 }, 140 { 141 .d_hash = vfat_hash, 142 .d_compare = vfat_cmp, 143 }, 144 { 145 .d_revalidate = vfat_revalidate, 146 .d_hash = vfat_hash, 147 .d_compare = vfat_cmp, 148 } 149}; 150 151/* Characters that are undesirable in an MS-DOS file name */ 152 153static inline wchar_t vfat_bad_char(wchar_t w) 154{ 155 return (w < 0x0020) 156 || (w == '*') || (w == '?') || (w == '<') || (w == '>') 157 || (w == '|') || (w == '"') || (w == ':') || (w == '/') 158 || (w == '\\'); 159} 160 161static inline wchar_t vfat_replace_char(wchar_t w) 162{ 163 return (w == '[') || (w == ']') || (w == ';') || (w == ',') 164 || (w == '+') || (w == '='); 165} 166 167static wchar_t vfat_skip_char(wchar_t w) 168{ 169 return (w == '.') || (w == ' '); 170} 171 172static inline int vfat_is_used_badchars(const wchar_t *s, int len) 173{ 174 int i; 175 176 for (i = 0; i < len; i++) 177 if (vfat_bad_char(s[i])) 178 return -EINVAL; 179 return 0; 180} 181 182static int vfat_valid_longname(const unsigned char *name, unsigned int len) 183{ 184 if (name[len - 1] == ' ') 185 return -EINVAL; 186 if (len >= 256) 187 return -ENAMETOOLONG; 188 return 0; 189} 190 191static int vfat_find_form(struct inode *dir, unsigned char *name) 192{ 193 struct fat_slot_info sinfo; 194 int err = fat_scan(dir, name, &sinfo); 195 if (err) 196 return -ENOENT; 197 brelse(sinfo.bh); 198 return 0; 199} 200 201/* 202 * 1) Valid characters for the 8.3 format alias are any combination of 203 * letters, uppercase alphabets, digits, any of the 204 * following special characters: 205 * $ % ' ` - @ { } ~ ! # ( ) & _ ^ 206 * In this case Longfilename is not stored in disk. 207 * 208 * WinNT's Extension: 209 * File name and extension name is contain uppercase/lowercase 210 * only. And it is expressed by CASE_LOWER_BASE and CASE_LOWER_EXT. 211 * 212 * 2) File name is 8.3 format, but it contain the uppercase and 213 * lowercase char, muliti bytes char, etc. In this case numtail is not 214 * added, but Longfilename is stored. 215 * 216 * 3) When the one except for the above, or the following special 217 * character are contained: 218 * . [ ] ; , + = 219 * numtail is added, and Longfilename must be stored in disk . 220 */ 221struct shortname_info { 222 unsigned char lower:1, 223 upper:1, 224 valid:1; 225}; 226#define INIT_SHORTNAME_INFO(x) do { \ 227 (x)->lower = 1; \ 228 (x)->upper = 1; \ 229 (x)->valid = 1; \ 230} while (0) 231 232static inline int to_shortname_char(struct nls_table *nls, 233 unsigned char *buf, int buf_size, 234 wchar_t *src, struct shortname_info *info) 235{ 236 int len; 237 238 if (vfat_skip_char(*src)) { 239 info->valid = 0; 240 return 0; 241 } 242 if (vfat_replace_char(*src)) { 243 info->valid = 0; 244 buf[0] = '_'; 245 return 1; 246 } 247 248 len = nls->uni2char(*src, buf, buf_size); 249 if (len <= 0) { 250 info->valid = 0; 251 buf[0] = '_'; 252 len = 1; 253 } else if (len == 1) { 254 unsigned char prev = buf[0]; 255 256 if (buf[0] >= 0x7F) { 257 info->lower = 0; 258 info->upper = 0; 259 } 260 261 buf[0] = nls_toupper(nls, buf[0]); 262 if (isalpha(buf[0])) { 263 if (buf[0] == prev) 264 info->lower = 0; 265 else 266 info->upper = 0; 267 } 268 } else { 269 info->lower = 0; 270 info->upper = 0; 271 } 272 273 return len; 274} 275 276/* 277 * Given a valid longname, create a unique shortname. Make sure the 278 * shortname does not exist 279 * Returns negative number on error, 0 for a normal 280 * return, and 1 for valid shortname 281 */ 282static int vfat_create_shortname(struct inode *dir, struct nls_table *nls, 283 wchar_t *uname, int ulen, 284 unsigned char *name_res, unsigned char *lcase) 285{ 286 struct fat_mount_options *opts = &MSDOS_SB(dir->i_sb)->options; 287 wchar_t *ip, *ext_start, *end, *name_start; 288 unsigned char base[9], ext[4], buf[8], *p; 289 unsigned char charbuf[NLS_MAX_CHARSET_SIZE]; 290 int chl, chi; 291 int sz = 0, extlen, baselen, i, numtail_baselen, numtail2_baselen; 292 int is_shortname; 293 struct shortname_info base_info, ext_info; 294 295 is_shortname = 1; 296 INIT_SHORTNAME_INFO(&base_info); 297 INIT_SHORTNAME_INFO(&ext_info); 298 299 /* Now, we need to create a shortname from the long name */ 300 ext_start = end = &uname[ulen]; 301 while (--ext_start >= uname) { 302 if (*ext_start == 0x002E) { /* is `.' */ 303 if (ext_start == end - 1) { 304 sz = ulen; 305 ext_start = NULL; 306 } 307 break; 308 } 309 } 310 311 if (ext_start == uname - 1) { 312 sz = ulen; 313 ext_start = NULL; 314 } else if (ext_start) { 315 /* 316 * Names which start with a dot could be just 317 * an extension eg. "...test". In this case Win95 318 * uses the extension as the name and sets no extension. 319 */ 320 name_start = &uname[0]; 321 while (name_start < ext_start) { 322 if (!vfat_skip_char(*name_start)) 323 break; 324 name_start++; 325 } 326 if (name_start != ext_start) { 327 sz = ext_start - uname; 328 ext_start++; 329 } else { 330 sz = ulen; 331 ext_start = NULL; 332 } 333 } 334 335 numtail_baselen = 6; 336 numtail2_baselen = 2; 337 for (baselen = i = 0, p = base, ip = uname; i < sz; i++, ip++) { 338 chl = to_shortname_char(nls, charbuf, sizeof(charbuf), 339 ip, &base_info); 340 if (chl == 0) 341 continue; 342 343 if (baselen < 2 && (baselen + chl) > 2) 344 numtail2_baselen = baselen; 345 if (baselen < 6 && (baselen + chl) > 6) 346 numtail_baselen = baselen; 347 for (chi = 0; chi < chl; chi++) { 348 *p++ = charbuf[chi]; 349 baselen++; 350 if (baselen >= 8) 351 break; 352 } 353 if (baselen >= 8) { 354 if ((chi < chl - 1) || (ip + 1) - uname < sz) 355 is_shortname = 0; 356 break; 357 } 358 } 359 if (baselen == 0) { 360 return -EINVAL; 361 } 362 363 extlen = 0; 364 if (ext_start) { 365 for (p = ext, ip = ext_start; extlen < 3 && ip < end; ip++) { 366 chl = to_shortname_char(nls, charbuf, sizeof(charbuf), 367 ip, &ext_info); 368 if (chl == 0) 369 continue; 370 371 if ((extlen + chl) > 3) { 372 is_shortname = 0; 373 break; 374 } 375 for (chi = 0; chi < chl; chi++) { 376 *p++ = charbuf[chi]; 377 extlen++; 378 } 379 if (extlen >= 3) { 380 if (ip + 1 != end) 381 is_shortname = 0; 382 break; 383 } 384 } 385 } 386 ext[extlen] = '\0'; 387 base[baselen] = '\0'; 388 389 /* Yes, it can happen. ".\xe5" would do it. */ 390 if (base[0] == DELETED_FLAG) 391 base[0] = 0x05; 392 393 /* OK, at this point we know that base is not longer than 8 symbols, 394 * ext is not longer than 3, base is nonempty, both don't contain 395 * any bad symbols (lowercase transformed to uppercase). 396 */ 397 398 memset(name_res, ' ', MSDOS_NAME); 399 memcpy(name_res, base, baselen); 400 memcpy(name_res + 8, ext, extlen); 401 *lcase = 0; 402 if (is_shortname && base_info.valid && ext_info.valid) { 403 if (vfat_find_form(dir, name_res) == 0) 404 return -EEXIST; 405 406 if (opts->shortname & VFAT_SFN_CREATE_WIN95) { 407 return (base_info.upper && ext_info.upper); 408 } else if (opts->shortname & VFAT_SFN_CREATE_WINNT) { 409 if ((base_info.upper || base_info.lower) && 410 (ext_info.upper || ext_info.lower)) { 411 if (!base_info.upper && base_info.lower) 412 *lcase |= CASE_LOWER_BASE; 413 if (!ext_info.upper && ext_info.lower) 414 *lcase |= CASE_LOWER_EXT; 415 return 1; 416 } 417 return 0; 418 } else { 419 BUG(); 420 } 421 } 422 423 if (opts->numtail == 0) 424 if (vfat_find_form(dir, name_res) < 0) 425 return 0; 426 427 /* 428 * Try to find a unique extension. This used to 429 * iterate through all possibilities sequentially, 430 * but that gave extremely bad performance. Windows 431 * only tries a few cases before using random 432 * values for part of the base. 433 */ 434 435 if (baselen > 6) { 436 baselen = numtail_baselen; 437 name_res[7] = ' '; 438 } 439 name_res[baselen] = '~'; 440 for (i = 1; i < 10; i++) { 441 name_res[baselen + 1] = i + '0'; 442 if (vfat_find_form(dir, name_res) < 0) 443 return 0; 444 } 445 446 i = jiffies & 0xffff; 447 sz = (jiffies >> 16) & 0x7; 448 if (baselen > 2) { 449 baselen = numtail2_baselen; 450 name_res[7] = ' '; 451 } 452 name_res[baselen + 4] = '~'; 453 name_res[baselen + 5] = '1' + sz; 454 while (1) { 455 sprintf(buf, "%04X", i); 456 memcpy(&name_res[baselen], buf, 4); 457 if (vfat_find_form(dir, name_res) < 0) 458 break; 459 i -= 11; 460 } 461 return 0; 462} 463 464/* Translate a string, including coded sequences into Unicode */ 465static int 466xlate_to_uni(const unsigned char *name, int len, unsigned char *outname, 467 int *longlen, int *outlen, int escape, int utf8, 468 struct nls_table *nls) 469{ 470 const unsigned char *ip; 471 unsigned char nc; 472 unsigned char *op; 473 unsigned int ec; 474 int i, k, fill; 475 int charlen; 476 477 if (utf8) { 478 int name_len = strlen(name); 479 480 *outlen = utf8_mbstowcs((wchar_t *)outname, name, PAGE_SIZE); 481 482 /* 483 * We stripped '.'s before and set len appropriately, 484 * but utf8_mbstowcs doesn't care about len 485 */ 486 *outlen -= (name_len - len); 487 488 op = &outname[*outlen * sizeof(wchar_t)]; 489 } else { 490 if (nls) { 491 for (i = 0, ip = name, op = outname, *outlen = 0; 492 i < len && *outlen <= 260; 493 *outlen += 1) 494 { 495 if (escape && (*ip == ':')) { 496 if (i > len - 5) 497 return -EINVAL; 498 ec = 0; 499 for (k = 1; k < 5; k++) { 500 nc = ip[k]; 501 ec <<= 4; 502 if (nc >= '0' && nc <= '9') { 503 ec |= nc - '0'; 504 continue; 505 } 506 if (nc >= 'a' && nc <= 'f') { 507 ec |= nc - ('a' - 10); 508 continue; 509 } 510 if (nc >= 'A' && nc <= 'F') { 511 ec |= nc - ('A' - 10); 512 continue; 513 } 514 return -EINVAL; 515 } 516 *op++ = ec & 0xFF; 517 *op++ = ec >> 8; 518 ip += 5; 519 i += 5; 520 } else { 521 if ((charlen = nls->char2uni(ip, len - i, (wchar_t *)op)) < 0) 522 return -EINVAL; 523 ip += charlen; 524 i += charlen; 525 op += 2; 526 } 527 } 528 } else { 529 for (i = 0, ip = name, op = outname, *outlen = 0; 530 i < len && *outlen <= 260; 531 i++, *outlen += 1) 532 { 533 *op++ = *ip++; 534 *op++ = 0; 535 } 536 } 537 } 538 if (*outlen > 260) 539 return -ENAMETOOLONG; 540 541 *longlen = *outlen; 542 if (*outlen % 13) { 543 *op++ = 0; 544 *op++ = 0; 545 *outlen += 1; 546 if (*outlen % 13) { 547 fill = 13 - (*outlen % 13); 548 for (i = 0; i < fill; i++) { 549 *op++ = 0xff; 550 *op++ = 0xff; 551 } 552 *outlen += fill; 553 } 554 } 555 556 return 0; 557} 558 559static int vfat_build_slots(struct inode *dir, const unsigned char *name, 560 int len, int is_dir, int cluster, 561 struct timespec *ts, 562 struct msdos_dir_slot *slots, int *nr_slots) 563{ 564 struct msdos_sb_info *sbi = MSDOS_SB(dir->i_sb); 565 struct fat_mount_options *opts = &sbi->options; 566 struct msdos_dir_slot *ps; 567 struct msdos_dir_entry *de; 568 unsigned long page; 569 unsigned char cksum, lcase; 570 unsigned char msdos_name[MSDOS_NAME]; 571 wchar_t *uname; 572 __le16 time, date; 573 int err, ulen, usize, i; 574 loff_t offset; 575 576 *nr_slots = 0; 577 err = vfat_valid_longname(name, len); 578 if (err) 579 return err; 580 581 page = __get_free_page(GFP_KERNEL); 582 if (!page) 583 return -ENOMEM; 584 585 uname = (wchar_t *)page; 586 err = xlate_to_uni(name, len, (unsigned char *)uname, &ulen, &usize, 587 opts->unicode_xlate, opts->utf8, sbi->nls_io); 588 if (err) 589 goto out_free; 590 591 err = vfat_is_used_badchars(uname, ulen); 592 if (err) 593 goto out_free; 594 595 err = vfat_create_shortname(dir, sbi->nls_disk, uname, ulen, 596 msdos_name, &lcase); 597 if (err < 0) 598 goto out_free; 599 else if (err == 1) { 600 de = (struct msdos_dir_entry *)slots; 601 err = 0; 602 goto shortname; 603 } 604 605 /* build the entry of long file name */ 606 cksum = fat_checksum(msdos_name); 607 608 *nr_slots = usize / 13; 609 for (ps = slots, i = *nr_slots; i > 0; i--, ps++) { 610 ps->id = i; 611 ps->attr = ATTR_EXT; 612 ps->reserved = 0; 613 ps->alias_checksum = cksum; 614 ps->start = 0; 615 offset = (i - 1) * 13; 616 fatwchar_to16(ps->name0_4, uname + offset, 5); 617 fatwchar_to16(ps->name5_10, uname + offset + 5, 6); 618 fatwchar_to16(ps->name11_12, uname + offset + 11, 2); 619 } 620 slots[0].id |= 0x40; 621 de = (struct msdos_dir_entry *)ps; 622 623shortname: 624 /* build the entry of 8.3 alias name */ 625 (*nr_slots)++; 626 memcpy(de->name, msdos_name, MSDOS_NAME); 627 de->attr = is_dir ? ATTR_DIR : ATTR_ARCH; 628 de->lcase = lcase; 629 fat_date_unix2dos(ts->tv_sec, &time, &date); 630 de->time = de->ctime = time; 631 de->date = de->cdate = de->adate = date; 632 de->ctime_cs = 0; 633 de->start = cpu_to_le16(cluster); 634 de->starthi = cpu_to_le16(cluster >> 16); 635 de->size = 0; 636out_free: 637 free_page(page); 638 return err; 639} 640 641static int vfat_add_entry(struct inode *dir, struct qstr *qname, int is_dir, 642 int cluster, struct timespec *ts, 643 struct fat_slot_info *sinfo) 644{ 645 struct msdos_dir_slot *slots; 646 unsigned int len; 647 int err, nr_slots; 648 649 len = vfat_striptail_len(qname); 650 if (len == 0) 651 return -ENOENT; 652 653 slots = kmalloc(sizeof(*slots) * MSDOS_SLOTS, GFP_KERNEL); 654 if (slots == NULL) 655 return -ENOMEM; 656 657 err = vfat_build_slots(dir, qname->name, len, is_dir, cluster, ts, 658 slots, &nr_slots); 659 if (err) 660 goto cleanup; 661 662 err = fat_add_entries(dir, slots, nr_slots, sinfo); 663 if (err) 664 goto cleanup; 665 666 /* update timestamp */ 667 dir->i_ctime = dir->i_mtime = dir->i_atime = *ts; 668 if (IS_DIRSYNC(dir)) 669 (void)fat_sync_inode(dir); 670 else 671 mark_inode_dirty(dir); 672cleanup: 673 kfree(slots); 674 return err; 675} 676 677static int vfat_find(struct inode *dir, struct qstr *qname, 678 struct fat_slot_info *sinfo) 679{ 680 unsigned int len = vfat_striptail_len(qname); 681 if (len == 0) 682 return -ENOENT; 683 return fat_search_long(dir, qname->name, len, sinfo); 684} 685 686static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry, 687 struct nameidata *nd) 688{ 689 struct super_block *sb = dir->i_sb; 690 struct fat_slot_info sinfo; 691 struct inode *inode = NULL; 692 struct dentry *alias; 693 int err, table; 694 695 lock_kernel(); 696 table = (MSDOS_SB(sb)->options.name_check == 's') ? 2 : 0; 697 dentry->d_op = &vfat_dentry_ops[table]; 698 699 err = vfat_find(dir, &dentry->d_name, &sinfo); 700 if (err) { 701 table++; 702 goto error; 703 } 704 inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos); 705 brelse(sinfo.bh); 706 if (IS_ERR(inode)) { 707 unlock_kernel(); 708 return ERR_PTR(PTR_ERR(inode)); 709 } 710 alias = d_find_alias(inode); 711 if (alias) { 712 if (d_invalidate(alias) == 0) 713 dput(alias); 714 else { 715 iput(inode); 716 unlock_kernel(); 717 return alias; 718 } 719 720 } 721error: 722 unlock_kernel(); 723 dentry->d_op = &vfat_dentry_ops[table]; 724 dentry->d_time = dentry->d_parent->d_inode->i_version; 725 dentry = d_splice_alias(inode, dentry); 726 if (dentry) { 727 dentry->d_op = &vfat_dentry_ops[table]; 728 dentry->d_time = dentry->d_parent->d_inode->i_version; 729 } 730 return dentry; 731} 732 733static int vfat_create(struct inode *dir, struct dentry *dentry, int mode, 734 struct nameidata *nd) 735{ 736 struct super_block *sb = dir->i_sb; 737 struct inode *inode; 738 struct fat_slot_info sinfo; 739 struct timespec ts; 740 int err; 741 742 lock_kernel(); 743 744 ts = CURRENT_TIME_SEC; 745 err = vfat_add_entry(dir, &dentry->d_name, 0, 0, &ts, &sinfo); 746 if (err) 747 goto out; 748 dir->i_version++; 749 750 inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos); 751 brelse(sinfo.bh); 752 if (IS_ERR(inode)) { 753 err = PTR_ERR(inode); 754 goto out; 755 } 756 inode->i_version++; 757 inode->i_mtime = inode->i_atime = inode->i_ctime = ts; 758 /* timestamp is already written, so mark_inode_dirty() is unneeded. */ 759 760 dentry->d_time = dentry->d_parent->d_inode->i_version; 761 d_instantiate(dentry, inode); 762out: 763 unlock_kernel(); 764 return err; 765} 766 767static int vfat_rmdir(struct inode *dir, struct dentry *dentry) 768{ 769 struct inode *inode = dentry->d_inode; 770 struct fat_slot_info sinfo; 771 int err; 772 773 lock_kernel(); 774 775 err = fat_dir_empty(inode); 776 if (err) 777 goto out; 778 err = vfat_find(dir, &dentry->d_name, &sinfo); 779 if (err) 780 goto out; 781 782 err = fat_remove_entries(dir, &sinfo); /* and releases bh */ 783 if (err) 784 goto out; 785 drop_nlink(dir); 786 787 clear_nlink(inode); 788 inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC; 789 fat_detach(inode); 790out: 791 unlock_kernel(); 792 793 return err; 794} 795 796static int vfat_unlink(struct inode *dir, struct dentry *dentry) 797{ 798 struct inode *inode = dentry->d_inode; 799 struct fat_slot_info sinfo; 800 int err; 801 802 lock_kernel(); 803 804 err = vfat_find(dir, &dentry->d_name, &sinfo); 805 if (err) 806 goto out; 807 808 err = fat_remove_entries(dir, &sinfo); /* and releases bh */ 809 if (err) 810 goto out; 811 clear_nlink(inode); 812 inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC; 813 fat_detach(inode); 814out: 815 unlock_kernel(); 816 817 return err; 818} 819 820static int vfat_mkdir(struct inode *dir, struct dentry *dentry, int mode) 821{ 822 struct super_block *sb = dir->i_sb; 823 struct inode *inode; 824 struct fat_slot_info sinfo; 825 struct timespec ts; 826 int err, cluster; 827 828 lock_kernel(); 829 830 ts = CURRENT_TIME_SEC; 831 cluster = fat_alloc_new_dir(dir, &ts); 832 if (cluster < 0) { 833 err = cluster; 834 goto out; 835 } 836 err = vfat_add_entry(dir, &dentry->d_name, 1, cluster, &ts, &sinfo); 837 if (err) 838 goto out_free; 839 dir->i_version++; 840 inc_nlink(dir); 841 842 inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos); 843 brelse(sinfo.bh); 844 if (IS_ERR(inode)) { 845 err = PTR_ERR(inode); 846 /* the directory was completed, just return a error */ 847 goto out; 848 } 849 inode->i_version++; 850 inode->i_nlink = 2; 851 inode->i_mtime = inode->i_atime = inode->i_ctime = ts; 852 /* timestamp is already written, so mark_inode_dirty() is unneeded. */ 853 854 dentry->d_time = dentry->d_parent->d_inode->i_version; 855 d_instantiate(dentry, inode); 856 857 unlock_kernel(); 858 return 0; 859 860out_free: 861 fat_free_clusters(dir, cluster); 862out: 863 unlock_kernel(); 864 return err; 865} 866 867static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry, 868 struct inode *new_dir, struct dentry *new_dentry) 869{ 870 struct buffer_head *dotdot_bh; 871 struct msdos_dir_entry *dotdot_de; 872 struct inode *old_inode, *new_inode; 873 struct fat_slot_info old_sinfo, sinfo; 874 struct timespec ts; 875 loff_t dotdot_i_pos, new_i_pos; 876 int err, is_dir, update_dotdot, corrupt = 0; 877 878 old_sinfo.bh = sinfo.bh = dotdot_bh = NULL; 879 old_inode = old_dentry->d_inode; 880 new_inode = new_dentry->d_inode; 881 lock_kernel(); 882 err = vfat_find(old_dir, &old_dentry->d_name, &old_sinfo); 883 if (err) 884 goto out; 885 886 is_dir = S_ISDIR(old_inode->i_mode); 887 update_dotdot = (is_dir && old_dir != new_dir); 888 if (update_dotdot) { 889 if (fat_get_dotdot_entry(old_inode, &dotdot_bh, &dotdot_de, 890 &dotdot_i_pos) < 0) { 891 err = -EIO; 892 goto out; 893 } 894 } 895 896 ts = CURRENT_TIME_SEC; 897 if (new_inode) { 898 if (is_dir) { 899 err = fat_dir_empty(new_inode); 900 if (err) 901 goto out; 902 } 903 new_i_pos = MSDOS_I(new_inode)->i_pos; 904 fat_detach(new_inode); 905 } else { 906 err = vfat_add_entry(new_dir, &new_dentry->d_name, is_dir, 0, 907 &ts, &sinfo); 908 if (err) 909 goto out; 910 new_i_pos = sinfo.i_pos; 911 } 912 new_dir->i_version++; 913 914 fat_detach(old_inode); 915 fat_attach(old_inode, new_i_pos); 916 if (IS_DIRSYNC(new_dir)) { 917 err = fat_sync_inode(old_inode); 918 if (err) 919 goto error_inode; 920 } else 921 mark_inode_dirty(old_inode); 922 923 if (update_dotdot) { 924 int start = MSDOS_I(new_dir)->i_logstart; 925 dotdot_de->start = cpu_to_le16(start); 926 dotdot_de->starthi = cpu_to_le16(start >> 16); 927 mark_buffer_dirty(dotdot_bh); 928 if (IS_DIRSYNC(new_dir)) { 929 err = sync_dirty_buffer(dotdot_bh); 930 if (err) 931 goto error_dotdot; 932 } 933 drop_nlink(old_dir); 934 if (!new_inode) 935 inc_nlink(new_dir); 936 } 937 938 err = fat_remove_entries(old_dir, &old_sinfo); /* and releases bh */ 939 old_sinfo.bh = NULL; 940 if (err) 941 goto error_dotdot; 942 old_dir->i_version++; 943 old_dir->i_ctime = old_dir->i_mtime = ts; 944 if (IS_DIRSYNC(old_dir)) 945 (void)fat_sync_inode(old_dir); 946 else 947 mark_inode_dirty(old_dir); 948 949 if (new_inode) { 950 drop_nlink(new_inode); 951 if (is_dir) 952 drop_nlink(new_inode); 953 new_inode->i_ctime = ts; 954 } 955out: 956 brelse(sinfo.bh); 957 brelse(dotdot_bh); 958 brelse(old_sinfo.bh); 959 unlock_kernel(); 960 961 return err; 962 963error_dotdot: 964 /* data cluster is shared, serious corruption */ 965 corrupt = 1; 966 967 if (update_dotdot) { 968 int start = MSDOS_I(old_dir)->i_logstart; 969 dotdot_de->start = cpu_to_le16(start); 970 dotdot_de->starthi = cpu_to_le16(start >> 16); 971 mark_buffer_dirty(dotdot_bh); 972 corrupt |= sync_dirty_buffer(dotdot_bh); 973 } 974error_inode: 975 fat_detach(old_inode); 976 fat_attach(old_inode, old_sinfo.i_pos); 977 if (new_inode) { 978 fat_attach(new_inode, new_i_pos); 979 if (corrupt) 980 corrupt |= fat_sync_inode(new_inode); 981 } else { 982 /* 983 * If new entry was not sharing the data cluster, it 984 * shouldn't be serious corruption. 985 */ 986 int err2 = fat_remove_entries(new_dir, &sinfo); 987 if (corrupt) 988 corrupt |= err2; 989 sinfo.bh = NULL; 990 } 991 if (corrupt < 0) { 992 fat_fs_panic(new_dir->i_sb, 993 "%s: Filesystem corrupted (i_pos %lld)", 994 __FUNCTION__, sinfo.i_pos); 995 } 996 goto out; 997} 998 999static const struct inode_operations vfat_dir_inode_operations = { 1000 .create = vfat_create, 1001 .lookup = vfat_lookup, 1002 .unlink = vfat_unlink, 1003 .mkdir = vfat_mkdir, 1004 .rmdir = vfat_rmdir, 1005 .rename = vfat_rename, 1006 .setattr = fat_notify_change, 1007 .getattr = fat_getattr, 1008}; 1009 1010static int vfat_fill_super(struct super_block *sb, void *data, int silent) 1011{ 1012 int res; 1013 1014 res = fat_fill_super(sb, data, silent, &vfat_dir_inode_operations, 1); 1015 if (res) 1016 return res; 1017 1018 if (MSDOS_SB(sb)->options.name_check != 's') 1019 sb->s_root->d_op = &vfat_dentry_ops[0]; 1020 else 1021 sb->s_root->d_op = &vfat_dentry_ops[2]; 1022 1023 return 0; 1024} 1025 1026static int vfat_get_sb(struct file_system_type *fs_type, 1027 int flags, const char *dev_name, 1028 void *data, struct vfsmount *mnt) 1029{ 1030 return get_sb_bdev(fs_type, flags, dev_name, data, vfat_fill_super, 1031 mnt); 1032} 1033 1034static struct file_system_type vfat_fs_type = { 1035 .owner = THIS_MODULE, 1036 .name = "vfat", 1037 .get_sb = vfat_get_sb, 1038 .kill_sb = kill_block_super, 1039 .fs_flags = FS_REQUIRES_DEV, 1040}; 1041 1042static int __init init_vfat_fs(void) 1043{ 1044 return register_filesystem(&vfat_fs_type); 1045} 1046 1047static void __exit exit_vfat_fs(void) 1048{ 1049 unregister_filesystem(&vfat_fs_type); 1050} 1051 1052MODULE_LICENSE("GPL"); 1053MODULE_DESCRIPTION("VFAT filesystem support"); 1054MODULE_AUTHOR("Gordon Chaffee"); 1055 1056module_init(init_vfat_fs) 1057module_exit(exit_vfat_fs) 1058