VirtualBox

Ignore:
Timestamp:
Nov 8, 2017 1:58:58 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
118976
Message:

DVM: Got a working pseudo vfs.

It's now possible to do stuff like:

RTLs -la :iprtvfs:file(vd,d:\VMs\DosVM\DOS.vmdk,ro):vfs(dvm)
RTLs -la :iprtvfs:file(vd,d:\VMs\DosVM\DOS.vmdk,ro):vfs(dvm):file(open,vol0):vfs(fat):/

Location:
trunk/src/VBox/Runtime/common/dvm
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/dvm/dvm.cpp

    r69609 r69616  
    376376    {
    377377        PCRTDVMFMTOPS pDvmFmtOps = g_aDvmFmts[i];
    378         if (!RTStrCmp(pDvmFmtOps->pcszFmt, pszFmt))
     378        if (!RTStrCmp(pDvmFmtOps->pszFmt, pszFmt))
    379379        {
    380380            int rc = pDvmFmtOps->pfnInitialize(&pThis->DvmDisk, &pThis->hVolMgrFmt);
     
    387387}
    388388
    389 RTDECL(const char *) RTDvmMapGetFormat(RTDVM hVolMgr)
     389RTDECL(const char *) RTDvmMapGetFormatName(RTDVM hVolMgr)
    390390{
    391391    PRTDVMINTERNAL pThis = hVolMgr;
     
    394394    AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, NULL);
    395395
    396     return pThis->pDvmFmtOps->pcszFmt;
     396    return pThis->pDvmFmtOps->pszFmt;
     397}
     398
     399RTDECL(RTDVMFORMATTYPE) RTDvmMapGetFormatType(RTDVM hVolMgr)
     400{
     401    PRTDVMINTERNAL pThis = hVolMgr;
     402    AssertPtrReturn(pThis, RTDVMFORMATTYPE_INVALID);
     403    AssertReturn(pThis->u32Magic == RTDVM_MAGIC, RTDVMFORMATTYPE_INVALID);
     404    AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, RTDVMFORMATTYPE_INVALID);
     405
     406    return pThis->pDvmFmtOps->enmFormat;
    397407}
    398408
     
    419429RTDECL(int) RTDvmMapQueryFirstVolume(RTDVM hVolMgr, PRTDVMVOLUME phVol)
    420430{
    421     int rc = VERR_DVM_MAP_EMPTY;
    422431    PRTDVMINTERNAL pThis = hVolMgr;
    423432    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     
    426435    AssertPtrReturn(phVol, VERR_INVALID_POINTER);
    427436
     437    int rc = VERR_DVM_MAP_EMPTY;
    428438    PRTDVMVOLUMEINTERNAL pVol = RTListGetFirst(&pThis->VolumeList, RTDVMVOLUMEINTERNAL, VolumeNode);
    429439    if (pVol)
  • trunk/src/VBox/Runtime/common/dvm/dvmbsdlabel.cpp

    r69609 r69616  
    521521    /* pcszFmt */
    522522    "BsdLabel",
     523    /* enmFormat, */
     524    RTDVMFORMATTYPE_BSD_LABLE,
    523525    /* pfnProbe */
    524526    rtDvmFmtBsdLblProbe,
  • trunk/src/VBox/Runtime/common/dvm/dvmgpt.cpp

    r69609 r69616  
    514514RTDVMFMTOPS g_rtDvmFmtGpt =
    515515{
    516     /* pcszFmt */
     516    /* pszFmt */
    517517    "GPT",
     518    /* enmFormat, */
     519    RTDVMFORMATTYPE_GPT,
    518520    /* pfnProbe */
    519521    rtDvmFmtGptProbe,
  • trunk/src/VBox/Runtime/common/dvm/dvmmbr.cpp

    r69111 r69616  
    401401RTDVMFMTOPS g_rtDvmFmtMbr =
    402402{
    403     /* pcszFmt */
     403    /* pszFmt */
    404404    "MBR",
     405    /* enmFormat */
     406    RTDVMFORMATTYPE_MBR,
    405407    /* pfnProbe */
    406408    rtDvmFmtMbrProbe,
  • trunk/src/VBox/Runtime/common/dvm/dvmvfs.cpp

    r69610 r69616  
    4848*   Structures and Typedefs                                                                                                      *
    4949*********************************************************************************************************************************/
    50 
    51 /**
    52  * The internal data of a DVM volume I/O stream.
    53  */
    54 typedef struct RTVFSDVMFILE
    55 {
    56     /** The volume the VFS file belongs to. */
    57     RTDVMVOLUME    hVol;
    58     /** Current position. */
    59     uint64_t       offCurPos;
    60 } RTVFSDVMFILE;
    61 /** Pointer to a the internal data of a DVM volume file. */
    62 typedef RTVFSDVMFILE *PRTVFSDVMFILE;
    63 
    6450/**
    6551 * A volume manager VFS for use in chains (thing pseudo/devfs).
     
    6854{
    6955    /** The volume manager. */
    70     RTDVM       hVolMgr;
     56    RTDVM           hVolMgr;
    7157    /** Whether to close it on success. */
    72     bool        fCloseDvm;
     58    bool            fCloseDvm;
    7359    /** Whether the access is read-only. */
    74     bool        fReadOnly;
     60    bool            fReadOnly;
    7561    /** Number of volumes. */
    76     uint32_t    cVolumes;
     62    uint32_t        cVolumes;
     63    /** Self reference. */
     64    RTVFS           hVfsSelf;
    7765} RTDVMVFSVOL;
    7866/** Poitner to a volume manager VFS. */
     
    8068
    8169/**
    82  * The volume manager VFS root dir data.
    83  */
    84 typedef struct RTDVMVFSROOTDIR
     70 * The volume manager VFS (root) dir data.
     71 */
     72typedef struct RTDVMVFSDIR
    8573{
    8674    /** Pointer to the VFS volume. */
     
    8876    /** The current directory offset. */
    8977    uint32_t        offDir;
    90 } RTDVMVFSROOTDIR;
    91 /** Poitner to a volume manager VFS root dir. */
    92 typedef RTDVMVFSROOTDIR *PRTDVMVFSROOTDIR;
     78    /** Set if we need to try return hCurVolume again because of buffer overflow. */
     79    bool            fReturnCurrent;
     80    /** The current DVM volume. */
     81    RTDVMVOLUME     hCurVolume;
     82} RTDVMVFSDIR;
     83/** Poitner to a volume manager VFS (root) dir. */
     84typedef RTDVMVFSDIR *PRTDVMVFSDIR;
     85
     86/**
     87 * The internal data of a DVM volume I/O stream.
     88 */
     89typedef struct RTVFSDVMFILE
     90{
     91    /** The volume the VFS file belongs to. */
     92    RTDVMVOLUME     hVol;
     93    /** Pointer to the VFS volume.  Can be NULL. */
     94    PRTDVMVFSVOL    pVfsVol;
     95    /** Current position. */
     96    uint64_t        offCurPos;
     97    /** Set if readable. */
     98    bool            fCanRead;
     99    /** Set if writable. */
     100    bool            fCanWrite;
     101} RTVFSDVMFILE;
     102/** Pointer to a the internal data of a DVM volume file. */
     103typedef RTVFSDVMFILE *PRTVFSDVMFILE;
    93104
    94105
     
    106117
    107118/**
     119 * Worker for rtDvmVfsFile_QueryInfo, rtDvmVfsDir_QueryEntryInfo, and
     120 * rtDvmVfsDir_ReadDir.
     121 */
     122static int rtDvmVfsFile_QueryInfoWorker(RTDVMVOLUME hVolume, RTDVM hVolMgr, bool fReadOnly,
     123                                        PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
     124{
     125
     126    pObjInfo->cbObject    = RTDvmVolumeGetSize(hVolume);
     127    pObjInfo->cbAllocated = pObjInfo->cbObject;
     128    RTTimeSpecSetNano(&pObjInfo->AccessTime, 0);
     129    RTTimeSpecSetNano(&pObjInfo->ModificationTime, 0);
     130    RTTimeSpecSetNano(&pObjInfo->ChangeTime, 0);
     131    RTTimeSpecSetNano(&pObjInfo->BirthTime, 0);
     132    pObjInfo->Attr.fMode = RTFS_TYPE_FILE | RTFS_DOS_NT_NORMAL;
     133    if (fReadOnly)
     134        pObjInfo->Attr.fMode |= RTFS_DOS_READONLY | 0444;
     135    else
     136        pObjInfo->Attr.fMode |= 0666;
     137
     138    switch (enmAddAttr)
     139    {
     140        case RTFSOBJATTRADD_NOTHING:
     141        case RTFSOBJATTRADD_UNIX:
     142            pObjInfo->Attr.u.Unix.uid           = (RTUID)RTDvmVolumeGetType(hVolume);
     143            pObjInfo->Attr.u.Unix.gid           = hVolMgr != NIL_RTDVM ? (RTGID)RTDvmMapGetFormatType(hVolMgr) : NIL_RTGID;
     144            pObjInfo->Attr.u.Unix.cHardlinks    = 1;
     145            pObjInfo->Attr.u.Unix.INodeIdDevice = 0;
     146            pObjInfo->Attr.u.Unix.INodeId       = 0;
     147            pObjInfo->Attr.u.Unix.fFlags        = 0;
     148            pObjInfo->Attr.u.Unix.GenerationId  = 0;
     149            pObjInfo->Attr.u.Unix.Device        = 0;
     150            break;
     151
     152        case RTFSOBJATTRADD_UNIX_OWNER:
     153        {
     154            RTDVMVOLTYPE enmType = RTDvmVolumeGetType(hVolume);
     155            pObjInfo->Attr.u.UnixOwner.uid = (RTUID)enmType;
     156            RTStrCopy(pObjInfo->Attr.u.UnixOwner.szName, sizeof(pObjInfo->Attr.u.UnixOwner.szName),
     157                      RTDvmVolumeTypeGetDescr(enmType));
     158            break;
     159        }
     160
     161        case RTFSOBJATTRADD_UNIX_GROUP:
     162            if (hVolMgr != NIL_RTDVM)
     163            {
     164                pObjInfo->Attr.u.UnixGroup.gid  = (RTGID)RTDvmMapGetFormatType(hVolMgr);
     165                RTStrCopy(pObjInfo->Attr.u.UnixGroup.szName, sizeof(pObjInfo->Attr.u.UnixGroup.szName),
     166                          RTDvmMapGetFormatName(hVolMgr));
     167            }
     168            else
     169            {
     170                pObjInfo->Attr.u.UnixGroup.gid  = NIL_RTGID;
     171                pObjInfo->Attr.u.UnixGroup.szName[0] = '\0';
     172            }
     173            break;
     174
     175        case RTFSOBJATTRADD_EASIZE:
     176            pObjInfo->Attr.u.EASize.cb = 0;
     177            break;
     178
     179        default:
     180            return VERR_INVALID_PARAMETER;
     181    }
     182    return VINF_SUCCESS;
     183}
     184
     185
     186/**
    108187 * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
    109188 */
    110189static DECLCALLBACK(int) rtDvmVfsFile_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
    111190{
    112     NOREF(pvThis);
    113     NOREF(pObjInfo);
    114     NOREF(enmAddAttr);
    115     return VERR_NOT_SUPPORTED;
     191    PRTVFSDVMFILE pThis = (PRTVFSDVMFILE)pvThis;
     192    return rtDvmVfsFile_QueryInfoWorker(pThis->hVol,
     193                                        pThis->pVfsVol ? pThis->pVfsVol->hVolMgr   : NIL_RTDVM,
     194                                        pThis->pVfsVol ? pThis->pVfsVol->fReadOnly : !pThis->fCanWrite,
     195                                        pObjInfo, enmAddAttr);
    116196}
    117197
     
    417497
    418498
    419 RTDECL(int) RTDvmVolumeCreateVfsFile(RTDVMVOLUME hVol, PRTVFSFILE phVfsFileOut)
     499/**
     500 * Internal worker for RTDvmVolumeCreateVfsFile and rtDvmVfsDir_OpenFile.
     501 *
     502 * @returns IPRT status code.
     503 * @param   pVfsVol         The VFS volume, optional.
     504 * @param   hVol            The volume handle. (Reference not consumed.)
     505 * @param   fOpen           RTFILE_O_XXX (valid).
     506 * @param   phVfsFileOut    Where to return the handle to the file.
     507 */
     508static int rtDvmVfsCreateFileForVolume(PRTDVMVFSVOL pVfsVol, RTDVMVOLUME hVol, uint64_t fOpen, PRTVFSFILE phVfsFileOut)
     509{
     510    uint32_t cRefs = RTDvmVolumeRetain(hVol);
     511    AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE);
     512
     513    /*
     514     * Create the volume file.
     515     */
     516    RTVFSFILE       hVfsFile;
     517    PRTVFSDVMFILE   pThis;
     518    int rc = RTVfsNewFile(&g_rtDvmVfsStdFileOps, sizeof(*pThis), fOpen, NIL_RTVFS, NIL_RTVFSLOCK, &hVfsFile, (void **)&pThis);
     519    if (RT_SUCCESS(rc))
     520    {
     521        pThis->offCurPos = 0;
     522        pThis->hVol      = hVol;
     523        pThis->fCanRead  = RT_BOOL(fOpen & RTFILE_O_READ);
     524        pThis->fCanWrite = RT_BOOL(fOpen & RTFILE_O_WRITE);
     525        pThis->pVfsVol   = pVfsVol;
     526
     527        *phVfsFileOut = hVfsFile;
     528        return VINF_SUCCESS;
     529    }
     530
     531    RTDvmVolumeRelease(hVol);
     532    return rc;
     533}
     534
     535
     536RTDECL(int) RTDvmVolumeCreateVfsFile(RTDVMVOLUME hVol, uint64_t fOpen, PRTVFSFILE phVfsFileOut)
    420537{
    421538    AssertPtrReturn(hVol, VERR_INVALID_HANDLE);
    422539    AssertPtrReturn(phVfsFileOut, VERR_INVALID_POINTER);
    423 
    424     uint32_t cRefs = RTDvmVolumeRetain(hVol);
    425     AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE);
    426 
    427     /*
    428      * Create the volume file.
    429      */
    430     RTVFSFILE       hVfsFile;
    431     PRTVFSDVMFILE   pThis;
    432     int rc = RTVfsNewFile(&g_rtDvmVfsStdFileOps, sizeof(*pThis), RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_WRITE,
    433                           NIL_RTVFS, NIL_RTVFSLOCK, &hVfsFile, (void **)&pThis);
     540    AssertReturn(fOpen & RTFILE_O_ACCESS_MASK, VERR_INVALID_FLAGS);
     541    AssertReturn(!(fOpen & ~RTFILE_O_VALID_MASK), VERR_INVALID_FLAGS);
     542    return rtDvmVfsCreateFileForVolume(NULL, hVol, fOpen, phVfsFileOut);
     543}
     544
     545
     546/**
     547 * @interface_method_impl{RTVFSOBJOPS,pfnClose}
     548 */
     549static DECLCALLBACK(int) rtDvmVfsDir_Close(void *pvThis)
     550{
     551    PRTDVMVFSDIR pThis = (PRTDVMVFSDIR)pvThis;
     552
     553    if (pThis->hCurVolume != NIL_RTDVMVOLUME)
     554    {
     555        RTDvmVolumeRelease(pThis->hCurVolume);
     556        pThis->hCurVolume = NIL_RTDVMVOLUME;
     557    }
     558
     559    pThis->pVfsVol = NULL;
     560
     561    return VINF_SUCCESS;
     562}
     563
     564
     565/**
     566 * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
     567 */
     568static DECLCALLBACK(int) rtDvmVfsDir_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
     569{
     570    PRTDVMVFSDIR pThis = (PRTDVMVFSDIR)pvThis;
     571    pObjInfo->cbObject    = pThis->pVfsVol->cVolumes;
     572    pObjInfo->cbAllocated = pThis->pVfsVol->cVolumes;
     573    RTTimeSpecSetNano(&pObjInfo->AccessTime, 0);
     574    RTTimeSpecSetNano(&pObjInfo->ModificationTime, 0);
     575    RTTimeSpecSetNano(&pObjInfo->ChangeTime, 0);
     576    RTTimeSpecSetNano(&pObjInfo->BirthTime, 0);
     577    pObjInfo->Attr.fMode = RTFS_TYPE_DIRECTORY | RTFS_DOS_DIRECTORY;
     578    if (pThis->pVfsVol->fReadOnly)
     579        pObjInfo->Attr.fMode |= RTFS_DOS_READONLY | 0555;
     580    else
     581        pObjInfo->Attr.fMode |= 0777;
     582
     583    switch (enmAddAttr)
     584    {
     585        case RTFSOBJATTRADD_NOTHING:
     586        case RTFSOBJATTRADD_UNIX:
     587            pObjInfo->Attr.u.Unix.uid           = NIL_RTUID;
     588            pObjInfo->Attr.u.Unix.gid           = (RTGID)RTDvmMapGetFormatType(pThis->pVfsVol->hVolMgr);
     589            pObjInfo->Attr.u.Unix.cHardlinks    = pThis->pVfsVol->cVolumes;
     590            pObjInfo->Attr.u.Unix.INodeIdDevice = 0;
     591            pObjInfo->Attr.u.Unix.INodeId       = 0;
     592            pObjInfo->Attr.u.Unix.fFlags        = 0;
     593            pObjInfo->Attr.u.Unix.GenerationId  = 0;
     594            pObjInfo->Attr.u.Unix.Device        = 0;
     595            break;
     596
     597        case RTFSOBJATTRADD_UNIX_OWNER:
     598            pObjInfo->Attr.u.UnixOwner.uid      = NIL_RTUID;
     599            pObjInfo->Attr.u.UnixOwner.szName[0] = '\0';
     600            break;
     601
     602        case RTFSOBJATTRADD_UNIX_GROUP:
     603            pObjInfo->Attr.u.UnixGroup.gid      = (RTGID)RTDvmMapGetFormatType(pThis->pVfsVol->hVolMgr);
     604            RTStrCopy(pObjInfo->Attr.u.UnixGroup.szName, sizeof(pObjInfo->Attr.u.UnixGroup.szName),
     605                      RTDvmMapGetFormatName(pThis->pVfsVol->hVolMgr));
     606            break;
     607
     608        case RTFSOBJATTRADD_EASIZE:
     609            pObjInfo->Attr.u.EASize.cb = 0;
     610            break;
     611
     612        default:
     613            return VERR_INVALID_PARAMETER;
     614    }
     615    return VINF_SUCCESS;
     616}
     617
     618
     619/**
     620 * @interface_method_impl{RTVFSOBJSETOPS,pfnMode}
     621 */
     622static DECLCALLBACK(int) rtDvmVfsDir_SetMode(void *pvThis, RTFMODE fMode, RTFMODE fMask)
     623{
     624    NOREF(pvThis); NOREF(fMode); NOREF(fMask);
     625    return VERR_NOT_SUPPORTED;
     626}
     627
     628
     629/**
     630 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetTimes}
     631 */
     632static DECLCALLBACK(int) rtDvmVfsDir_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
     633                                             PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
     634{
     635    NOREF(pvThis); NOREF(pAccessTime); NOREF(pModificationTime); NOREF(pChangeTime); NOREF(pBirthTime);
     636    return VERR_NOT_SUPPORTED;
     637}
     638
     639
     640/**
     641 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetOwner}
     642 */
     643static DECLCALLBACK(int) rtDvmVfsDir_SetOwner(void *pvThis, RTUID uid, RTGID gid)
     644{
     645    RT_NOREF(pvThis, uid, gid);
     646    return VERR_NOT_SUPPORTED;
     647}
     648
     649
     650/**
     651 * @interface_method_impl{RTVFSOBJOPS,pfnTraversalOpen}
     652 */
     653static DECLCALLBACK(int) rtDvmVfsDir_TraversalOpen(void *pvThis, const char *pszEntry, PRTVFSDIR phVfsDir,
     654                                                  PRTVFSSYMLINK phVfsSymlink, PRTVFS phVfsMounted)
     655{
     656    RT_NOREF(pvThis, pszEntry);
     657
     658    /* We don't do any subdirs. */
     659    if (phVfsSymlink)
     660        *phVfsSymlink = NIL_RTVFSSYMLINK;
     661    if (phVfsMounted)
     662        *phVfsMounted = NIL_RTVFS;
     663    if (phVfsDir)
     664        *phVfsDir = NIL_RTVFSDIR;
     665    return VERR_PATH_NOT_FOUND;
     666}
     667
     668
     669static int rtDvmVfsDir_FindEntry(PRTDVMVFSDIR pThis, const char *pszEntry, PRTDVMVOLUME phVolume)
     670{
     671    /*
     672     * Enumerate the volumes and try match the volume name.
     673     */
     674    int rc;
     675    PRTDVMVFSVOL pVfsVol = pThis->pVfsVol;
     676    if (pVfsVol->cVolumes > 0)
     677    {
     678        /* The first volume. */
     679        uint32_t iVol = 0;
     680        RTDVMVOLUME hVol;
     681        rc = RTDvmMapQueryFirstVolume(pThis->pVfsVol->hVolMgr, &hVol);
     682        while (RT_SUCCESS(rc))
     683        {
     684            /* Match the name. */
     685            bool  fMatch;
     686            char *pszVolName;
     687            rc = RTDvmVolumeQueryName(hVol, &pszVolName);
     688            if (RT_SUCCESS(rc))
     689            {
     690                fMatch = RTStrCmp(pszEntry, pszVolName) == 0 && *pszVolName != '\0';
     691                RTStrFree(pszVolName);
     692            }
     693            else if (rc == VERR_NOT_SUPPORTED)
     694                fMatch = false;
     695            else
     696            {
     697                RTDvmVolumeRelease(hVol);
     698                break;
     699            }
     700
     701            /* Match the sequential volume number. */
     702            if (!fMatch)
     703            {
     704                char szTmp[16];
     705                RTStrPrintf(szTmp, sizeof(szTmp), "vol%u", iVol);
     706                fMatch = RTStrCmp(pszEntry, szTmp) == 0;
     707            }
     708
     709            if (fMatch)
     710            {
     711                *phVolume = hVol;
     712                return VINF_SUCCESS;
     713            }
     714
     715            /* More volumes? */
     716            iVol++;
     717            if (iVol >= pVfsVol->cVolumes)
     718            {
     719                RTDvmVolumeRelease(hVol);
     720                rc = VERR_FILE_NOT_FOUND;
     721                break;
     722            }
     723
     724            /* Get the next volume. */
     725            RTDVMVOLUME hVolNext;
     726            rc = RTDvmMapQueryNextVolume(pThis->pVfsVol->hVolMgr, hVol, &hVolNext);
     727            RTDvmVolumeRelease(hVol);
     728            hVol = hVolNext;
     729        }
     730    }
     731    else
     732        rc = VERR_FILE_NOT_FOUND;
     733    return rc;
     734}
     735
     736
     737/**
     738 * @interface_method_impl{RTVFSDIROPS,pfnOpenFile}
     739 */
     740static DECLCALLBACK(int) rtDvmVfsDir_OpenFile(void *pvThis, const char *pszFilename, uint32_t fOpen, PRTVFSFILE phVfsFile)
     741{
     742    PRTDVMVFSDIR pThis = (PRTDVMVFSDIR)pvThis;
     743    RTDVMVOLUME  hVolume;
     744    int rc = rtDvmVfsDir_FindEntry(pThis, pszFilename, &hVolume);
    434745    if (RT_SUCCESS(rc))
    435746    {
    436         pThis->offCurPos = 0;
    437         pThis->hVol      = hVol;
    438 
    439         *phVfsFileOut = hVfsFile;
    440         return VINF_SUCCESS;
    441     }
    442     else
    443         RTDvmVolumeRelease(hVol);
     747        if (   (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_OPEN
     748            || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_OPEN_CREATE
     749            || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_CREATE_REPLACE)
     750        {
     751            if (   !(fOpen & RTFILE_O_WRITE)
     752                || !pThis->pVfsVol->fReadOnly)
     753                rc = rtDvmVfsCreateFileForVolume(pThis->pVfsVol, hVolume, fOpen, phVfsFile);
     754            else
     755                rc = VERR_WRITE_PROTECT;
     756        }
     757        else
     758            rc = VERR_ALREADY_EXISTS;
     759        RTDvmVolumeRelease(hVolume);
     760    }
    444761    return rc;
    445762}
    446763
     764
     765/**
     766 * @interface_method_impl{RTVFSDIROPS,pfnOpenDir}
     767 */
     768static DECLCALLBACK(int) rtDvmVfsDir_OpenDir(void *pvThis, const char *pszSubDir, uint32_t fFlags, PRTVFSDIR phVfsDir)
     769{
     770    NOREF(pvThis); NOREF(pszSubDir); NOREF(fFlags); NOREF(phVfsDir);
     771    return VERR_FILE_NOT_FOUND;
     772}
     773
     774
     775/**
     776 * @interface_method_impl{RTVFSDIROPS,pfnCreateDir}
     777 */
     778static DECLCALLBACK(int) rtDvmVfsDir_CreateDir(void *pvThis, const char *pszSubDir, RTFMODE fMode, PRTVFSDIR phVfsDir)
     779{
     780    RT_NOREF(pvThis, pszSubDir, fMode, phVfsDir);
     781    return VERR_NOT_SUPPORTED;
     782}
     783
     784
     785/**
     786 * @interface_method_impl{RTVFSDIROPS,pfnOpenSymlink}
     787 */
     788static DECLCALLBACK(int) rtDvmVfsDir_OpenSymlink(void *pvThis, const char *pszSymlink, PRTVFSSYMLINK phVfsSymlink)
     789{
     790    RT_NOREF(pvThis, pszSymlink, phVfsSymlink);
     791    return VERR_NOT_SUPPORTED;
     792}
     793
     794
     795/**
     796 * @interface_method_impl{RTVFSDIROPS,pfnCreateSymlink}
     797 */
     798static DECLCALLBACK(int) rtDvmVfsDir_CreateSymlink(void *pvThis, const char *pszSymlink, const char *pszTarget,
     799                                                  RTSYMLINKTYPE enmType, PRTVFSSYMLINK phVfsSymlink)
     800{
     801    RT_NOREF(pvThis, pszSymlink, pszTarget, enmType, phVfsSymlink);
     802    return VERR_NOT_SUPPORTED;
     803}
     804
     805
     806/**
     807 * @interface_method_impl{RTVFSDIROPS,pfnQueryEntryInfo}
     808 */
     809static DECLCALLBACK(int) rtDvmVfsDir_QueryEntryInfo(void *pvThis, const char *pszEntry,
     810                                                    PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
     811{
     812    PRTDVMVFSDIR pThis = (PRTDVMVFSDIR)pvThis;
     813    RTDVMVOLUME  hVolume;
     814    int rc = rtDvmVfsDir_FindEntry(pThis, pszEntry, &hVolume);
     815    if (RT_SUCCESS(rc))
     816    {
     817        rc = rtDvmVfsFile_QueryInfoWorker(hVolume, pThis->pVfsVol->hVolMgr, pThis->pVfsVol->fReadOnly, pObjInfo, enmAddAttr);
     818        RTDvmVolumeRelease(hVolume);
     819    }
     820    return rc;
     821}
     822
     823
     824/**
     825 * @interface_method_impl{RTVFSDIROPS,pfnUnlinkEntry}
     826 */
     827static DECLCALLBACK(int) rtDvmVfsDir_UnlinkEntry(void *pvThis, const char *pszEntry, RTFMODE fType)
     828{
     829    RT_NOREF(pvThis, pszEntry, fType);
     830    return VERR_NOT_IMPLEMENTED;
     831}
     832
     833
     834/**
     835 * @interface_method_impl{RTVFSDIROPS,pfnRenameEntry}
     836 */
     837static DECLCALLBACK(int) rtDvmVfsDir_RenameEntry(void *pvThis, const char *pszEntry, RTFMODE fType, const char *pszNewName)
     838{
     839    RT_NOREF(pvThis, pszEntry, fType, pszNewName);
     840    return VERR_NOT_IMPLEMENTED;
     841}
     842
     843
     844/**
     845 * @interface_method_impl{RTVFSDIROPS,pfnRewindDir}
     846 */
     847static DECLCALLBACK(int) rtDvmVfsDir_RewindDir(void *pvThis)
     848{
     849    PRTDVMVFSDIR pThis = (PRTDVMVFSDIR)pvThis;
     850
     851    if (pThis->hCurVolume != NIL_RTDVMVOLUME)
     852    {
     853        RTDvmVolumeRelease(pThis->hCurVolume);
     854        pThis->hCurVolume = NIL_RTDVMVOLUME;
     855    }
     856    pThis->fReturnCurrent = false;
     857    pThis->offDir         = 0;
     858
     859    return VINF_SUCCESS;
     860}
     861
     862
     863/**
     864 * @interface_method_impl{RTVFSDIROPS,pfnReadDir}
     865 */
     866static DECLCALLBACK(int) rtDvmVfsDir_ReadDir(void *pvThis, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry,
     867                                            RTFSOBJATTRADD enmAddAttr)
     868{
     869    PRTDVMVFSDIR pThis   = (PRTDVMVFSDIR)pvThis;
     870    PRTDVMVFSVOL pVfsVol = pThis->pVfsVol;
     871    int          rc;
     872
     873    /*
     874     * Get the volume to return info about.
     875     */
     876    if (!pThis->fReturnCurrent)
     877    {
     878        if (pThis->offDir < pVfsVol->cVolumes)
     879        {
     880            RTDVMVOLUME hNextVolume;
     881            if (pThis->offDir == 0)
     882                rc = RTDvmMapQueryFirstVolume(pVfsVol->hVolMgr, &hNextVolume);
     883            else
     884                rc = RTDvmMapQueryNextVolume(pVfsVol->hVolMgr, pThis->hCurVolume, &hNextVolume);
     885            if (RT_FAILURE(rc))
     886                return rc;
     887            RTDvmVolumeRelease(pThis->hCurVolume);
     888            pThis->hCurVolume = hNextVolume;
     889        }
     890        else
     891        {
     892            RTDvmVolumeRelease(pThis->hCurVolume);
     893            pThis->hCurVolume = NIL_RTDVMVOLUME;
     894            return VERR_NO_MORE_FILES;
     895        }
     896    }
     897
     898    /*
     899     * Figure out the name length.
     900     */
     901    char szVolNo[16];
     902    RTStrPrintf(szVolNo, sizeof(szVolNo), "vol%u", pThis->offDir);
     903
     904    char *pszVolName;
     905    rc = RTDvmVolumeQueryName(pThis->hCurVolume, &pszVolName);
     906    if (   RT_SUCCESS(rc)
     907        || rc == VERR_NOT_SUPPORTED)
     908    {
     909        if (rc == VERR_NOT_SUPPORTED)
     910            pszVolName = szVolNo;
     911        else if (*pszVolName == '\0')
     912        {
     913            RTStrFree(pszVolName);
     914            pszVolName = szVolNo;
     915        }
     916
     917        size_t cchVolName = strlen(pszVolName);
     918        size_t cbNeeded   = RT_OFFSETOF(RTDIRENTRYEX,  szName[cchVolName + 1]);
     919        if (cbNeeded <= *pcbDirEntry)
     920        {
     921            *pcbDirEntry = cbNeeded;
     922
     923            /* Do the names. */
     924            pDirEntry->cbName = (uint16_t)cchVolName;
     925            memcpy(pDirEntry->szName, pszVolName, cchVolName + 1);
     926            if (pszVolName != szVolNo)
     927            {
     928                RTStrFree(pszVolName);
     929
     930                PRTUTF16 pwszShortName = pDirEntry->wszShortName;
     931                size_t   cwcShortName = 0;
     932                rc = RTStrToUtf16Ex(szVolNo, RTSTR_MAX, &pwszShortName, RT_ELEMENTS(pDirEntry->wszShortName), &cwcShortName);
     933                AssertRC(rc);
     934                pDirEntry->cwcShortName = (uint16_t)cwcShortName;
     935            }
     936            else
     937            {
     938                pDirEntry->cwcShortName = 0;
     939                pDirEntry->wszShortName[0] = '\0';
     940            }
     941
     942            /* Do the rest. */
     943            rc = rtDvmVfsFile_QueryInfoWorker(pThis->hCurVolume, pVfsVol->hVolMgr, pVfsVol->fReadOnly,
     944                                              &pDirEntry->Info, enmAddAttr);
     945            pThis->fReturnCurrent = !RT_SUCCESS(rc);
     946            pThis->offDir        += RT_SUCCESS(rc);
     947            return rc;
     948        }
     949
     950        *pcbDirEntry = cbNeeded;
     951        rc = VERR_BUFFER_OVERFLOW;
     952
     953        if (pszVolName != szVolNo)
     954            RTStrFree(pszVolName);
     955    }
     956
     957    pThis->fReturnCurrent = true;
     958    return rc;
     959}
     960
     961
     962/**
     963 * DVM (root) directory operations.
     964 */
     965static const RTVFSDIROPS g_rtDvmVfsDirOps =
     966{
     967    { /* Obj */
     968        RTVFSOBJOPS_VERSION,
     969        RTVFSOBJTYPE_DIR,
     970        "DvmDir",
     971        rtDvmVfsDir_Close,
     972        rtDvmVfsDir_QueryInfo,
     973        RTVFSOBJOPS_VERSION
     974    },
     975    RTVFSDIROPS_VERSION,
     976    0,
     977    { /* ObjSet */
     978        RTVFSOBJSETOPS_VERSION,
     979        RT_OFFSETOF(RTVFSDIROPS, Obj) - RT_OFFSETOF(RTVFSDIROPS, ObjSet),
     980        rtDvmVfsDir_SetMode,
     981        rtDvmVfsDir_SetTimes,
     982        rtDvmVfsDir_SetOwner,
     983        RTVFSOBJSETOPS_VERSION
     984    },
     985    rtDvmVfsDir_TraversalOpen,
     986    rtDvmVfsDir_OpenFile,
     987    rtDvmVfsDir_OpenDir,
     988    rtDvmVfsDir_CreateDir,
     989    rtDvmVfsDir_OpenSymlink,
     990    rtDvmVfsDir_CreateSymlink,
     991    rtDvmVfsDir_QueryEntryInfo,
     992    rtDvmVfsDir_UnlinkEntry,
     993    rtDvmVfsDir_RenameEntry,
     994    rtDvmVfsDir_RewindDir,
     995    rtDvmVfsDir_ReadDir,
     996    RTVFSDIROPS_VERSION,
     997};
    447998
    448999
     
    4801031static DECLCALLBACK(int) rtDvmVfsVol_OpenRoot(void *pvThis, PRTVFSDIR phVfsDir)
    4811032{
    482     //PRTDVMVFSVOL pThis = (PRTDVMVFSVOL)pvThis;
    483 
    484     //rtDvmDirShrd_Retain(pThis->pRootDir); /* consumed by the next call */
    485     //return rtDvmDir_NewWithShared(pThis, pThis->pRootDir, phVfsDir);
    486     RT_NOREF(pvThis, phVfsDir);
    487     return VERR_NOT_IMPLEMENTED;
     1033    PRTDVMVFSVOL pThis = (PRTDVMVFSVOL)pvThis;
     1034
     1035    PRTDVMVFSDIR pNewDir;
     1036    int rc = RTVfsNewDir(&g_rtDvmVfsDirOps, sizeof(*pNewDir), 0 /*fFlags*/, pThis->hVfsSelf,
     1037                         NIL_RTVFSLOCK /*use volume lock*/, phVfsDir, (void **)&pNewDir);
     1038    if (RT_SUCCESS(rc))
     1039    {
     1040        pNewDir->offDir         = 0;
     1041        pNewDir->pVfsVol        = pThis;
     1042        pNewDir->fReturnCurrent = false;
     1043        pNewDir->hCurVolume     = NIL_RTDVMVOLUME;
     1044    }
     1045    return rc;
    4881046}
    4891047
     
    6011159                pThis->fReadOnly = pElement->uProvider == (uint64_t)true;
    6021160                pThis->cVolumes  = RTDvmMapGetValidVolumes(hVolMgr);
     1161                pThis->hVfsSelf  = hVfs;
    6031162
    6041163                *phVfsObj = RTVfsObjFromVfs(hVfs);
     
    6361195    /* pszName = */             "dvm",
    6371196    /* ListEntry = */           { NULL, NULL },
    638     /* pszHelp = */             "Opens a container image using the VD API.\n",
     1197    /* pszHelp = */             "Opens a container image using the VD API.\n"
     1198                                "Optionally takes one parameter 'ro' (read only) or 'rw' (read write).\n",
    6391199    /* pfnValidate = */         rtDvmVfsChain_Validate,
    6401200    /* pfnInstantiate = */      rtDvmVfsChain_Instantiate,
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