Changeset 5258 in vbox
- Timestamp:
- Oct 12, 2007 9:57:23 AM (18 years ago)
- svn:sync-xref-src-repo-rev:
- 25242
- Location:
- trunk/src/VBox
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostServices/SharedFolders/vbsf.cpp
r5090 r5258 362 362 uint32_t len = strlen(pszFullPath); 363 363 char *src = pszFullPath + len - 1; 364 364 365 365 Log(("Handle case insenstive guest fs on top of host case sensitive fs for %s\n", pszFullPath)); 366 366 … … 415 415 else 416 416 rc = VERR_FILE_NOT_FOUND; 417 417 418 418 if (rc == VERR_FILE_NOT_FOUND || rc == VERR_PATH_NOT_FOUND) 419 419 { … … 460 460 } 461 461 462 463 static int vbsfOpenFile (SHFLHANDLE *phHandle, const char *pszPath, SHFLCREATEPARMS *pParms, bool fCreate) 464 { 462 /** 463 * Convert shared folder create flags (see include/iprt/shflsvc.h) into iprt create flags. 464 * 465 * @returns iprt status code 466 * @param fShflFlags shared folder create flags 467 * @retval pfOpen iprt create flags 468 */ 469 static int vbsfConvertFileOpenFlags(unsigned fShflFlags, unsigned *pfOpen) 470 { 471 unsigned fOpen = 0; 465 472 int rc = VINF_SUCCESS; 466 473 467 LogFlow(("vbsfOpenFile: pszPath = %s, pParms = %p, fCreate = %d\n", 468 pszPath, pParms, fCreate)); 469 470 /** @todo r=bird: You should've requested a better RTFileOpen API! This code could certainly have 471 * benefitted from it. I've done the long overdue adjustment of RTFileOpen so it better reflect 472 * what a decent OS should be able to do. I've also added some OS specific flags (non-blocking, 473 * delete sharing), and I'm not picky about adding more if that required. (I'm only picky about 474 * how they are treated on platforms which doesn't support them.) 475 * Because of the restrictions in the old version of RTFileOpen this code contains dangerous race 476 * conditions. File creation is one example where you may easily kill a file just created by 477 * another user. 478 */ 479 480 /* Open or create a file. */ 481 unsigned fOpen; 482 483 Log(("SHFL create flags %08x\n", pParms->CreateFlags)); 484 485 if (BIT_FLAG(pParms->CreateFlags, SHFL_CF_DIRECTORY)) 486 { 487 fOpen = RTFILE_O_OPEN; 488 } 489 else 490 fOpen = fCreate? RTFILE_O_CREATE_REPLACE: RTFILE_O_OPEN; 491 492 switch (BIT_FLAG(pParms->CreateFlags, SHFL_CF_ACCESS_MASK_RW)) 474 switch (BIT_FLAG(fShflFlags, SHFL_CF_ACCESS_MASK_RW)) 493 475 { 494 476 default: 495 477 case SHFL_CF_ACCESS_NONE: 496 478 { 497 /** @todo treat this as read access, but theoretically this could be a no access request ed. */479 /** @todo treat this as read access, but theoretically this could be a no access request. */ 498 480 fOpen |= RTFILE_O_READ; 499 481 Log(("FLAG: SHFL_CF_ACCESS_NONE\n")); … … 524 506 525 507 /* Sharing mask */ 526 switch (BIT_FLAG( pParms->CreateFlags, SHFL_CF_ACCESS_MASK_DENY))508 switch (BIT_FLAG(fShflFlags, SHFL_CF_ACCESS_MASK_DENY)) 527 509 { 528 510 default: … … 548 530 } 549 531 550 SHFLHANDLE handle; 551 SHFLFILEHANDLE *pHandle; 552 553 if (BIT_FLAG(pParms->CreateFlags, SHFL_CF_DIRECTORY)) 554 { 555 handle = vbsfAllocDirHandle(); 556 pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(handle, SHFL_HF_TYPE_DIR); 532 /* Open/Create action mask */ 533 switch (BIT_FLAG(fShflFlags, SHFL_CF_ACT_MASK_IF_EXISTS)) 534 { 535 case SHFL_CF_ACT_OPEN_IF_EXISTS: 536 if (SHFL_CF_ACT_CREATE_IF_NEW == BIT_FLAG(fShflFlags, SHFL_CF_ACT_MASK_IF_NEW)) 537 { 538 fOpen |= RTFILE_O_OPEN_CREATE; 539 Log(("FLAGS: SHFL_CF_ACT_OPEN_IF_EXISTS and SHFL_CF_ACT_CREATE_IF_NEW\n")); 540 } 541 else if (SHFL_CF_ACT_FAIL_IF_NEW == BIT_FLAG(fShflFlags, SHFL_CF_ACT_MASK_IF_NEW)) 542 { 543 fOpen |= RTFILE_O_OPEN; 544 Log(("FLAGS: SHFL_CF_ACT_OPEN_IF_EXISTS and SHFL_CF_ACT_FAIL_IF_NEW\n")); 545 } 546 else 547 { 548 Log(("FLAGS: invalid open/create action combination\n")); 549 rc = VERR_INVALID_PARAMETER; 550 } 551 break; 552 case SHFL_CF_ACT_FAIL_IF_EXISTS: 553 if (SHFL_CF_ACT_CREATE_IF_NEW == BIT_FLAG(fShflFlags, SHFL_CF_ACT_MASK_IF_NEW)) 554 { 555 fOpen |= RTFILE_O_CREATE; 556 Log(("FLAGS: SHFL_CF_ACT_FAIL_IF_EXISTS and SHFL_CF_ACT_CREATE_IF_NEW\n")); 557 } 558 else 559 { 560 Log(("FLAGS: invalid open/create action combination\n")); 561 rc = VERR_INVALID_PARAMETER; 562 } 563 break; 564 case SHFL_CF_ACT_REPLACE_IF_EXISTS: 565 if (SHFL_CF_ACT_CREATE_IF_NEW == BIT_FLAG(fShflFlags, SHFL_CF_ACT_MASK_IF_NEW)) 566 { 567 fOpen |= RTFILE_O_CREATE_REPLACE; 568 Log(("FLAGS: SHFL_CF_ACT_REPLACE_IF_EXISTS and SHFL_CF_ACT_CREATE_IF_NEW\n")); 569 } 570 else if (SHFL_CF_ACT_FAIL_IF_NEW == BIT_FLAG(fShflFlags, SHFL_CF_ACT_MASK_IF_NEW)) 571 { 572 fOpen |= RTFILE_O_OPEN | RTFILE_O_TRUNCATE; 573 Log(("FLAGS: SHFL_CF_ACT_REPLACE_IF_EXISTS and SHFL_CF_ACT_FAIL_IF_NEW\n")); 574 } 575 else 576 { 577 Log(("FLAGS: invalid open/create action combination\n")); 578 rc = VERR_INVALID_PARAMETER; 579 } 580 break; 581 case SHFL_CF_ACT_OVERWRITE_IF_EXISTS: 582 if (SHFL_CF_ACT_CREATE_IF_NEW == BIT_FLAG(fShflFlags, SHFL_CF_ACT_MASK_IF_NEW)) 583 { 584 fOpen |= RTFILE_O_CREATE_REPLACE; 585 Log(("FLAGS: SHFL_CF_ACT_OVERWRITE_IF_EXISTS and SHFL_CF_ACT_CREATE_IF_NEW\n")); 586 } 587 else if (SHFL_CF_ACT_FAIL_IF_NEW == BIT_FLAG(fShflFlags, SHFL_CF_ACT_MASK_IF_NEW)) 588 { 589 fOpen |= RTFILE_O_OPEN | RTFILE_O_TRUNCATE; 590 Log(("FLAGS: SHFL_CF_ACT_OVERWRITE_IF_EXISTS and SHFL_CF_ACT_FAIL_IF_NEW\n")); 591 } 592 else 593 { 594 Log(("FLAGS: invalid open/create action combination\n")); 595 rc = VERR_INVALID_PARAMETER; 596 } 597 break; 598 default: 599 rc = VERR_INVALID_PARAMETER; 600 Log(("FLAG: SHFL_CF_ACT_MASK_IF_EXISTS - invalid parameter\n")); 601 } 602 603 if (RT_SUCCESS(rc)) 604 { 605 *pfOpen = fOpen; 606 } 607 return rc; 608 } 609 610 /** 611 * Open a file or create and open a new one. 612 * 613 * @returns IPRT status code 614 * @param pszPath Path to the file or folder on the host. 615 * @param pParms->CreateFlags Creation or open parameters, see include/VBox/shflsvc.h 616 * @param pParms->Info When a new file is created this specifies the initial parameters. 617 * When a file is created or overwritten, it also specifies the 618 * initial size. 619 * @retval pParms->Result Shared folder status code, see include/VBox/shflsvc.h 620 * @retval pParms->Handle On success the (shared folder) handle of the file opened or 621 * created 622 * @retval pParms->Info On success the parameters of the file opened or created 623 */ 624 static int vbsfOpenFile (const char *pszPath, SHFLCREATEPARMS *pParms) 625 { 626 LogFlow(("vbsfOpenFile: pszPath = %s, pParms = %p\n", pszPath, pParms)); 627 Log(("SHFL create flags %08x\n", pParms->CreateFlags)); 628 629 SHFLHANDLE handle = SHFL_HANDLE_NIL; 630 SHFLFILEHANDLE *pHandle = 0; 631 /* Open or create a file. */ 632 unsigned fOpen = 0; 633 int rc = vbsfConvertFileOpenFlags(pParms->CreateFlags, &fOpen); 634 if (RT_SUCCESS(rc)) 635 { 636 handle = vbsfAllocFileHandle(); 637 } 638 if (SHFL_HANDLE_NIL != handle) 639 { 640 rc = VERR_NO_MEMORY; /* If this fails - rewritten immediately on success. */ 641 pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(handle, SHFL_HF_TYPE_FILE); 642 } 643 if (0 != pHandle) 644 { 645 rc = RTFileOpen(&pHandle->file.Handle, pszPath, fOpen); 646 } 647 if (RT_FAILURE (rc)) 648 { 649 switch (rc) 650 { 651 case VERR_FILE_NOT_FOUND: 652 pParms->Result = SHFL_FILE_NOT_FOUND; 653 break; 654 case VERR_PATH_NOT_FOUND: 655 pParms->Result = SHFL_PATH_NOT_FOUND; 656 break; 657 case VERR_ALREADY_EXISTS: 658 RTFSOBJINFO info; 659 660 /** @todo Possible race left here. */ 661 if (RT_SUCCESS(RTPathQueryInfo (pszPath, &info, RTFSOBJATTRADD_NOTHING))) 662 { 663 pParms->Info = info; 664 } 665 pParms->Result = SHFL_FILE_EXISTS; 666 break; 667 default: 668 pParms->Result = SHFL_NO_RESULT; 669 } 670 } 671 if (RT_SUCCESS(rc)) 672 { 673 /** @note The shared folder status code is very approximate, as the runtime 674 * does not really provide this information. */ 675 pParms->Result = SHFL_FILE_EXISTS; /* We lost the information as to whether it was 676 created when we eliminated the race. */ 677 if ( ( SHFL_CF_ACT_REPLACE_IF_EXISTS 678 == BIT_FLAG(pParms->CreateFlags, SHFL_CF_ACT_MASK_IF_EXISTS)) 679 || ( SHFL_CF_ACT_OVERWRITE_IF_EXISTS 680 == BIT_FLAG(pParms->CreateFlags, SHFL_CF_ACT_MASK_IF_EXISTS))) 681 { 682 /* For now, we do not treat a failure here as fatal. */ 683 /* @todo Also set the size for SHFL_CF_ACT_CREATE_IF_NEW if 684 SHFL_CF_ACT_FAIL_IF_EXISTS is set. */ 685 RTFileSetSize(pHandle->file.Handle, pParms->Info.cbObject); 686 pParms->Result = SHFL_FILE_REPLACED; 687 } 688 if ( ( SHFL_CF_ACT_FAIL_IF_EXISTS 689 == BIT_FLAG(pParms->CreateFlags, SHFL_CF_ACT_MASK_IF_EXISTS)) 690 || ( SHFL_CF_ACT_CREATE_IF_NEW 691 == BIT_FLAG(pParms->CreateFlags, SHFL_CF_ACT_MASK_IF_NEW))) 692 { 693 pParms->Result = SHFL_FILE_CREATED; 694 } 695 #if 0 696 /* @todo */ 697 /* Set new attributes. */ 698 if ( ( SHFL_CF_ACT_REPLACE_IF_EXISTS 699 == BIT_FLAG(pParms->CreateFlags, SHFL_CF_ACT_MASK_IF_EXISTS)) 700 || ( SHFL_CF_ACT_CREATE_IF_NEW 701 == BIT_FLAG(pParms->CreateFlags, SHFL_CF_ACT_MASK_IF_NEW))) 702 { 703 RTFileSetTimes(pHandle->file.Handle, 704 &pParms->Info.AccessTime, 705 &pParms->Info.ModificationTime, 706 &pParms->Info.ChangeTime, 707 &pParms->Info.BirthTime 708 ); 709 710 RTFileSetMode (pHandle->file.Handle, pParms->Info.Attr.fMode); 711 } 712 #endif 713 RTFSOBJINFO info; 714 715 /* Get file information */ 716 rc = RTFileQueryInfo (pHandle->file.Handle, &info, RTFSOBJATTRADD_NOTHING); 717 if (RT_SUCCESS(rc)) 718 { 719 pParms->Info = info; 720 } 721 } 722 if (RT_FAILURE(rc)) 723 { 724 if ( (0 != pHandle) 725 && (NIL_RTFILE != pHandle->file.Handle) 726 && (0 != pHandle->file.Handle)) 727 { 728 RTFileClose(pHandle->file.Handle); 729 pHandle->file.Handle = NIL_RTFILE; 730 } 731 if (SHFL_HANDLE_NIL != handle) 732 { 733 vbsfFreeHandle (handle); 734 } 557 735 } 558 736 else 559 737 { 560 handle = vbsfAllocFileHandle(); 561 pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(handle, SHFL_HF_TYPE_FILE); 562 } 563 564 if (pHandle == NULL) 565 { 566 rc = VERR_NO_MEMORY; 738 pParms->Handle = handle; 739 } 740 LogFlow(("vbsfOpenFile: rc = %Vrc\n", rc)); 741 return rc; 742 } 743 744 /** 745 * Open a folder or create and open a new one. 746 * 747 * @returns IPRT status code 748 * @param pszPath Path to the file or folder on the host. 749 * @param pParms->CreateFlags Creation or open parameters, see include/VBox/shflsvc.h 750 * @retval pParms->Result Shared folder status code, see include/VBox/shflsvc.h 751 * @retval pParms->Handle On success the (shared folder) handle of the folder opened or 752 * created 753 * @retval pParms->Info On success the parameters of the folder opened or created 754 * 755 * @note folders are created with fMode = 0777 756 */ 757 static int vbsfOpenDir (const char *pszPath, SHFLCREATEPARMS *pParms) 758 { 759 LogFlow(("vbsfOpenDir: pszPath = %s, pParms = %p\n", pszPath, pParms)); 760 Log(("SHFL create flags %08x\n", pParms->CreateFlags)); 761 762 int rc = VERR_NO_MEMORY; 763 SHFLHANDLE handle = vbsfAllocDirHandle(); 764 SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(handle, SHFL_HF_TYPE_DIR); 765 if (0 != pHandle) 766 { 767 rc = VINF_SUCCESS; 768 pParms->Result = SHFL_FILE_EXISTS; /* May be overwritten with SHFL_FILE_CREATED. */ 769 /** @todo Can anyone think of a sensible, race-less way to do this? Although 770 I suspect that the race is inherent, due to the API available... */ 771 /* Try to create the folder first if "create if new" is specified. If this 772 fails, and "open if exists" is specified, then we ignore the failure and try 773 to open the folder anyway. */ 774 if ( SHFL_CF_ACT_CREATE_IF_NEW 775 == BIT_FLAG(pParms->CreateFlags, SHFL_CF_ACT_MASK_IF_NEW)) 776 { 777 /** @todo render supplied attributes. 778 * bird: The guest should specify this. For windows guests RTFS_DOS_DIRECTORY should suffice. */ 779 RTFMODE fMode = 0777; 780 781 pParms->Result = SHFL_FILE_CREATED; 782 rc = RTDirCreate(pszPath, fMode); 783 if (RT_FAILURE (rc)) 784 { 785 switch (rc) 786 { 787 case VERR_ALREADY_EXISTS: 788 pParms->Result = SHFL_FILE_EXISTS; 789 break; 790 case VERR_PATH_NOT_FOUND: 791 pParms->Result = SHFL_PATH_NOT_FOUND; 792 break; 793 default: 794 pParms->Result = SHFL_NO_RESULT; 795 } 796 } 797 } 798 if ( RT_SUCCESS(rc) 799 || ( SHFL_CF_ACT_OPEN_IF_EXISTS 800 == BIT_FLAG(pParms->CreateFlags, SHFL_CF_ACT_MASK_IF_EXISTS))) 801 { 802 /* Open the directory now */ 803 rc = RTDirOpen (&pHandle->dir.Handle, pszPath); 804 if (RT_SUCCESS(rc)) 805 { 806 RTFSOBJINFO info; 807 808 rc = RTDirQueryInfo (pHandle->dir.Handle, &info, RTFSOBJATTRADD_NOTHING); 809 if (RT_SUCCESS(rc)) 810 { 811 pParms->Info = info; 812 } 813 } 814 else 815 { 816 switch (rc) 817 { 818 case VERR_FILE_NOT_FOUND: /* Does this make sense? */ 819 pParms->Result = SHFL_FILE_NOT_FOUND; 820 break; 821 case VERR_PATH_NOT_FOUND: 822 pParms->Result = SHFL_PATH_NOT_FOUND; 823 break; 824 case VERR_ACCESS_DENIED: 825 pParms->Result = SHFL_FILE_EXISTS; 826 break; 827 default: 828 pParms->Result = SHFL_NO_RESULT; 829 } 830 } 831 } 832 } 833 if (RT_FAILURE(rc)) 834 { 835 if ( (0 != pHandle) 836 && (0 != pHandle->dir.Handle)) 837 { 838 RTDirClose(pHandle->dir.Handle); 839 pHandle->dir.Handle = 0; 840 } 841 if (SHFL_HANDLE_NIL != handle) 842 { 843 vbsfFreeHandle (handle); 844 } 567 845 } 568 846 else 569 847 { 570 /* Must obviously create the directory, before trying to open it. */571 if (BIT_FLAG(pParms->CreateFlags, SHFL_CF_DIRECTORY))572 {573 if (fCreate)574 {575 /** @todo render supplied attributes.576 * bird: The guest should specify this. For windows guests RTFS_DOS_DIRECTORY should suffice. */577 RTFMODE fMode = 0777;578 579 rc = RTDirCreate(pszPath, fMode);580 if (VBOX_FAILURE(rc))581 {582 vbsfFreeHandle (handle);583 return rc;584 }585 }586 /* Open the directory now */587 if (VBOX_SUCCESS(rc))588 {589 rc = RTDirOpen (&pHandle->dir.Handle, pszPath);590 if (VBOX_FAILURE (rc))591 {592 vbsfFreeHandle (handle);593 *phHandle = SHFL_HANDLE_NIL;594 return rc;595 }596 }597 }598 else599 {600 rc = RTFileOpen(&pHandle->file.Handle, pszPath, fOpen);601 }602 603 if (VBOX_SUCCESS (rc))604 {605 *phHandle = handle;606 }607 else608 {609 vbsfFreeHandle (handle);610 }611 }612 613 LogFlow(("vbsfOpenFile: rc = %Vrc\n", rc));614 615 616 return rc;617 }618 619 static int vbsfOpenExisting (const char *pszFullPath, SHFLCREATEPARMS *pParms)620 {621 int rc = VINF_SUCCESS;622 623 LogFlow(("vbsfOpenExisting: pszFullPath = %s, pParms = %p\n",624 pszFullPath, pParms));625 626 /* Open file. */627 SHFLHANDLE handle;628 629 rc = vbsfOpenFile (&handle, pszFullPath, pParms, false);630 if (VBOX_SUCCESS (rc))631 {632 848 pParms->Handle = handle; 633 849 } 634 635 LogFlow(("vbsfOpenExisting: rc = %d\n", rc)); 636 637 return rc; 638 } 639 640 641 static int vbsfOpenReplace (const char *pszPath, SHFLCREATEPARMS *pParms, bool bReplace, RTFSOBJINFO *pInfo) 642 { 643 int rc = VINF_SUCCESS; 644 645 LogFlow(("vbsfOpenReplace: pszPath = %s, pParms = %p, bReplace = %d\n", 646 pszPath, pParms, bReplace)); 647 648 if (BIT_FLAG(pParms->CreateFlags, SHFL_CF_DIRECTORY)) 649 { 650 /* Replace operation is not applicable to a directory. */ 651 rc = VERR_INVALID_PARAMETER; 652 } 653 else 654 { 655 SHFLHANDLE handle = SHFL_HANDLE_NIL; 656 SHFLFILEHANDLE *pHandle; 657 658 rc = vbsfOpenFile (&handle, pszPath, pParms, true); 659 // We are loosing an information regarding the cause of failure here 660 // -- malc 661 pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(handle, SHFL_HF_TYPE_FILE); 662 if (!pHandle) 663 { 664 AssertFailed(); 665 rc = VERR_INVALID_HANDLE; 666 } 667 668 if (VBOX_SUCCESS (rc)) 669 { 670 671 /* Set new file attributes */ 672 673 rc = RTFileSetSize(pHandle->file.Handle, pParms->Info.cbObject); 674 if (rc != VINF_SUCCESS) 675 { 676 AssertMsg(rc == VINF_SUCCESS, ("RTFileSetSize failed with %d\n", rc)); 677 return rc; 678 } 679 680 if (bReplace) 681 { 682 #if 0 683 /* @todo */ 684 /* Set new attributes. */ 685 RTFileSetTimes(pHandle->file.Handle, 686 &pParms->Info.AccessTime, 687 &pParms->Info.ModificationTime, 688 &pParms->Info.ChangeTime, 689 &pParms->Info.BirthTime 690 ); 691 692 RTFileSetMode (pHandle->file.Handle, pParms->Info.Attr.fMode); 693 #endif 694 } 695 696 pParms->Result = SHFL_FILE_REPLACED; 697 pParms->Handle = handle; 698 } 699 } 700 701 LogFlow(("vbsfOpenReplace: rc = %Vrc\n", rc)); 702 703 return rc; 704 } 705 706 static int vbsfOpenCreate (const char *pszPath, SHFLCREATEPARMS *pParms) 707 { 708 int rc = VINF_SUCCESS; 709 710 LogFlow(("vbsfOpenCreate: pszPath = %s, pParms = %p\n", 711 pszPath, pParms)); 712 713 SHFLHANDLE handle = SHFL_HANDLE_NIL; 714 SHFLFILEHANDLE *pHandle; 715 716 rc = vbsfOpenFile (&handle, pszPath, pParms, true); 717 pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(handle, SHFL_HF_TYPE_FILE | SHFL_HF_TYPE_DIR); 718 if (!pHandle) 719 { 720 AssertFailed(); 721 rc = VERR_INVALID_HANDLE; 722 } 723 724 if (VBOX_SUCCESS (rc)) 725 { 726 #if 0 727 if (!BIT_FLAG(pParms->CreateFlags, SHFL_CF_DIRECTORY)) 728 { 729 /* @todo */ 730 RTFileSetSize(pHandle->file.Handle, pParms->Info.cbObject); 731 732 RTFileSetTimes(pHandle->file.Handle, 733 &pParms->Info.AccessTime, 734 &pParms->Info.ModificationTime, 735 &pParms->Info.ChangeTime, 736 &pParms->Info.BirthTime 737 ); 738 739 RTFileSetMode (pHandle->file.Handle, pParms->Info.Attr.fMode); 740 } 741 #endif 742 743 pParms->Result = SHFL_FILE_CREATED; 744 pParms->Handle = handle; 745 } 746 747 LogFlow(("vbsfOpenCreate: rc = %Vrc\n", rc)); 748 749 return rc; 750 } 751 850 LogFlow(("vbsfOpenDir: rc = %Vrc\n", rc)); 851 return rc; 852 } 752 853 753 854 static int vbsfCloseDir (SHFLFILEHANDLE *pHandle) … … 789 890 } 790 891 791 892 /** 893 * Look up file or folder information by host path. 894 * 895 * @returns iprt status code (currently VINF_SUCCESS) 896 * @param pszFullPath The path of the file to be looked up 897 * @retval pParms->Result Status of the operation (success or error) 898 * @retval pParms->Info On success, information returned about the file 899 */ 900 static int vbsfLookupFile(char *pszPath, SHFLCREATEPARMS *pParms) 901 { 902 RTFSOBJINFO info; 903 int rc; 904 905 rc = RTPathQueryInfo (pszPath, &info, RTFSOBJATTRADD_NOTHING); 906 LogFlow(("SHFL_CF_LOOKUP\n")); 907 /* Client just wants to know if the object exists. */ 908 switch (rc) 909 { 910 case VINF_SUCCESS: 911 { 912 pParms->Info = info; 913 pParms->Result = SHFL_FILE_EXISTS; 914 break; 915 } 916 917 case VERR_FILE_NOT_FOUND: 918 { 919 pParms->Result = SHFL_FILE_NOT_FOUND; 920 rc = VINF_SUCCESS; 921 break; 922 } 923 924 case VERR_PATH_NOT_FOUND: 925 { 926 pParms->Result = SHFL_PATH_NOT_FOUND; 927 rc = VINF_SUCCESS; 928 break; 929 } 930 } 931 return rc; 932 } 933 934 /** 935 * Create or open a file or folder. Perform character set and case 936 * conversion on the file name if necessary. 937 * 938 * @returns IPRT status code, but see note below 939 * @param pClient Data structure describing the client accessing the shared 940 * folder 941 * @param root The index of the shared folder in the table of mappings. 942 * The host path of the shared folder is found using this. 943 * @param pPath The path of the file or folder relative to the host path 944 * indexed by root. 945 * @param cbPath Presumably the length of the path in pPath. Actually 946 * ignored, as pPath contains a length parameter. 947 * @param pParms->Info If a new file is created or an old one overwritten, set 948 * these attributes 949 * @retval pParms->Result Shared folder result code, see include/VBox/shflsvc.h 950 * @retval pParms->Handle Shared folder handle to the newly opened file 951 * @retval pParms->Info Attributes of the file or folder opened 952 * 953 * @note This function returns success if a "non-exceptional" error occurred, 954 * such as "no such file". In this case, the caller should check the 955 * pParms->Result return value and whether pParms->Handle is valid. 956 */ 792 957 int vbsfCreate (SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLSTRING *pPath, uint32_t cbPath, SHFLCREATEPARMS *pParms) 793 958 { … … 800 965 /** @todo */ 801 966 802 /* Build a host full path for the given path 803 * and convert ucs2 to utf8 if necessary. 967 /* Build a host full path for the given path, handle file name case issues (if the guest 968 * expects case-insensitive paths but the host is case-sensitive) and convert ucs2 to utf8 if 969 * necessary. 804 970 */ 805 971 char *pszFullPath = NULL; … … 808 974 rc = vbsfBuildFullPath (pClient, root, pPath, cbPath, &pszFullPath, &cbFullPathRoot); 809 975 810 /* @todo This mess needs to change. RTFileOpen supports all the open/creation methods */811 812 976 if (VBOX_SUCCESS (rc)) 813 977 { … … 816 980 pParms->Handle = SHFL_HANDLE_NIL; 817 981 818 /* Query path information. */819 RTFSOBJINFO info;820 821 /** r=bird: This is likely to create race conditions.822 * What is a file now can be a directory when you open it. */823 rc = RTPathQueryInfo (pszFullPath, &info, RTFSOBJATTRADD_NOTHING);824 LogFlow(("RTPathQueryInfo returned %Vrc\n", rc));825 826 982 if (BIT_FLAG(pParms->CreateFlags, SHFL_CF_LOOKUP)) 827 983 { 828 LogFlow(("SHFL_CF_LOOKUP\n")); 829 /* Client just wants to know if the object exists. */ 830 switch (rc) 831 { 832 case VINF_SUCCESS: 984 rc = vbsfLookupFile(pszFullPath, pParms); 985 } 986 else 987 { 988 /* Query path information. */ 989 RTFSOBJINFO info; 990 991 rc = RTPathQueryInfo (pszFullPath, &info, RTFSOBJATTRADD_NOTHING); 992 LogFlow(("RTPathQueryInfo returned %Vrc\n", rc)); 993 994 if (RT_SUCCESS(rc)) 995 { 996 /* Mark it as a directory in case the caller didn't. */ 997 /** 998 * @todo I left this in in order not to change the behaviour of the 999 * function too much. Is it really needed, and should it really be 1000 * here? 1001 */ 1002 if (BIT_FLAG(info.Attr.fMode, RTFS_DOS_DIRECTORY)) 833 1003 { 834 pParms->Info = info; 835 pParms->Result = SHFL_FILE_EXISTS; 836 break; 1004 pParms->CreateFlags |= SHFL_CF_DIRECTORY; 837 1005 } 838 839 case VERR_FILE_NOT_FOUND: 1006 /** 1007 * @todo This should be in the Windows Guest Additions, as no-one else 1008 * needs it. 1009 */ 1010 if (BIT_FLAG(pParms->CreateFlags, SHFL_CF_OPEN_TARGET_DIRECTORY)) 840 1011 { 841 pParms->Result = SHFL_FILE_NOT_FOUND; 842 rc = VINF_SUCCESS; 843 break; 1012 vbsfStripLastComponent (pszFullPath, cbFullPathRoot); 1013 pParms->CreateFlags &= ~SHFL_CF_ACT_MASK_IF_EXISTS; 1014 pParms->CreateFlags &= ~SHFL_CF_ACT_MASK_IF_NEW; 1015 pParms->CreateFlags |= SHFL_CF_DIRECTORY; 1016 pParms->CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS; 1017 pParms->CreateFlags |= SHFL_CF_ACT_FAIL_IF_NEW; 844 1018 } 845 846 case VERR_PATH_NOT_FOUND: 847 { 848 pParms->Result = SHFL_PATH_NOT_FOUND; 849 rc = VINF_SUCCESS; 850 break; 851 } 852 } 853 } 854 else if (rc == VINF_SUCCESS) 855 { 856 /* File object exists. */ 857 pParms->Result = SHFL_FILE_EXISTS; 858 859 /* Mark it as a directory in case the caller didn't. */ 860 if (BIT_FLAG(info.Attr.fMode, RTFS_DOS_DIRECTORY)) 861 { 862 pParms->CreateFlags |= SHFL_CF_DIRECTORY; 863 } 864 865 if (BIT_FLAG(pParms->CreateFlags, SHFL_CF_OPEN_TARGET_DIRECTORY)) 866 { 867 pParms->Info = info; 868 vbsfStripLastComponent (pszFullPath, cbFullPathRoot); 869 rc = vbsfOpenExisting (pszFullPath, pParms); 1019 } 1020 if (BIT_FLAG(pParms->CreateFlags, SHFL_CF_DIRECTORY)) 1021 { 1022 rc = vbsfOpenDir (pszFullPath, pParms); 870 1023 } 871 1024 else 872 1025 { 873 if ( BIT_FLAG(pParms->CreateFlags, SHFL_CF_DIRECTORY) 874 && !BIT_FLAG(info.Attr.fMode, RTFS_DOS_DIRECTORY)) 875 { 876 /* Caller wanted a directory but the existing object is not a directory. 877 * Do not open the object then. 878 */ 879 ; /* do nothing */ 880 } 881 else 882 { 883 switch (BIT_FLAG(pParms->CreateFlags, SHFL_CF_ACT_MASK_IF_EXISTS)) 884 { 885 case SHFL_CF_ACT_OPEN_IF_EXISTS: 886 { 887 pParms->Info = info; 888 rc = vbsfOpenExisting (pszFullPath, pParms); 889 break; 890 } 891 892 case SHFL_CF_ACT_FAIL_IF_EXISTS: 893 { 894 /* NIL handle value will tell client that object was not opened. 895 * Just copy information about the object. 896 */ 897 pParms->Info = info; 898 break; 899 } 900 901 case SHFL_CF_ACT_REPLACE_IF_EXISTS: 902 { 903 rc = vbsfOpenReplace (pszFullPath, pParms, true, &info); 904 break; 905 } 906 907 case SHFL_CF_ACT_OVERWRITE_IF_EXISTS: 908 { 909 rc = vbsfOpenReplace (pszFullPath, pParms, false, &info); 910 pParms->Info = info; 911 break; 912 } 913 914 default: 915 { 916 rc = VERR_INVALID_PARAMETER; 917 } 918 } 919 } 920 } 921 } 922 else 923 if (rc == VERR_FILE_NOT_FOUND) 924 { 925 LogFlow(("pParms->CreateFlags = %x\n", pParms->CreateFlags)); 926 927 rc = VINF_SUCCESS; 928 929 /* File object does not exist. */ 930 pParms->Result = SHFL_FILE_NOT_FOUND; 931 932 if (BIT_FLAG(pParms->CreateFlags, SHFL_CF_OPEN_TARGET_DIRECTORY)) 933 { 934 switch (BIT_FLAG(pParms->CreateFlags, SHFL_CF_ACT_MASK_IF_NEW)) 935 { 936 case SHFL_CF_ACT_CREATE_IF_NEW: 937 { 938 rc = vbsfOpenCreate (pszFullPath, pParms); 939 break; 940 } 941 942 case SHFL_CF_ACT_FAIL_IF_NEW: 943 { 944 /* NIL handle value will tell client that object was not created. */ 945 pParms->Result = SHFL_PATH_NOT_FOUND; 946 break; 947 } 948 949 default: 950 { 951 rc = VERR_INVALID_PARAMETER; 952 break; 953 } 954 } 955 } 956 else 957 { 958 switch (BIT_FLAG(pParms->CreateFlags, SHFL_CF_ACT_MASK_IF_NEW)) 959 { 960 case SHFL_CF_ACT_CREATE_IF_NEW: 961 { 962 rc = vbsfOpenCreate (pszFullPath, pParms); 963 break; 964 } 965 966 case SHFL_CF_ACT_FAIL_IF_NEW: 967 { 968 /* NIL handle value will tell client that object was not created. */ 969 break; 970 } 971 972 default: 973 { 974 rc = VERR_INVALID_PARAMETER; 975 } 976 } 977 } 978 } 979 else 980 if (rc == VERR_PATH_NOT_FOUND) 981 { 982 rc = VINF_SUCCESS; 983 984 pParms->Result = SHFL_PATH_NOT_FOUND; 985 } 986 987 if (rc == VINF_SUCCESS && pParms->Handle != SHFL_HANDLE_NIL) 988 { 989 uint32_t bufsize = sizeof(pParms->Info); 990 991 rc = vbsfQueryFileInfo(pClient, root, pParms->Handle, SHFL_INFO_GET|SHFL_INFO_FILE, &bufsize, (uint8_t *)&pParms->Info); 992 AssertRC(rc); 1026 rc = vbsfOpenFile (pszFullPath, pParms); 1027 } 993 1028 } 994 1029 … … 1644 1679 1645 1680 #ifndef DEBUG_dmik 1646 Assert(rc == VINF_SUCCESS || rc == VERR_DIR_NOT_EMPTY); 1681 // VERR_ACCESS_DENIED for example? 1682 // Assert(rc == VINF_SUCCESS || rc == VERR_DIR_NOT_EMPTY); 1647 1683 #endif 1648 1684 /* free the path string */ -
trunk/src/VBox/Runtime/fileio.cpp
r4372 r5258 128 128 if ( (fOpen & (~RTFILE_O_VALID_MASK | RTFILE_O_NON_BLOCK)) 129 129 || !(fOpen & RTFILE_O_ACCESS_MASK) 130 || (fOpen & (RTFILE_O_TRUNCATE | RTFILE_O_ DENY_WRITE)) == RTFILE_O_TRUNCATE130 || (fOpen & (RTFILE_O_TRUNCATE | RTFILE_O_WRITE)) == RTFILE_O_TRUNCATE 131 131 ) 132 132 {
Note:
See TracChangeset
for help on using the changeset viewer.