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 | } | ||