VirtualBox

Changeset 75266 in vbox


Ignore:
Timestamp:
Nov 6, 2018 6:15:26 AM (6 years ago)
Author:
vboxsync
Message:

Modified to use com:: interfaces. Works on Linux and MacOS now.

Location:
trunk/src/VBox/ImageMounter/vboxraw
Files:
1 added
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ImageMounter/vboxraw/vboxraw.cpp

    r74444 r75266  
    2020*   Header Files                                                                                                                 *
    2121*********************************************************************************************************************************/
    22 
    2322#define LOG_GROUP LOG_GROUP_DEFAULT /** @todo log group */
    24 #define VBox_WITH_XPCOM
     23#define UNUSED(x) (void)(x)
    2524
    2625#define FUSE_USE_VERSION 27
    2726#if defined(RT_OS_DARWIN) || defined(RT_OS_LINUX) || defined(RT_OS_FEEBSD)
    28 #   define UNIXY
     27#   define UNIX_DERIVATIVE
    2928#endif
    3029#define MAX_READERS (INT32_MAX / 32)
    3130
    32 #include <VBox/vd.h>
    33 #include <VBox/log.h>
    34 #include <VBox/err.h>
    35 #include <iprt/critsect.h>
    36 #include <iprt/assert.h>
    37 #include <iprt/message.h>
    38 #include <iprt/asm.h>
    39 #include <iprt/mem.h>
    40 #include <iprt/string.h>
    41 #include <iprt/initterm.h>
    42 #include <iprt/stream.h>
    43 #include <iprt/types.h>
    44 #include <iprt/path.h>
    45 
    4631#include <fuse.h>
    47 #ifdef UNIXY
     32#ifdef UNIX_DERIVATIVE
    4833#include <errno.h>
    4934#include <fcntl.h>
     
    5742# undef PVM     /* Blasted old BSD mess still hanging around darwin. */
    5843#endif
    59 
    60 /*
    61  * Include the XPCOM headers
    62  */
     44#ifdef RT_OS_LINUX
     45# include <linux/fs.h>
     46# include <linux/hdreg.h>
     47#endif
    6348#include <VirtualBox_XPCOM.h>
    64 #include <nsIComponentRegistrar.h>
    65 #include <nsIServiceManager.h>
    66 #include <nsEventQueueUtils.h>
    67 #include <nsIExceptionService.h>
    68 #include <nsMemory.h>
    69 #include <nsArray.h>
    70 #include <nsString.h>
    71 #include <nsReadableUtils.h>
     49#include <VBox/com/VirtualBox.h>
     50#include <VBox/vd.h>
     51#include <VBox/log.h>
     52#include <VBox/err.h>
     53#include <VBox/com/ErrorInfo.h>
     54#include <VBox/com/NativeEventQueue.h>
     55#include <VBox/com/com.h>
     56#include <VBox/com/string.h>
     57#include <VBox/com/Guid.h>
     58#include <VBox/com/array.h>
     59#include <VBox/com/errorprint.h>
     60
     61#include <iprt/initterm.h>
     62#include <iprt/critsect.h>
     63#include <iprt/assert.h>
     64#include <iprt/message.h>
     65#include <iprt/asm.h>
     66#include <iprt/mem.h>
     67#include <iprt/string.h>
     68#include <iprt/initterm.h>
     69#include <iprt/stream.h>
     70#include <iprt/types.h>
     71#include <iprt/path.h>
     72
     73using namespace com;
    7274
    7375enum {
     
    9294#define PADMAX                      50
    9395#define MAX_ID_LEN                  256
     96#define CSTR(arg) Utf8Str(arg).c_str()
    9497
    9598static struct fuse_operations   g_vboxrawOps;
     
    103106char *nsIDToString(nsID *guid);
    104107void printErrorInfo();
    105 
    106108/** XPCOM stuff */
    107 static struct {
    108     nsCOMPtr<nsIServiceManager>     serviceManager;
    109     nsCOMPtr<nsIEventQueue>         eventQ;
    110     nsCOMPtr<nsIComponentManager>   manager;
    111     nsCOMPtr<IVirtualBox>           virtualBox;
    112 } g_XPCOM;
    113109
    114110static struct vboxrawOpts {
     
    118114     uint32_t cHddImageDiffMax;
    119115     uint32_t fList;
    120      uint32_t fWriteable;
     116     uint32_t fAllowRoot;
     117     uint32_t fRW;
    121118     uint32_t fVerbose;
    122119} g_vboxrawOpts;
     
    126123static struct fuse_opt vboxrawOptDefs[] = {
    127124    OPTION("--list",          fList,            1),
     125    OPTION("--root",          fAllowRoot,       1),
    128126    OPTION("--vm=%s",         pszVm,            0),
    129127    OPTION("--maxdiff=%d",    cHddImageDiffMax, 1),
    130128    OPTION("--diff=%d",       cHddImageDiffMax, 1),
    131129    OPTION("--image=%s",      pszImage,         0),
    132     OPTION("--writable",      fWriteable,       1),
     130    OPTION("--rw",            fRW,              1),
    133131    OPTION("--verbose",       fVerbose,         1),
    134132    FUSE_OPT_KEY("-h",        USAGE_FLAG),
     
    149147                "%s options:\n"
    150148                "    [--list]                              List media\n"
     149                "    [--root]                              Same as -o allow_root\n"
     150                "    [--rw]                                writeable (default = readonly)\n"
    151151                "    [--vm <name | UUID >]                 vm UUID (limit media list to specific VM)\n\n"
    152152                "    [--diff=<diff #> ]                    Apply diffs to base image up "
     
    181181    int rc = 0;
    182182
    183 #ifdef UNIXY
     183#ifdef UNIX_DERIVATIVE
    184184#   ifdef RT_OS_DARWIN
    185185        notsup = O_APPEND | O_NONBLOCK | O_SYMLINK | O_NOCTTY | O_SHLOCK | O_EXLOCK |
     
    189189                 /* | O_LARGEFILE | O_SYNC | ? */
    190190#   elif defined(RT_OS_FREEBSD)
    191         notsup = O_APPEND | O_ASYNC | O_DIRECT | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK';
     191        notsup = O_APPEND | O_ASYNC | O_DIRECT | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK;
    192192                 /* | O_LARGEFILE | O_SYNC | ? */
    193193#   endif
     
    199199    rc -EINVAL;
    200200
    201 #ifdef UNIXY
     201#ifdef UNIX_DERIVATIVE
    202202    if ((pInfo->flags & O_ACCMODE) == O_ACCMODE)
    203203        rc = -EINVAL;
     
    258258    LogFlowFunc(("\"%s\"\n", pszPath));
    259259    return 0;
     260}
     261
     262static int retryableVDRead(PVDISK pvDisk, uint64_t offset, void *pvBuf, size_t cbRead)
     263{
     264    int rc = -1;
     265    int cRetry = 5;
     266    do
     267    {
     268        if (cRetry < 5)
     269            Log(("(rc=%d retrying read)\n", rc));
     270        rc = VDRead(pvDisk, offset, pvBuf, cbRead);
     271    } while (RT_FAILURE(rc) && --cRetry);
     272    return rc;
    260273}
    261274
     
    295308        if (    !(offset & VBoxRAW_MIN_SIZE_MASK_OFF)
    296309            &&  !(cbBuf   & VBoxRAW_MIN_SIZE_MASK_OFF))
    297             rc2 = VDRead(g_pVDisk, offset, pbBuf, cbBuf);
     310        {
     311                rc2 = retryableVDRead(g_pVDisk, offset, pbBuf, cbBuf);
     312                if (RT_FAILURE(rc2))
     313                {
     314                    rc = -RTErrConvertToErrno(rc2);
     315                    LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
     316                    return rc;
     317                }
     318        }
    298319        else
    299320        {
     
    305326            {
    306327                /* a single partial block. */
    307                 rc2 = VDRead(g_pVDisk, offset & VBoxRAW_MIN_SIZE_MASK_BLK, abBlock, VBoxRAW_MIN_SIZE);
     328                rc2 = retryableVDRead(g_pVDisk, offset & VBoxRAW_MIN_SIZE_MASK_BLK, abBlock, VBoxRAW_MIN_SIZE);
    308329                if (RT_SUCCESS(rc2))
     330                {
    309331                    memcpy(pbBuf, &abBlock[offset & VBoxRAW_MIN_SIZE_MASK_OFF], cbBuf);
     332                }
     333                else
     334                {
     335                    rc = -RTErrConvertToErrno(rc2);
     336                    LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
     337                    return rc;
     338                }
    310339            }
    311340            else
     
    315344                if (offset & VBoxRAW_MIN_SIZE_MASK_OFF)
    316345                {
    317                     rc2 = VDRead(g_pVDisk, offset & VBoxRAW_MIN_SIZE_MASK_BLK, abBlock, VBoxRAW_MIN_SIZE);
     346                    rc2 = retryableVDRead(g_pVDisk, offset & VBoxRAW_MIN_SIZE_MASK_BLK, abBlock, VBoxRAW_MIN_SIZE);
    318347                    if (RT_SUCCESS(rc2))
    319348                    {
     
    324353                        cbBuf   -= cbCopy;
    325354                    }
     355                    else
     356                    {
     357                        rc = -RTErrConvertToErrno(rc2);
     358                        LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
     359                        return rc;
     360                    }
    326361                }
    327362
     
    331366                {
    332367                    size_t cbRead = cbBuf & VBoxRAW_MIN_SIZE_MASK_BLK;
    333                     rc2 = VDRead(g_pVDisk, offset, pbBuf, cbRead);
     368                    rc2 = retryableVDRead(g_pVDisk, offset, pbBuf, cbRead);
    334369                    if (RT_SUCCESS(rc2))
    335370                    {
     
    337372                        offset += cbRead;
    338373                        cbBuf   -= cbRead;
     374                    }
     375                    else
     376                    {
     377                        rc = -RTErrConvertToErrno(rc2);
     378                        LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
     379                        return rc;
    339380                    }
    340381                }
     
    345386                if (cbBuf && RT_SUCCESS(rc2))
    346387                {
    347                     rc2 = VDRead(g_pVDisk, offset, abBlock, VBoxRAW_MIN_SIZE);
    348                     if (RT_SUCCESS(rc2))
     388                    rc2 = retryableVDRead(g_pVDisk, offset, abBlock, VBoxRAW_MIN_SIZE);
     389                    if (RT_SUCCESS(rc2)) {
    349390                        memcpy(pbBuf, &abBlock[0], cbBuf);
     391                    }
     392                    else
     393                    {
     394                        rc = -RTErrConvertToErrno(rc2);
     395                        LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
     396                        return rc;
     397                    }
    350398                }
    351399            }
     
    356404            rc = cbBuf;
    357405        else
     406        {
    358407            rc = -RTErrConvertToErrno(rc2);
     408            LogFlowFunc(("Error rc2=%d, rc=%d=%s\n", rc2, rc, strerror(rc)));
     409        }
    359410        return rc;
    360411    }
     
    369420    (void) pszPath;
    370421    (void) pInfo;
     422
    371423
    372424    AssertReturn((int)cbBuf >= 0, -EINVAL);
     
    375427    AssertReturn((off_t)(offset + cbBuf) >= offset, -EINVAL);
    376428
     429
    377430    LogFlowFunc(("offset=%#llx size=%#zx path=\"%s\"\n", (uint64_t)offset, cbBuf, pszPath));
    378431
    379432    int rc;
    380     if ((off_t)(offset + cbBuf) < offset)
     433    if (!g_vboxrawOpts.fRW)
     434        rc = -EPERM;
     435    else if ((off_t)(offset + cbBuf) < offset)
    381436        rc = -EINVAL;
    382437    else if (offset >= g_cbPrimary)
     
    396451        if (    !(offset & VBoxRAW_MIN_SIZE_MASK_OFF)
    397452            &&  !(cbBuf   & VBoxRAW_MIN_SIZE_MASK_OFF))
    398             rc2 = VDWrite(g_pVDisk, offset, pbBuf, cbBuf);
     453        {
     454                rc2 = VDWrite(g_pVDisk, offset, pbBuf, cbBuf);
     455                if (RT_FAILURE(rc2))
     456                {
     457                    rc = -RTErrConvertToErrno(rc2);
     458                    LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
     459                    return rc;
     460                }
     461        }
    399462        else
    400463        {
     
    412475                    /* Update the block */
    413476                    rc2 = VDWrite(g_pVDisk, offset & VBoxRAW_MIN_SIZE_MASK_BLK, abBlock, VBoxRAW_MIN_SIZE);
     477                    if (RT_FAILURE(rc2))
     478                    {
     479                        rc = -RTErrConvertToErrno(rc2);
     480                        LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
     481                        return rc;
     482                    }
     483                }
     484                else
     485                {
     486                    rc = -RTErrConvertToErrno(rc2);
     487                    LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
     488                    return rc;
    414489                }
    415490            }
     
    429504                        cbBuf   -= cbCopy;
    430505                        rc2 = VDWrite(g_pVDisk, offset & VBoxRAW_MIN_SIZE_MASK_BLK, abBlock, VBoxRAW_MIN_SIZE);
     506                        if (RT_FAILURE(rc2))
     507                        {
     508                            rc = -RTErrConvertToErrno(rc2);
     509                            LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
     510                            return rc;
     511                        }
     512                    }
     513                    else
     514                    {
     515                        rc = -RTErrConvertToErrno(rc2);
     516                        LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
     517                        return rc;
    431518                    }
    432519                }
     
    443530                        offset += cbWrite;
    444531                        cbBuf   -= cbWrite;
     532                    }
     533                    if (RT_FAILURE(rc2))
     534                    {
     535                        rc = -RTErrConvertToErrno(rc2);
     536                        LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
     537                        return rc;
    445538                    }
    446539                }
     
    456549                        memcpy(&abBlock[0], pbBuf, cbBuf);
    457550                        rc2 = VDWrite(g_pVDisk, offset, abBlock, VBoxRAW_MIN_SIZE);
     551                        if (RT_FAILURE(rc2))
     552                        {
     553                            rc = -RTErrConvertToErrno(rc2);
     554                            LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
     555                            return rc;
     556                        }
     557                    }
     558                    else
     559                    {
     560                        rc = -RTErrConvertToErrno(rc2);
     561                        LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc)));
     562                        return rc;
    458563                    }
    459564                }
     
    465570            rc = cbBuf;
    466571        else
     572        {
    467573            rc = -RTErrConvertToErrno(rc2);
     574            LogFlowFunc(("Error rc2=%d, rc=%d=%s\n", rc2, rc, strerror(rc)));
    468575            return rc;
     576        }
    469577    }
    470578    return rc;
     
    472580
    473581/** @copydoc fuse_operations::getattr */
    474 static int vboxrawOp_getattr(const char *pszPath,
    475             struct stat *stbuf)
     582static int
     583vboxrawOp_getattr(const char *pszPath, struct stat *stbuf)
    476584{
    477585    int rc = 0;
     
    491599        if (rc < 0)
    492600            return rc;
     601
     602        stbuf->st_size = VDGetSize(g_pVDisk, 0);
    493603        stbuf->st_nlink = 1;
    494604    }
     
    501611        stbuf->st_mode = S_IFLNK | 0444;
    502612        stbuf->st_nlink = 1;
     613        stbuf->st_uid = 0;
     614        stbuf->st_gid = 0;
    503615    } else
    504616        rc = -ENOENT;
     
    508620
    509621/** @copydoc fuse_operations::readdir */
    510 static int vboxrawOp_readdir(const char *pszPath, void *pvBuf, fuse_fill_dir_t pfnFiller,
     622static int
     623vboxrawOp_readdir(const char *pszPath, void *pvBuf, fuse_fill_dir_t pfnFiller,
    511624                              off_t offset, struct fuse_file_info *pInfo)
    512625
     
    543656
    544657/** @copydoc fuse_operations::readlink */
    545 static int vboxrawOp_readlink(const char *pszPath, char *buf, size_t size)
     658static int
     659vboxrawOp_readlink(const char *pszPath, char *buf, size_t size)
    546660{
    547661    (void) pszPath;
     
    550664}
    551665
    552 
    553 static int
     666static void
    554667listMedia(IMachine *pMachine)
    555668{
    556     IMediumAttachment **pMediumAttachments = NULL;
    557     PRUint32 pMediumAttachmentsSize = 0;
    558     nsresult rc = pMachine->GetMediumAttachments(&pMediumAttachmentsSize,  &pMediumAttachments);
    559     if (NS_SUCCEEDED(rc))
    560     {
    561         for (PRUint32 i = 0; i < pMediumAttachmentsSize; i++)
    562         {
    563             IMedium *pMedium;
    564             DeviceType_T deviceType;
    565             nsXPIDLString pMediumUuid;
    566             nsXPIDLString pMediumName;
    567             nsXPIDLString pMediumPath;
    568 
    569             pMediumAttachments[i]->GetType(&deviceType);
    570             if (deviceType == DeviceType_HardDisk)
    571             {
    572                 rc = pMediumAttachments[i]->GetMedium(&pMedium);
    573                 if (NS_SUCCEEDED(rc) && pMedium)
    574                 {
    575                     IMedium *pParent = pMedium;
    576                     IMedium *pEarliestAncestor;
    577                     while (pParent != nsnull)
    578                     {
    579                         pEarliestAncestor = pParent;
    580                         pParent->GetParent(&pParent);
    581                     }
    582                     PRUint32 cChildren = 1;
    583                     IMedium **aMediumChildren = nsnull;
    584                     IMedium *pChild = pEarliestAncestor;
    585                     uint32_t ancestorNumber = 0;
    586                     RTPrintf("\n");
    587                     do
    588                     {
    589                         rc = pChild->GetName(getter_Copies(pMediumName));
    590                         if (NS_FAILED(rc))
    591                              return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: "
    592                                 "Couldn't access pMedium name rc=%#x\n", rc);
    593 
    594                         rc = pChild->GetId(getter_Copies(pMediumUuid));
    595                         if (NS_FAILED(rc))
    596                              return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: "
    597                                 "Couldn't access pMedium ID rc=%#x\n", rc);
    598 
    599                         rc = pChild->GetLocation(getter_Copies(pMediumPath));
    600                         if (NS_FAILED(rc))
    601                              return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: "
    602                                 "Couldn't access pMedium location rc=%#x\n", rc);
    603 
    604                         const char *pszMediumName = ToNewCString(pMediumName);
    605                         const char *pszMediumUuid = ToNewCString(pMediumUuid);
    606                         const char *pszMediumPath = ToNewCString(pMediumPath);
    607 
    608                         if (ancestorNumber == 0)
    609                         {
    610                             RTPrintf("   -----------------------\n");
    611                             RTPrintf("   HDD base:   \"%s\"\n",   pszMediumName);
    612                             RTPrintf("   UUID:       %s\n",       pszMediumUuid);
    613                             RTPrintf("   Location:   %s\n\n",     pszMediumPath);
    614                         }
    615                         else
    616                         {
    617                             RTPrintf("     Diff %d:\n", ancestorNumber);
    618                             RTPrintf("          UUID:       %s\n",   pszMediumUuid);
    619                             RTPrintf("          Location:   %s\n\n", pszMediumPath);
    620                         }
    621 
    622                         free((void*)pszMediumName);
    623                         free((void*)pszMediumUuid);
    624                         free((void*)pszMediumPath);
    625 
    626                         rc = pChild->GetChildren(&cChildren, &aMediumChildren);
    627                         if (NS_FAILED(rc))
    628                              return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: "
    629                                 "could not get children of media! rc=%#x\n", rc);
    630 
    631                         pChild = aMediumChildren[0];
    632                         ++ancestorNumber;
    633                     } while(NS_SUCCEEDED(rc) && cChildren);
    634                 }
    635                 pMedium->Release();
    636             }
     669    int rc = 0;
     670    com::SafeIfaceArray<IMediumAttachment> pMediumAttachments;
     671
     672    CHECK_ERROR(pMachine, COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(pMediumAttachments)));
     673    for (size_t i = 0; i < pMediumAttachments.size(); i++)
     674    {
     675        ComPtr<IMedium> pMedium;
     676        DeviceType_T deviceType;
     677        Bstr pMediumUuid;
     678        Bstr pMediumName;
     679        Bstr pMediumPath;
     680
     681        CHECK_ERROR(pMediumAttachments[i], COMGETTER(Type)(&deviceType));
     682
     683        if (deviceType == DeviceType_HardDisk)
     684        {
     685            CHECK_ERROR(pMediumAttachments[i], COMGETTER(Medium)(pMedium.asOutParam()));
     686            if (pMedium.isNull())
     687                return;
     688
     689            MediumState_T state;
     690            CHECK_ERROR(pMedium, COMGETTER(State)(&state));
     691            if (FAILED(rc))
     692                return;
     693            if (state == MediumState_Inaccessible)
     694            {
     695                CHECK_ERROR(pMedium, RefreshState(&state));
     696                if (FAILED(rc))
     697                return;
     698            }
     699
     700            ComPtr<IMedium> pEarliestAncestor;
     701            CHECK_ERROR(pMedium, COMGETTER(Base)(pEarliestAncestor.asOutParam()));
     702            ComPtr<IMedium> pChild = pEarliestAncestor;
     703            uint32_t ancestorNumber = 0;
     704            if (pEarliestAncestor.isNull())
     705                return;
     706            RTPrintf("\n");
     707            do
     708            {
     709                com::SafeIfaceArray<IMedium> aMediumChildren;
     710                CHECK_ERROR(pChild, COMGETTER(Name)(pMediumName.asOutParam()));
     711                CHECK_ERROR(pChild, COMGETTER(Id)(pMediumUuid.asOutParam()));
     712                CHECK_ERROR(pChild, COMGETTER(Location)(pMediumPath.asOutParam()));
     713
     714                if (ancestorNumber == 0)
     715                {
     716                    RTPrintf("   -----------------------\n");
     717                    RTPrintf("   HDD base:   \"%s\"\n",   CSTR(pMediumName));
     718                    RTPrintf("   UUID:       %s\n",       CSTR(pMediumUuid));
     719                    RTPrintf("   Location:   %s\n\n",     CSTR(pMediumPath));
     720                }
     721                else
     722                {
     723                    RTPrintf("     Diff %d:\n", ancestorNumber);
     724                    RTPrintf("          UUID:       %s\n",    CSTR(pMediumUuid));
     725                    RTPrintf("          Location:   %s\n\n",  CSTR(pMediumPath));
     726                }
     727                CHECK_ERROR_BREAK(pChild, COMGETTER(Children)(ComSafeArrayAsOutParam(aMediumChildren)));
     728                pChild = (aMediumChildren.size()) ? aMediumChildren[0] : NULL;
     729                ++ancestorNumber;
     730            } while(pChild);
    637731        }
    638732    }
    639     return rc;
    640 
    641733}
    642734/**
     
    645737 * @param virtualBox VirtualBox instance object.
    646738 */
    647 static int
    648 listVMs(IVirtualBox *virtualBox)
    649 {
    650     IMachine **ppMachines = NULL;
    651     PRUint32 cMachines = 0;
    652     nsresult rc;
    653 
    654     rc = virtualBox->GetMachines(&cMachines, &ppMachines);
    655     if (NS_SUCCEEDED(rc))
    656     {
    657         for (PRUint32 i = 0; i < cMachines; ++ i)
    658         {
    659             IMachine *pMachine = ppMachines[i];
    660             if (pMachine)
    661             {
    662                 PRBool isAccessible = PR_FALSE;
    663                 pMachine->GetAccessible(&isAccessible);
    664 
    665                 if (isAccessible)
    666                 {
    667                     nsXPIDLString pMachineUuid;
    668                     nsXPIDLString pMachineName;
    669                     nsXPIDLString pMachinePath;
    670 
    671                     rc = pMachine->GetName(getter_Copies(pMachineName));
    672                     if (NS_FAILED(rc))
    673                          return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: "
    674                             "Couldn't access pMachine name rc=%#x\n", rc);
    675 
    676                     rc = pMachine->GetId(getter_Copies(pMachineUuid));
    677                     if (NS_FAILED(rc))
    678                          return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: "
    679                             "Couldn't access pMachine Id rc=%#x\n", rc);
    680 
    681                     rc = pMachine->GetStateFilePath(getter_Copies(pMachinePath));
    682                     if (NS_FAILED(rc))
    683                          return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: "
    684                             "Couldn't access pMachine Location rc=%#x\n", rc);
    685 
    686                     const char *pszMachineName = ToNewCString(pMachineName);
    687                     const char *pszMachineUuid = ToNewCString(pMachineUuid);
    688                     const char *pszMachinePath = ToNewCString(pMachinePath);
    689 
    690                     if (   g_vboxrawOpts.pszVm == NULL
    691                         || RTStrNCmp(pszMachineUuid, g_vboxrawOpts.pszVm, MAX_ID_LEN) == 0
    692                         || RTStrNCmp(pszMachineName, g_vboxrawOpts.pszVm, MAX_ID_LEN) == 0)
    693                     {
    694                         RTPrintf("------------------------------------------------------\n");
    695                         RTPrintf("VM Name:   \"%s\"\n", pszMachineName);
    696                         RTPrintf("UUID:      %s\n",     pszMachineUuid);
    697                         RTPrintf("Location:  %s\n",     pszMachinePath);
    698 
    699                         rc = listMedia(pMachine);
    700                         if (NS_FAILED(rc))
    701                             return rc;
    702 
    703                         RTPrintf("\n");
    704                     }
    705                     free((void *)pszMachineUuid);
    706                     free((void *)pszMachineName);
    707                     free((void *)pszMachinePath);
    708                 }
    709                 pMachine->Release();
     739static void
     740listVMs(IVirtualBox *pVirtualBox)
     741{
     742    HRESULT rc = 0;
     743    com::SafeIfaceArray<IMachine> pMachines;
     744    CHECK_ERROR(pVirtualBox, COMGETTER(Machines)(ComSafeArrayAsOutParam(pMachines)));
     745    for (size_t i = 0; i < pMachines.size(); ++i)
     746    {
     747        ComPtr<IMachine> pMachine = pMachines[i];
     748        if (pMachine)
     749        {
     750            BOOL fAccessible;
     751            CHECK_ERROR(pMachines[i], COMGETTER(Accessible)(&fAccessible));
     752            if (fAccessible)
     753            {
     754                Bstr pMachineName;
     755                Bstr pMachineUuid;
     756                Bstr pDescription;
     757                Bstr pMachineLocation;
     758
     759                CHECK_ERROR(pMachine, COMGETTER(Name)(pMachineName.asOutParam()));
     760                CHECK_ERROR(pMachine, COMGETTER(Id)(pMachineUuid.asOutParam()));
     761                CHECK_ERROR(pMachine, COMGETTER(Description)(pDescription.asOutParam()));
     762                CHECK_ERROR(pMachine, COMGETTER(SettingsFilePath)(pMachineLocation.asOutParam()));
     763
     764                if (   g_vboxrawOpts.pszVm == NULL
     765                    || RTStrNCmp(CSTR(pMachineUuid), g_vboxrawOpts.pszVm, MAX_ID_LEN) == 0
     766                    || RTStrNCmp((const char *)pMachineName.raw(), g_vboxrawOpts.pszVm, MAX_ID_LEN) == 0)
     767                {
     768                    RTPrintf("------------------------------------------------------\n");
     769                    RTPrintf("VM Name:   \"%s\"\n", CSTR(pMachineName));
     770                    RTPrintf("UUID:      %s\n",     CSTR(pMachineUuid));
     771                    if (*pDescription.raw() != '\0')
     772                        RTPrintf("Description:  %s\n",      CSTR(pDescription));
     773                    RTPrintf("Location:  %s\n",      CSTR(pMachineLocation));
     774
     775                    listMedia(pMachine);
     776
     777                    RTPrintf("\n");
     778                }
    710779            }
    711780        }
    712781    }
    713     return rc;
    714 }
    715 
    716 static int
    717 searchForBaseImage(IVirtualBox *virtualBox, char *pszImageString, IMedium **baseImage)
    718 {
    719     PRUint32 cDisks;
    720     IMedium **ppDisks;
    721 
    722     nsresult rc = virtualBox->GetHardDisks(&cDisks, &ppDisks);
    723     if (NS_SUCCEEDED(rc))
    724     {
    725         for (PRUint32 i = 0; i < cDisks && ppDisks[i]; i++)
    726         {
    727             if (ppDisks[i])
    728             {
    729                 nsXPIDLString pMediumUuid;
    730                 nsXPIDLString pMediumName;
    731 
    732                 rc = ppDisks[i]->GetName(getter_Copies(pMediumName));
    733                 if (NS_FAILED(rc))
    734                      return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: "
    735                         "Couldn't access pMedium name rc=%#x\n", rc);
    736 
    737                 rc = ppDisks[i]->GetId(getter_Copies(pMediumUuid));
    738                 if (NS_FAILED(rc))
    739                      return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: "
    740                         "Couldn't access pMedium Id rc=%#x\n", rc);
    741 
    742                 const char *pszMediumName = ToNewCString(pMediumName);
    743                 const char *pszMediumUuid = ToNewCString(pMediumUuid);
    744 
    745                 if (   RTStrCmp(pszImageString, pszMediumUuid) == 0
    746                     || RTStrCmp(pszImageString, pszMediumName) == 0)
    747                 {
    748                     *baseImage = ppDisks[i];
    749                     free((void*)pszMediumUuid);
    750                     free((void*)pszMediumName);
    751                     return rc;
    752                 }
    753                 ppDisks[i]->Release();
    754                 free((void*)pszMediumUuid);
    755                 free((void*)pszMediumName);
     782}
     783
     784static void
     785searchForBaseImage(IVirtualBox *pVirtualBox, char *pszImageString, ComPtr<IMedium> *pBaseImage)
     786{
     787    int rc = 0;
     788    com::SafeIfaceArray<IMedium> aDisks;
     789
     790    CHECK_ERROR(pVirtualBox, COMGETTER(HardDisks)(ComSafeArrayAsOutParam(aDisks)));
     791    for (size_t i = 0; i < aDisks.size() && aDisks[i]; i++)
     792    {
     793        if (aDisks[i])
     794        {
     795            Bstr pMediumUuid;
     796            Bstr pMediumName;
     797
     798            CHECK_ERROR(aDisks[i], COMGETTER(Name)(pMediumName.asOutParam()));
     799            CHECK_ERROR(aDisks[i], COMGETTER(Id)(pMediumUuid.asOutParam()));
     800
     801            if (   RTStrCmp(pszImageString, CSTR(pMediumUuid)) == 0
     802                || RTStrCmp(pszImageString, CSTR(pMediumName)) == 0)
     803            {
     804                *pBaseImage = aDisks[i];
     805                return;
    756806            }
    757807        }
    758808    }
    759     return rc;
    760809}
    761810
     
    780829    g_vboxrawOps.readdir     = vboxrawOp_readdir;
    781830    g_vboxrawOps.readlink    = vboxrawOp_readlink;
    782 
    783831    struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
    784832
     
    786834
    787835    rc = fuse_opt_parse(&args, &g_vboxrawOpts, vboxrawOptDefs, vboxrawOptHandler);
     836    if (g_vboxrawOpts.fAllowRoot)
     837        fuse_opt_add_arg(&args, "-oallow_root");
     838
    788839    if (rc == -1)
    789840        return RTMsgErrorExitFailure("vboxraw: ERROR: Couldn't parse fuse options, rc=%Rrc\n", rc);
    790841
    791842    /*
    792      * Initialize XPCOM to so we can use the API
     843     * Initialize COM.
    793844     */
    794     rc = NS_InitXPCOM2(getter_AddRefs(g_XPCOM.serviceManager), nsnull, nsnull);
    795     if (NS_FAILED(rc))
    796          return RTMsgErrorExitFailure("vboxraw: ERROR: "
    797             "XPCOM could not be initialized! rc=%#x\n", rc);
    798 
    799     rc = NS_GetMainEventQ(getter_AddRefs(g_XPCOM.eventQ));
    800     if (NS_FAILED(rc))
    801          return RTMsgErrorExitFailure("vboxraw: ERROR: "
    802             "could not get main event queue! rc=%#x\n", rc);
    803 
    804     rc = NS_GetComponentManager(getter_AddRefs(g_XPCOM.manager));
    805     if (NS_FAILED(rc))
    806          return RTMsgErrorExitFailure("vboxraw: ERROR: "
    807             "couldn't get the component manager! rc=%#x\n", rc);
    808 
    809     rc = g_XPCOM.manager->CreateInstanceByContractID(NS_VIRTUALBOX_CONTRACTID,
    810                                              nsnull,
    811                                              NS_GET_IID(IVirtualBox),
    812                                              getter_AddRefs(g_XPCOM.virtualBox));
    813     if (NS_FAILED(rc))
    814          return RTMsgErrorExitFailure("vboxraw: ERROR: "
    815             "could not instantiate VirtualBox object! rc=%#x\n", rc);
     845    using namespace com;
     846    HRESULT hrc = com::Initialize();
     847    if (FAILED(hrc))
     848    {
     849# ifdef VBOX_WITH_XPCOM
     850        if (hrc == NS_ERROR_FILE_ACCESS_DENIED)
     851        {
     852            char szHome[RTPATH_MAX] = "";
     853            com::GetVBoxUserHomeDirectory(szHome, sizeof(szHome));
     854            return RTMsgErrorExit(RTEXITCODE_FAILURE,
     855                   "Failed to initialize COM because the global settings directory '%s' is not accessible!", szHome);
     856        }
     857# endif
     858            return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to initialize COM! (hrc=%Rhrc)", hrc);
     859    }
     860
     861    /*
     862     * Get the remote VirtualBox object and create a local session object.
     863     */
     864    ComPtr<IVirtualBoxClient> pVirtualBoxClient;
     865    ComPtr<IVirtualBox> pVirtualBox;
     866
     867    hrc = pVirtualBoxClient.createInprocObject(CLSID_VirtualBoxClient);
     868    if (SUCCEEDED(hrc))
     869        hrc = pVirtualBoxClient->COMGETTER(VirtualBox)(pVirtualBox.asOutParam());
     870    if (FAILED(hrc))
     871         return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to get IVirtualBox object! (hrc=%Rhrc)", hrc);
    816872
    817873    if (g_vboxrawOpts.fVerbose)
     
    819875
    820876    if (g_vboxrawOpts.fList)
    821         return listVMs(g_XPCOM.virtualBox);
     877    {
     878         listVMs(pVirtualBox);
     879         return 0;
     880    }
    822881
    823882    if (g_vboxrawOpts.pszImage == NULL)
     883    {
    824884            RTMsgErrorExitFailure("vboxraw: ERROR: "
    825885                "Must provide at at least --list or --image option\n");
    826 
    827     IMedium *pBaseImageMedium = NULL;
     886            return 0;
     887    }
     888    ComPtr<IMedium> pBaseImageMedium = NULL;
    828889    char    *pszFormat;
    829890    VDTYPE  enmType;
    830891
    831     rc = searchForBaseImage(g_XPCOM.virtualBox, g_vboxrawOpts.pszImage, &pBaseImageMedium);
    832     if (NS_FAILED(rc))
    833         RTMsgErrorExitFailure("vboxraw: ERROR: "
    834             "Couldn't locate base image \"%s\"\n", g_vboxrawOpts.pszImage);
    835 
     892    searchForBaseImage(pVirtualBox, g_vboxrawOpts.pszImage, &pBaseImageMedium);
    836893    if (pBaseImageMedium == NULL)
    837894    {
     
    844901            return cbNameMax;
    845902
    846         char *pszBounceA = (char *)RTMemAlloc(cbNameMax + 1);
    847         if (!pszBounceA)
    848             return VERR_NO_MEMORY;
    849         memset(pszBounceA, 0, cbNameMax + 1);
    850 
    851         char *pszBounceB = (char *)RTMemAlloc(cbNameMax + 1);
    852         if (!pszBounceB)
    853             return VERR_NO_MEMORY;
    854         memset(pszBounceB, 0, cbNameMax + 1);
    855 
    856         RTStrCopy(pszBounceA, cbNameMax, g_vboxrawOpts.pszImage);
    857         while (readlink(pszBounceA, pszBounceB, cbNameMax) >= 0)
    858             RTStrCopy(pszBounceA, cbNameMax, pszBounceB);
    859 
    860         free(g_vboxrawOpts.pszImage);
    861 
    862         g_pszBaseImagePath = RTStrDup(pszBounceA);
     903        g_pszBaseImagePath = RTStrDup(g_vboxrawOpts.pszImage);
    863904        if (g_pszBaseImagePath == NULL)
    864905            return RTMsgErrorExitFailure("vboxraw: out of memory\n");
    865 
    866         RTMemFree(pszBounceA);
    867         RTMemFree(pszBounceB);
    868906
    869907        if (access(g_pszBaseImagePath, F_OK) < 0)
     
    875913                    "Virtual disk image not readable: \"%s\"\n", g_pszBaseImagePath);
    876914
    877         if ( g_vboxrawOpts.fWriteable && access(g_vboxrawOpts.pszImage, W_OK) < 0)
     915        if ( g_vboxrawOpts.fRW && access(g_vboxrawOpts.pszImage, W_OK) < 0)
    878916             return RTMsgErrorExitFailure("vboxraw: ERROR: "
    879917                    "Virtual disk image not writeable: \"%s\"\n", g_pszBaseImagePath);
     
    889927
    890928        g_pszBaseImageName = g_u.split.apszComps[g_u.split.cComps - 1];
    891         rc = searchForBaseImage(g_XPCOM.virtualBox, g_pszBaseImageName, &pBaseImageMedium);
     929        searchForBaseImage(pVirtualBox, g_pszBaseImageName, &pBaseImageMedium);
    892930
    893931        if (pBaseImageMedium == NULL)
     
    923961    if (g_pVDisk == NULL)
    924962    {
    925         IMedium **aMediumChildren = nsnull;
    926         IMedium *pChild = pBaseImageMedium;
    927         PRUint32 cChildren;
     963        com::SafeIfaceArray<IMedium> aMediumChildren;
     964        ComPtr<IMedium> pChild = pBaseImageMedium;
    928965        uint32_t diffNumber = 0; /* diff # 0 = base image */
    929 
    930966        do
    931967        {
    932             nsXPIDLString pMediumUuid;
    933             nsXPIDLString pMediumName;
    934             nsXPIDLString pMediumPath;
    935 
    936             rc = pChild->GetName(getter_Copies(pMediumName));
    937             if (NS_FAILED(rc))
    938                  return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: "
    939                     "Couldn't access pMedium name rc=%#x\n", rc);
    940 
    941             rc = pChild->GetId(getter_Copies(pMediumUuid));
    942             if (NS_FAILED(rc))
    943                  return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: "
    944                     "Couldn't access pMedium ID rc=%#x\n", rc);
    945 
    946             rc = pChild->GetLocation(getter_Copies(pMediumPath));
    947             if (NS_FAILED(rc))
    948                  return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: "
    949                     "Couldn't access pMedium location rc=%#x\n", rc);
    950 
    951             const char *pszMediumName = ToNewCString(pMediumName);
    952             const char *pszMediumUuid = ToNewCString(pMediumUuid);
    953             const char *pszMediumPath = ToNewCString(pMediumPath);
     968            Bstr pMediumName;
     969            Bstr pMediumPath;
     970
     971            CHECK_ERROR(pChild, COMGETTER(Name)(pMediumName.asOutParam()));
     972            CHECK_ERROR(pChild, COMGETTER(Location)(pMediumPath.asOutParam()));
    954973
    955974            if (pChild == pBaseImageMedium)
    956975            {
    957976                free((void *)g_pszBaseImageName);
    958                 g_pszBaseImageName = RTStrDup(pszMediumName);
     977                g_pszBaseImageName = RTStrDup(CSTR(pMediumName));
    959978
    960979                free((void *)g_pszBaseImagePath);
    961                 g_pszBaseImagePath = RTStrDup(pszMediumPath);
    962 
    963                 free((void *)pszMediumUuid);
    964                 free((void *)pszMediumName);
    965 
     980                g_pszBaseImagePath = RTStrDup(CSTR(pMediumPath));
    966981                if (g_pszBaseImageName == NULL)
    967982                    return RTMsgErrorExitFailure("vboxraw: out of memory\n");
     
    977992                    return RTMsgErrorExitFailure("vboxraw: VDGetFormat(,,%s,,) "
    978993                        "failed (during HDD container creation), rc=%Rrc\n", g_pszBaseImagePath, rc);
    979 
    980994                if (g_vboxrawOpts.fVerbose)
    981995                    RTPrintf("vboxraw: Creating container for base image of format %s\n", pszFormat);
     
    9861000                    return RTMsgErrorExitFailure("vboxraw: ERROR: Couldn't create virtual disk container\n");
    9871001            }
    988             else
    989             {
    990                 free((void *)pszMediumUuid);
    991                 free((void *)pszMediumName);
    992             }
    9931002            if ( g_vboxrawOpts.cHddImageDiffMax != 0 && diffNumber > g_vboxrawOpts.cHddImageDiffMax)
    9941003                break;
     
    9981007                if (diffNumber == 0)
    9991008                    RTPrintf("\nvboxraw: Opening base image into container:\n       %s\n",
    1000                         pszMediumPath);
     1009                        g_pszBaseImagePath);
    10011010                else
    10021011                    RTPrintf("\nvboxraw: Opening difference image #%d into container:\n       %s\n",
    1003                         diffNumber, pszMediumPath);
    1004             }
    1005 
    1006             rc = VDOpen(g_pVDisk, pszFormat, pszMediumPath, 0, NULL /* pVDIfsImage */);
     1012                        diffNumber, g_pszBaseImagePath);
     1013            }
     1014
     1015            rc = VDOpen(g_pVDisk, pszFormat, g_pszBaseImagePath, 0, NULL /* pVDIfsImage */);
    10071016            if (RT_FAILURE(rc))
    10081017            {
    10091018                VDClose(g_pVDisk, false /* fDeletes */);
    1010                 free((void *)pszMediumPath);
    1011                 return RTMsgErrorExitFailure("vboxraw: VDOpen(,,%s,,) failed, rc=%Rrc\n", pszMediumPath, rc);
    1012             }
    1013 
    1014             rc = pChild->GetChildren(&cChildren, &aMediumChildren);
    1015             if (NS_FAILED(rc))
    1016             {
    1017                 free((void *)pszMediumPath);
    1018                 return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: "
    1019                     "Couldn't get children of medium, rc=%Rrc\n", pszMediumPath, rc);
    1020             }
    1021 
    1022             pChild = aMediumChildren[0];
     1019                return RTMsgErrorExitFailure("vboxraw: VDOpen(,,%s,,) failed, rc=%Rrc\n",
     1020                   g_pszBaseImagePath, rc);
     1021            }
     1022
     1023            CHECK_ERROR(pChild, COMGETTER(Children)(ComSafeArrayAsOutParam(aMediumChildren)));
     1024
     1025            if (aMediumChildren.size() != 0) {
     1026                pChild = aMediumChildren[0];
     1027            }
     1028
     1029            aMediumChildren.setNull();
     1030
    10231031            ++diffNumber;
    1024             free((void *)pszMediumPath);
    1025 
    1026 
    1027         } while(NS_SUCCEEDED(rc) && cChildren);
     1032
     1033
     1034        } while(NS_SUCCEEDED(rc) && aMediumChildren.size());
    10281035    }
    10291036
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