diff options
Diffstat (limited to 'fs/cifs/misc.c')
| -rw-r--r-- | fs/cifs/misc.c | 160 |
1 files changed, 152 insertions, 8 deletions
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 7b38d3059a83..db14b503d89e 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include "cifs_debug.h" | 28 | #include "cifs_debug.h" |
| 29 | #include "smberr.h" | 29 | #include "smberr.h" |
| 30 | #include "nterr.h" | 30 | #include "nterr.h" |
| 31 | #include "cifs_unicode.h" | ||
| 31 | 32 | ||
| 32 | extern mempool_t *cifs_sm_req_poolp; | 33 | extern mempool_t *cifs_sm_req_poolp; |
| 33 | extern mempool_t *cifs_req_poolp; | 34 | extern mempool_t *cifs_req_poolp; |
| @@ -451,25 +452,30 @@ is_valid_oplock_break(struct smb_hdr *buf) | |||
| 451 | atomic_inc(&tcon->num_oplock_brks); | 452 | atomic_inc(&tcon->num_oplock_brks); |
| 452 | #endif | 453 | #endif |
| 453 | list_for_each(tmp1,&tcon->openFileList){ | 454 | list_for_each(tmp1,&tcon->openFileList){ |
| 454 | netfile = list_entry(tmp1,struct cifsFileInfo,tlist); | 455 | netfile = list_entry(tmp1,struct cifsFileInfo, |
| 456 | tlist); | ||
| 455 | if(pSMB->Fid == netfile->netfid) { | 457 | if(pSMB->Fid == netfile->netfid) { |
| 456 | struct cifsInodeInfo *pCifsInode; | 458 | struct cifsInodeInfo *pCifsInode; |
| 457 | read_unlock(&GlobalSMBSeslock); | 459 | read_unlock(&GlobalSMBSeslock); |
| 458 | cFYI(1,("Matching file id, processing oplock break")); | 460 | cFYI(1,("file id match, oplock break")); |
| 459 | pCifsInode = | 461 | pCifsInode = |
| 460 | CIFS_I(netfile->pInode); | 462 | CIFS_I(netfile->pInode); |
| 461 | pCifsInode->clientCanCacheAll = FALSE; | 463 | pCifsInode->clientCanCacheAll = FALSE; |
| 462 | if(pSMB->OplockLevel == 0) | 464 | if(pSMB->OplockLevel == 0) |
| 463 | pCifsInode->clientCanCacheRead = FALSE; | 465 | pCifsInode->clientCanCacheRead |
| 466 | = FALSE; | ||
| 464 | pCifsInode->oplockPending = TRUE; | 467 | pCifsInode->oplockPending = TRUE; |
| 465 | AllocOplockQEntry(netfile->pInode, netfile->netfid, tcon); | 468 | AllocOplockQEntry(netfile->pInode, |
| 469 | netfile->netfid, | ||
| 470 | tcon); | ||
| 466 | cFYI(1,("about to wake up oplock thd")); | 471 | cFYI(1,("about to wake up oplock thd")); |
| 467 | wake_up_process(oplockThread); | 472 | if(oplockThread) |
| 473 | wake_up_process(oplockThread); | ||
| 468 | return TRUE; | 474 | return TRUE; |
| 469 | } | 475 | } |
| 470 | } | 476 | } |
| 471 | read_unlock(&GlobalSMBSeslock); | 477 | read_unlock(&GlobalSMBSeslock); |
| 472 | cFYI(1,("No matching file for oplock break on connection")); | 478 | cFYI(1,("No matching file for oplock break")); |
| 473 | return TRUE; | 479 | return TRUE; |
| 474 | } | 480 | } |
| 475 | } | 481 | } |
| @@ -490,7 +496,7 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length) | |||
| 490 | 496 | ||
| 491 | buffer = (unsigned char *) smb_buf; | 497 | buffer = (unsigned char *) smb_buf; |
| 492 | for (i = 0, j = 0; i < smb_buf_length; i++, j++) { | 498 | for (i = 0, j = 0; i < smb_buf_length; i++, j++) { |
| 493 | if (i % 8 == 0) { /* we have reached the beginning of line */ | 499 | if (i % 8 == 0) { /* have reached the beginning of line */ |
| 494 | printk(KERN_DEBUG "| "); | 500 | printk(KERN_DEBUG "| "); |
| 495 | j = 0; | 501 | j = 0; |
| 496 | } | 502 | } |
| @@ -501,7 +507,7 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length) | |||
| 501 | else | 507 | else |
| 502 | debug_line[1 + (2 * j)] = '_'; | 508 | debug_line[1 + (2 * j)] = '_'; |
| 503 | 509 | ||
| 504 | if (i % 8 == 7) { /* we have reached end of line, time to print ascii */ | 510 | if (i % 8 == 7) { /* reached end of line, time to print ascii */ |
| 505 | debug_line[16] = 0; | 511 | debug_line[16] = 0; |
| 506 | printk(" | %s\n", debug_line); | 512 | printk(" | %s\n", debug_line); |
| 507 | } | 513 | } |
| @@ -514,3 +520,141 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length) | |||
| 514 | printk( " | %s\n", debug_line); | 520 | printk( " | %s\n", debug_line); |
| 515 | return; | 521 | return; |
| 516 | } | 522 | } |
| 523 | |||
| 524 | /* Windows maps these to the user defined 16 bit Unicode range since they are | ||
| 525 | reserved symbols (along with \ and /), otherwise illegal to store | ||
| 526 | in filenames in NTFS */ | ||
| 527 | #define UNI_ASTERIK (__u16) ('*' + 0xF000) | ||
| 528 | #define UNI_QUESTION (__u16) ('?' + 0xF000) | ||
| 529 | #define UNI_COLON (__u16) (':' + 0xF000) | ||
| 530 | #define UNI_GRTRTHAN (__u16) ('>' + 0xF000) | ||
| 531 | #define UNI_LESSTHAN (__u16) ('<' + 0xF000) | ||
| 532 | #define UNI_PIPE (__u16) ('|' + 0xF000) | ||
| 533 | #define UNI_SLASH (__u16) ('\\' + 0xF000) | ||
| 534 | |||
| 535 | /* Convert 16 bit Unicode pathname from wire format to string in current code | ||
| 536 | page. Conversion may involve remapping up the seven characters that are | ||
| 537 | only legal in POSIX-like OS (if they are present in the string). Path | ||
| 538 | names are little endian 16 bit Unicode on the wire */ | ||
| 539 | int | ||
| 540 | cifs_convertUCSpath(char *target, const __le16 * source, int maxlen, | ||
| 541 | const struct nls_table * cp) | ||
| 542 | { | ||
| 543 | int i,j,len; | ||
| 544 | __u16 src_char; | ||
| 545 | |||
| 546 | for(i = 0, j = 0; i < maxlen; i++) { | ||
| 547 | src_char = le16_to_cpu(source[i]); | ||
| 548 | switch (src_char) { | ||
| 549 | case 0: | ||
| 550 | goto cUCS_out; /* BB check this BB */ | ||
| 551 | case UNI_COLON: | ||
| 552 | target[j] = ':'; | ||
| 553 | break; | ||
| 554 | case UNI_ASTERIK: | ||
| 555 | target[j] = '*'; | ||
| 556 | break; | ||
| 557 | case UNI_QUESTION: | ||
| 558 | target[j] = '?'; | ||
| 559 | break; | ||
| 560 | /* BB We can not handle remapping slash until | ||
| 561 | all the calls to build_path_from_dentry | ||
| 562 | are modified, as they use slash as separator BB */ | ||
| 563 | /* case UNI_SLASH: | ||
| 564 | target[j] = '\\'; | ||
| 565 | break;*/ | ||
| 566 | case UNI_PIPE: | ||
| 567 | target[j] = '|'; | ||
| 568 | break; | ||
| 569 | case UNI_GRTRTHAN: | ||
| 570 | target[j] = '>'; | ||
| 571 | break; | ||
| 572 | case UNI_LESSTHAN: | ||
| 573 | target[j] = '<'; | ||
| 574 | default: | ||
| 575 | len = cp->uni2char(src_char, &target[j], | ||
| 576 | NLS_MAX_CHARSET_SIZE); | ||
| 577 | if(len > 0) { | ||
| 578 | j += len; | ||
| 579 | continue; | ||
| 580 | } else { | ||
| 581 | target[j] = '?'; | ||
| 582 | } | ||
| 583 | } | ||
| 584 | j++; | ||
| 585 | /* make sure we do not overrun callers allocated temp buffer */ | ||
| 586 | if(j >= (2 * NAME_MAX)) | ||
| 587 | break; | ||
| 588 | } | ||
| 589 | cUCS_out: | ||
| 590 | target[j] = 0; | ||
| 591 | return j; | ||
| 592 | } | ||
| 593 | |||
| 594 | /* Convert 16 bit Unicode pathname to wire format from string in current code | ||
| 595 | page. Conversion may involve remapping up the seven characters that are | ||
| 596 | only legal in POSIX-like OS (if they are present in the string). Path | ||
| 597 | names are little endian 16 bit Unicode on the wire */ | ||
| 598 | int | ||
| 599 | cifsConvertToUCS(__le16 * target, const char *source, int maxlen, | ||
| 600 | const struct nls_table * cp, int mapChars) | ||
| 601 | { | ||
| 602 | int i,j,charlen; | ||
| 603 | int len_remaining = maxlen; | ||
| 604 | char src_char; | ||
| 605 | |||
| 606 | if(!mapChars) | ||
| 607 | return cifs_strtoUCS((wchar_t *) target, source, PATH_MAX, cp); | ||
| 608 | |||
| 609 | for(i = 0, j = 0; i < maxlen; j++) { | ||
| 610 | src_char = source[i]; | ||
| 611 | switch (src_char) { | ||
| 612 | case 0: | ||
| 613 | goto ctoUCS_out; | ||
| 614 | case ':': | ||
| 615 | target[j] = cpu_to_le16(UNI_COLON); | ||
| 616 | break; | ||
| 617 | case '*': | ||
| 618 | target[j] = cpu_to_le16(UNI_ASTERIK); | ||
| 619 | break; | ||
| 620 | case '?': | ||
| 621 | target[j] = cpu_to_le16(UNI_QUESTION); | ||
| 622 | break; | ||
| 623 | case '<': | ||
| 624 | target[j] = cpu_to_le16(UNI_LESSTHAN); | ||
| 625 | break; | ||
| 626 | case '>': | ||
| 627 | target[j] = cpu_to_le16(UNI_GRTRTHAN); | ||
| 628 | break; | ||
| 629 | case '|': | ||
| 630 | target[j] = cpu_to_le16(UNI_PIPE); | ||
| 631 | break; | ||
| 632 | /* BB We can not handle remapping slash until | ||
| 633 | all the calls to build_path_from_dentry | ||
| 634 | are modified, as they use slash as separator BB */ | ||
| 635 | /* case '\\': | ||
| 636 | target[j] = cpu_to_le16(UNI_SLASH); | ||
| 637 | break;*/ | ||
| 638 | default: | ||
| 639 | charlen = cp->char2uni(source+i, | ||
| 640 | len_remaining, target+j); | ||
| 641 | /* if no match, use question mark, which | ||
| 642 | at least in some cases servers as wild card */ | ||
| 643 | if(charlen < 1) { | ||
| 644 | target[j] = cpu_to_le16(0x003f); | ||
| 645 | charlen = 1; | ||
| 646 | } | ||
| 647 | len_remaining -= charlen; | ||
| 648 | /* character may take more than one byte in the | ||
| 649 | the source string, but will take exactly two | ||
| 650 | bytes in the target string */ | ||
| 651 | i+= charlen; | ||
| 652 | continue; | ||
| 653 | } | ||
| 654 | i++; /* move to next char in source string */ | ||
| 655 | len_remaining--; | ||
| 656 | } | ||
| 657 | |||
| 658 | ctoUCS_out: | ||
| 659 | return i; | ||
| 660 | } | ||
