VirtualBox

Changeset 105658 in vbox


Ignore:
Timestamp:
Aug 13, 2024 10:35:19 AM (9 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
164351
Message:

Main: Add possibility to save the NVRAM file as a directory tree instead of a tar archive for easier access to the individual components

Location:
trunk/src/VBox/Main
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified trunk/src/VBox/Main/include/NvramStoreImpl.h

    r105627 r105658  
    122122
    123123    int i_loadStoreFromTar(RTVFSFSSTREAM hVfsFssTar);
     124    int i_loadStoreFromDir(RTVFSDIR hVfsDir, const char *pszNamespace);
    124125    int i_saveStoreAsTar(const char *pszPath);
     126    int i_saveStoreAsDir(const char *pszPath);
    125127
    126128    int i_retainCryptoIf(PCVBOXCRYPTOIF *ppCryptoIf);
  • TabularUnified trunk/src/VBox/Main/src-all/NvramStoreImpl.cpp

    r105628 r105658  
    4949#include <iprt/efi.h>
    5050#include <iprt/file.h>
     51#include <iprt/path.h>
    5152#include <iprt/vfs.h>
    5253#include <iprt/zip.h>
     
    714715
    715716#endif /* VBOX_WITH_FULL_VM_ENCRYPTION */
     717
     718/**
     719 * Loads the NVRAM store from the given VFS directory handle.
     720 *
     721 * @returns IPRT status code.
     722 * @param   hVfsDir             Handle to the NVRAM root VFS directory.
     723 * @param   pszNamespace        The namespace to load the content for.
     724 */
     725int NvramStore::i_loadStoreFromDir(RTVFSDIR hVfsDir, const char *pszNamespace)
     726{
     727    int vrc = VINF_SUCCESS;
     728
     729    RTVFSDIR hNamespaceDir = NIL_RTVFSDIR;
     730    vrc = RTVfsDirOpenDir(hVfsDir, pszNamespace, 0 /*fFlags*/, &hNamespaceDir);
     731    if (RT_SUCCESS(vrc))
     732    {
     733        for (;;)
     734        {
     735            RTDIRENTRYEX DirEntry; /* ASSUMES that no entry has a longer name than what RTDIRENTRYEX provides by default. */
     736            size_t cbDir = sizeof(DirEntry);
     737            vrc = RTVfsDirReadEx(hNamespaceDir, &DirEntry, &cbDir, RTFSOBJATTRADD_NOTHING);
     738            if (RT_FAILURE(vrc))
     739            {
     740                if (vrc == VERR_NO_MORE_FILES)
     741                    vrc = VINF_SUCCESS;
     742                break;
     743            }
     744
     745            if (RT_SUCCESS(vrc))
     746            {
     747                switch (DirEntry.Info.Attr.fMode & RTFS_TYPE_MASK)
     748                {
     749                    case RTFS_TYPE_FILE:
     750                    {
     751                        LogRel(("NvramStore: Loading '%s' from directory '%s'\n", DirEntry.szName, pszNamespace));
     752
     753                        RTVFSIOSTREAM hVfsIosEntry;
     754                        vrc = RTVfsDirOpenFileAsIoStream(hNamespaceDir, DirEntry.szName, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE, &hVfsIosEntry);
     755                        if (RT_SUCCESS(vrc))
     756                        {
     757                            RTVFSIOSTREAM hVfsIosDecrypted = NIL_RTVFSIOSTREAM;
     758
     759#ifdef VBOX_WITH_FULL_VM_ENCRYPTION
     760                            PCVBOXCRYPTOIF pCryptoIf = NULL;
     761                            SecretKey *pKey = NULL;
     762
     763                            if (   m->bd->strKeyId.isNotEmpty()
     764                                && m->bd->strKeyStore.isNotEmpty())
     765                                vrc = i_setupEncryptionOrDecryption(hVfsIosEntry, false /*fEncrypt*/,
     766                                                                    &pCryptoIf, &pKey, &hVfsIosDecrypted);
     767#endif
     768                            if (RT_SUCCESS(vrc))
     769                            {
     770                                RTVFSFILE hVfsFileEntry;
     771                                vrc = RTVfsMemorizeIoStreamAsFile(hVfsIosDecrypted != NIL_RTVFSIOSTREAM
     772                                                                  ? hVfsIosDecrypted
     773                                                                  : hVfsIosEntry,
     774                                                                  RTFILE_O_READ | RTFILE_O_WRITE, &hVfsFileEntry);
     775                                if (RT_SUCCESS(vrc))
     776                                    m->mapNvram[Utf8StrFmt("%s/%s", pszNamespace, DirEntry.szName)] = hVfsFileEntry;
     777                            }
     778
     779#ifdef VBOX_WITH_FULL_VM_ENCRYPTION
     780                            if (hVfsIosDecrypted != NIL_RTVFSIOSTREAM)
     781                                i_releaseEncryptionOrDecryptionResources(hVfsIosDecrypted, pCryptoIf, pKey);
     782#endif
     783
     784                            RTVfsIoStrmRelease(hVfsIosEntry);
     785                        }
     786                        else
     787                            LogRel(("Failed to open '%s' in NVRAM store '%s', vrc=%Rrc\n", DirEntry.szName, pszNamespace, vrc));
     788
     789                        break;
     790                    }
     791                    case RTFS_TYPE_DIRECTORY:
     792                        break;
     793                    default:
     794                        vrc = VERR_NOT_SUPPORTED;
     795                        break;
     796                }
     797            }
     798
     799            if (RT_FAILURE(vrc))
     800                break;
     801        }
     802
     803        RTVfsDirRelease(hNamespaceDir);
     804    }
     805
     806    return vrc;
     807}
     808
    716809
    717810/**
     
    830923        }
    831924    }
     925    else if (vrc == VERR_IS_A_DIRECTORY) /* Valid if the NVRAM was saved with VBoxInternal2/SaveNvramContentAsDirectory 1. */
     926    {
     927        RTVFSDIR hNvramDir = NIL_RTVFSDIR;
     928        vrc = RTVfsDirOpenNormal(pszPath, 0 /*fFlags*/, &hNvramDir);
     929        if (RT_SUCCESS(vrc))
     930        {
     931            for (;;)
     932            {
     933                RTDIRENTRYEX DirEntry; /* ASSUMES that no entry has a longer name than what RTDIRENTRYEX provides by default. */
     934                size_t cbDir = sizeof(DirEntry);
     935
     936                vrc = RTVfsDirReadEx(hNvramDir, &DirEntry, &cbDir, RTFSOBJATTRADD_NOTHING);
     937                if (RT_FAILURE(vrc))
     938                {
     939                    if (vrc == VERR_NO_MORE_FILES)
     940                        vrc = VINF_SUCCESS;
     941                    break;
     942                }
     943
     944                /* This ASSUMES that the structure follows the <namespace>/<file> naming scheme. */
     945                if (RT_SUCCESS(vrc))
     946                {
     947                    switch (DirEntry.Info.Attr.fMode & RTFS_TYPE_MASK)
     948                    {
     949                        case RTFS_TYPE_FILE:
     950                            break;
     951                        case RTFS_TYPE_DIRECTORY:
     952                        {
     953                            if (   (DirEntry.szName[0] == '.' && DirEntry.szName[1] == '\0')
     954                                || (DirEntry.szName[0] == '.' && DirEntry.szName[1] == '.' && DirEntry.szName[2] == '\0'))
     955                                break;
     956
     957                            vrc = i_loadStoreFromDir(hNvramDir, DirEntry.szName);
     958                            break;
     959                        }
     960                        default:
     961                            vrc = VERR_NOT_SUPPORTED;
     962                            break;
     963                    }
     964                }
     965
     966                if (RT_FAILURE(vrc))
     967                    break;
     968            }
     969
     970            RTVfsDirRelease(hNvramDir);
     971        }
     972        else
     973            LogRelMax(10, ("NVRAM store '%s' couldn't be opened as a directory, vrc=%Rrc\n", pszPath, vrc));
     974
     975    }
    832976    else if (vrc == VERR_FILE_NOT_FOUND) /* Valid for the first run where no NVRAM file is there. */
    833977        vrc = VINF_SUCCESS;
     
    9051049
    9061050
     1051/**
     1052 * Saves the NVRAM store as a directory tree.
     1053 */
     1054int NvramStore::i_saveStoreAsDir(const char *pszPath)
     1055{
     1056    int vrc = VINF_SUCCESS;
     1057    if (RTDirExists(pszPath))
     1058        vrc = RTDirRemoveRecursive(pszPath, RTDIRRMREC_F_CONTENT_AND_DIR);
     1059    else if (RTPathExists(pszPath))
     1060        vrc = RTPathUnlink(pszPath, 0 /*fUnlink*/);
     1061    if (RT_FAILURE(vrc))
     1062    {
     1063        LogRel(("Failed to delete existing NVRAM store '%s': %Rrc\n", vrc));
     1064        return vrc;
     1065    }
     1066
     1067    vrc = RTDirCreate(pszPath, 0700 /*fMode*/, RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_NOT_CRITICAL);
     1068    if (RT_SUCCESS(vrc))
     1069    {
     1070        NvramStoreIter it = m->mapNvram.begin();
     1071
     1072        while (it != m->mapNvram.end())
     1073        {
     1074            /** @todo r=aeichner This is pretty in-efficient but not called often (not at all by default)
     1075             *                   and there aren't many entries anyway. */
     1076            char szPathOut[RTPATH_MAX];
     1077            char szPathFile[RTPATH_MAX];
     1078
     1079            /* Construct the path excluding the filename. */
     1080            vrc = RTStrCopy(szPathFile, sizeof(szPathFile), it->first.c_str());
     1081            if (RT_FAILURE(vrc))
     1082                break;
     1083            RTPathStripFilename(szPathFile);
     1084            vrc = RTPathJoin(szPathOut, sizeof(szPathOut), pszPath, szPathFile);
     1085            if (RT_FAILURE(vrc))
     1086                break;
     1087
     1088            /* Create the directory structure. */
     1089            vrc = RTDirCreateFullPathEx(szPathOut, 0700 /*fMode*/, RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_NOT_CRITICAL);
     1090            if (RT_FAILURE(vrc))
     1091                break;
     1092
     1093            vrc = RTVfsFileSeek(it->second, 0 /*offSeek*/, RTFILE_SEEK_BEGIN, NULL /*poffActual*/);
     1094            AssertRC(vrc);
     1095
     1096            /* Construct path, including the filename now. */
     1097            vrc = RTPathJoin(szPathOut, sizeof(szPathOut), pszPath, it->first.c_str());
     1098            if (RT_FAILURE(vrc))
     1099                break;
     1100
     1101            /* Write the file, encrypting it if required. */
     1102            RTVFSFILE hVfsFile;
     1103            vrc = RTVfsFileOpenNormal(szPathOut, RTFILE_O_WRITE | RTFILE_O_DENY_WRITE | RTFILE_O_CREATE_REPLACE,
     1104                                      &hVfsFile);
     1105            if (RT_SUCCESS(vrc))
     1106            {
     1107                RTVFSIOSTREAM hVfsIos = RTVfsFileToIoStream(hVfsFile);
     1108                RTVFSIOSTREAM hVfsIosEncrypted = NIL_RTVFSIOSTREAM;
     1109
     1110#ifdef VBOX_WITH_FULL_VM_ENCRYPTION
     1111                PCVBOXCRYPTOIF pCryptoIf = NULL;
     1112                SecretKey *pKey = NULL;
     1113
     1114                if (   m->bd->strKeyId.isNotEmpty()
     1115                    && m->bd->strKeyStore.isNotEmpty())
     1116                    vrc = i_setupEncryptionOrDecryption(hVfsIos, true /*fEncrypt*/,
     1117                                                        &pCryptoIf, &pKey, &hVfsIosEncrypted);
     1118#endif
     1119
     1120                if (RT_SUCCESS(vrc))
     1121                {
     1122                    RTVFSIOSTREAM hVfsIosSrc = RTVfsFileToIoStream(it->second);
     1123                    vrc = RTVfsUtilPumpIoStreams(hVfsIosSrc,
     1124                                                   hVfsIosEncrypted != NIL_RTVFSIOSTREAM
     1125                                                 ? hVfsIosEncrypted
     1126                                                 : hVfsIos, 0 /*cbBufHint*/);
     1127                    RTVfsIoStrmRelease(hVfsIosSrc);
     1128#ifdef VBOX_WITH_FULL_VM_ENCRYPTION
     1129                    if (hVfsIosEncrypted != NIL_RTVFSIOSTREAM)
     1130                        i_releaseEncryptionOrDecryptionResources(hVfsIosEncrypted, pCryptoIf, pKey);
     1131#endif
     1132                }
     1133
     1134                RTVfsIoStrmRelease(hVfsIos);
     1135                RTVfsFileRelease(hVfsFile);
     1136            }
     1137
     1138            it++;
     1139        }
     1140
     1141        /* Cleanup in case of error. */
     1142        if (RT_FAILURE(vrc))
     1143        {
     1144            int vrc2 = RTDirRemoveRecursive(pszPath, RTDIRRMREC_F_CONTENT_AND_DIR);
     1145            if (RT_FAILURE(vrc2))
     1146                LogRel(("Cleaning up NVRAM store '%s' failed with %Rrc (after creation failed with %Rrc)\n", vrc2, vrc));
     1147        }
     1148    }
     1149    else
     1150        LogRel(("NVRAM store '%s' directory creation failed: %Rrc\n", pszPath, vrc));
     1151
     1152    return vrc;
     1153}
     1154
     1155
    9071156int NvramStore::i_retainCryptoIf(PCVBOXCRYPTOIF *ppCryptoIf)
    9081157{
     
    10011250        }
    10021251        else if (m->mapNvram.size())
    1003             vrc = i_saveStoreAsTar(strPath.c_str());
     1252        {
     1253            /* Check whether the NVRAM content is supposed to be saved under a directory. */
     1254#ifndef VBOX_COM_INPROC
     1255            Machine * const         pMachine = m->pParent;
     1256#else
     1257            const ComPtr<IMachine> &pMachine = m->pParent->i_machine();
     1258#endif
     1259
     1260            Bstr bstrName("VBoxInternal2/SaveNvramContentAsDirectory");
     1261            Bstr bstrValue;
     1262            HRESULT hrc = pMachine->GetExtraData(bstrName.raw(), bstrValue.asOutParam());
     1263            if (FAILED(hrc))
     1264                throw hrc;
     1265
     1266            bool fSaveAsDir = fSaveAsDir = bstrValue == "1";
     1267
     1268            if (fSaveAsDir)
     1269                vrc = i_saveStoreAsDir(strPath.c_str());
     1270            else
     1271                vrc = i_saveStoreAsTar(strPath.c_str());
     1272        }
    10041273        /* else: No NVRAM content to store so we are done here. */
    10051274    }
  • TabularUnified trunk/src/VBox/Main/src-server/MachineImpl.cpp

    r105605 r105658  
    95619561                        newNVRAMFile.stripSuffix();
    95629562                        newNVRAMFile += ".nvram";
    9563                         RTFileRename(NVRAMFile.c_str(), newNVRAMFile.c_str(), 0);
     9563                        RTPathRename(NVRAMFile.c_str(), newNVRAMFile.c_str(), 0);
    95649564                    }
    95659565                }
     
    96109610                RTFileRename(newConfigFile.c_str(), configFile.c_str(), 0);
    96119611                if (NVRAMFile.isNotEmpty() && newNVRAMFile.isNotEmpty())
    9612                     RTFileRename(newNVRAMFile.c_str(), NVRAMFile.c_str(), 0);
     9612                    RTPathRename(newNVRAMFile.c_str(), NVRAMFile.c_str(), 0);
    96139613            }
    96149614            if (dirRenamed)
Note: See TracChangeset for help on using the changeset viewer.

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