VirtualBox

Changeset 41549 in vbox


Ignore:
Timestamp:
Jun 1, 2012 5:29:05 PM (13 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
78314
Message:

VFS/Filesystem: Convert the filesystem specific code to the VFS framework and make it work

Location:
trunk
Files:
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/filesystem.h

    r40036 r41549  
    2727#define ___iprt_filesystem_h
    2828
     29#include <iprt/cdefs.h>
    2930#include <iprt/types.h>
     31#include <iprt/vfs.h>
    3032
    3133RT_C_DECLS_BEGIN
    3234
    33 /** @defgroup grp_filesystem           IPRT Filesystem
     35/** @defgroup grp_filesystem           IPRT Filesystem VFS
    3436 * @{
    3537 */
    3638
    37 /** Handle to a filesystem. */
    38 typedef struct RTFILESYSTEMINT         *RTFILESYSTEM;
    39 /** A pointer to a filesystem handle. */
    40 typedef RTFILESYSTEM                   *PRTFILESYSTEM;
    41 /** NIL filesystem handle. */
    42 #define NIL_RTFILESYSTEM               ((RTFILESYSTEM)~0)
    43 
    4439/**
    45  * Callback to read data from the underlying medium of the filesystem.
     40 * Detect the filesystem in the image given by the VFS file handle
     41 * and create a new VFS object.
    4642 *
    4743 * @returns IPRT status code.
    48  * @param   pvUser    Opaque user data passed on creation.
    49  * @param   off       Offset to start reading from.
    50  * @param   pvBuf     Where to store the read data.
    51  * @param   cbRead    How many bytes to read.
     44 * @retval VERR_NOT_SUPPORTED if the filesystem is not recognized.
     45 * @param  hVfsFile    The file to use as the filesystem medium.
     46 * @param  phVfs       Where to store the VFS handle on success.
    5247 */
    53 typedef DECLCALLBACK(int) FNRTFILESYSTEMREAD(void *pvUser, uint64_t off, void *pvBuf, size_t cbRead);
    54 /** Pointer to a read callback. */
    55 typedef FNRTFILESYSTEMREAD *PFNRTFILESYSTEMREAD;
    56 
    57 /**
    58  * Callback to write data to the underlying medium of the filesystem.
    59  *
    60  * @returns IPRT status code.
    61  * @param   pvUser    Opaque user data passed on creation.
    62  * @param   off       Offset to start writing to.
    63  * @param   pvBuf     The data to write.
    64  * @param   cbRead    How many bytes to write.
    65  */
    66 typedef DECLCALLBACK(int) FNRTFILESYSTEMWRITE(void *pvUser, uint64_t off, const void *pvBuf, size_t cbWrite);
    67 /** Pointer to a read callback. */
    68 typedef FNRTFILESYSTEMWRITE *PFNRTFILESYSTEMWRITE;
    69 
    70 /**
    71  * Probes for and opens a filesystem from the given medium.
    72  *
    73  * @returns IPRT status code.
    74  * @retval  VERR_NOT_SUPPORTED if the filesystem on the given medium is unsupported.
    75  * @param   phFs         Where to store the handle to the filesystem object on success.
    76  * @param   pfnRead      Read callback for the medium.
    77  * @param   pfnWrite     Write callback for the medium.
    78  * @param   cbMedium     Size of the whole medium.
    79  * @param   cbSector     Size of one sector on the medium.
    80  * @param   pvUser       Opaque user data used in the read/write callbacks.
    81  * @param   fFlags       Flags to open the filesystem with.
    82  */
    83 RTDECL(int) RTFilesystemOpen(PRTFILESYSTEM phFs, PFNRTFILESYSTEMREAD pfnRead,
    84                              PFNRTFILESYSTEMWRITE pfnWrite, uint64_t cbMedium,
    85                              uint64_t cbSector, void *pvUser, uint32_t fFlags);
    86 
    87 /**
    88  * Retain a given filesystem object.
    89  *
    90  * @returns New reference count on success, UINT32_MAX on failure.
    91  * @param   hFs          The filesystem object handle.
    92  */
    93 RTDECL(uint32_t) RTFilesystemRetain(RTFILESYSTEM hFs);
    94 
    95 /**
    96  * Releases a given volume manager.
    97  *
    98  * @returns New reference count on success (0 if closed), UINT32_MAX on failure.
    99  * @param   hFs          The filesystem object handle.
    100  */
    101 RTDECL(uint32_t) RTFilesystemRelease(RTFILESYSTEM hFs);
    102 
    103 /**
    104  * Returns the format name of the used filesystem.
    105  *
    106  * @returns Name of the filesystem format used.
    107  * @param   hFs          The filesystem object handle.
    108  */
    109 RTDECL(const char *) RTFilesystemGetFormat(RTFILESYSTEM hFs);
    110 
    111 /**
    112  * Returns the smallest accessible unit of the filesystem.
    113  *
    114  * @returns Block size of the given filesystem or 0 on failure.
    115  * @param   hFs          The filesystem object handle.
    116  */
    117 RTDECL(uint64_t) RTFilesystemGetBlockSize(RTFILESYSTEM hFs);
    118 
    119 /**
    120  * Queries whether the given range on the medium is used by the filesystem.
    121  *
    122  * @returns IPRT status code.
    123  * @param   hFs          The filesystem object handle.
    124  * @param   offStart     The start offset on the medium to check for.
    125  * @param   cb           Size of the range to check for.
    126  * @param   pfUsed       Where to store whether the range is in use by the filesystem
    127  *                       on success.
    128  */
    129 RTDECL(int) RTFilesystemQueryRangeUse(RTFILESYSTEM hFs, uint64_t offStart,
    130                                       size_t cb, bool *pfUsed);
     48RTDECL(int) RTFilesystemVfsFromFile(RTVFSFILE hVfsFile, PRTVFS phVfs);
    13149
    13250/** @} */
  • trunk/include/iprt/mangling.h

    r41169 r41549  
    514514# define RTFileWrite                                    RT_MANGLER(RTFileWrite)
    515515# define RTFileWriteAt                                  RT_MANGLER(RTFileWriteAt)
    516 # define RTFilesystemOpen                               RT_MANGLER(RTFilesystemOpen)
    517 # define RTFilesystemRetain                             RT_MANGLER(RTFilesystemRetain)
    518 # define RTFilesystemRelease                            RT_MANGLER(RTFilesystemRelease)
    519 # define RTFilesystemGetFormat                          RT_MANGLER(RTFilesystemGetFormat)
    520 # define RTFilesystemGetBlockSize                       RT_MANGLER(RTFilesystemGetBlockSize)
    521 # define RTFilesystemQueryRangeUse                      RT_MANGLER(RTFilesystemQueryRangeUse)
     516# define RTFilesystemVfsFromFile                        RT_MANGLER(RTFilesystemVfsFromFile)
    522517# define RTFsQueryProperties                            RT_MANGLER(RTFsQueryProperties)
    523518# define RTFsQuerySerial                                RT_MANGLER(RTFsQuerySerial)
     
    16841679# define RTVfsIoStrmQueryInfo                           RT_MANGLER(RTVfsIoStrmQueryInfo)
    16851680# define RTVfsIoStrmRead                                RT_MANGLER(RTVfsIoStrmRead)
     1681# define RTVfsIoStrmReadAt                              RT_MANGLER(RTVfsIoStrmReadAt)
    16861682# define RTVfsIoStrmRelease                             RT_MANGLER(RTVfsIoStrmRelease)
    16871683# define RTVfsIoStrmRetain                              RT_MANGLER(RTVfsIoStrmRetain)
     
    16931689# define RTVfsIoStrmValidateUtf8Encoding                RT_MANGLER(RTVfsIoStrmValidateUtf8Encoding)
    16941690# define RTVfsIoStrmWrite                               RT_MANGLER(RTVfsIoStrmWrite)
     1691# define RTVfsIoStrmWriteAt                             RT_MANGLER(RTVfsIoStrmWriteAt)
    16951692# define RTVfsIoStrmZeroFill                            RT_MANGLER(RTVfsIoStrmZeroFill)
    16961693# define RTVfsLockAcquireReadSlow                       RT_MANGLER(RTVfsLockAcquireReadSlow)
  • trunk/include/iprt/vfs.h

    r37596 r41549  
    118118                                       char *pszMountPoint, size_t cbMountPoint);
    119119
     120/**
     121 * Checks whether a given range is in use by the virtual filesystem.
     122 *
     123 * @returns IPRT status code.
     124 * @param   hVfs        VFS handle.
     125 * @param   off         Start offset to check.
     126 * @param   cb          Number of bytes to check.
     127 * @param   pfUsed      Where to store the result.
     128 */
     129RTDECL(int)         RTVfsIsRangeInUse(RTVFS hVfs, uint64_t off, size_t cb,
     130                                      bool *pfUsed);
    120131
    121132/** @defgroup grp_vfs_dir           VFS Base Object API
     
    521532 */
    522533RTDECL(int)         RTVfsIoStrmRead(RTVFSIOSTREAM hVfsIos, void *pvBuf, size_t cbToRead, bool fBlocking, size_t *pcbRead);
     534RTDECL(int)         RTVfsIoStrmReadAt(RTVFSIOSTREAM hVfsIos, RTFOFF off, void *pvBuf, size_t cbToRead, bool fBlocking, size_t *pcbRead);
    523535
    524536/**
     
    539551 */
    540552RTDECL(int)         RTVfsIoStrmWrite(RTVFSIOSTREAM hVfsIos, const void *pvBuf, size_t cbToWrite, bool fBlocking, size_t *pcbWritten);
     553RTDECL(int)         RTVfsIoStrmWriteAt(RTVFSIOSTREAM hVfsIos, RTFOFF off, const void *pvBuf, size_t cbToWrite, bool fBlocking, size_t *pcbWritten);
    541554
    542555/**
  • trunk/include/iprt/vfslowlevel.h

    r36555 r41549  
    187187    DECLCALLBACKMEMBER(int, pfnOpenRoot)(void *pvThis, PRTVFSDIR phVfsDir);
    188188
     189    /**
     190     * Checks whether a given range in the underlying medium
     191     * is in use by the virtual filesystem.
     192     *
     193     * @returns IPRT status code.
     194     * @param   pvThis      The implementation specific data.
     195     * @param   off         Start offset to check.
     196     * @param   cb          Number of bytes to check.
     197     * @param   pfUsed      Where to store whether the given range is in use.
     198     */
     199    DECLCALLBACKMEMBER(int, pfnIsRangeInUse)(void *pvThis, RTFOFF off, size_t cb,
     200                                             bool *pfUsed);
     201
    189202    /** @todo There will be more methods here to optimize opening and
    190203     *        querying. */
     
    220233/** @}  */
    221234
     235/**
     236 * Creates a new VFS handle.
     237 *
     238 * @returns IPRT status code
     239 * @param   pVfs Ops            The VFS operations.
     240 * @param   cbInstance          The size of the instance data.
     241 * @param   hVfs                The VFS handle to associate this VFS with.
     242 *                              NIL_VFS is ok.
     243 * @param   hLock               Handle to a custom lock to be used with the new
     244 *                              object.  The reference is consumed.  NIL and
     245 *                              special lock handles are fine.
     246 * @param   phVfs               Where to return the new handle.
     247 * @param   ppvInstance         Where to return the pointer to the instance data
     248 *                              (size is @a cbInstance).
     249 */
     250RTDECL(int) RTVfsNew(PCRTVFSOPS pVfsOps, size_t cbInstance, RTVFS hVfs, RTVFSLOCK hLock,
     251                     PRTVFS phVfs, void **ppvInstance);
    222252
    223253/**
  • trunk/src/VBox/Runtime/Makefile.kmk

    r41477 r41549  
    281281        common/dvm/dvmgpt.cpp \
    282282        common/dvm/dvmmbr.cpp \
     283        common/dvm/dvmvfs.cpp \
    283284        common/err/errinfo.cpp \
    284285        common/err/errmsg.cpp \
  • trunk/src/VBox/Runtime/common/dvm/dvm.cpp

    r40293 r41549  
    469469{
    470470    int rc = VINF_SUCCESS;
    471     bool fAllocated = false;
    472471    PRTDVMINTERNAL       pThis = hVolMgr;
    473472    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     
    478477                 VERR_INVALID_PARAMETER);
    479478
    480     while (   cb > 0
    481            && !fAllocated)
    482     {
    483         PRTDVMVOLUMEINTERNAL pVol;
    484         bool fVolFound = false;
    485         uint64_t cbIntersect;
    486         uint64_t offVol;
    487 
    488         /*
    489          * Search through all volumes. It is not possible to
    490          * get all start sectors and sizes of all volumes here
    491          * because volumes can be scattered around the disk for certain formats.
    492          * Linux LVM is one example, extents of logical volumes don't need to be
    493          * contigous on the medium.
    494          */
    495         RTListForEach(&pThis->VolumeList, pVol, RTDVMVOLUMEINTERNAL, VolumeNode)
     479    /* Check whether the range is inuse by the volume manager metadata first. */
     480    rc = pThis->pDvmFmtOps->pfnQueryRangeUse(pThis->hVolMgrFmt, off, cb, pfAllocated);
     481    if (RT_FAILURE(rc))
     482        return rc;
     483
     484    if (!*pfAllocated)
     485    {
     486        bool fAllocated = false;
     487
     488        while (   cb > 0
     489               && !fAllocated)
    496490        {
    497             bool fIntersect = pThis->pDvmFmtOps->pfnVolumeIsRangeIntersecting(pVol->hVolFmt, off,
    498                                                                               cb, &offVol,
    499                                                                               &cbIntersect);
    500             if (fIntersect)
     491            PRTDVMVOLUMEINTERNAL pVol;
     492            bool fVolFound = false;
     493            uint64_t cbIntersect;
     494            uint64_t offVol;
     495
     496            /*
     497             * Search through all volumes. It is not possible to
     498             * get all start sectors and sizes of all volumes here
     499             * because volumes can be scattered around the disk for certain formats.
     500             * Linux LVM is one example, extents of logical volumes don't need to be
     501             * contigous on the medium.
     502             */
     503            RTListForEach(&pThis->VolumeList, pVol, RTDVMVOLUMEINTERNAL, VolumeNode)
    501504            {
    502                 fVolFound = true;
    503                 if (pVol->pfnQueryBlockStatus)
     505                bool fIntersect = pThis->pDvmFmtOps->pfnVolumeIsRangeIntersecting(pVol->hVolFmt, off,
     506                                                                                  cb, &offVol,
     507                                                                                  &cbIntersect);
     508                if (fIntersect)
    504509                {
    505                     bool fVolAllocated = true;
    506 
    507                     rc = pVol->pfnQueryBlockStatus(pVol->pvUser, offVol, cbIntersect,
    508                                                    &fVolAllocated);
    509                     if (RT_FAILURE(rc))
    510                         break;
     510                    fVolFound = true;
     511                    if (pVol->pfnQueryBlockStatus)
     512                    {
     513                        bool fVolAllocated = true;
     514
     515                        rc = pVol->pfnQueryBlockStatus(pVol->pvUser, offVol, cbIntersect,
     516                                                       &fVolAllocated);
     517                        if (RT_FAILURE(rc))
     518                            break;
     519                        else if (fVolAllocated)
     520                        {
     521                            fAllocated = true;
     522                            break;
     523                        }
     524                    }
     525                    else if (!(pThis->fFlags & DVM_FLAGS_NO_STATUS_CALLBACK_MARK_AS_UNUSED))
     526                        fAllocated = true;
     527                    /* else, flag is set, continue. */
     528
     529                    cb  -= cbIntersect;
     530                    off += cbIntersect;
     531                    break;
    511532                }
    512                 else if (!(pThis->fFlags & DVM_FLAGS_NO_STATUS_CALLBACK_MARK_AS_UNUSED))
     533            }
     534
     535            if (!fVolFound)
     536            {
     537                if (pThis->fFlags & DVM_FLAGS_UNUSED_SPACE_MARK_AS_USED)
    513538                    fAllocated = true;
    514                 /* else, flag is set, continue. */
    515 
    516                 cb  -= cbIntersect;
    517                 off += cbIntersect;
    518                 break;
     539
     540                cb  -= pThis->DvmDisk.cbSector;
     541                off += pThis->DvmDisk.cbSector;
    519542            }
    520543        }
    521544
    522         if (!fVolFound)
    523         {
    524             if (pThis->fFlags & DVM_FLAGS_UNUSED_SPACE_MARK_AS_USED)
    525                 fAllocated = true;
    526 
    527             cb  -= pThis->DvmDisk.cbSector;
    528             off += pThis->DvmDisk.cbSector;
    529         }
    530     }
    531 
    532     *pfAllocated = fAllocated;
     545        *pfAllocated = fAllocated;
     546    }
    533547
    534548    return rc;
  • trunk/src/VBox/Runtime/common/dvm/dvmbsdlabel.cpp

    r40949 r41549  
    343343}
    344344
     345static DECLCALLBACK(int) rtDvmFmtBsdLblQueryRangeUse(RTDVMFMT hVolMgrFmt,
     346                                                     uint64_t off, uint64_t cbRange,
     347                                                     bool *pfUsed)
     348{
     349    PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
     350
     351    if (off <= RTDVM_BSDLBL_LBA2BYTE(1, pThis->pDisk))
     352        *pfUsed = true;
     353    else
     354        *pfUsed = false;
     355
     356    return VINF_SUCCESS;
     357}
     358
    345359DECLCALLBACK(uint32_t) rtDvmFmtBsdLblGetValidVolumes(RTDVMFMT hVolMgrFmt)
    346360{
     
    513527    /* pfnClose */
    514528    rtDvmFmtBsdLblClose,
     529    /* pfnQueryRangeUse */
     530    rtDvmFmtBsdLblQueryRangeUse,
    515531    /* pfnGetValidVolumes */
    516532    rtDvmFmtBsdLblGetValidVolumes,
  • trunk/src/VBox/Runtime/common/dvm/dvmgpt.cpp

    r40949 r41549  
    342342}
    343343
     344static DECLCALLBACK(int) rtDvmFmtGptQueryRangeUse(RTDVMFMT hVolMgrFmt,
     345                                                  uint64_t off, uint64_t cbRange,
     346                                                  bool *pfUsed)
     347{
     348    PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
     349
     350    if (off < 33*pThis->pDisk->cbSector)
     351        *pfUsed = true;
     352    else
     353        *pfUsed = false;
     354
     355    return VINF_SUCCESS;
     356}
     357
    344358static DECLCALLBACK(uint32_t) rtDvmFmtGptGetValidVolumes(RTDVMFMT hVolMgrFmt)
    345359{
     
    531545    /* pfnClose */
    532546    rtDvmFmtGptClose,
     547    /* pfnQueryRangeUse */
     548    rtDvmFmtGptQueryRangeUse,
    533549    /* pfnGetValidVolumes */
    534550    rtDvmFmtGptGetValidVolumes,
  • trunk/src/VBox/Runtime/common/dvm/dvmmbr.cpp

    r40298 r41549  
    212212}
    213213
     214static DECLCALLBACK(int) rtDvmFmtMbrQueryRangeUse(RTDVMFMT hVolMgrFmt,
     215                                                  uint64_t off, uint64_t cbRange,
     216                                                  bool *pfUsed)
     217{
     218    PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
     219
     220    /* MBR uses the first sector only. */
     221    if (off < 512)
     222        *pfUsed = true;
     223    else
     224        *pfUsed = false;
     225
     226    return VINF_SUCCESS;
     227}
     228
    214229static DECLCALLBACK(uint32_t) rtDvmFmtMbrGetValidVolumes(RTDVMFMT hVolMgrFmt)
    215230{
     
    399414    /* pfnClose */
    400415    rtDvmFmtMbrClose,
     416    /* pfnQueryRangeUse */
     417    rtDvmFmtMbrQueryRangeUse,
    401418    /* pfnGetValidVolumes */
    402419    rtDvmFmtMbrGetValidVolumes,
  • trunk/src/VBox/Runtime/common/dvm/dvmvfs.cpp

    r41094 r41549  
    9393
    9494    Assert(pSgBuf->cSegs == 1);
    95     Assert(off < 0);
    9695    NOREF(fBlocking);
    9796
     
    149148
    150149    Assert(pSgBuf->cSegs == 1);
    151     Assert(off < 0);
    152150    NOREF(fBlocking);
    153151
  • trunk/src/VBox/Runtime/common/filesystem/filesystem.cpp

    r40038 r41549  
    4141
    4242/*******************************************************************************
    43 *   Structures and Typedefs                                                    *
    44 *******************************************************************************/
    45 
    46 /**
    47  * Medium descriptor.
    48  */
    49 typedef struct RTFILESYSTEMMEDIUMINT
    50 {
    51     /** Size of the medium in bytes. */
    52     uint64_t                cbMedium;
    53     /** Sector size. */
    54     uint64_t                cbSector;
    55     /** Read callback */
    56     PFNRTFILESYSTEMREAD     pfnRead;
    57     /** Write callback. */
    58     PFNRTFILESYSTEMWRITE    pfnWrite;
    59     /** Opaque user data. */
    60     void                    *pvUser;
    61 } RTFILESYSTEMMEDIUMINT;
    62 /** Pointer to a disk descriptor. */
    63 typedef RTFILESYSTEMMEDIUMINT *PRTFILESYSTEMMEDIUMINT;
    64 /** Pointer to a const descriptor. */
    65 typedef const RTFILESYSTEMMEDIUMINT *PCRTFILESYSTEMMEDIUMINT;
    66 
    67 /**
    68  * The internal filesystem object structure.
    69  */
    70 typedef struct RTFILESYSTEMINT
    71 {
    72     /** The filesytem object magic (RTFILESYSTEM_MAGIC). */
    73     uint32_t              u32Magic;
    74     /** Medium descriptor. */
    75     RTFILESYSTEMMEDIUMINT Medium;
    76     /** Filesystem format operations */
    77     PCRTFILESYSTEMFMTOPS  pcFsFmtOps;
    78     /** Filesystem format handle. */
    79     RTFILESYSTEMFMT       hFsFmt;
    80     /** Reference counter. */
    81     uint32_t volatile     cRefs;
    82 } RTFILESYSTEMINT;
    83 /** Pointer to an internal volume manager. */
    84 typedef RTFILESYSTEMINT *PRTFILESYSTEMINT;
    85 
    86 /*******************************************************************************
    8743*  Global variables                                                            *
    8844*******************************************************************************/
    89 extern RTFILESYSTEMFMTOPS g_rtFilesystemFmtExt;
    9045
    9146/**
    9247 * Supported volume formats.
    9348 */
    94 static PCRTFILESYSTEMFMTOPS g_aFilesystemFmts[] =
     49static PCRTFILESYSTEMDESC g_aFsFmts[] =
    9550{
    96     &g_rtFilesystemFmtExt
     51    &g_rtFsExt
    9752};
    9853
    99 DECLHIDDEN(uint64_t) rtFilesystemMediumGetSize(RTFILESYSTEMMEDIUM hMedium)
    100 {
    101     PRTFILESYSTEMMEDIUMINT pMedInt = hMedium;
    102     AssertPtrReturn(pMedInt, 0);
    103 
    104     return pMedInt->cbMedium;
    105 }
    106 
    107 DECLHIDDEN(int) rtFilesystemMediumRead(RTFILESYSTEMMEDIUM hMedium, uint64_t off,
    108                                        void *pvBuf, size_t cbRead)
    109 {
    110     PRTFILESYSTEMMEDIUMINT pMedInt = hMedium;
    111     AssertPtrReturn(pMedInt, VERR_INVALID_HANDLE);
    112 
    113     return pMedInt->pfnRead(pMedInt->pvUser, off, pvBuf, cbRead);
    114 }
    115 
    116 DECLHIDDEN(int) rtFilesystemMediumWrite(RTFILESYSTEMMEDIUM hMedium, uint64_t off,
    117                                         const void *pvBuf, size_t cbWrite)
    118 {
    119     PRTFILESYSTEMMEDIUMINT pMedInt = hMedium;
    120     AssertPtrReturn(pMedInt, VERR_INVALID_HANDLE);
    121 
    122     return pMedInt->pfnWrite(pMedInt->pvUser, off, pvBuf, cbWrite);
    123 }
    124 
    125 RTDECL(uint32_t) RTFilesystemRetain(RTFILESYSTEM hFs)
    126 {
    127     PRTFILESYSTEMINT pThis = hFs;
    128     AssertPtrReturn(pThis, UINT32_MAX);
    129     AssertReturn(pThis->u32Magic == RTFILESYSTEM_MAGIC, UINT32_MAX);
    130 
    131     uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
    132     AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
    133     return cRefs;
    134 }
    135 
    136 /**
    137  * Destroys a volume manager handle.
    138  *
    139  * @param   pThis               The filesystem object to destroy.
    140  */
    141 static void rtFilesystemDestroy(PRTFILESYSTEMINT pThis)
    142 {
    143     if (pThis->hFsFmt != NIL_RTFILESYSTEMFMT)
    144     {
    145         AssertPtr(pThis->pcFsFmtOps);
    146 
    147         /* Let the backend do it's own cleanup first. */
    148         pThis->pcFsFmtOps->pfnClose(pThis->hFsFmt);
    149         pThis->hFsFmt = NIL_RTFILESYSTEMFMT;
    150     }
    151 
    152     pThis->Medium.cbMedium   = 0;
    153     pThis->Medium.pvUser   = NULL;
    154     pThis->Medium.pfnRead  = NULL;
    155     pThis->Medium.pfnWrite = NULL;
    156     pThis->u32Magic        = RTFILESYSTEM_MAGIC_DEAD;
    157     RTMemFree(pThis);
    158 }
    159 
    160 RTDECL(uint32_t) RTFilesystemRelease(RTFILESYSTEM hFs)
    161 {
    162     PRTFILESYSTEMINT pThis = hFs;
    163     if (pThis == NIL_RTFILESYSTEM)
    164         return 0;
    165     AssertPtrReturn(pThis, UINT32_MAX);
    166     AssertReturn(pThis->u32Magic == RTFILESYSTEM_MAGIC, UINT32_MAX);
    167 
    168     uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
    169     AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
    170     if (cRefs == 0)
    171         rtFilesystemDestroy(pThis);
    172     return cRefs;
    173 }
    174 
    175 RTDECL(int) RTFilesystemOpen(PRTFILESYSTEM phFs, PFNRTFILESYSTEMREAD pfnRead,
    176                              PFNRTFILESYSTEMWRITE pfnWrite, uint64_t cbMedium,
    177                              uint64_t cbSector, void *pvUser, uint32_t fFlags)
     54static int rtFsGetFormat(RTVFSFILE hVfsFile, PCRTFILESYSTEMDESC *ppFsDesc)
    17855{
    17956    int                   rc = VINF_SUCCESS;
    18057    uint32_t              uScoreMax = RTFILESYSTEM_MATCH_SCORE_UNSUPPORTED;
    181     PCRTFILESYSTEMFMTOPS  pcFsFmtOpsMatch = NULL;
    182     PRTFILESYSTEMINT      pThis = NULL;
    183     AssertPtrReturn(phFs, VERR_INVALID_POINTER);
    184     AssertPtrReturn(pfnRead, VERR_INVALID_POINTER);
     58    PCRTFILESYSTEMDESC    pFsFmtMatch = NULL;
    18559
    186     pThis = (PRTFILESYSTEMINT)RTMemAllocZ(sizeof(RTFILESYSTEMINT));
    187     if (!pThis)
    188         return VERR_NO_MEMORY;
    189 
    190     pThis->u32Magic        = RTFILESYSTEM_MAGIC;
    191     pThis->Medium.cbMedium = cbMedium;
    192     pThis->Medium.cbSector = cbSector;
    193     pThis->Medium.pfnRead  = pfnRead;
    194     pThis->Medium.pfnWrite = pfnWrite;
    195     pThis->Medium.pvUser   = pvUser;
    196     pThis->cRefs           = 1;
    197 
    198     for (unsigned i = 0; i < RT_ELEMENTS(g_aFilesystemFmts); i++)
     60    for (unsigned i = 0; i < RT_ELEMENTS(g_aFsFmts); i++)
    19961    {
    20062        uint32_t uScore;
    201         PCRTFILESYSTEMFMTOPS pcFsFmtOps = g_aFilesystemFmts[i];
     63        PCRTFILESYSTEMDESC pFsFmt = g_aFsFmts[i];
    20264
    203         rc = pcFsFmtOps->pfnProbe(&pThis->Medium, &uScore);
     65        rc = pFsFmt->pfnProbe(hVfsFile, &uScore);
    20466        if (   RT_SUCCESS(rc)
    20567            && uScore > uScoreMax)
    20668        {
    207             pcFsFmtOpsMatch = pcFsFmtOps;
    208             uScoreMax       = uScore;
     69            pFsFmtMatch = pFsFmt;
     70            uScoreMax   = uScore;
    20971        }
    21072        else if (RT_FAILURE(rc))
     
    21678        if (uScoreMax > RTFILESYSTEM_MATCH_SCORE_UNSUPPORTED)
    21779        {
    218             AssertPtr(pcFsFmtOpsMatch);
    219 
    220             /* Open the format. */
    221             rc = pcFsFmtOpsMatch->pfnOpen(&pThis->Medium, &pThis->hFsFmt);
    222             if (RT_SUCCESS(rc))
    223                 pThis->pcFsFmtOps = pcFsFmtOpsMatch;
     80            AssertPtr(pFsFmtMatch);
     81            *ppFsDesc = pFsFmtMatch;
    22482        }
    22583        else
     
    22785    }
    22886
     87    return rc;
     88}
     89
     90RTDECL(int) RTFilesystemVfsFromFile(RTVFSFILE hVfsFile, PRTVFS phVfs)
     91{
     92    int rc = VINF_SUCCESS;
     93    PCRTFILESYSTEMDESC pFsDesc = NULL;
     94    RTVFS hVfs = NIL_RTVFS;
     95    void *pvThis = NULL;
     96
     97    AssertPtrReturn(hVfsFile, VERR_INVALID_HANDLE);
     98    AssertPtrReturn(phVfs, VERR_INVALID_POINTER);
     99
     100    rc = rtFsGetFormat(hVfsFile, &pFsDesc);
    229101    if (RT_SUCCESS(rc))
    230         *phFs = pThis;
    231     else
    232         RTMemFree(pThis);
     102    {
     103        rc = RTVfsNew(&pFsDesc->VfsOps, pFsDesc->cbFs, NIL_RTVFS, NIL_RTVFSLOCK,
     104                      &hVfs, &pvThis);
     105        if (RT_SUCCESS(rc))
     106        {
     107            rc = pFsDesc->pfnInit(pvThis, hVfsFile);
     108            if (RT_SUCCESS(rc))
     109                *phVfs = hVfs;
     110            else
     111                RTVfsRelease(hVfs);
     112        }
     113    }
    233114
    234115    return rc;
    235116}
    236117
    237 RTDECL(const char *) RTFilesystemGetFormat(RTFILESYSTEM hFs)
    238 {
    239     PRTFILESYSTEMINT pThis = hFs;
    240     AssertPtrReturn(pThis, NULL);
    241     AssertReturn(pThis->u32Magic == RTFILESYSTEM_MAGIC, NULL);
    242118
    243     return pThis->pcFsFmtOps->pcszFmt;
    244 }
    245 
    246 RTDECL(uint64_t) RTFilesystemGetBlockSize(RTFILESYSTEM hFs)
    247 {
    248     PRTFILESYSTEMINT pThis = hFs;
    249     AssertPtrReturn(pThis, 0);
    250     AssertReturn(pThis->u32Magic == RTFILESYSTEM_MAGIC, 0);
    251 
    252     return pThis->pcFsFmtOps->pfnGetBlockSize(pThis->hFsFmt);
    253 }
    254 
    255 RTDECL(int) RTFilesystemQueryRangeUse(RTFILESYSTEM hFs, uint64_t offStart, size_t cb,
    256                                       bool *pfUsed)
    257 {
    258     PRTFILESYSTEMINT pThis = hFs;
    259     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    260     AssertReturn(pThis->u32Magic == RTFILESYSTEM_MAGIC, VERR_INVALID_HANDLE);
    261     AssertPtrReturn(pfUsed, VERR_INVALID_POINTER);
    262     AssertReturn(offStart + cb <= pThis->Medium.cbMedium, VERR_OUT_OF_RANGE);
    263 
    264     return pThis->pcFsFmtOps->pfnQueryRangeUse(pThis->hFsFmt, offStart, cb, pfUsed);
    265 }
  • trunk/src/VBox/Runtime/common/filesystem/filesystemext.cpp

    r40038 r41549  
    3535#include <iprt/filesystem.h>
    3636#include <iprt/string.h>
     37#include <iprt/vfs.h>
    3738#include "internal/filesystem.h"
    3839
     
    151152 * Cached block group descriptor data.
    152153 */
    153 typedef struct RTFILESYSTEMFMTEXTBLKGRP
     154typedef struct RTFILESYSTEMEXTBLKGRP
    154155{
    155156    /** Start offset (in bytes and from the start of the disk). */
     
    160161     * and number of blocks per group). */
    161162    uint8_t     abBlockBitmap[1];
    162 } RTFILESYSTEMFMTEXTBLKGRP;
     163} RTFILESYSTEMEXTBLKGRP;
    163164/** Pointer to block group descriptor data. */
    164 typedef RTFILESYSTEMFMTEXTBLKGRP *PRTFILESYSTEMFMTEXTBLKGRP;
     165typedef RTFILESYSTEMEXTBLKGRP *PRTFILESYSTEMEXTBLKGRP;
    165166
    166167/**
    167168 * Ext2/3 filesystem data.
    168169 */
    169 typedef struct RTFILESYSTEMFMTINT
    170 {
    171     /** Handle to the underlying medium. */
    172     RTFILESYSTEMMEDIUM        hMedium;
     170typedef struct RTFILESYSTEMEXT
     171{
     172    /** VFS file handle. */
     173    RTVFSFILE                 hVfsFile;
    173174    /** Block number of the superblock. */
    174175    uint32_t                  iSbBlock;
     
    180181    unsigned                  cBlockGroups;
    181182    /** Cached block group descriptor data. */
    182     PRTFILESYSTEMFMTEXTBLKGRP pBlkGrpDesc;
    183 } RTFILESYSTEMFMTINT;
     183    PRTFILESYSTEMEXTBLKGRP    pBlkGrpDesc;
     184} RTFILESYSTEMEXT;
    184185/** Pointer to the ext filesystem data. */
    185 typedef RTFILESYSTEMFMTINT *PRTFILESYSTEMFMTINT;
     186typedef RTFILESYSTEMEXT *PRTFILESYSTEMEXT;
    186187
    187188/*******************************************************************************
     
    196197 * @param   iBlkGrp  Block group number to load.
    197198 */
    198 static int rtFilesystemExtLoadBlkGrpDesc(PRTFILESYSTEMFMTINT pThis, uint32_t iBlkGrp)
     199static int rtFsExtLoadBlkGrpDesc(PRTFILESYSTEMEXT pThis, uint32_t iBlkGrp)
    199200{
    200201    int rc = VINF_SUCCESS;
    201     PRTFILESYSTEMFMTEXTBLKGRP pBlkGrpDesc = pThis->pBlkGrpDesc;
     202    PRTFILESYSTEMEXTBLKGRP pBlkGrpDesc = pThis->pBlkGrpDesc;
    202203    uint64_t offRead = (pThis->iSbBlock + 1) * pThis->cbBlock;
    203204    BlockGroupDesc BlkDesc;
     
    210211    if (!pBlkGrpDesc)
    211212    {
    212         size_t cbBlkDesc = RT_OFFSETOF(RTFILESYSTEMFMTEXTBLKGRP, abBlockBitmap[cbBlockBitmap]);
    213         pBlkGrpDesc = (PRTFILESYSTEMFMTEXTBLKGRP)RTMemAllocZ(cbBlkDesc);
     213        size_t cbBlkDesc = RT_OFFSETOF(RTFILESYSTEMEXTBLKGRP, abBlockBitmap[cbBlockBitmap]);
     214        pBlkGrpDesc = (PRTFILESYSTEMEXTBLKGRP)RTMemAllocZ(cbBlkDesc);
    214215        if (!pBlkGrpDesc)
    215216            return VERR_NO_MEMORY;
    216217    }
    217218
    218     rc = rtFilesystemMediumRead(pThis->hMedium, offRead, &BlkDesc, sizeof(BlkDesc));
     219    rc = RTVfsFileReadAt(pThis->hVfsFile, offRead, &BlkDesc, sizeof(BlkDesc), NULL);
    219220    if (RT_SUCCESS(rc))
    220221    {
    221222        pBlkGrpDesc->offStart = pThis->iSbBlock + (uint64_t)iBlkGrp * pThis->cBlocksPerGroup * pThis->cbBlock;
    222223        pBlkGrpDesc->offLast  = pBlkGrpDesc->offStart + pThis->cBlocksPerGroup * pThis->cbBlock;
    223         rc = rtFilesystemMediumRead(pThis->hMedium, BlkDesc.offBlockBitmap * pThis->cbBlock,
    224                                     &pBlkGrpDesc->abBlockBitmap[0], cbBlockBitmap);
     224        rc = RTVfsFileReadAt(pThis->hVfsFile, BlkDesc.offBlockBitmap * pThis->cbBlock,
     225                             &pBlkGrpDesc->abBlockBitmap[0], cbBlockBitmap, NULL);
    225226    }
    226227
     
    230231}
    231232
    232 static DECLCALLBACK(int) rtFilesystemExtProbe(RTFILESYSTEMMEDIUM hMedium, uint32_t *puScore)
     233static bool rtFsExtIsBlockRangeInUse(PRTFILESYSTEMEXTBLKGRP pBlkGrpDesc,
     234                                     uint32_t offBlockStart, uint32_t cBlocks)
     235{
     236    bool fUsed = false;
     237
     238    while (cBlocks)
     239    {
     240        uint32_t idxByte = offBlockStart / 8;
     241        uint32_t iBit = offBlockStart % 8;
     242
     243        if (pBlkGrpDesc->abBlockBitmap[idxByte] & RT_BIT(iBit))
     244        {
     245            fUsed = true;
     246            break;
     247        }
     248
     249        cBlocks--;
     250        offBlockStart++;
     251    }
     252
     253    return fUsed;
     254}
     255
     256
     257static DECLCALLBACK(int) rtFsExtProbe(RTVFSFILE hVfsFile, uint32_t *puScore)
    233258{
    234259    int rc = VINF_SUCCESS;
    235     uint64_t cbMedium = rtFilesystemMediumGetSize(hMedium);
     260    uint64_t cbMedium = 0;
    236261
    237262    *puScore = RTFILESYSTEM_MATCH_SCORE_UNSUPPORTED;
    238263
    239     if (cbMedium >= 2*sizeof(ExtSuperBlock))
    240     {
    241         ExtSuperBlock SuperBlock;
    242 
    243         rc = rtFilesystemMediumRead(hMedium, 1024, &SuperBlock, sizeof(ExtSuperBlock));
    244         if (RT_SUCCESS(rc))
     264    rc = RTVfsFileGetSize(hVfsFile, &cbMedium);
     265    if (RT_SUCCESS(rc))
     266    {
     267        if (cbMedium >= 2*sizeof(ExtSuperBlock))
    245268        {
     269            ExtSuperBlock SuperBlock;
     270
     271            rc = RTVfsFileReadAt(hVfsFile, 1024, &SuperBlock, sizeof(ExtSuperBlock), NULL);
     272            if (RT_SUCCESS(rc))
     273            {
    246274#if defined(RT_BIGENDIAN)
    247             /** @todo: Convert to host endianess. */
     275                /** @todo: Convert to host endianess. */
    248276#endif
    249             if (SuperBlock.u16Signature == RTFILESYSTEM_EXT2_SIGNATURE)
    250                 *puScore = RTFILESYSTEM_MATCH_SCORE_SUPPORTED;
     277                if (SuperBlock.u16Signature == RTFILESYSTEM_EXT2_SIGNATURE)
     278                    *puScore = RTFILESYSTEM_MATCH_SCORE_SUPPORTED;
     279            }
    251280        }
    252281    }
     
    255284}
    256285
    257 static DECLCALLBACK(int) rtFilesystemExtOpen(RTFILESYSTEMMEDIUM hMedium, PRTFILESYSTEMFMT phFsFmt)
     286static DECLCALLBACK(int) rtFsExtInit(void *pvThis, RTVFSFILE hVfsFile)
    258287{
    259288    int rc = VINF_SUCCESS;
    260     PRTFILESYSTEMFMTINT pThis;
     289    PRTFILESYSTEMEXT pThis = (PRTFILESYSTEMEXT)pvThis;
    261290    ExtSuperBlock SuperBlock;
    262291
    263     pThis = (PRTFILESYSTEMFMTINT)RTMemAllocZ(sizeof(RTFILESYSTEMFMTINT));
    264     if (!pThis)
    265         return VERR_NO_MEMORY;
    266 
    267     pThis->hMedium     = hMedium;
     292    pThis->hVfsFile    = hVfsFile;
    268293    pThis->pBlkGrpDesc = NULL;
    269294
    270     rc = rtFilesystemMediumRead(hMedium, 1024, &SuperBlock, sizeof(ExtSuperBlock));
     295    rc = RTVfsFileReadAt(hVfsFile, 1024, &SuperBlock, sizeof(ExtSuperBlock), NULL);
    271296    if (RT_SUCCESS(rc))
    272297    {
     
    284309
    285310            /* Load first block group descriptor. */
    286             rc = rtFilesystemExtLoadBlkGrpDesc(pThis, 0);
     311            rc = rtFsExtLoadBlkGrpDesc(pThis, 0);
    287312        }
    288313    }
    289314
    290     if (RT_SUCCESS(rc))
    291         *phFsFmt = pThis;
    292     else
    293     {
    294         if (pThis->pBlkGrpDesc)
    295             RTMemFree(pThis->pBlkGrpDesc);
    296         RTMemFree(pThis);
    297     }
    298 
    299315    return rc;
    300316}
    301317
    302 static DECLCALLBACK(int) rtFilesystemExtClose(RTFILESYSTEMFMT hFsFmt)
    303 {
    304     PRTFILESYSTEMFMTINT pThis = hFsFmt;
     318static DECLCALLBACK(void) rtFsExtDestroy(void *pvThis)
     319{
     320    PRTFILESYSTEMEXT pThis = (PRTFILESYSTEMEXT)pvThis;
    305321
    306322    if (pThis->pBlkGrpDesc)
    307323        RTMemFree(pThis->pBlkGrpDesc);
    308     RTMemFree(pThis);
    309 
    310     return VINF_SUCCESS;
    311 }
    312 
    313 static DECLCALLBACK(uint64_t) rtFilesystemExtGetBlockSize(RTFILESYSTEMFMT hFsFmt)
    314 {
    315     PRTFILESYSTEMFMTINT pThis = hFsFmt;
    316 
    317     return pThis->cbBlock;
    318 }
    319 
    320 static bool rtFilesystemExtIsBlockRangeInUse(PRTFILESYSTEMFMTEXTBLKGRP pBlkGrpDesc,
    321                                              uint32_t offBlockStart,
    322                                              uint32_t cBlocks)
    323 {
    324     bool fUsed = false;
    325 
    326     while (cBlocks)
    327     {
    328         uint32_t idxByte = offBlockStart / 8;
    329         uint32_t iBit = offBlockStart % 8;
    330 
    331         if (pBlkGrpDesc->abBlockBitmap[idxByte] & RT_BIT(iBit))
    332         {
    333             fUsed = true;
    334             break;
    335         }
    336 
    337         cBlocks--;
    338         offBlockStart++;
    339     }
    340 
    341     return fUsed;
    342 }
    343 
    344 static DECLCALLBACK(int) rtFilesystemExtQueryRangeUse(RTFILESYSTEMFMT hFsFmt, uint64_t offStart,
    345                                                       size_t cb, bool *pfUsed)
     324}
     325
     326static DECLCALLBACK(int) rtFsExtOpenRoot(void *pvThis, PRTVFSDIR phVfsDir)
     327{
     328    return VERR_NOT_IMPLEMENTED;
     329}
     330
     331static DECLCALLBACK(int) rtFsExtIsRangeInUse(void *pvThis, RTFOFF off, size_t cb,
     332                                             bool *pfUsed)
    346333{
    347334    int rc = VINF_SUCCESS;
    348     PRTFILESYSTEMFMTINT pThis = hFsFmt;
     335    uint64_t offStart = (uint64_t)off;
     336    PRTFILESYSTEMEXT pThis = (PRTFILESYSTEMEXT)pvThis;
     337
     338    *pfUsed = false;
    349339
    350340    while (cb > 0)
     
    360350        {
    361351            /* Load new block descriptor. */
    362             rc = rtFilesystemExtLoadBlkGrpDesc(pThis, iBlockGroup);
     352            rc = rtFsExtLoadBlkGrpDesc(pThis, iBlockGroup);
    363353            if (RT_FAILURE(rc))
    364354                break;
     
    366356
    367357        cbThis = RT_MIN(cb, pThis->pBlkGrpDesc->offLast - offStart + 1);
    368         fUsed = rtFilesystemExtIsBlockRangeInUse(pThis->pBlkGrpDesc, offBlockRelStart,
    369                                                  cbThis / pThis->cbBlock +
    370                                                  cbThis % pThis->cbBlock
    371                                                  ? 1
    372                                                  : 0);
     358        fUsed = rtFsExtIsBlockRangeInUse(pThis->pBlkGrpDesc, offBlockRelStart,
     359                                         cbThis / pThis->cbBlock +
     360                                         (cbThis % pThis->cbBlock ? 1 : 0));
    373361
    374362        if (fUsed)
     
    378366        }
    379367
    380         cb -= cbThis;
     368        cb       -= cbThis;
    381369        offStart += cbThis;
    382370    }
     
    385373}
    386374
    387 RTFILESYSTEMFMTOPS g_rtFilesystemFmtExt =
    388 {
    389     /* pcszFmt */
    390     "EXT",
    391     /* pfnProbe */
    392     rtFilesystemExtProbe,
    393     /* pfnOpen */
    394     rtFilesystemExtOpen,
    395     /* pfnClose */
    396     rtFilesystemExtClose,
    397     /* pfnGetBlockSize */
    398     rtFilesystemExtGetBlockSize,
    399     /* pfnQueryRangeUse */
    400     rtFilesystemExtQueryRangeUse
     375DECL_HIDDEN_CONST(RTFILESYSTEMDESC) const g_rtFsExt =
     376{
     377    /** cbFs */
     378    sizeof(RTFILESYSTEMEXT),
     379    /** VfsOps */
     380    {
     381        /** uVersion. */
     382        RTVFSOPS_VERSION,
     383        /** fFeatures */
     384        0,
     385        /** pszName */
     386        "ExtVfsOps",
     387        /** pfnDestroy */
     388        rtFsExtDestroy,
     389        /** pfnOpenRoot */
     390        rtFsExtOpenRoot,
     391        /** pfnIsRangeInUse */
     392        rtFsExtIsRangeInUse,
     393        /** uEndMarker */
     394        RTVFSOPS_VERSION
     395    },
     396    /** pfnProbe */
     397    rtFsExtProbe,
     398    /** pfnInit */
     399    rtFsExtInit
    401400};
    402401
  • trunk/src/VBox/Runtime/common/vfs/vfsbase.cpp

    r39083 r41549  
    15801580
    15811581/*
     1582 * F I L E S Y S T E M   R O O T
     1583 * F I L E S Y S T E M   R O O T
     1584 * F I L E S Y S T E M   R O O T
     1585 */
     1586
     1587
     1588RTDECL(int) RTVfsNew(PCRTVFSOPS pVfsOps, size_t cbInstance, RTVFS hVfs, RTVFSLOCK hLock,
     1589                     PRTVFS phVfs, void **ppvInstance)
     1590{
     1591    /*
     1592     * Validate the input, be extra strict in strict builds.
     1593     */
     1594    AssertPtr(pVfsOps);
     1595    AssertReturn(pVfsOps->uVersion   == RTVFSOPS_VERSION, VERR_VERSION_MISMATCH);
     1596    AssertReturn(pVfsOps->uEndMarker == RTVFSOPS_VERSION, VERR_VERSION_MISMATCH);
     1597    Assert(cbInstance > 0);
     1598    AssertPtr(ppvInstance);
     1599    AssertPtr(phVfs);
     1600
     1601    /*
     1602     * Allocate the handle + instance data.
     1603     */
     1604    size_t const cbThis = RT_ALIGN_Z(sizeof(RTVFSINTERNAL), RTVFS_INST_ALIGNMENT)
     1605                        + RT_ALIGN_Z(cbInstance, RTVFS_INST_ALIGNMENT);
     1606    RTVFSINTERNAL *pThis = (RTVFSINTERNAL *)RTMemAllocZ(cbThis);
     1607    if (!pThis)
     1608        return VERR_NO_MEMORY;
     1609
     1610    int rc = rtVfsObjInitNewObject(&pThis->Base, NULL, hVfs, hLock,
     1611                                   (char *)pThis + RT_ALIGN_Z(sizeof(*pThis), RTVFS_INST_ALIGNMENT));
     1612    if (RT_FAILURE(rc))
     1613    {
     1614        RTMemFree(pThis);
     1615        return rc;
     1616    }
     1617
     1618    pThis->uMagic = RTVFS_MAGIC;
     1619    pThis->pOps   = pVfsOps;
     1620
     1621    *phVfs       = pThis;
     1622    *ppvInstance = pThis->Base.pvThis;
     1623    return VINF_SUCCESS;
     1624}
     1625
     1626
     1627RTDECL(uint32_t)    RTVfsRetain(RTVFS hVfs)
     1628{
     1629    RTVFSINTERNAL *pThis = hVfs;
     1630    AssertPtrReturn(pThis, UINT32_MAX);
     1631    AssertReturn(pThis->uMagic == RTVFS_MAGIC, UINT32_MAX);
     1632    return rtVfsObjRetain(&pThis->Base);
     1633}
     1634
     1635
     1636RTDECL(uint32_t)    RTVfsRelease(RTVFS hVfs)
     1637{
     1638    RTVFSINTERNAL *pThis = hVfs;
     1639    if (pThis == NIL_RTVFS)
     1640        return 0;
     1641    AssertPtrReturn(pThis, UINT32_MAX);
     1642    AssertReturn(pThis->uMagic == RTVFS_MAGIC, UINT32_MAX);
     1643    return rtVfsObjRelease(&pThis->Base);
     1644}
     1645
     1646
     1647RTDECL(int)         RTVfsIsRangeInUse(RTVFS hVfs, uint64_t off, size_t cb,
     1648                                      bool *pfUsed)
     1649{
     1650    RTVFSINTERNAL *pThis = hVfs;
     1651    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     1652    AssertReturn(pThis->uMagic == RTVFS_MAGIC, VERR_INVALID_HANDLE);
     1653
     1654    RTVfsLockAcquireWrite(pThis->Base.hLock);
     1655    int rc = pThis->pOps->pfnIsRangeInUse(pThis->Base.pvThis, off, cb, pfUsed);
     1656    RTVfsLockReleaseWrite(pThis->Base.hLock);
     1657
     1658    return rc;
     1659}
     1660
     1661
     1662/*
    15821663 *
    15831664 *  F I L E S Y S T E M   S T R E A M
     
    19862067
    19872068
     2069RTDECL(int) RTVfsIoStrmReadAt(RTVFSIOSTREAM hVfsIos, RTFOFF off, void *pvBuf, size_t cbToRead,
     2070                              bool fBlocking, size_t *pcbRead)
     2071{
     2072    AssertPtrNullReturn(pcbRead, VERR_INVALID_POINTER);
     2073    if (pcbRead)
     2074        *pcbRead = 0;
     2075    RTVFSIOSTREAMINTERNAL *pThis = hVfsIos;
     2076    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     2077    AssertReturn(pThis->uMagic == RTVFSIOSTREAM_MAGIC, VERR_INVALID_HANDLE);
     2078    AssertReturn(fBlocking || pcbRead, VERR_INVALID_PARAMETER);
     2079    AssertReturn(pThis->fFlags & RTFILE_O_READ, VERR_ACCESS_DENIED);
     2080
     2081    RTSGSEG Seg = { pvBuf, cbToRead };
     2082    RTSGBUF SgBuf;
     2083    RTSgBufInit(&SgBuf, &Seg, 1);
     2084
     2085    RTVfsLockAcquireWrite(pThis->Base.hLock);
     2086    int rc = pThis->pOps->pfnRead(pThis->Base.pvThis, off, &SgBuf, fBlocking, pcbRead);
     2087    RTVfsLockReleaseWrite(pThis->Base.hLock);
     2088    return rc;
     2089}
     2090
     2091
    19882092RTDECL(int) RTVfsIoStrmWrite(RTVFSIOSTREAM hVfsIos, const void *pvBuf, size_t cbToWrite, bool fBlocking, size_t *pcbWritten)
    19892093{
     
    20032107    RTVfsLockAcquireWrite(pThis->Base.hLock);
    20042108    int rc = pThis->pOps->pfnWrite(pThis->Base.pvThis, -1 /*off*/, &SgBuf, fBlocking, pcbWritten);
     2109    RTVfsLockReleaseWrite(pThis->Base.hLock);
     2110    return rc;
     2111}
     2112
     2113
     2114RTDECL(int) RTVfsIoStrmWriteAt(RTVFSIOSTREAM hVfsIos, RTFOFF off, const void *pvBuf, size_t cbToWrite,
     2115                               bool fBlocking, size_t *pcbWritten)
     2116{
     2117    AssertPtrNullReturn(pcbWritten, VERR_INVALID_POINTER);
     2118    if (pcbWritten)
     2119        *pcbWritten = 0;
     2120    RTVFSIOSTREAMINTERNAL *pThis = hVfsIos;
     2121    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     2122    AssertReturn(pThis->uMagic == RTVFSIOSTREAM_MAGIC, VERR_INVALID_HANDLE);
     2123    AssertReturn(fBlocking || pcbWritten, VERR_INVALID_PARAMETER);
     2124    AssertReturn(pThis->fFlags & RTFILE_O_WRITE, VERR_ACCESS_DENIED);
     2125
     2126    RTSGSEG Seg = { (void *)pvBuf, cbToWrite };
     2127    RTSGBUF SgBuf;
     2128    RTSgBufInit(&SgBuf, &Seg, 1);
     2129
     2130    RTVfsLockAcquireWrite(pThis->Base.hLock);
     2131    int rc = pThis->pOps->pfnWrite(pThis->Base.pvThis, off, &SgBuf, fBlocking, pcbWritten);
    20052132    RTVfsLockReleaseWrite(pThis->Base.hLock);
    20062133    return rc;
     
    24202547
    24212548
    2422 /// @todo RTDECL(int) RTVfsFileWriteAt(RTVFSFILE hVfsFile, RTFOFF off, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten);
    2423 /// @todo RTDECL(int) RTVfsFileReadAt(RTVFSFILE hVfsFile, RTFOFF off, void *pvBuf, size_t cbToRead, size_t *pcbRead);
     2549RTDECL(int)         RTVfsFileWriteAt(RTVFSFILE hVfsFile, RTFOFF off, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten)
     2550{
     2551    AssertPtrNullReturn(pcbWritten, VERR_INVALID_POINTER);
     2552    if (pcbWritten)
     2553        *pcbWritten = 0;
     2554    RTVFSFILEINTERNAL *pThis = hVfsFile;
     2555    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     2556    AssertReturn(pThis->uMagic == RTVFSFILE_MAGIC, VERR_INVALID_HANDLE);
     2557
     2558    int rc = RTVfsFileSeek(hVfsFile, off, RTFILE_SEEK_BEGIN, NULL);
     2559    if (RT_SUCCESS(rc))
     2560        rc = RTVfsIoStrmWriteAt(&pThis->Stream, off, pvBuf, cbToWrite, true /*fBlocking*/, pcbWritten);
     2561
     2562    return rc;
     2563}
     2564
     2565
     2566RTDECL(int)         RTVfsFileReadAt(RTVFSFILE hVfsFile, RTFOFF off, void *pvBuf, size_t cbToRead, size_t *pcbRead)
     2567{
     2568    AssertPtrNullReturn(pcbRead, VERR_INVALID_POINTER);
     2569    if (pcbRead)
     2570        *pcbRead = 0;
     2571    RTVFSFILEINTERNAL *pThis = hVfsFile;
     2572    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     2573    AssertReturn(pThis->uMagic == RTVFSFILE_MAGIC, VERR_INVALID_HANDLE);
     2574
     2575    int rc = RTVfsFileSeek(hVfsFile, off, RTFILE_SEEK_BEGIN, NULL);
     2576    if (RT_SUCCESS(rc))
     2577        rc = RTVfsIoStrmReadAt(&pThis->Stream, off, pvBuf, cbToRead, true /*fBlocking*/, pcbRead);
     2578
     2579    return rc;
     2580}
    24242581
    24252582
     
    24752632    return rc;
    24762633}
     2634
     2635
     2636RTDECL(int) RTVfsFileGetSize(RTVFSFILE hVfsFile, uint64_t *pcbSize)
     2637{
     2638    RTVFSFILEINTERNAL *pThis = hVfsFile;
     2639    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     2640    AssertReturn(pThis->uMagic == RTVFSFILE_MAGIC, VERR_INVALID_HANDLE);
     2641    AssertPtrReturn(pcbSize, VERR_INVALID_POINTER);
     2642
     2643    RTVfsLockAcquireWrite(pThis->Stream.Base.hLock);
     2644    int rc = pThis->pOps->pfnQuerySize(pThis->Stream.Base.pvThis, pcbSize);
     2645    RTVfsLockReleaseWrite(pThis->Stream.Base.hLock);
     2646
     2647    return rc;
     2648}
  • trunk/src/VBox/Runtime/include/internal/dvm.h

    r40137 r41549  
    122122
    123123    /**
     124     * Returns whether the given range is in use by the volume manager.
     125     *
     126     * @returns IPRT status code.
     127     * @param   hVolMgrFmt      The format specific volume manager handle.
     128     * @param   offStart        Start offset of the range.
     129     * @param   cbRange         Size of the range to check in bytes.
     130     * @param   pfUsed          Where to store whether the range is in use by the
     131     *                          volume manager.
     132     */
     133    DECLCALLBACKMEMBER(int, pfnQueryRangeUse)(RTDVMFMT hVolMgrFmt,
     134                                              uint64_t off, uint64_t cbRange,
     135                                              bool *pfUsed);
     136
     137    /**
    124138     * Gets the number of valid volumes in the map.
    125139     *
  • trunk/src/VBox/Runtime/include/internal/filesystem.h

    r40029 r41549  
    3131#include <iprt/err.h>
    3232#include <iprt/assert.h>
     33#include <iprt/vfslowlevel.h>
    3334#include "internal/magics.h"
    3435
    3536RT_C_DECLS_BEGIN
    3637
    37 /** A filesystem format handle. */
    38 typedef struct RTFILESYSTEMFMTINT   *RTFILESYSTEMFMT;
    39 /** Pointer to a filesystem format handle. */
    40 typedef RTFILESYSTEMFMT             *PRTFILESYSTEMFMT;
    41 /** NIL filesystem format handle. */
    42 #define NIL_RTFILESYSTEMFMT         ((RTFILESYSTEMFMT)~0)
     38/*******************************************************************************
     39*   Structures and Typedefs                                                    *
     40*******************************************************************************/
    4341
    44 /** A medium handle. */
    45 typedef struct RTFILESYSTEMMEDIUMINT *RTFILESYSTEMMEDIUM;
    46 /** Pointer to a medium handle. */
    47 typedef RTFILESYSTEMMEDIUM *PRTFILESYSTEMMEDIUM;
     42/** Filesystem format specific initialization structure. */
     43typedef DECLCALLBACK(int) FNRTFILESYSTEMINIT(void *pvThis, RTVFSFILE hVfsFile);
     44/** Pointer to a format specific initialization structure. */
     45typedef FNRTFILESYSTEMINIT *PFNRTFILESYSTEMINIT;
    4846
    49 /** Score to indicate that the backend can't handle the format at all */
    5047#define RTFILESYSTEM_MATCH_SCORE_UNSUPPORTED 0
    51 /** Score to indicate that a backend supports the format
    52  * but there can be other backends. */
    53 #define RTFILESYSTEM_MATCH_SCORE_SUPPORTED   (UINT32_MAX/2)
    54 /** Score to indicate a perfect match. */
    55 #define RTFILESYSTEM_MATCH_SCORE_PERFECT     UINT32_MAX
     48#define RTFILESYSTEM_MATCH_SCORE_SUPPORTED UINT32_MAX
    5649
    5750/**
    58  * Filesystem format operations.
     51 * Filesystem descriptor.
    5952 */
    60 typedef struct RTFILESYSTEMFMTOPS
     53typedef struct RTFILESYSTEMDESC
    6154{
    62     /** Name of the format. */
    63     const char *pcszFmt;
     55    /** Size of the filesystem specific state in bytes. */
     56    size_t        cbFs;
     57    /** Pointer to the VFS vtable. */
     58    RTVFSOPS      VfsOps;
    6459
    6560    /**
    66      * Probes the given disk for known structures.
     61     * Probes the underlying for a known filesystem.
    6762     *
    6863     * @returns IPRT status code.
    69      * @param   hMedium          Medium handle.
    70      * @param   puScore          Where to store the match score on success.
     64     * @param   hVfsFile    VFS file handle of the underlying medium.
     65     * @param   puScore     Where to store the match score on success.
    7166     */
    72     DECLCALLBACKMEMBER(int, pfnProbe)(RTFILESYSTEMMEDIUM hMedium, uint32_t *puScore);
     67    DECLCALLBACKMEMBER(int, pfnProbe) (RTVFSFILE hVfsFile, uint32_t *puScore);
    7368
    7469    /**
    75      * Opens the format to set up all structures.
     70     * Initializes the given filesystem state.
    7671     *
    7772     * @returns IPRT status code.
    78      * @param   hMedium          Medium handle.
    79      * @param   phFileSysFmt     Where to store the filesystem format instance on success.
     73     * @param   pvThis      Uninitialized filesystem state.
     74     * @param   hVfsFile    VFS file handle of the underlying medium.
    8075     */
    81     DECLCALLBACKMEMBER(int, pfnOpen)(RTFILESYSTEMMEDIUM hMedium, PRTFILESYSTEMFMT phFsFmt);
     76    DECLCALLBACKMEMBER(int, pfnInit) (void *pvThis, RTVFSFILE hVfsFile);
    8277
    83     /**
    84      * Closes the filesystem format.
    85      *
    86      * @returns IPRT status code.
    87      * @param   hFsFmt           The format specific filesystem handle.
    88      */
    89     DECLCALLBACKMEMBER(int, pfnClose)(RTFILESYSTEMFMT hFsFmt);
     78} RTFILESYSTEMDESC;
     79/** Pointer to a filesystem descriptor. */
     80typedef RTFILESYSTEMDESC *PRTFILESYSTEMDESC;
     81typedef const RTFILESYSTEMDESC *PCRTFILESYSTEMDESC;
    9082
    91     /**
    92      * Returns block size of the given filesystem.
    93      *
    94      * @returns Block size of filesystem.
    95      * @param   hFsFmt           The format specific filesystem handle.
    96      */
    97     DECLCALLBACKMEMBER(uint64_t, pfnGetBlockSize)(RTFILESYSTEMFMT hFsFmt);
    98 
    99     /**
    100      * Query the use of the given range in the filesystem.
    101      *
    102      * @returns IPRT status code.
    103      * @param   hFsFmt           The format specific filesystem handle.
    104      * @param   offStart         Start offset to check.
    105      * @param   cb               Size of the range to check.
    106      * @param   pfUsed           Where to store whether the range is in use
    107      *                           by the filesystem.
    108      */
    109     DECLCALLBACKMEMBER(int, pfnQueryRangeUse)(RTFILESYSTEMFMT hFsFmt, uint64_t offStart,
    110                                               size_t cb, bool *pfUsed);
    111 
    112 } RTFILESYSTEMFMTOPS;
    113 /** Pointer to a filesystem format ops table. */
    114 typedef RTFILESYSTEMFMTOPS *PRTFILESYSTEMFMTOPS;
    115 /** Pointer to a const filesystem format ops table. */
    116 typedef const RTFILESYSTEMFMTOPS *PCRTFILESYSTEMFMTOPS;
    117 
    118 /** Converts a LBA number to the byte offset. */
    119 #define RTFILESYSTEM_LBA2BYTE(lba, disk) ((lba) * (disk)->cbSector)
    120 /** Converts a Byte offset to the LBA number. */
    121 #define RTFILESYSTEM_BYTE2LBA(off, disk) ((off) / (disk)->cbSector)
    122 
    123 /**
    124  * Return size of the medium in bytes.
    125  *
    126  * @returns Size of the medium in bytes.
    127  * @param   hMedium    The medium handle.
    128  */
    129 DECLHIDDEN(uint64_t) rtFilesystemMediumGetSize(RTFILESYSTEMMEDIUM hMedium);
    130 
    131 /**
    132  * Read from the medium at the given offset.
    133  *
    134  * @returns IPRT status code.
    135  * @param   hMedium  The medium handle to read from.
    136  * @param   off      Start offset.
    137  * @param   pvBuf    Destination buffer.
    138  * @param   cbRead   How much to read.
    139  */
    140 DECLHIDDEN(int) rtFilesystemMediumRead(RTFILESYSTEMMEDIUM hMedium, uint64_t off,
    141                                        void *pvBuf, size_t cbRead);
    142 
    143 /**
    144  * Write to the disk at the given offset.
    145  *
    146  * @returns IPRT status code.
    147  * @param   hMedium  The medium handle to write to.
    148  * @param   off      Start offset.
    149  * @param   pvBuf    Source buffer.
    150  * @param   cbWrite  How much to write.
    151  */
    152 DECLHIDDEN(int) rtFilesystemMediumWrite(RTFILESYSTEMMEDIUM hMedium, uint64_t off,
    153                                         const void *pvBuf, size_t cbWrite);
     83extern DECLHIDDEN(RTFILESYSTEMDESC const) g_rtFsExt;
    15484
    15585RT_C_DECLS_END
  • trunk/src/VBox/Runtime/include/internal/magics.h

    r40855 r41549  
    5959/** The value of RTFILEAIOREQINT::u32Magic. (Stephen Edwin King)  */
    6060#define RTFILEAIOREQ_MAGIC              UINT32_C(0x19470921)
    61 /** The value of RTFILESYSTEMINT::u32Magic. (John Scalzi) */
    62 #define RTFILESYSTEM_MAGIC              UINT32_C(0x19690510)
    63 /** The value of RTFILESYSTEMINT::u32Magic after close. */
    64 #define RTFILESYSTEM_MAGIC_DEAD         (~RTFILESYSTEM_MAGIC)
    6561/** The value of RTENVINTERNAL::u32Magic. (Rumiko Takahashi) */
    6662#define RTENV_MAGIC                     UINT32_C(0x19571010)
  • trunk/src/VBox/Runtime/testcase/tstRTFilesystem.cpp

    r40029 r41549  
    3030*******************************************************************************/
    3131#include <iprt/filesystem.h>
    32 
     32#include <iprt/vfs.h>
    3333#include <iprt/err.h>
    3434#include <iprt/test.h>
     
    4141*******************************************************************************/
    4242
    43 static int filesystemDiskRead(void *pvUser, uint64_t off, void *pvBuf, size_t cbRead)
    44 {
    45     RTFILE hFile = (RTFILE)pvUser;
    46 
    47     return RTFileReadAt(hFile, off, pvBuf, cbRead, NULL);
    48 }
    49 
    50 static int filesystemDiskWrite(void *pvUser, uint64_t off, const void *pvBuf, size_t cbWrite)
    51 {
    52     RTFILE hFile = (RTFILE)pvUser;
    53 
    54     return RTFileWriteAt(hFile, off, pvBuf, cbWrite, NULL);
    55 }
    56 
    57 static int tstRTFilesystem(RTTEST hTest, RTFILE hFile, uint64_t cb)
     43static int tstRTFilesystem(RTTEST hTest, RTVFSFILE hVfsFile)
    5844{
    5945    int rc = VINF_SUCCESS;
     46    RTVFS hVfs = NIL_RTVFS;
    6047
    6148    RTTestSubF(hTest, "Create filesystem object");
    62     RTFILESYSTEM hFs;
    63     rc = RTFilesystemOpen(&hFs, filesystemDiskRead, filesystemDiskWrite, cb, 512, hFile, 0 /* fFlags */);
     49
     50    rc = RTFilesystemVfsFromFile(hVfsFile, &hVfs);
    6451    if (RT_FAILURE(rc))
    6552    {
    66         RTTestIFailed("RTFilesystemOpen -> %Rrc", rc);
     53        RTTestIFailed("RTFilesystemVfsFromFile -> %Rrc", rc);
    6754        return rc;
    6855    }
    69 
    70     RTTestIPrintf(RTTESTLVL_ALWAYS, "Successfully opened filesystem with format: %s.\n",
    71                   RTFilesystemGetFormat(hFs));
    72     RTTestIPrintf(RTTESTLVL_ALWAYS, "Block size is: %llu.\n",
    73                   RTFilesystemGetBlockSize(hFs));
    7456
    7557    /* Check all blocks. */
     
    7759    uint32_t cBlocksUsed = 0;
    7860    uint32_t cBlocksUnused = 0;
     61    uint64_t cbFs = 0;
    7962
    80     while (off < cb)
     63    rc = RTVfsFileGetSize(hVfsFile, &cbFs);
     64    if (RT_FAILURE(rc))
     65    {
     66        RTTestIFailed("RTVfsFileGetSize -> %Rrc", rc);
     67        return rc;
     68    }
     69
     70    while (off < cbFs)
    8171    {
    8272        bool fUsed = false;
    8373
    84         rc = RTFilesystemQueryRangeUse(hFs, off, 1024, &fUsed);
     74        rc = RTVfsIsRangeInUse(hVfs, off, 1024, &fUsed);
    8575        if (RT_FAILURE(rc))
    8676        {
    87             RTTestIFailed("RTFileSysQueryRangeUse -> %Rrc", rc);
     77            RTTestIFailed("RTVfsIsRangeInUse -> %Rrc", rc);
    8878            break;
    8979        }
     
    10191                      cBlocksUsed, cBlocksUnused);
    10292
    103     RTFilesystemRelease(hFs);
     93    RTVfsRelease(hVfs);
    10494
    10595    return rc;
     
    128118    /* Open image. */
    129119    RTFILE hFile;
    130     uint64_t cb = 0;
     120    RTVFSFILE hVfsFile;
    131121    rc = RTFileOpen(&hFile, argv[1], RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_READ);
    132122    if (RT_FAILURE(rc))
     
    136126    }
    137127
    138     rc = RTFileGetSize(hFile, &cb);
    139     if (   RT_FAILURE(rc)
    140         || cb % 512 != 0) /* Assume 512 byte sector size. */
     128    rc = RTVfsFileFromRTFile(hFile, 0, false, &hVfsFile);
     129    if (RT_FAILURE(rc))
    141130    {
    142         RTTestIFailed("RTFileGetSize -> %Rrc", rc);
     131        RTTestIFailed("RTVfsFileFromRTFile -> %Rrc", rc);
    143132        return RTTestSummaryAndDestroy(hTest);
    144133    }
    145134
    146     rc = tstRTFilesystem(hTest, hFile, cb);
     135    rc = tstRTFilesystem(hTest, hVfsFile);
    147136
    148137    RTTESTI_CHECK(rc == VINF_SUCCESS);
     138
     139    RTVfsFileRelease(hVfsFile);
    149140
    150141    /*
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