Changeset 27246 in vbox for trunk/src/VBox/Runtime/r3
- Timestamp:
- Mar 10, 2010 12:51:15 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/dir.cpp
r21675 r27246 723 723 724 724 725 RTDECL(int) RTDirRemoveRecursive(const char *pszPath) 726 { 727 int rc; 728 729 if (!RTDirExists(pszPath)) 730 return VINF_SUCCESS; 731 732 char szAbsPath[RTPATH_MAX]; 733 /** @todo use RTPathReal here instead? */ 734 rc = RTPathAbs(pszPath, szAbsPath, sizeof(szAbsPath)); 725 /** 726 * Recursion worker for RTDirRemoveRecursive. 727 * 728 * @returns IPRT status code. 729 * @param pszBuf The path buffer. Contains the abs path to the 730 * directory to recurse into. Trailing slash. 731 * @param cchDir The length of the directory we're cursing into, 732 * including the trailing slash. 733 * @param pDirEntry The dir entry buffer. (Shared to save stack.) 734 * @param pObjInfo The object info buffer. (ditto) 735 */ 736 static int rtDirRemoveRecursiveSub(char *pszBuf, size_t cchDir, PRTDIRENTRY pDirEntry, PRTFSOBJINFO pObjInfo) 737 { 738 AssertReturn(RTPATH_IS_SLASH(pszBuf[cchDir - 1]), VERR_INTERNAL_ERROR_4); 739 740 /* 741 * Enumerate the directory content and dispose of it. 742 */ 743 PRTDIR pDir; 744 int rc = RTDirOpen(&pDir, pszBuf); 735 745 if (RT_FAILURE(rc)) 736 746 return rc; 737 738 PRTDIR pDir = NULL; 739 rc = RTDirOpen(&pDir, szAbsPath); 740 if (RT_SUCCESS(rc)) 741 { 742 RTDIRENTRY dirEntry; 743 size_t cbDirEntry = sizeof(dirEntry); 744 745 while ((rc = RTDirRead(pDir, &dirEntry, NULL /* Passing an argument won't work here yet. */)) == VINF_SUCCESS) 747 while (RT_SUCCESS(rc = RTDirRead(pDir, pDirEntry, NULL))) 748 { 749 if ( pDirEntry->szName[0] != '.' 750 || pDirEntry->cbName > 2 751 || ( pDirEntry->cbName == 2 752 && pDirEntry->szName[1] != '.') 753 ) 746 754 { 747 char* pszEntry = NULL; 748 rc = RTStrAPrintf(&pszEntry, "%s/%s", szAbsPath, dirEntry.szName); 749 if( RT_SUCCESS(rc) 750 && strcmp(dirEntry.szName, ".") 751 && strcmp(dirEntry.szName, "..")) 752 { 753 switch (dirEntry.enmType) 755 /* Construct the full name of the entry. */ 756 if (cchDir + pDirEntry->cbName + 1 /* dir slash */ >= RTPATH_MAX) 757 { 758 rc = VERR_FILENAME_TOO_LONG; 759 break; 760 } 761 memcpy(&pszBuf[cchDir], pDirEntry->szName, pDirEntry->cbName + 1); 762 763 /* Deal with the unknown type. */ 764 if (pDirEntry->enmType == RTDIRENTRYTYPE_UNKNOWN) 765 { 766 rc = RTPathQueryInfoEx(pszBuf, pObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK); 767 if (RT_SUCCESS(rc) && RTFS_IS_DIRECTORY(pObjInfo->Attr.fMode)) 768 pDirEntry->enmType = RTDIRENTRYTYPE_DIRECTORY; 769 else if (RT_SUCCESS(rc) && RTFS_IS_FILE(pObjInfo->Attr.fMode)) 770 pDirEntry->enmType = RTDIRENTRYTYPE_FILE; 771 else if (RT_SUCCESS(rc) && RTFS_IS_SYMLINK(pObjInfo->Attr.fMode)) 772 pDirEntry->enmType = RTDIRENTRYTYPE_SYMLINK; 773 } 774 775 /* Try the delete the fs object. */ 776 switch (pDirEntry->enmType) 777 { 778 case RTDIRENTRYTYPE_FILE: 779 rc = RTFileDelete(pszBuf); 780 break; 781 782 case RTDIRENTRYTYPE_DIRECTORY: 754 783 { 755 case RTDIRENTRYTYPE_FILE: 756 757 rc = RTFileDelete(pszEntry); 758 break; 759 760 case RTDIRENTRYTYPE_DIRECTORY: 761 762 rc = RTDirRemoveRecursive(pszEntry); 763 break; 764 765 default: 766 /** @todo not implemented yet. */ 767 break; 784 size_t cchSubDir = cchDir + pDirEntry->cbName; 785 pszBuf[cchSubDir++] = '/'; 786 pszBuf[cchSubDir] = '\0'; 787 rc = rtDirRemoveRecursiveSub(pszBuf, cchSubDir, pDirEntry, pObjInfo); 788 if (RT_SUCCESS(rc)) 789 { 790 pszBuf[cchSubDir] = '\0'; 791 rc = RTDirRemove(pszBuf); 792 } 793 break; 768 794 } 769 795 770 RTStrFree(pszEntry); 796 //case RTDIRENTRYTYPE_SYMLINK: 797 // rc = RTSymlinkDelete(pszBuf); 798 // break; 799 800 default: 801 /** @todo not implemented yet. */ 802 rc = VINF_SUCCESS; 803 break; 771 804 } 772 773 805 if (RT_FAILURE(rc)) 774 806 break; 775 807 } 776 if (rc == VERR_NO_MORE_FILES) 777 rc = VINF_SUCCESS; 778 779 RTDirClose(pDir); 808 } 809 if (rc == VERR_NO_MORE_FILES) 810 rc = VINF_SUCCESS; 811 RTDirClose(pDir); 812 return rc; 813 } 814 815 816 RTDECL(int) RTDirRemoveRecursive(const char *pszPath, uint32_t fFlags) 817 { 818 AssertReturn(!(fFlags & ~RTDIRRMREC_F_VALID_MASK), VERR_INVALID_PARAMETER); 819 820 /* Get an absolute path because this is easier to work with. */ 821 /** @todo use RTPathReal here instead? */ 822 char szAbsPath[RTPATH_MAX]; 823 int rc = RTPathAbs(pszPath, szAbsPath, sizeof(szAbsPath)); 824 if (RT_FAILURE(rc)) 825 return rc; 826 827 /* This API is not permitted applied to the root of anything. */ 828 if (RTPathCountComponents(szAbsPath) <= 1) 829 return VERR_ACCESS_DENIED; 830 831 /* Because of the above restriction, we never have to deal with the root 832 slash problem and can safely strip any trailing slashes and add a 833 definite one. */ 834 RTPathStripTrailingSlash(szAbsPath); 835 size_t cchAbsPath = strlen(szAbsPath); 836 if (cchAbsPath + 1 >= RTPATH_MAX) 837 return VERR_FILENAME_TOO_LONG; 838 szAbsPath[cchAbsPath++] = '/'; 839 szAbsPath[cchAbsPath] = 0; 840 841 /* Check if it exists so we can return quietly if it doesn't. */ 842 RTFSOBJINFO SharedObjInfoBuf; 843 rc = RTPathQueryInfoEx(szAbsPath, &SharedObjInfoBuf, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK); 844 if ( rc == VERR_PATH_NOT_FOUND 845 || rc == VERR_FILE_NOT_FOUND) 846 return VINF_SUCCESS; 847 if (RT_FAILURE(rc)) 848 return rc; 849 if (!RTFS_IS_DIRECTORY(SharedObjInfoBuf.Attr.fMode)) 850 return VERR_NOT_A_DIRECTORY; 851 852 /* We're all set for the recursion now, so get going. */ 853 RTDIRENTRY SharedDirEntryBuf; 854 rc = rtDirRemoveRecursiveSub(szAbsPath, cchAbsPath, &SharedDirEntryBuf, &SharedObjInfoBuf); 855 856 /* Remove the specified directory if desired and removing the content was 857 successful. */ 858 if ( RT_SUCCESS(rc) 859 && !(fFlags & RTDIRRMREC_F_CONTENT_ONLY)) 860 { 861 szAbsPath[cchAbsPath] = 0; 780 862 rc = RTDirRemove(szAbsPath); 781 863 } 782 783 LogFlow(("RTDirRemoveRecursive(%p:{%s}): returns %Rrc\n", pszPath, pszPath, rc));784 864 return rc; 785 865 }
Note:
See TracChangeset
for help on using the changeset viewer.