VirtualBox

Changeset 78111 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Apr 11, 2019 2:10:07 PM (6 years ago)
Author:
vboxsync
Message:

Guest Control/VBoxService: Added support for deleting empty directory structures only, and handle DIRREMOVEREC_FLAG_CONTENT_AND_DIR and DIRREMOVEREC_FLAG_CONTENT_ONLY separately (so that also directory content gets removed).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp

    r77069 r78111  
    121121
    122122
     123/**
     124 * Recursion worker for vgsvcGstCtrlSessionHandleDirRemove.
     125 * Only (recursively) removes directory structures which are not empty. Will fail if not empty.
     126 *
     127 * @returns IPRT status code.
     128 * @param   pszDir              The directory buffer.  Contains the abs path to the
     129 *                              directory to recurse into.  Trailing slash.
     130 * @param   cchDir              The length of the directory we're recursing into,
     131 *                              including the trailing slash.
     132 * @param   pDirEntry           The dir entry buffer.  (Shared to save stack.)
     133 * @param   pObjInfo            The object info buffer.  (ditto)
     134 */
     135static int vgsvcGstCtrlSessionHandleDirRemoveSub(char *pszDir, size_t cchDir, PRTDIRENTRY pDirEntry, PRTFSOBJINFO pObjInfo)
     136{
     137    RTDIR hDir;
     138    int rc = RTDirOpen(&hDir, pszDir);
     139    if (RT_FAILURE(rc))
     140        return rc;
     141
     142    while (RT_SUCCESS(rc = RTDirRead(hDir, pDirEntry, NULL)))
     143    {
     144        if (!RTDirEntryIsStdDotLink(pDirEntry))
     145        {
     146            /* Construct the full name of the entry. */
     147            if (cchDir + pDirEntry->cbName + 1 /* dir slash */ >= RTPATH_MAX)
     148            {
     149                rc = VERR_FILENAME_TOO_LONG;
     150                break;
     151            }
     152            memcpy(&pszDir[cchDir], pDirEntry->szName, pDirEntry->cbName + 1);
     153
     154            /* Deal with the unknown type. */
     155            if (pDirEntry->enmType == RTDIRENTRYTYPE_UNKNOWN)
     156            {
     157                rc = RTPathQueryInfoEx(pszDir, pObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
     158                if (RT_SUCCESS(rc) && RTFS_IS_DIRECTORY(pObjInfo->Attr.fMode))
     159                    pDirEntry->enmType = RTDIRENTRYTYPE_DIRECTORY;
     160                else if (RT_SUCCESS(rc) && RTFS_IS_FILE(pObjInfo->Attr.fMode))
     161                    pDirEntry->enmType = RTDIRENTRYTYPE_FILE;
     162                else if (RT_SUCCESS(rc) && RTFS_IS_SYMLINK(pObjInfo->Attr.fMode))
     163                    pDirEntry->enmType = RTDIRENTRYTYPE_SYMLINK;
     164            }
     165
     166            /* Try the delete the fs object. */
     167            switch (pDirEntry->enmType)
     168            {
     169                case RTDIRENTRYTYPE_DIRECTORY:
     170                {
     171                    size_t cchSubDir = cchDir + pDirEntry->cbName;
     172                    pszDir[cchSubDir++] = '/';
     173                    pszDir[cchSubDir]   = '\0';
     174                    rc = vgsvcGstCtrlSessionHandleDirRemoveSub(pszDir, cchSubDir, pDirEntry, pObjInfo);
     175                    if (RT_SUCCESS(rc))
     176                    {
     177                        pszDir[cchSubDir] = '\0';
     178                        rc = RTDirRemove(pszDir);
     179                    }
     180                    break;
     181                }
     182
     183                /** @todo Implement deleting symlinks? Play safe for now. */
     184
     185                default:
     186                    rc = VERR_DIR_NOT_EMPTY;
     187                    break;
     188            }
     189            if (RT_FAILURE(rc))
     190               break;
     191        }
     192    }
     193    if (rc == VERR_NO_MORE_FILES)
     194        rc = VINF_SUCCESS;
     195    RTDirClose(hDir);
     196    return rc;
     197}
     198
     199
    123200static int vgsvcGstCtrlSessionHandleDirRemove(PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx)
    124201{
     
    141218            if (fFlags & DIRREMOVEREC_FLAG_RECURSIVE)
    142219            {
    143                 uint32_t fFlagsRemRec = RTDIRRMREC_F_CONTENT_AND_DIR; /* Set default. */
    144                 if (fFlags & DIRREMOVEREC_FLAG_CONTENT_ONLY)
    145                     fFlagsRemRec |= RTDIRRMREC_F_CONTENT_ONLY;
    146                 rc = RTDirRemoveRecursive(szDir, fFlagsRemRec);
     220                if (   fFlags & DIRREMOVEREC_FLAG_CONTENT_AND_DIR
     221                    || fFlags & DIRREMOVEREC_FLAG_CONTENT_ONLY)
     222                {
     223                    uint32_t fFlagsRemRec = 0;
     224                    if (fFlags & DIRREMOVEREC_FLAG_CONTENT_AND_DIR)
     225                        fFlagsRemRec |= RTDIRRMREC_F_CONTENT_AND_DIR;
     226                    else if (fFlags & DIRREMOVEREC_FLAG_CONTENT_ONLY)
     227                        fFlagsRemRec |= RTDIRRMREC_F_CONTENT_ONLY;
     228                    rc = RTDirRemoveRecursive(szDir, fFlagsRemRec);
     229                }
     230                else /* Only remove empty directory structures. Will fail if non-empty. */
     231                {
     232                    RTDIRENTRY  dirEntry;
     233                    RTFSOBJINFO objInfo;
     234                    rc = vgsvcGstCtrlSessionHandleDirRemoveSub(szDir, strlen(szDir), &dirEntry, &objInfo);
     235                }
    147236                VGSvcVerbose(4, "[Dir %s]: rmdir /s (%#x) -> rc=%Rrc\n", szDir, fFlags, rc);
    148237            }
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette